Beispiel #1
0
static void record_live(FILE *f, void* state, struct timeval *tm, char *buf, int len)
{
    struct timeval tv, wall;

    gettimeofday(&wall, 0);
    tv=*tm;
    tadd(tv, *((struct timeval*)state));
    tsub(tv, wall);
    if (tv.tv_sec>=0 && (tv.tv_sec || tv.tv_usec)) // can't go back in time
        select(0, 0, 0, 0, &tv);
    else
        tsub(*(struct timeval*)state, tv); // move the origin by the (negative) time skipped
    fwrite(buf, 1, len, f);
    fflush(f);
}
Beispiel #2
0
static void aio_write_done(void *opaque, int ret)
{
    struct aio_ctx *ctx = opaque;
    struct timeval t2;

    gettimeofday(&t2, NULL);


    if (ret < 0) {
        printf("aio_write failed: %s\n", strerror(-ret));
        goto out;
    }

    if (ctx->qflag) {
        goto out;
    }

    /* Finally, report back -- -C gives a parsable format */
    t2 = tsub(t2, ctx->t1);
    print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
                 ctx->qiov.size, 1, ctx->Cflag);
out:
    qemu_io_free(ctx->buf);
    qemu_iovec_destroy(&ctx->qiov);
    g_free(ctx);
}
Beispiel #3
0
static void play_live(FILE *f,
    void *(synch_init_wait)(struct timeval *ts, void *arg),
    void *(synch_wait)(struct timeval *tv, void *arg),
    void *(synch_print)(char *buf, int len, void *arg),
    void *arg, struct timeval *cont)
{
    struct timeval tv, tp, tm;
    char buf[BUFFER_SIZE];
    int len;

    if (cont)
        tp=*cont;
    else
    {
        gettimeofday(&tp, 0);
        synch_init_wait(&tp, arg);
    }

    // using read() not fread(), we need unbuffered IO
    while ((len=read(fileno(f), buf, BUFFER_SIZE))>0)
    {
        gettimeofday(&tv, 0);
        tm=tv;
        tsub(tm, tp);
        synch_wait(&tm, arg);
        tp=tv;
        synch_print(buf, len, arg);
    }
}
Beispiel #4
0
static void
aio_write_done(void *opaque, int ret)
{
	struct aio_ctx *ctx = opaque;
	struct timeval t2;

	gettimeofday(&t2, NULL);


	if (ret < 0) {
		printf("aio_write failed: %s\n", strerror(-ret));
		goto out;
	}

	if (ctx->qflag) {
		goto out;
	}

	
	t2 = tsub(t2, ctx->t1);
	print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
		     ctx->qiov.size, 1, ctx->Cflag);
out:
	qemu_io_free(ctx->buf);
	free(ctx);
}
Beispiel #5
0
static void get_pos(void)
{
    if (play_state==2)
    {
        gettimeofday(&tr, 0);
        tsub(tr, t0);
        tmul1000(tr, speed);
    }
}
Beispiel #6
0
static int discard_f(int argc, char **argv)
{
    struct timeval t1, t2;
    int Cflag = 0, qflag = 0;
    int c, ret;
    int64_t offset;
    int count;

    while ((c = getopt(argc, argv, "Cq")) != EOF) {
        switch (c) {
        case 'C':
            Cflag = 1;
            break;
        case 'q':
            qflag = 1;
            break;
        default:
            return command_usage(&discard_cmd);
        }
    }

    if (optind != argc - 2) {
        return command_usage(&discard_cmd);
    }

    offset = cvtnum(argv[optind]);
    if (offset < 0) {
        printf("non-numeric length argument -- %s\n", argv[optind]);
        return 0;
    }

    optind++;
    count = cvtnum(argv[optind]);
    if (count < 0) {
        printf("non-numeric length argument -- %s\n", argv[optind]);
        return 0;
    }

    gettimeofday(&t1, NULL);
    ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS,
                       count >> BDRV_SECTOR_BITS);
    gettimeofday(&t2, NULL);

    if (ret < 0) {
        printf("discard failed: %s\n", strerror(-ret));
        goto out;
    }

    /* Finally, report back -- -C gives a parsable format */
    if (!qflag) {
        t2 = tsub(t2, t1);
        print_report("discard", &t2, offset, count, count, 1, Cflag);
    }

out:
    return 0;
}
Beispiel #7
0
static void* record_live_init(FILE *f, struct timeval *tm)
{
    struct timeval *tv;

    tv=malloc(sizeof(struct timeval));
    gettimeofday(tv, 0);
    tsub(*tv, *tm);

    return tv;
}
Beispiel #8
0
Datei: AF.c Projekt: tongfw/pcp
int
__pmAFunregister(int afid)
{
    qelt		*qp;
    qelt		*priorp;
    struct timeval	now;
    struct timeval	interval;

    if (PM_MULTIPLE_THREADS(PM_SCOPE_AF))
	return PM_ERR_THREAD;

    if (!block)
	AFhold();
    for (qp = root, priorp = NULL; qp != NULL && qp->q_afid != afid; qp = qp->q_next)
	    priorp = qp;

    if (qp == NULL) {
	if (!block)
	    AFrelse();
	return -1;
    }

    if (priorp == NULL) {
	root = qp->q_next;
	if (root != NULL) {
	    /*
	     * we removed the head of the queue, set itimer for the
	     * new head of queue
	     */
	    interval = root->q_when;
	    __pmtimevalNow(&now);
	    tsub(&interval, &now);
	    if (interval.tv_sec == 0 && interval.tv_usec < MIN_ITIMER_USEC)
		/* use minimal delay (platform dependent) */
		interval.tv_usec = MIN_ITIMER_USEC;
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_AF) {
		__pmPrintStamp(stderr, &now);
		fprintf(stderr, " AFsetitimer for delta ");
		printdelta(stderr, &interval);
		fputc('\n', stderr);
	    }
#endif
	    AFsetitimer(&interval);
	}
    }
    else
	priorp->q_next = qp->q_next;

    free(qp);

    if (!block)
	AFrelse();
    return 0;
}
Beispiel #9
0
static int replay_play(struct timeval *delay)
{ // structures touched: tev, vt
    struct timeval tr1;
    ttyrec_frame fn;

    switch (play_state)
    {
    case 0:
    default:
    case 1:
        return 0;
    case 2:
        gettimeofday(&tr, 0);
        tsub(tr, t0);
        tmul1000(tr, speed);
        tr1=tr;
        tadd(tr1, tdate);
        if (tev_cur && tev_cur->len>tev_curlp)
        {
            tty_write(vt, tev_cur->data+tev_curlp, tev_cur->len-tev_curlp);
            tev_curlp=tev_cur->len;
        }
        while ((fn=ttyrec_next_frame(ttr, tev_cur)) && tcmp(fn->t, tr1)==-1)
        {
            tev_cur=fn;
            if (tev_cur->data)
                tty_write(vt, tev_cur->data, tev_cur->len);
            tev_curlp=tev_cur->len;
        }
        if ((fn=ttyrec_next_frame(ttr, tev_cur)))
        {
            *delay=fn->t;
            tsub(*delay, tdate);
            tsub(*delay, tr);
            tdiv1000(*delay, speed);
            return 1;
        }
        play_state=tev_done?0:3;
    case 3:
        return 0;
    }
}
Beispiel #10
0
// find the frame containing time "tr", update "t0"
static void replay_seek(void)
{
    struct timeval t;

    t=tr;
    tadd(t, tdate);
    tev_cur=ttyrec_seek(ttr, &t, &vt);
    tev_curlp=0;

    gettimeofday(&t0, 0);
    tdiv1000(tr, speed);
    tsub(t0, tr);
}
Beispiel #11
0
Datei: AF.c Projekt: tongfw/pcp
int
__pmAFregister(const struct timeval *delta, void *data, void (*func)(int, void *))
{
    qelt		*qp;
    struct timeval	now;
    struct timeval	interval;

    if (PM_MULTIPLE_THREADS(PM_SCOPE_AF))
	return PM_ERR_THREAD;

    if (!block)
	AFhold();
    if (afid == 0x8000 && !block)	/* first time */
	AFrearm();
    if ((qp = (qelt *)malloc(sizeof(qelt))) == NULL) {
	return -oserror();
    }
    qp->q_afid = ++afid;
    qp->q_data = data;
    qp->q_delta = *delta;
    qp->q_func = func;
    __pmtimevalNow(&qp->q_when);
    tadd(&qp->q_when, &qp->q_delta);

    enqueue(qp);
    if (root == qp) {
	/* we ended up at the head of the list, set itimer */
	interval = qp->q_when;
	__pmtimevalNow(&now);
	tsub(&interval, &now);

	if (interval.tv_sec == 0 && interval.tv_usec < MIN_ITIMER_USEC)
	    /* use minimal delay (platform dependent) */
	    interval.tv_usec = MIN_ITIMER_USEC;

#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_AF) {
	    __pmPrintStamp(stderr, &now);
	    fprintf(stderr, " AFsetitimer for delta ");
	    printdelta(stderr, &interval);
	    fputc('\n', stderr);
	}
#endif
	AFsetitimer(&interval);
    }

    if (!block)
	AFrelse();
    return qp->q_afid;
}
Beispiel #12
0
static void replay_start(void)
{
    tty tev_vt;
    ttyrec_frame tev_tail;
    struct timeval doomsday;

    ttyrec_free(ttr);
    tev_vt=tty_init(defsx, defsy, 1);
    tev_vt->cp437=1;
    tty_printf(tev_vt, "\e[36m");
    tty_printf(tev_vt, _("Termplay v%s\n\n"),
        "\e[36;1m"PACKAGE_VERSION"\e[0;36m");
    tty_printf(tev_vt, "\e[0m");

    tr.tv_sec=tr.tv_usec=0;
    tev_done=0;
    tmax.tv_sec=tmax.tv_usec=0;
    progmax=0;
    progdiv=1000000;
    progval=-1;
    // TODO: re-enable threading
#ifdef THREADED
    pth=CreateThread(0, 0, (LPTHREAD_START_ROUTINE)playfile, (LPDWORD)0, 0, 0);
#else
//    printf("Buffering: started.\n");
    playfile(tev_vt);
//    printf("Buffering: done.\n");
    tev_done=1;
    tev_cur=ttyrec_seek(ttr, 0, 0);
    tdate=tev_cur->t;
    replay_seek();
    doomsday.tv_sec=1ULL<<(sizeof(doomsday.tv_sec)*8-1)-1;
    doomsday.tv_usec=0;
    tev_tail=ttyrec_seek(ttr, &doomsday, 0);
    tmax=tev_tail->t;
    tsub(tmax, tdate);
    if (tmax.tv_sec<100)
        progdiv=10000;
    else
        progdiv=1000000;
    selstart.tv_sec=0;
    selstart.tv_usec=0;
    selend=tmax;
    progmax=tmax.tv_sec*(1000000/progdiv)+tmax.tv_usec/progdiv;
    set_prog_max();
    set_prog();
#endif
}
Beispiel #13
0
static void replay_pause(void)
{
    switch (play_state)
    {
    case 0:
    default:
    case 1:
        break;
    case 2:
        gettimeofday(&tr, 0);
        tsub(tr, t0);
        tmul1000(tr, speed);
    case 3:
        play_state=1;
    }
}
Beispiel #14
0
static void
sleeptill(struct timeval sched)
{
    int sts;
    struct timeval curr;	/* current time */
    struct timespec delay;	/* interval to sleep */
    struct timespec left;	/* remaining sleep time */

    __pmtimevalNow(&curr);
    tospec(tsub(sched, curr), &delay);
    for (;;) {		/* loop to catch early wakeup by nanosleep */
	sts = nanosleep(&delay, &left);
	if (sts == 0 || (sts < 0 && errno != EINTR))
	    break;
	delay = left;
    }
}
Beispiel #15
0
static void replay_resume(void)
{
    struct timeval t;

    switch (play_state)
    {
    case 0:
    default:
    case 1:
        gettimeofday(&t0, 0);
        t=tr;
        tdiv1000(t, speed);
        tsub(t0, t);
        play_state=2;
        break;
    case 2:
    case 3:
        break;
    }
}
Beispiel #16
0
static void
aio_read_done(void *opaque, int ret)
{
    struct aio_ctx *ctx = opaque;
    struct timeval t2;

    gettimeofday(&t2, NULL);

    if (ret < 0) {
        printf("readv failed: %s\n", strerror(-ret));
        goto out;
    }

    if (ctx->Pflag) {
        void *cmp_buf = malloc(ctx->qiov.size);

        memset(cmp_buf, ctx->pattern, ctx->qiov.size);
        if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
            printf("Pattern verification failed at offset %"
                   PRId64 ", %zd bytes\n",
                   ctx->offset, ctx->qiov.size);
        }
        free(cmp_buf);
    }

    if (ctx->qflag) {
        goto out;
    }

    if (ctx->vflag) {
        dump_buffer(ctx->buf, ctx->offset, ctx->qiov.size);
    }

    /* Finally, report back -- -C gives a parsable format */
    t2 = tsub(t2, ctx->t1);
    print_report("read", &t2, ctx->offset, ctx->qiov.size,
                 ctx->qiov.size, 1, ctx->Cflag);
