1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00

tests: speedup kmsg processing

Since there could be multiple readers of kmsg (test & journald) it needs
to be fast, to capture things like sysrq trace.

But to capture whole output it would need to prioritize reading of kmsg,
thus we would first log kernel messages and followed by command output.

As a trade-off always log command output first and use large drain
buffer so is captures most of messages, but occasionaly miss some
lines.
This commit is contained in:
Zdenek Kabelac 2014-03-03 19:08:22 +01:00
parent 52007a9191
commit 719261a33a

View File

@ -180,7 +180,7 @@ static void _append_buf(const char *buf, size_t len)
kill(-pid, SIGINT); kill(-pid, SIGINT);
return; return;
} }
readbuf_sz = readbuf_sz ? 2 * readbuf_sz : 16384; readbuf_sz = 2 * (readbuf_used + len + readbuf_sz);
readbuf = realloc(readbuf, readbuf_sz); readbuf = realloc(readbuf, readbuf_sz);
} }
@ -226,19 +226,17 @@ static const char *_append_with_stamp(const char *buf, int stamp)
return bb; return bb;
} }
static void drain(int fd, size_t size_limit) static int drain(int fd)
{ {
char buf[4096 + 1]; char buf[2 * 1024 * 1024 + 1]; /* try to capture large sysrq trace */
const char *bp; const char *bp;
int stamp = 0; int stamp = 0;
int sz, total_sz = 0; int sz;
static int stdout_last = -1, stdout_counter = 0; static int stdout_last = -1, stdout_counter = 0;
static int outfile_last = -1, outfile_counter = 0; static int outfile_last = -1, outfile_counter = 0;
while ((sz = read(fd, buf, sizeof(buf) - 1)) > 0) { if ((sz = read(fd, buf, sizeof(buf) - 1)) > 0) {
if (fullbuffer)
continue;
buf[sz] = '\0'; buf[sz] = '\0';
bp = (verbose < 2) ? buf : _append_with_stamp(buf, stamp); bp = (verbose < 2) ? buf : _append_with_stamp(buf, stamp);
if (sz > (bp - buf)) { if (sz > (bp - buf)) {
@ -253,13 +251,32 @@ static void drain(int fd, size_t size_limit)
trickle(stdout, &stdout_last, &stdout_counter); trickle(stdout, &stdout_last, &stdout_counter);
if (outfile) if (outfile)
trickle(outfile, &outfile_last, &outfile_counter); trickle(outfile, &outfile_last, &outfile_counter);
total_sz += sz;
if (total_sz > size_limit) {
printf("\n...Trimmed output...\n");
break;
}
} }
return sz;
}
static int drain_fds(int fd1, int fd2, long timeout)
{
int ret;
fd_set set;
struct timeval selectwait = { .tv_usec = timeout };
FD_ZERO(&set);
FD_SET(fd1, &set);
if (fd2 >= 0)
FD_SET(fd2, &set);
if ((ret = select(fd2 > fd1 ? fd2 + 1 : fd1 + 1, &set, NULL, NULL, &selectwait)) <= 0)
return ret;
if (FD_ISSET(fd1, &set) && drain(fd1) > 0)
return fd1 + 1;
if (fd2 >= 0 && FD_ISSET(fd2, &set) && drain(fd2) > 0)
return fd2 + 1;
return -1;
} }
static const char *duration(time_t start, const struct rusage *usage) static const char *duration(time_t start, const struct rusage *usage)
@ -378,15 +395,13 @@ static void run(int i, char *f) {
char buf[128]; char buf[128];
char outpath[PATH_MAX]; char outpath[PATH_MAX];
char *c = outpath + strlen(results) + 1; char *c = outpath + strlen(results) + 1;
struct timeval selectwait;
struct stat statbuf; struct stat statbuf;
fd_set set;
int runaway = 0; int runaway = 0;
int no_write = 0; int no_write = 0;
int collect_debug = 0; int collect_debug = 0;
int fd_debuglog = -1; int fd_debuglog = -1;
int fd_kmsg = -1; int fd_kmsg;
FILE *kmsg; int ret;
//close(fds[1]); //close(fds[1]);
testdirdebug[0] = '\0'; /* Capture RUNTESTDIR */ testdirdebug[0] = '\0'; /* Capture RUNTESTDIR */
@ -400,16 +415,10 @@ static void run(int i, char *f) {
perror("fopen"); perror("fopen");
/* Mix-in kernel log message */ /* Mix-in kernel log message */
if (!(kmsg = fopen("/proc/kmsg", "r"))) if ((fd_kmsg = open("/proc/kmsg", O_RDONLY | O_NONBLOCK)) < 0)
perror("fopen kmsg"); perror("open kmsg");
else if ((fd_kmsg = fileno(kmsg)) >= 0) { else if (lseek(fd_kmsg, 0L, SEEK_END) == (off_t) -1)
if ((fcntl(fd_kmsg, F_SETFL, O_NONBLOCK ) == -1)) { perror("lseek kmsg");
perror("fcntl kmsg");
fclose(kmsg);
kmsg = NULL;
} else if (fseek(kmsg, 0L, SEEK_END))
perror("fseek kmsg");
}
while ((w = wait4(pid, &st, WNOHANG, &usage)) == 0) { while ((w = wait4(pid, &st, WNOHANG, &usage)) == 0) {
if ((fullbuffer && fullbuffer++ == 8000) || if ((fullbuffer && fullbuffer++ == 8000) ||
@ -435,11 +444,7 @@ static void run(int i, char *f) {
break; break;
} }
FD_ZERO(&set); if ((ret = drain_fds(fds[0], fd_kmsg, 500000)) <= 0) {
FD_SET(fds[0], &set);
selectwait.tv_sec = 0;
selectwait.tv_usec = 500000; /* timeout 0.5s */
if (select(fds[0] + 1, &set, NULL, NULL, &selectwait) <= 0) {
/* Still checking debug log size if it's not growing too much */ /* Still checking debug log size if it's not growing too much */
if (!unlimited && testdirdebug[0] && if (!unlimited && testdirdebug[0] &&
(stat(testdirdebug, &statbuf) == 0) && (stat(testdirdebug, &statbuf) == 0) &&
@ -451,26 +456,25 @@ static void run(int i, char *f) {
no_write++; no_write++;
continue; continue;
} } else if (ret == (fds[0] + 1))
drain(fds[0], INT32_MAX); no_write = 0;
no_write = 0;
if (fd_kmsg >= 0)
drain(fd_kmsg, INT32_MAX);
} }
if (w != pid) { if (w != pid) {
perror("waitpid"); perror("waitpid");
exit(206); exit(206);
} }
drain(fds[0], INT32_MAX);
if (fd_kmsg >= 0) while (!fullbuffer && (drain_fds(fds[0], fd_kmsg, 0) > 0))
drain(fd_kmsg, INT32_MAX); /* read out what was left */;
if (die == 2) if (die == 2)
interrupted(i, f); interrupted(i, f);
else if (runaway) { else if (runaway) {
if (collect_debug && if (collect_debug &&
(fd_debuglog = open(testdirdebug, O_RDONLY)) != -1) { (fd_debuglog = open(testdirdebug, O_RDONLY)) != -1) {
/* Normally read only first 4MB */ runaway = unlimited ? INT32_MAX : 4 * 1024 * 1024;
drain(fd_debuglog, unlimited ? INT32_MAX : 4 * 1024 * 1024); while (!fullbuffer && runaway > 0 && (ret = drain(fd_debuglog)) > 0)
runaway -= ret;
close(fd_debuglog); close(fd_debuglog);
} }
timeout(i, f); timeout(i, f);
@ -484,8 +488,8 @@ static void run(int i, char *f) {
} else } else
failed(i, f, st); failed(i, f, st);
if (kmsg) if (fd_kmsg >= 0)
fclose(kmsg); close(fd_kmsg);
if (outfile) if (outfile)
fclose(outfile); fclose(outfile);
if (fullbuffer) if (fullbuffer)