out:
    qemu_io_free(ctx->buf);
    free(ctx);
}
Beispiel #17
0
static int read_f(int argc, char **argv)
{
    struct timeval t1, t2;
    int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
    int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
    int c, cnt;
    char *buf;
    int64_t offset;
    int count;
    /* Some compilers get confused and warn if this is not initialized.  */
    int total = 0;
    int pattern = 0, pattern_offset = 0, pattern_count = 0;

    while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
        switch (c) {
        case 'b':
            bflag = 1;
            break;
        case 'C':
            Cflag = 1;
            break;
        case 'l':
            lflag = 1;
            pattern_count = cvtnum(optarg);
            if (pattern_count < 0) {
                printf("non-numeric length argument -- %s\n", optarg);
                return 0;
            }
            break;
        case 'p':
            pflag = 1;
            break;
        case 'P':
            Pflag = 1;
            pattern = parse_pattern(optarg);
            if (pattern < 0) {
                return 0;
            }
            break;
        case 'q':
            qflag = 1;
            break;
        case 's':
            sflag = 1;
            pattern_offset = cvtnum(optarg);
            if (pattern_offset < 0) {
                printf("non-numeric length argument -- %s\n", optarg);
                return 0;
            }
            break;
        case 'v':
            vflag = 1;
            break;
        default:
            return command_usage(&read_cmd);
        }
    }

    if (optind != argc - 2) {
        return command_usage(&read_cmd);
    }

    if (bflag && pflag) {
        printf("-b and -p cannot be specified at the same time\n");
        return 0;
    }

    offset = cvtnum(argv[optind]);
    if (offset < 0) {
        printf("non-numeric length argument -- %s\n", argv[optind]);
        return 0;
    }

    optind++;
    count = cvtnum(argv[optind]);
    if (count < 0) {
        printf("non-numeric length argument -- %s\n", argv[optind]);
        return 0;
    }

    if (!Pflag && (lflag || sflag)) {
        return command_usage(&read_cmd);
    }

    if (!lflag) {
        pattern_count = count - pattern_offset;
    }

    if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {
        printf("pattern verification range exceeds end of read data\n");
        return 0;
    }

    if (!pflag) {
        if (offset & 0x1ff) {
            printf("offset %" PRId64 " is not sector aligned\n",
                   offset);
            return 0;
        }
        if (count & 0x1ff) {
            printf("count %d is not sector aligned\n",
                   count);
            return 0;
        }
    }

    buf = qemu_io_alloc(count, 0xab);

    gettimeofday(&t1, NULL);
    if (pflag) {
        cnt = do_pread(buf, offset, count, &total);
    } else if (bflag) {
        cnt = do_load_vmstate(buf, offset, count, &total);
    } else {
        cnt = do_read(buf, offset, count, &total);
    }
    gettimeofday(&t2, NULL);

    if (cnt < 0) {
        printf("read failed: %s\n", strerror(-cnt));
        goto out;
    }

    if (Pflag) {
        void *cmp_buf = g_malloc(pattern_count);
        memset(cmp_buf, pattern, pattern_count);
        if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
            printf("Pattern verification failed at offset %"
                   PRId64 ", %d bytes\n",
                   offset + pattern_offset, pattern_count);
        }
        g_free(cmp_buf);
    }

    if (qflag) {
        goto out;
    }

    if (vflag) {
        dump_buffer(buf, offset, count);
    }

    /* Finally, report back -- -C gives a parsable format */
    t2 = tsub(t2, t1);
    print_report("read", &t2, offset, count, total, cnt, Cflag);

out:
    qemu_io_free(buf);

    return 0;
}
Beispiel #18
0
static int
sendfile_f(
	int		argc,
	char		**argv)
{
	off64_t		offset = 0;
	long long	count, total;
	size_t		blocksize, sectsize;
	struct timeval	t1, t2;
	char		s1[64], s2[64], ts[64];
	char		*infile = NULL;
	int		Cflag, qflag;
	int		c, fd = -1;

	Cflag = qflag = 0;
	init_cvtnum(&blocksize, &sectsize);
	while ((c = getopt(argc, argv, "Cf:i:q")) != EOF) {
		switch (c) {
		case 'C':
			Cflag = 1;
			break;
		case 'q':
			qflag = 1;
			break;
		case 'f':
			fd = atoi(argv[1]);
			if (fd < 0 || fd >= filecount) {
				printf(_("value %d is out of range (0-%d)\n"),
					fd, filecount-1);
				return 0;
			}
			break;
		case 'i':
			infile = optarg;
			break;
		default:
			return command_usage(&sendfile_cmd);
		}
	}
	if (infile && fd != -1)
		return command_usage(&sendfile_cmd);

	if (!infile)
		fd = filetable[fd].fd;
	else if ((fd = openfile(infile, NULL, IO_READONLY, 0)) < 0)
		return 0;

	if (optind == argc - 2) {
		offset = cvtnum(blocksize, sectsize, argv[optind]);
		if (offset < 0) {
			printf(_("non-numeric offset argument -- %s\n"),
				argv[optind]);
			goto done;
		}
		optind++;
		count = cvtnum(blocksize, sectsize, argv[optind]);
		if (count < 0) {
			printf(_("non-numeric length argument -- %s\n"),
				argv[optind]);
			goto done;
		}
	} else {
		struct stat64	stat;

		if (fstat64(fd, &stat) < 0) {
			perror("fstat64");
			goto done;
		}
		count = stat.st_size;
	}

	gettimeofday(&t1, NULL);
	c = send_buffer(offset, count, fd, &total);
	if (c < 0)
		goto done;
	if (qflag)
		goto done;
	gettimeofday(&t2, NULL);
	t2 = tsub(t2, t1);

	/* Finally, report back -- -C gives a parsable format */
	timestr(&t2, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
	if (!Cflag) {
		cvtstr((double)total, s1, sizeof(s1));
		cvtstr(tdiv((double)total, t2), s2, sizeof(s2));
		printf(_("sent %lld/%lld bytes from offset %lld\n"),
			total, count, (long long)offset);
		printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"),
			s1, c, ts, s2, tdiv((double)c, t2));
	} else {/* bytes,ops,time,bytes/sec,ops/sec */
		printf("%lld,%d,%s,%.3f,%.3f\n",
			total, c, ts,
			tdiv((double)total, t2), tdiv((double)c, t2));
	}
done:
	if (infile)
		close(fd);
	return 0;
}
Beispiel #19
0
static int
pread_f(
	int		argc,
	char		**argv)
{
	size_t		bsize;
	off64_t		offset;
	unsigned int	zeed = 0;
	long long	count, total, tmp;
	size_t		fsblocksize, fssectsize;
	struct timeval	t1, t2;
	char		s1[64], s2[64], ts[64];
	char		*sp;
	int		Cflag, qflag, uflag, vflag;
	int		eof = 0, direction = IO_FORWARD;
	int		c;

	Cflag = qflag = uflag = vflag = 0;
	init_cvtnum(&fsblocksize, &fssectsize);
	bsize = fsblocksize;

	while ((c = getopt(argc, argv, "b:BCFRquvV:Z:")) != EOF) {
		switch (c) {
		case 'b':
			tmp = cvtnum(fsblocksize, fssectsize, optarg);
			if (tmp < 0) {
				printf(_("non-numeric bsize -- %s\n"), optarg);
				return 0;
			}
			bsize = tmp;
			break;
		case 'C':
			Cflag = 1;
			break;
		case 'F':
			direction = IO_FORWARD;
			break;
		case 'B':
			direction = IO_BACKWARD;
			break;
		case 'R':
			direction = IO_RANDOM;
			break;
		case 'q':
			qflag = 1;
			break;
		case 'u':
			uflag = 1;
			break;
		case 'v':
			vflag = 1;
			break;
#ifdef HAVE_PREADV
		case 'V':
			vectors = strtoul(optarg, &sp, 0);
			if (!sp || sp == optarg) {
				printf(_("non-numeric vector count == %s\n"),
					optarg);
				return 0;
			}
			break;
#endif
		case 'Z':
			zeed = strtoul(optarg, &sp, 0);
			if (!sp || sp == optarg) {
				printf(_("non-numeric seed -- %s\n"), optarg);
				return 0;
			}
			break;
		default:
			return command_usage(&pread_cmd);
		}
	}
	if (optind != argc - 2)
		return command_usage(&pread_cmd);

	offset = cvtnum(fsblocksize, fssectsize, argv[optind]);
	if (offset < 0 && (direction & (IO_RANDOM|IO_BACKWARD))) {
		eof = -1;	/* read from EOF */
	} else if (offset < 0) {
		printf(_("non-numeric length argument -- %s\n"), argv[optind]);
		return 0;
	}
	optind++;
	count = cvtnum(fsblocksize, fssectsize, argv[optind]);
	if (count < 0 && (direction & (IO_RANDOM|IO_FORWARD))) {
		eof = -1;	/* read to EOF */
	} else if (count < 0) {
		printf(_("non-numeric length argument -- %s\n"), argv[optind]);
		return 0;
	}

	if (alloc_buffer(bsize, uflag, 0xabababab) < 0)
		return 0;

	gettimeofday(&t1, NULL);
	switch (direction) {
	case IO_RANDOM:
		if (!zeed)	/* srandom seed */
			zeed = time(NULL);
		c = read_random(file->fd, offset, count, &total, zeed, eof);
		break;
	case IO_FORWARD:
		c = read_forward(file->fd, offset, count, &total, vflag, 0, eof);
		if (eof)
			count = total;
		break;
	case IO_BACKWARD:
		c = read_backward(file->fd, &offset, &count, &total, eof);
		break;
	default:
		ASSERT(0);
	}
	if (c < 0)
		return 0;
	if (qflag)
		return 0;
	gettimeofday(&t2, NULL);
	t2 = tsub(t2, t1);

	/* Finally, report back -- -C gives a parsable format */
	timestr(&t2, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
	if (!Cflag) {
		cvtstr((double)total, s1, sizeof(s1));
		cvtstr(tdiv((double)total, t2), s2, sizeof(s2));
		printf(_("read %lld/%lld bytes at offset %lld\n"),
			total, count, (long long)offset);
		printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"),
			s1, c, ts, s2, tdiv((double)c, t2));
	} else {/* bytes,ops,time,bytes/sec,ops/sec */
		printf("%lld,%d,%s,%.3f,%.3f\n",
			total, c, ts,
			tdiv((double)total, t2), tdiv((double)c, t2));
	}
	return 0;
}
Beispiel #20
0
/*
 * Report process resource utilisation.  Formatting options:
 * "Shell" format: 0.000u 0.000s 0:00.00 0.0%      0+0k 0+0io 0pf+0w
 * Verbose format:
 * 0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 0maxresident)k
 * 0inputs+0outputs (0major+0minor)pagefaults 0swaps
 * Comma Separated Value format: 0.000,0.000,00:00:00.00,0.0,0,0,0,0,0,0
 */
static int
getrusage_f(
	int		argc,
	char		**argv)
{
	struct timeval	wallclk, timenow;
	struct rusage	rusage;
	double		usrtime, systime, elapsed, pct_cpu;
	char		ts[64];
	int		Cflag, vflag;
	int		c;

	Cflag = vflag = 0;
	while ((c = getopt(argc, argv, "Cv")) != EOF) {
		switch (c) {
		case 'C':
			Cflag = 1;
			break;
		case 'v':
			vflag = 1;
			break;
		default:
			return command_usage(&getrusage_cmd);
		}
	}
	if (optind != argc)
		return command_usage(&getrusage_cmd);

	if (getrusage(RUSAGE_SELF, &rusage) < 0) {
		perror("getrusage");
		return 0;
	}

	gettimeofday(&timenow, NULL);
	wallclk = tsub(timenow, stopwatch);
	elapsed = (double)wallclk.tv_sec +
		  ((double)wallclk.tv_usec / 1000000.0);
	usrtime = (double)rusage.ru_utime.tv_sec +
		  ((double)rusage.ru_utime.tv_usec / 1000000.0);
	systime = (double)rusage.ru_stime.tv_sec +
		  ((double)rusage.ru_stime.tv_usec / 1000000.0);
	if (elapsed < usrtime + systime)
		pct_cpu = 100.0;
	else
		pct_cpu = ((usrtime + systime) / elapsed) * 100;
	c = Cflag ? VERBOSE_FIXED_TIME : TERSE_FIXED_TIME;
	timestr(&wallclk, ts, sizeof(ts), c);

	if (Cflag)
		printf("%.3f,%.3f,%s,%.1f,%ld,%ld,%ld,%ld,%ld,%ld,%ld\n",
			usrtime, systime, ts, pct_cpu,
			rusage.ru_majflt, rusage.ru_minflt, rusage.ru_nswap,
			rusage.ru_inblock, rusage.ru_oublock,
			rusage.ru_nvcsw, rusage.ru_nivcsw);
	else if (vflag)
		printf("%.2fuser %.2fsystem %selapsed %.0f%%CPU "
		       "(%ldavgtext+%ldavgdata %ldmaxresident)k\n"
		       "%ldinputs+%ldoutputs "
			"(%ldmajor+%ldminor)pagefaults %ldswaps\n",
			usrtime, systime, ts, pct_cpu,
			rusage.ru_ixrss, rusage.ru_idrss, rusage.ru_maxrss,
			rusage.ru_inblock, rusage.ru_oublock,
			rusage.ru_majflt, rusage.ru_minflt, rusage.ru_nswap);
	else
		printf("%.3fu %.3fs %s %.1f%%\t"
		       "%ld+%ldk %ld+%ldio %ldpf+%ldw\n",
			usrtime, systime, ts, pct_cpu,
			rusage.ru_maxrss, rusage.ru_ixrss,
			rusage.ru_inblock, rusage.ru_oublock,
			rusage.ru_majflt, rusage.ru_nswap);
	return 0;
}
Beispiel #21
0
static int
reflink_f(
	int		argc,
	char		**argv)
{
	off64_t		soffset = 0, doffset = 0;
	long long	count = 0, total;
	char		s1[64], s2[64], ts[64];
	char		*infile = NULL;
	int		Cflag, qflag, wflag, Wflag;
	struct xfs_ioctl_clone_range_args	args;
	size_t		fsblocksize, fssectsize;
	struct timeval	t1, t2;
	int		c, fd = -1;

	Cflag = qflag = wflag = Wflag = 0;
	init_cvtnum(&fsblocksize, &fssectsize);

	while ((c = getopt(argc, argv, "CqwW")) != EOF) {
		switch (c) {
		case 'C':
			Cflag = 1;
			break;
		case 'q':
			qflag = 1;
			break;
		case 'w':
			wflag = 1;
			break;
		case 'W':
			Wflag = 1;
			break;
		default:
			return command_usage(&reflink_cmd);
		}
	}
	if (optind != argc - 4 && optind != argc - 1)
		return command_usage(&reflink_cmd);
	infile = argv[optind];
	optind++;
	if (optind == argc)
		goto clone_all;
	soffset = cvtnum(fsblocksize, fssectsize, argv[optind]);
	if (soffset < 0) {
		printf(_("non-numeric src offset argument -- %s\n"), argv[optind]);
		return 0;
	}
	optind++;
	doffset = cvtnum(fsblocksize, fssectsize, argv[optind]);
	if (doffset < 0) {
		printf(_("non-numeric dest offset argument -- %s\n"), argv[optind]);
		return 0;
	}
	optind++;
	count = cvtnum(fsblocksize, fssectsize, argv[optind]);
	if (count < 1) {
		printf(_("non-positive length argument -- %s\n"), argv[optind]);
		return 0;
	}

clone_all:
	c = IO_READONLY;
	fd = openfile(infile, NULL, c, 0);
	if (fd < 0)
		return 0;

	gettimeofday(&t1, NULL);
	if (count) {
		args.src_fd = fd;
		args.src_offset = soffset;
		args.src_length = count;
		args.dest_offset = doffset;
		c = ioctl(file->fd, XFS_IOC_CLONE_RANGE, &args);
	} else {
		c = ioctl(file->fd, XFS_IOC_CLONE, fd);
	}
	if (c < 0) {
		perror(_("reflink"));
		goto done;
	}
	total = count;
	c = 1;
	if (Wflag)
		fsync(file->fd);
	if (wflag)
		fdatasync(file->fd);
	if (qflag)
		goto done;
	gettimeofday(&t2, NULL);
	t2 = tsub(t2, t1);

	/* Finally, report back -- -C gives a parsable format */
	timestr(&t2, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
	if (!Cflag) {
		cvtstr((double)total, s1, sizeof(s1));
		cvtstr(tdiv((double)total, t2), s2, sizeof(s2));
		printf(_("linked %lld/%lld bytes at offset %lld\n"),
			total, count, (long long)doffset);
		printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"),
			s1, c, ts, s2, tdiv((double)c, t2));
	} else {/* bytes,ops,time,bytes/sec,ops/sec */
		printf("%lld,%d,%s,%.3f,%.3f\n",
			total, c, ts,
			tdiv((double)total, t2), tdiv((double)c, t2));
	}
done:
	close(fd);
	return 0;
}
Beispiel #22
0
static int
pwrite_f(
	int		argc,
	char		**argv)
{
	size_t		bsize;
	off64_t		offset, skip = 0;
	long long	count, total, tmp;
	unsigned int	zeed = 0, seed = 0xcdcdcdcd;
	size_t		fsblocksize, fssectsize;
	struct timeval	t1, t2;
	char		s1[64], s2[64], ts[64];
	char		*sp, *infile = NULL;
	int		Cflag, qflag, uflag, dflag, wflag, Wflag;
	int		direction = IO_FORWARD;
	int		c, fd = -1;

	Cflag = qflag = uflag = dflag = wflag = Wflag = 0;
	init_cvtnum(&fsblocksize, &fssectsize);
	bsize = fsblocksize;

	while ((c = getopt(argc, argv, "b:Cdf:i:qs:S:uwWZ:")) != EOF) {
		switch (c) {
		case 'b':
			tmp = cvtnum(fsblocksize, fssectsize, optarg);
			if (tmp < 0) {
				printf(_("non-numeric bsize -- %s\n"), optarg);
				return 0;
			}
			bsize = tmp;
			break;
		case 'C':
			Cflag = 1;
			break;
		case 'F':
			direction = IO_FORWARD;
			break;
		case 'B':
			direction = IO_BACKWARD;
			break;
		case 'R':
			direction = IO_RANDOM;
			break;
		case 'd':
			dflag = 1;
			break;
		case 'f':
		case 'i':
			infile = optarg;
			break;
		case 's':
			skip = cvtnum(fsblocksize, fssectsize, optarg);
			if (skip < 0) {
				printf(_("non-numeric skip -- %s\n"), optarg);
				return 0;
			}
			break;
		case 'S':
			seed = strtoul(optarg, &sp, 0);
			if (!sp || sp == optarg) {
				printf(_("non-numeric seed -- %s\n"), optarg);
				return 0;
			}
			break;
		case 'q':
			qflag = 1;
			break;
		case 'u':
			uflag = 1;
			break;
		case 'w':
			wflag = 1;
			break;
		case 'W':
			Wflag = 1;
			break;
		case 'Z':
			zeed = strtoul(optarg, &sp, 0);
			if (!sp || sp == optarg) {
				printf(_("non-numeric seed -- %s\n"), optarg);
				return 0;
			}
			break;
		default:
			return command_usage(&pwrite_cmd);
		}
	}
	if (((skip || dflag) && !infile) || (optind != argc - 2))
		return command_usage(&pwrite_cmd);
	if (infile && direction != IO_FORWARD)
		return command_usage(&pwrite_cmd);
	offset = cvtnum(fsblocksize, fssectsize, argv[optind]);
	if (offset < 0) {
		printf(_("non-numeric offset argument -- %s\n"), argv[optind]);
		return 0;
	}
	optind++;
	count = cvtnum(fsblocksize, fssectsize, argv[optind]);
	if (count < 0) {
		printf(_("non-numeric length argument -- %s\n"), argv[optind]);
		return 0;
	}

	if (alloc_buffer(bsize, uflag, seed) < 0)
		return 0;

	c = IO_READONLY | (dflag ? IO_DIRECT : 0);
	if (infile && ((fd = openfile(infile, NULL, c, 0)) < 0))
		return 0;

	gettimeofday(&t1, NULL);
	switch (direction) {
	case IO_RANDOM:
		if (!zeed)	/* srandom seed */
			zeed = time(NULL);
		c = write_random(offset, count, zeed, &total);
		break;
	case IO_FORWARD:
		c = write_buffer(offset, count, bsize, fd, skip, &total);
		break;
	case IO_BACKWARD:
		c = write_backward(offset, &count, &total);
		break;
	default:
		total = 0;
		ASSERT(0);
	}
	if (c < 0)
		goto done;
	if (Wflag)
		fsync(file->fd);
	if (wflag)
		fdatasync(file->fd);
	if (qflag)
		goto done;
	gettimeofday(&t2, NULL);
	t2 = tsub(t2, t1);

	/* Finally, report back -- -C gives a parsable format */
	timestr(&t2, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
	if (!Cflag) {
		cvtstr((double)total, s1, sizeof(s1));
		cvtstr(tdiv((double)total, t2), s2, sizeof(s2));
		printf(_("wrote %lld/%lld bytes at offset %lld\n"),
			total, count, (long long)offset);
		printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"),
			s1, c, ts, s2, tdiv((double)c, t2));
	} else {/* bytes,ops,time,bytes/sec,ops/sec */
		printf("%lld,%d,%s,%.3f,%.3f\n",
			total, c, ts,
			tdiv((double)total, t2), tdiv((double)c, t2));
	}
done:
	if (infile)
		close(fd);
	return 0;
}
Beispiel #23
0
static int
pread_f(
	int		argc,
	char		**argv)
{
	size_t		bsize;
	off64_t		offset;
	unsigned int	zeed = 0;
	long long	count, total, tmp;
	size_t		fsblocksize, fssectsize;
	struct timeval	t1, t2;
	char		*sp;
	int		Cflag, qflag, uflag, vflag;
	int		eof = 0, direction = IO_FORWARD;
	int		c;

	Cflag = qflag = uflag = vflag = 0;
	init_cvtnum(&fsblocksize, &fssectsize);
	bsize = fsblocksize;

	while ((c = getopt(argc, argv, "b:BCFRquvV:Z:")) != EOF) {
		switch (c) {
		case 'b':
			tmp = cvtnum(fsblocksize, fssectsize, optarg);
			if (tmp < 0) {
				printf(_("non-numeric bsize -- %s\n"), optarg);
				return 0;
			}
			bsize = tmp;
			break;
		case 'C':
			Cflag = 1;
			break;
		case 'F':
			direction = IO_FORWARD;
			break;
		case 'B':
			direction = IO_BACKWARD;
			break;
		case 'R':
			direction = IO_RANDOM;
			break;
		case 'q':
			qflag = 1;
			break;
		case 'u':
			uflag = 1;
			break;
		case 'v':
			vflag = 1;
			break;
#ifdef HAVE_PREADV
		case 'V':
			vectors = strtoul(optarg, &sp, 0);
			if (!sp || sp == optarg) {
				printf(_("non-numeric vector count == %s\n"),
					optarg);
				return 0;
			}
			break;
#endif
		case 'Z':
			zeed = strtoul(optarg, &sp, 0);
			if (!sp || sp == optarg) {
				printf(_("non-numeric seed -- %s\n"), optarg);
				return 0;
			}
			break;
		default:
			return command_usage(&pread_cmd);
		}
	}
	if (optind != argc - 2)
		return command_usage(&pread_cmd);

	offset = cvtnum(fsblocksize, fssectsize, argv[optind]);
	if (offset < 0 && (direction & (IO_RANDOM|IO_BACKWARD))) {
		eof = -1;	/* read from EOF */
	} else if (offset < 0) {
		printf(_("non-numeric length argument -- %s\n"), argv[optind]);
		return 0;
	}
	optind++;
	count = cvtnum(fsblocksize, fssectsize, argv[optind]);
	if (count < 0 && (direction & (IO_RANDOM|IO_FORWARD))) {
		eof = -1;	/* read to EOF */
	} else if (count < 0) {
		printf(_("non-numeric length argument -- %s\n"), argv[optind]);
		return 0;
	}

	if (alloc_buffer(bsize, uflag, 0xabababab) < 0)
		return 0;

	gettimeofday(&t1, NULL);
	switch (direction) {
	case IO_RANDOM:
		if (!zeed)	/* srandom seed */
			zeed = time(NULL);
		c = read_random(file->fd, offset, count, &total, zeed, eof);
		break;
	case IO_FORWARD:
		c = read_forward(file->fd, offset, count, &total, vflag, 0, eof);
		if (eof)
			count = total;
		break;
	case IO_BACKWARD:
		c = read_backward(file->fd, &offset, &count, &total, eof);
		break;
	default:
		ASSERT(0);
	}
	if (c < 0)
		return 0;
	if (qflag)
		return 0;
	gettimeofday(&t2, NULL);
	t2 = tsub(t2, t1);

	report_io_times("read", &t2, (long long)offset, count, total, c, Cflag);
	return 0;
}
Beispiel #24
0
int
main(int argc, char **argv)
{
    int			c;
    int			sts;
    int			sep = __pmPathSeparator();
    int			use_localtime = 0;
    int			isdaemon = 0;
    char		*pmnsfile = PM_NS_DEFAULT;
    char		*username;
    char		*logfile = "pmlogger.log";
				    /* default log (not archive) file name */
    char		*endnum;
    int			i;
    task_t		*tp;
    optcost_t		ocp;
    __pmFdSet		readyfds;
    char		*p;
    char		*runtime = NULL;
    int	    		ctx;		/* handle corresponding to ctxp below */
    __pmContext  	*ctxp;		/* pmlogger has just this one context */
    int			niter;
    pid_t               target_pid = 0;

    __pmGetUsername(&username);

    /*
     * Warning:
     *		If any of the pmlogger options change, make sure the
     *		corresponding changes are made to pmnewlog when pmlogger
     *		options are passed through from the control file
     */
    while ((c = pmgetopt_r(argc, argv, &opts)) != EOF) {
	switch (c) {

	case 'c':		/* config file */
	    if (access(opts.optarg, F_OK) == 0)
		configfile = opts.optarg;
	    else {
		/* does not exist as given, try the standard place */
		char *sysconf = pmGetConfig("PCP_VAR_DIR");
		int sz = strlen(sysconf)+strlen("/config/pmlogger/")+strlen(opts.optarg)+1;
		if ((configfile = (char *)malloc(sz)) == NULL)
		    __pmNoMem("config file name", sz, PM_FATAL_ERR);
		snprintf(configfile, sz,
			"%s%c" "config%c" "pmlogger%c" "%s",
			sysconf, sep, sep, sep, opts.optarg);
		if (access(configfile, F_OK) != 0) {
		    /* still no good, error handling happens below */
		    free(configfile);
		    configfile = opts.optarg;
		}
	    }
	    break;

	case 'D':	/* debug flag */
	    sts = __pmParseDebug(opts.optarg);
	    if (sts < 0) {
		pmprintf("%s: unrecognized debug flag specification (%s)\n",
			pmProgname, opts.optarg);
		opts.errors++;
	    }
	    else
		pmDebug |= sts;
	    break;

	case 'h':		/* hostname for PMCD to contact */
	    pmcd_host_conn = opts.optarg;
	    break;

	case 'l':		/* log file name */
	    logfile = opts.optarg;
	    break;

	case 'L':		/* linger if not primary logger */
	    linger = 1;
	    break;

	case 'm':		/* note for port map file */
	    note = opts.optarg;
	    isdaemon = ((strcmp(note, "pmlogger_check") == 0) ||
			(strcmp(note, "pmlogger_daily") == 0));
	    break;

	case 'n':		/* alternative name space file */
	    pmnsfile = opts.optarg;
	    break;

	case 'p':
	    target_pid = (int)strtol(opts.optarg, &endnum, 10);
	    if (*endnum != '\0') {
		pmprintf("%s: invalid process identifier (%s)\n",
			 pmProgname, opts.optarg);
		opts.errors++;
	    } else if (!__pmProcessExists(target_pid)) {
		pmprintf("%s: PID error - no such process (%d)\n",
			 pmProgname, target_pid);
		opts.errors++;
	    }
	    break;

	case 'P':		/* this is the primary pmlogger */
	    primary = 1;
	    isdaemon = 1;
	    break;

	case 'r':		/* report sizes of pmResult records */
	    rflag = 1;
	    break;

	case 's':		/* exit size */
	    sts = ParseSize(opts.optarg, &exit_samples, &exit_bytes, &exit_time);
	    if (sts < 0) {
		pmprintf("%s: illegal size argument '%s' for exit size\n",
			pmProgname, opts.optarg);
		opts.errors++;
	    }
	    else if (exit_time.tv_sec > 0) {
		__pmAFregister(&exit_time, NULL, run_done_callback);
	    }
	    break;

	case 'T':		/* end time */
	    runtime = opts.optarg;
            break;

	case 't':		/* change default logging interval */
	    if (pmParseInterval(opts.optarg, &delta, &p) < 0) {
		pmprintf("%s: illegal -t argument\n%s", pmProgname, p);
		free(p);
		opts.errors++;
	    }
	    break;

	case 'U':		/* run as named user */
	    username = opts.optarg;
	    isdaemon = 1;
	    break;

	case 'u':		/* flush output buffers after each fetch */
	    /*
	     * all archive write I/O is unbuffered now, so maintain -u
	     * for backwards compatibility only
	     */
	    break;

	case 'v':		/* volume switch after given size */
	    sts = ParseSize(opts.optarg, &vol_switch_samples, &vol_switch_bytes,
			    &vol_switch_time);
	    if (sts < 0) {
		pmprintf("%s: illegal size argument '%s' for volume size\n", 
			pmProgname, opts.optarg);
		opts.errors++;
	    }
	    else if (vol_switch_time.tv_sec > 0) {
		vol_switch_afid = __pmAFregister(&vol_switch_time, NULL, 
						 vol_switch_callback);
            }
	    break;

        case 'V': 
	    archive_version = (int)strtol(opts.optarg, &endnum, 10);
	    if (*endnum != '\0' || archive_version != PM_LOG_VERS02) {
		pmprintf("%s: -V requires a version number of %d\n",
			 pmProgname, PM_LOG_VERS02); 
		opts.errors++;
	    }
	    break;

	case 'x':		/* recording session control fd */
	    rsc_fd = (int)strtol(opts.optarg, &endnum, 10);
	    if (*endnum != '\0' || rsc_fd < 0) {
		pmprintf("%s: -x requires a non-negative numeric argument\n", pmProgname);
		opts.errors++;
	    }
	    else {
		time(&rsc_start);
	    }
	    break;

	case 'y':
	    use_localtime = 1;
	    break;

	case '?':
	default:
	    opts.errors++;
	    break;
	}
    }

    if (primary && pmcd_host != NULL) {
	pmprintf(
	    "%s: -P and -h are mutually exclusive; use -P only when running\n"
	    "%s on the same (local) host as the PMCD to which it connects.\n",
		pmProgname, pmProgname);
	opts.errors++;
    }

    if (!opts.errors && opts.optind != argc - 1) {
	pmprintf("%s: insufficient arguments\n", pmProgname);
	opts.errors++;
    }

    if (opts.errors) {
	pmUsageMessage(&opts);
	exit(1);
    }

    if (rsc_fd != -1 && note == NULL) {
	/* add default note to indicate running with -x */
	static char	xnote[10];
	snprintf(xnote, sizeof(xnote), "-x %d", rsc_fd);
	note = xnote;
    }

    /* if we are running as a daemon, change user early */
    if (isdaemon)
	__pmSetProcessIdentity(username);

    __pmOpenLog("pmlogger", logfile, stderr, &sts);
    if (sts != 1) {
	fprintf(stderr, "%s: Warning: log file (%s) creation failed\n", pmProgname, logfile);
	/* continue on ... writing to stderr */
    }

    /* base name for archive is here ... */
    archBase = argv[opts.optind];

    if (pmcd_host_conn == NULL)
	pmcd_host_conn = "local:";

    /* initialise access control */
    if (__pmAccAddOp(PM_OP_LOG_ADV) < 0 ||
	__pmAccAddOp(PM_OP_LOG_MAND) < 0 ||
	__pmAccAddOp(PM_OP_LOG_ENQ) < 0) {
	fprintf(stderr, "%s: access control initialisation failed\n", pmProgname);
	exit(1);
    }

    if (pmnsfile != PM_NS_DEFAULT) {
	if ((sts = pmLoadASCIINameSpace(pmnsfile, 1)) < 0) {
	    fprintf(stderr, "%s: Cannot load namespace from \"%s\": %s\n", pmProgname, pmnsfile, pmErrStr(sts));
	    exit(1);
	}
    }

    if ((ctx = pmNewContext(PM_CONTEXT_HOST, pmcd_host_conn)) < 0) {
	fprintf(stderr, "%s: Cannot connect to PMCD on host \"%s\": %s\n", pmProgname, pmcd_host_conn, pmErrStr(ctx));
	exit(1);
    }
    pmcd_host = (char *)pmGetContextHostName(ctx);
    if (strlen(pmcd_host) == 0) {
	fprintf(stderr, "%s: pmGetContextHostName(%d) failed\n",
	    pmProgname, ctx);
	exit(1);
    }

    if (rsc_fd == -1) {
	/* no -x, so register client id with pmcd */
	__pmSetClientIdArgv(argc, argv);
    }

    /*
     * discover fd for comms channel to PMCD ... 
     */
    if ((ctxp = __pmHandleToPtr(ctx)) == NULL) {
	fprintf(stderr, "%s: botch: __pmHandleToPtr(%d) returns NULL!\n", pmProgname, ctx);
	exit(1);
    }
    pmcdfd = ctxp->c_pmcd->pc_fd;
    PM_UNLOCK(ctxp->c_lock);

    if (configfile != NULL) {
	if ((yyin = fopen(configfile, "r")) == NULL) {
	    fprintf(stderr, "%s: Cannot open config file \"%s\": %s\n",
		pmProgname, configfile, osstrerror());
	    exit(1);
	}
    }
    else {
	/* **ANY** Lex would read from stdin automagically */
	configfile = "<stdin>";
    }

    __pmOptFetchGetParams(&ocp);
    ocp.c_scope = 1;
    __pmOptFetchPutParams(&ocp);

    /* prevent early timer events ... */
    __pmAFblock();

    if (yyparse() != 0)
	exit(1);
    if (configfile != NULL)
	fclose(yyin);
    yyend();

#ifdef PCP_DEBUG
    fprintf(stderr, "Config parsed\n");
#endif

    fprintf(stderr, "Starting %slogger for host \"%s\" via \"%s\"\n",
            primary ? "primary " : "", pmcd_host, pmcd_host_conn);

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_LOG) {
	fprintf(stderr, "optFetch Cost Parameters: pmid=%d indom=%d fetch=%d scope=%d\n",
		ocp.c_pmid, ocp.c_indom, ocp.c_fetch, ocp.c_scope);

	fprintf(stderr, "\nAfter loading config ...\n");
	for (tp = tasklist; tp != NULL; tp = tp->t_next) {
	    if (tp->t_numvalid == 0)
		continue;
	    fprintf(stderr, " state: %sin log, %savail, %s, %s",
		PMLC_GET_INLOG(tp->t_state) ? "" : "not ",
		PMLC_GET_AVAIL(tp->t_state) ? "" : "un",
		PMLC_GET_MAND(tp->t_state) ? "mand" : "adv",
		PMLC_GET_ON(tp->t_state) ? "on" : "off");
	    fprintf(stderr, " delta: %ld usec", 
			(long)1000 * tp->t_delta.tv_sec + tp->t_delta.tv_usec);
	    fprintf(stderr, " numpmid: %d\n", tp->t_numpmid);
	    for (i = 0; i < tp->t_numpmid; i++) {
		fprintf(stderr, "  %s (%s):\n", pmIDStr(tp->t_pmidlist[i]), tp->t_namelist[i]);
	    }
	    __pmOptFetchDump(stderr, tp->t_fetch);
	}
    }
#endif

    if (!primary && tasklist == NULL && !linger) {
	fprintf(stderr, "Nothing to log, and not the primary logger instance ... good-bye\n");
	exit(1);
    }

    if ((sts = __pmLogCreate(pmcd_host, archBase, archive_version, &logctl)) < 0) {
	fprintf(stderr, "__pmLogCreate: %s\n", pmErrStr(sts));
	exit(1);
    }
    else {
	/*
	 * try and establish $TZ from the remote PMCD ...
	 * Note the label record has been set up, but not written yet
	 */
	char		*name = "pmcd.timezone";
	pmID		pmid;
	pmResult	*resp;

	__pmtimevalNow(&epoch);
	sts = pmUseContext(ctx);

	if (sts >= 0)
	    sts = pmLookupName(1, &name, &pmid);
	if (sts >= 0)
	    sts = pmFetch(1, &pmid, &resp);
	if (sts >= 0) {
	    if (resp->vset[0]->numval > 0) { /* pmcd.timezone present */
		strcpy(logctl.l_label.ill_tz, resp->vset[0]->vlist[0].value.pval->vbuf);
		/* prefer to use remote time to avoid clock drift problems */
		epoch = resp->timestamp;		/* struct assignment */
		if (! use_localtime)
		    pmNewZone(logctl.l_label.ill_tz);
	    }
#ifdef PCP_DEBUG
	    else if (pmDebug & DBG_TRACE_LOG) {
		fprintf(stderr,
			"main: Could not get timezone from host %s\n",
			pmcd_host);
	    }
#endif
	    pmFreeResult(resp);
	}
    }

    /* do ParseTimeWindow stuff for -T */
    if (runtime) {
        struct timeval res_end;    /* time window end */
        struct timeval start;
        struct timeval end;
        struct timeval last_delta;
        char *err_msg;             /* parsing error message */
        time_t now;
        struct timeval now_tv;

        time(&now);
        now_tv.tv_sec = now;
        now_tv.tv_usec = 0; 

        start = now_tv;
        end.tv_sec = INT_MAX;
        end.tv_usec = INT_MAX;
        sts = __pmParseTime(runtime, &start, &end, &res_end, &err_msg);
        if (sts < 0) {
	    fprintf(stderr, "%s: illegal -T argument\n%s", pmProgname, err_msg);
            exit(1);
        }

        last_delta = res_end;
        tsub(&last_delta, &now_tv);
	__pmAFregister(&last_delta, NULL, run_done_callback);

        last_stamp = res_end;
    }

    fprintf(stderr, "Archive basename: %s\n", archBase);

#ifndef IS_MINGW
    /* detach yourself from the launching process */
    if (isdaemon)
        setpgid(getpid(), 0);
#endif

    /* set up control port */
    init_ports();
    __pmFD_ZERO(&fds);
    for (i = 0; i < CFD_NUM; ++i) {
	if (ctlfds[i] >= 0)
	    __pmFD_SET(ctlfds[i], &fds);
    }
#ifndef IS_MINGW
    __pmFD_SET(pmcdfd, &fds);
#endif
    if (rsc_fd != -1)
	__pmFD_SET(rsc_fd, &fds);
    numfds = maxfd() + 1;

    if ((sts = do_preamble()) < 0)
	fprintf(stderr, "Warning: problem writing archive preamble: %s\n",
	    pmErrStr(sts));

    sts = 0;		/* default exit status */

    parse_done = 1;	/* enable callback processing */
    __pmAFunblock();

    for ( ; ; ) {
	int		nready;

#ifdef PCP_DEBUG
	if ((pmDebug & DBG_TRACE_APPL2) && (pmDebug & DBG_TRACE_DESPERATE)) {
	    fprintf(stderr, "before __pmSelectRead(%d,...): run_done_alarm=%d vol_switch_alarm=%d log_alarm=%d\n", numfds, run_done_alarm, vol_switch_alarm, log_alarm);
	}
#endif

	niter = 0;
	while (log_alarm && niter++ < 10) {
	    __pmAFblock();
	    log_alarm = 0;
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_APPL2)
		fprintf(stderr, "delayed callback: log_alarm\n");
#endif
	    for (tp = tasklist; tp != NULL; tp = tp->t_next) {
		if (tp->t_alarm) {
		    tp->t_alarm = 0;
		    do_work(tp);
		}
	    }
	    __pmAFunblock();
	}

	if (vol_switch_alarm) {
	    __pmAFblock();
	    vol_switch_alarm = 0;
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_APPL2)
		fprintf(stderr, "delayed callback: vol_switch_alarm\n");
#endif
	    newvolume(VOL_SW_TIME);
	    __pmAFunblock();
	}

	if (run_done_alarm) {
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_APPL2)
		fprintf(stderr, "delayed callback: run_done_alarm\n");
#endif
	    run_done(0, NULL);
	    /*NOTREACHED*/
	}

	__pmFD_COPY(&readyfds, &fds);
	nready = __pmSelectRead(numfds, &readyfds, NULL);

#ifdef PCP_DEBUG
	if ((pmDebug & DBG_TRACE_APPL2) && (pmDebug & DBG_TRACE_DESPERATE)) {
	    fprintf(stderr, "__pmSelectRead(%d,...) done: nready=%d run_done_alarm=%d vol_switch_alarm=%d log_alarm=%d\n", numfds, nready, run_done_alarm, vol_switch_alarm, log_alarm);
	}
#endif

	__pmAFblock();
	if (nready > 0) {

	    /* handle request on control port */
	    for (i = 0; i < CFD_NUM; ++i) {
		if (ctlfds[i] >= 0 && __pmFD_ISSET(ctlfds[i], &readyfds)) {
		    if (control_req(ctlfds[i])) {
			/* new client has connected */
			__pmFD_SET(clientfd, &fds);
			if (clientfd >= numfds)
			    numfds = clientfd + 1;
		    }
		}
	    }
	    if (clientfd >= 0 && __pmFD_ISSET(clientfd, &readyfds)) {
		/* process request from client, save clientfd in case client
		 * closes connection, resetting clientfd to -1
		 */
		int	fd = clientfd;

		if (client_req()) {
		    /* client closed connection */
		    __pmFD_CLR(fd, &fds);
		    __pmCloseSocket(clientfd);
		    clientfd = -1;
		    numfds = maxfd() + 1;
		    qa_case = 0;
		}
	    }
#ifndef IS_MINGW
	    if (pmcdfd >= 0 && __pmFD_ISSET(pmcdfd, &readyfds)) {
		/*
		 * do not expect this, given synchronous commumication with the
		 * pmcd ... either pmcd has terminated, or bogus PDU ... or its
		 * Win32 and we are operating under the different conditions of
		 * our AF.c implementation there, which has to deal with a lack
		 * of signal support on Windows - race condition exists between
		 * this check and the async event timer callback.
		 */
		__pmPDU		*pb;
		__pmPDUHdr	*php;
		sts = __pmGetPDU(pmcdfd, ANY_SIZE, TIMEOUT_NEVER, &pb);
		if (sts <= 0) {
		    if (sts < 0)
			fprintf(stderr, "Error: __pmGetPDU: %s\n", pmErrStr(sts));
		    disconnect(sts);
		}
		else {
		    php = (__pmPDUHdr *)pb;
		    fprintf(stderr, "Error: Unsolicited %s PDU from PMCD\n",
			__pmPDUTypeStr(php->type));
		    disconnect(PM_ERR_IPC);
		}
		if (sts > 0)
		    __pmUnpinPDUBuf(pb);
	    }
#endif
	    if (rsc_fd >= 0 && __pmFD_ISSET(rsc_fd, &readyfds)) {
		/*
		 * some action on the recording session control fd
		 * end-of-file means launcher has quit, otherwise we
		 * expect one of these commands
		 *	V<number>\n	- version
		 *	F<folio>\n	- folio name
		 *	P<name>\n	- launcher's name
		 *	R\n		- launcher can replay
		 *	D\n		- detach from launcher
		 *	Q\n		- quit pmlogger
		 */
		char	rsc_buf[MAXPATHLEN];
		char	*rp = rsc_buf;
		char	myc;
		int	fake_x = 0;

		for (rp = rsc_buf; ; rp++) {
		    if (read(rsc_fd, &myc, 1) <= 0) {
#ifdef PCP_DEBUG
			if (pmDebug & DBG_TRACE_APPL2)
			    fprintf(stderr, "recording session control: eof\n");
#endif
			if (rp != rsc_buf) {
			    *rp = '\0';
			    fprintf(stderr, "Error: incomplete recording session control message: \"%s\"\n", rsc_buf);
			}
			fake_x = 1;
			break;
		    }
		    if (rp >= &rsc_buf[MAXPATHLEN]) {
			fprintf(stderr, "Error: absurd recording session control message: \"%100.100s ...\"\n", rsc_buf);
			fake_x = 1;
			break;
		    }
		    if (myc == '\n') {
			*rp = '\0';
			break;
		    }
		    *rp = myc;
		}

#ifdef PCP_DEBUG
		if (pmDebug & DBG_TRACE_APPL2) {
		    if (fake_x == 0)
			fprintf(stderr, "recording session control: \"%s\"\n", rsc_buf);
		}
#endif

		if (fake_x)
		    do_dialog('X');
		else if (strcmp(rsc_buf, "Q") == 0 ||
		         strcmp(rsc_buf, "D") == 0 ||
			 strcmp(rsc_buf, "?") == 0)
		    do_dialog(rsc_buf[0]);
		else if (rsc_buf[0] == 'F')
		    folio_name = strdup(&rsc_buf[1]);
		else if (rsc_buf[0] == 'P')
		    rsc_prog = strdup(&rsc_buf[1]);
		else if (strcmp(rsc_buf, "R") == 0)
		    rsc_replay = 1;
		else if (rsc_buf[0] == 'V' && rsc_buf[1] == '0') {
		    /*
		     * version 0 of the recording session control ...
		     * this is all we grok at the moment
		     */
		    ;
		}
		else {
		    fprintf(stderr, "Error: illegal recording session control message: \"%s\"\n", rsc_buf);
		    do_dialog('X');
		}
	    }
	}
	else if (vol_switch_flag) {
	    newvolume(VOL_SW_SIGHUP);
	    vol_switch_flag = 0;
	}
	else if (nready < 0 && neterror() != EINTR)
	    fprintf(stderr, "Error: select: %s\n", netstrerror());

	__pmAFunblock();

	if (target_pid && !__pmProcessExists(target_pid))
	    exit(EXIT_SUCCESS);

	if (exit_code)
	    break;
    }
    exit(exit_code);
}
Beispiel #25
0
static int writev_f(int argc, char **argv)
{
    struct timeval t1, t2;
    int Cflag = 0, qflag = 0;
    int c, cnt;
    char *buf;
    int64_t offset;
    /* Some compilers get confused and warn if this is not initialized.  */
    int total = 0;
    int nr_iov;
    int pattern = 0xcd;
    QEMUIOVector qiov;

    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
        switch (c) {
        case 'C':
            Cflag = 1;
            break;
        case 'q':
            qflag = 1;
            break;
        case 'P':
            pattern = parse_pattern(optarg);
            if (pattern < 0) {
                return 0;
            }
            break;
        default:
            return command_usage(&writev_cmd);
        }
    }

    if (optind > argc - 2) {
        return command_usage(&writev_cmd);
    }

    offset = cvtnum(argv[optind]);
    if (offset < 0) {
        printf("non-numeric length argument -- %s\n", argv[optind]);
        return 0;
    }
    optind++;

    if (offset & 0x1ff) {
        printf("offset %" PRId64 " is not sector aligned\n",
               offset);
        return 0;
    }

    nr_iov = argc - optind;
    buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
    if (buf == NULL) {
        return 0;
    }

    gettimeofday(&t1, NULL);
    cnt = do_aio_writev(&qiov, offset, &total);
    gettimeofday(&t2, NULL);

    if (cnt < 0) {
        printf("writev failed: %s\n", strerror(-cnt));
        goto out;
    }

    if (qflag) {
        goto out;
    }

    /* Finally, report back -- -C gives a parsable format */
    t2 = tsub(t2, t1);
    print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
out:
    qemu_iovec_destroy(&qiov);
    qemu_io_free(buf);
    return 0;
}
Beispiel #26
0
static int readv_f(int argc, char **argv)
{
    struct timeval t1, t2;
    int Cflag = 0, qflag = 0, vflag = 0;
    int c, cnt;
    char *buf;
    int64_t offset;
    /* Some compilers get confused and warn if this is not initialized.  */
    int total = 0;
    int nr_iov;
    QEMUIOVector qiov;
    int pattern = 0;
    int Pflag = 0;

    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
        switch (c) {
        case 'C':
            Cflag = 1;
            break;
        case 'P':
            Pflag = 1;
            pattern = parse_pattern(optarg);
            if (pattern < 0) {
                return 0;
            }
            break;
        case 'q':
            qflag = 1;
            break;
        case 'v':
            vflag = 1;
            break;
        default:
            return command_usage(&readv_cmd);
        }
    }

    if (optind > argc - 2) {
        return command_usage(&readv_cmd);
    }


    offset = cvtnum(argv[optind]);
    if (offset < 0) {
        printf("non-numeric length argument -- %s\n", argv[optind]);
        return 0;
    }
    optind++;

    if (offset & 0x1ff) {
        printf("offset %" PRId64 " is not sector aligned\n",
               offset);
        return 0;
    }

    nr_iov = argc - optind;
    buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
    if (buf == NULL) {
        return 0;
    }

    gettimeofday(&t1, NULL);
    cnt = do_aio_readv(&qiov, offset, &total);
    gettimeofday(&t2, NULL);

    if (cnt < 0) {
        printf("readv failed: %s\n", strerror(-cnt));
        goto out;
    }

    if (Pflag) {
        void *cmp_buf = g_malloc(qiov.size);
        memset(cmp_buf, pattern, qiov.size);
        if (memcmp(buf, cmp_buf, qiov.size)) {
            printf("Pattern verification failed at offset %"
                   PRId64 ", %zd bytes\n", offset, qiov.size);
        }
        g_free(cmp_buf);
    }

    if (qflag) {
        goto out;
    }

    if (vflag) {
        dump_buffer(buf, offset, qiov.size);
    }

    /* Finally, report back -- -C gives a parsable format */
    t2 = tsub(t2, t1);
    print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);

out:
    qemu_iovec_destroy(&qiov);
    qemu_io_free(buf);
    return 0;
}
Beispiel #27
0
static int write_f(int argc, char **argv)
{
    struct timeval t1, t2;
    int Cflag = 0, pflag = 0, qflag = 0, bflag = 0, Pflag = 0, zflag = 0;
    int cflag = 0;
    int c, cnt;
    char *buf = NULL;
    int64_t offset;
    int count;
    /* Some compilers get confused and warn if this is not initialized.  */
    int total = 0;
    int pattern = 0xcd;

    while ((c = getopt(argc, argv, "bcCpP:qz")) != EOF) {
        switch (c) {
        case 'b':
            bflag = 1;
            break;
        case 'c':
            cflag = 1;
            break;
        case 'C':
            Cflag = 1;
            break;
        case 'p':
            pflag = 1;
            break;
        case 'P':
            Pflag = 1;
            pattern = parse_pattern(optarg);
            if (pattern < 0) {
                return 0;
            }
            break;
        case 'q':
            qflag = 1;
            break;
        case 'z':
            zflag = 1;
            break;
        default:
            return command_usage(&write_cmd);
        }
    }

    if (optind != argc - 2) {
        return command_usage(&write_cmd);
    }

    if (bflag + pflag + zflag > 1) {
        printf("-b, -p, or -z cannot be specified at the same time\n");
        return 0;
    }

    if (zflag && Pflag) {
        printf("-z and -P cannot be specified at the same time\n");
        return 0;
    }

    offset = cvtnum(argv[optind]);
    if (offset < 0) {
        printf("non-numeric length argument -- %s\n", argv[optind]);
        return 0;
    }

    optind++;
    count = cvtnum(argv[optind]);
    if (count < 0) {
        printf("non-numeric length argument -- %s\n", argv[optind]);
        return 0;
    }

    if (!pflag) {
        if (offset & 0x1ff) {
            printf("offset %" PRId64 " is not sector aligned\n",
                   offset);
            return 0;
        }

        if (count & 0x1ff) {
            printf("count %d is not sector aligned\n",
                   count);
            return 0;
        }
    }

    if (!zflag) {
        buf = qemu_io_alloc(count, pattern);
    }

    gettimeofday(&t1, NULL);
    if (pflag) {
        cnt = do_pwrite(buf, offset, count, &total);
    } else if (bflag) {
        cnt = do_save_vmstate(buf, offset, count, &total);
    } else if (zflag) {
        cnt = do_co_write_zeroes(offset, count, &total);
    } else if (cflag) {
        cnt = do_write_compressed(buf, offset, count, &total);
    } else {
        cnt = do_write(buf, offset, count, &total);
    }
    gettimeofday(&t2, NULL);

    if (cnt < 0) {
        printf("write failed: %s\n", strerror(-cnt));
        goto out;
    }

    if (qflag) {
        goto out;
    }

    /* Finally, report back -- -C gives a parsable format */
    t2 = tsub(t2, t1);
    print_report("wrote", &t2, offset, count, total, cnt, Cflag);

out:
    if (!zflag) {
        qemu_io_free(buf);
    }

    return 0;
}
Beispiel #28
0
static int
write_f(int argc, char **argv)
{
	struct timeval t1, t2;
	int Cflag = 0, pflag = 0, qflag = 0, bflag = 0;
	int c, cnt;
	char *buf;
	int64_t offset;
	int count;
        
        int total = 0;
	int pattern = 0xcd;

	while ((c = getopt(argc, argv, "bCpP:q")) != EOF) {
		switch (c) {
		case 'b':
			bflag = 1;
			break;
		case 'C':
			Cflag = 1;
			break;
		case 'p':
			pflag = 1;
			break;
		case 'P':
			pattern = parse_pattern(optarg);
			if (pattern < 0)
				return 0;
			break;
		case 'q':
			qflag = 1;
			break;
		default:
			return command_usage(&write_cmd);
		}
	}

	if (optind != argc - 2)
		return command_usage(&write_cmd);

	if (bflag && pflag) {
		printf("-b and -p cannot be specified at the same time\n");
		return 0;
	}

	offset = cvtnum(argv[optind]);
	if (offset < 0) {
		printf("non-numeric length argument -- %s\n", argv[optind]);
		return 0;
	}

	optind++;
	count = cvtnum(argv[optind]);
	if (count < 0) {
		printf("non-numeric length argument -- %s\n", argv[optind]);
		return 0;
	}

	if (!pflag) {
		if (offset & 0x1ff) {
                        printf("offset %" PRId64 " is not sector aligned\n",
                               offset);
			return 0;
		}

		if (count & 0x1ff) {
			printf("count %d is not sector aligned\n",
				count);
			return 0;
		}
	}

	buf = qemu_io_alloc(count, pattern);

	gettimeofday(&t1, NULL);
	if (pflag)
		cnt = do_pwrite(buf, offset, count, &total);
	else if (bflag)
		cnt = do_save_vmstate(buf, offset, count, &total);
	else
		cnt = do_write(buf, offset, count, &total);
	gettimeofday(&t2, NULL);

	if (cnt < 0) {
		printf("write failed: %s\n", strerror(-cnt));
		goto out;
	}

	if (qflag)
		goto out;

	
	t2 = tsub(t2, t1);
	print_report("wrote", &t2, offset, count, total, cnt, Cflag);

out:
	qemu_io_free(buf);

	return 0;
}
Beispiel #29
0
static int multiwrite_f(int argc, char **argv)
{
    struct timeval t1, t2;
    int Cflag = 0, qflag = 0;
    int c, cnt;
    char **buf;
    int64_t offset, first_offset = 0;
    /* Some compilers get confused and warn if this is not initialized.  */
    int total = 0;
    int nr_iov;
    int nr_reqs;
    int pattern = 0xcd;
    QEMUIOVector *qiovs;
    int i;
    BlockRequest *reqs;

    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
        switch (c) {
        case 'C':
            Cflag = 1;
            break;
        case 'q':
            qflag = 1;
            break;
        case 'P':
            pattern = parse_pattern(optarg);
            if (pattern < 0) {
                return 0;
            }
            break;
        default:
            return command_usage(&writev_cmd);
        }
    }

    if (optind > argc - 2) {
        return command_usage(&writev_cmd);
    }

    nr_reqs = 1;
    for (i = optind; i < argc; i++) {
        if (!strcmp(argv[i], ";")) {
            nr_reqs++;
        }
    }

    reqs = g_malloc0(nr_reqs * sizeof(*reqs));
    buf = g_malloc0(nr_reqs * sizeof(*buf));
    qiovs = g_malloc(nr_reqs * sizeof(*qiovs));

    for (i = 0; i < nr_reqs && optind < argc; i++) {
        int j;

        /* Read the offset of the request */
        offset = cvtnum(argv[optind]);
        if (offset < 0) {
            printf("non-numeric offset argument -- %s\n", argv[optind]);
            goto out;
        }
        optind++;

        if (offset & 0x1ff) {
            printf("offset %lld is not sector aligned\n",
                   (long long)offset);
            goto out;
        }

        if (i == 0) {
            first_offset = offset;
        }

        /* Read lengths for qiov entries */
        for (j = optind; j < argc; j++) {
            if (!strcmp(argv[j], ";")) {
                break;
            }
        }

        nr_iov = j - optind;

        /* Build request */
        buf[i] = create_iovec(&qiovs[i], &argv[optind], nr_iov, pattern);
        if (buf[i] == NULL) {
            goto out;
        }

        reqs[i].qiov = &qiovs[i];
        reqs[i].sector = offset >> 9;
        reqs[i].nb_sectors = reqs[i].qiov->size >> 9;

        optind = j + 1;

        pattern++;
    }

    /* If there were empty requests at the end, ignore them */
    nr_reqs = i;

    gettimeofday(&t1, NULL);
    cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
    gettimeofday(&t2, NULL);

    if (cnt < 0) {
        printf("aio_multiwrite failed: %s\n", strerror(-cnt));
        goto out;
    }

    if (qflag) {
        goto out;
    }

    /* Finally, report back -- -C gives a parsable format */
    t2 = tsub(t2, t1);
    print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
out:
    for (i = 0; i < nr_reqs; i++) {
        qemu_io_free(buf[i]);
        if (reqs[i].qiov != NULL) {
            qemu_iovec_destroy(&qiovs[i]);
        }
    }
    g_free(buf);
    g_free(reqs);
    g_free(qiovs);
    return 0;
}
Beispiel #30
0
static int
multiwrite_f(int argc, char **argv)
{
	struct timeval t1, t2;
	int Cflag = 0, qflag = 0;
	int c, cnt;
	char **buf;
	int64_t offset, first_offset = 0;
	
	int total = 0;
	int nr_iov;
	int nr_reqs;
	int pattern = 0xcd;
	QEMUIOVector *qiovs;
	int i;
	BlockRequest *reqs;

	while ((c = getopt(argc, argv, "CqP:")) != EOF) {
		switch (c) {
		case 'C':
			Cflag = 1;
			break;
		case 'q':
			qflag = 1;
			break;
		case 'P':
			pattern = parse_pattern(optarg);
			if (pattern < 0)
				return 0;
			break;
		default:
			return command_usage(&writev_cmd);
		}
	}

	if (optind > argc - 2)
		return command_usage(&writev_cmd);

	nr_reqs = 1;
	for (i = optind; i < argc; i++) {
		if (!strcmp(argv[i], ";")) {
			nr_reqs++;
		}
	}

	reqs = qemu_malloc(nr_reqs * sizeof(*reqs));
	buf = qemu_malloc(nr_reqs * sizeof(*buf));
	qiovs = qemu_malloc(nr_reqs * sizeof(*qiovs));

	for (i = 0; i < nr_reqs; i++) {
		int j;

		
		offset = cvtnum(argv[optind]);
		if (offset < 0) {
			printf("non-numeric offset argument -- %s\n", argv[optind]);
			return 0;
		}
		optind++;

		if (offset & 0x1ff) {
			printf("offset %lld is not sector aligned\n",
				(long long)offset);
			return 0;
		}

        if (i == 0) {
            first_offset = offset;
        }

		
		for (j = optind; j < argc; j++) {
			if (!strcmp(argv[j], ";")) {
				break;
			}
		}

		nr_iov = j - optind;

		
		reqs[i].qiov = &qiovs[i];
		buf[i] = create_iovec(reqs[i].qiov, &argv[optind], nr_iov, pattern);
		reqs[i].sector = offset >> 9;
		reqs[i].nb_sectors = reqs[i].qiov->size >> 9;

		optind = j + 1;

		offset += reqs[i].qiov->size;
		pattern++;
	}

	gettimeofday(&t1, NULL);
	cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
	gettimeofday(&t2, NULL);

	if (cnt < 0) {
		printf("aio_multiwrite failed: %s\n", strerror(-cnt));
		goto out;
	}

	if (qflag)
		goto out;

	
	t2 = tsub(t2, t1);
	print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
out:
	for (i = 0; i < nr_reqs; i++) {
		qemu_io_free(buf[i]);
		qemu_iovec_destroy(&qiovs[i]);
	}
	qemu_free(buf);
	qemu_free(reqs);
	qemu_free(qiovs);
	return 0;
}