Revision 43642b38

b/qemu-io.c
20 20

  
21 21
#define VERSION	"0.0.1"
22 22

  
23
#define CMD_NOFILE_OK	0x01
23
#define CMD_NOFILE_OK   0x01
24 24

  
25 25
char *progname;
26 26
static BlockDriverState *bs;
......
35 35
 */
36 36
static int parse_pattern(const char *arg)
37 37
{
38
	char *endptr = NULL;
39
	long pattern;
38
    char *endptr = NULL;
39
    long pattern;
40 40

  
41
	pattern = strtol(arg, &endptr, 0);
42
	if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
43
		printf("%s is not a valid pattern byte\n", arg);
44
		return -1;
45
	}
41
    pattern = strtol(arg, &endptr, 0);
42
    if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
43
        printf("%s is not a valid pattern byte\n", arg);
44
        return -1;
45
    }
46 46

  
47
	return pattern;
47
    return pattern;
48 48
}
49 49

  
50 50
/*
......
54 54
 * that is specified on the command line.
55 55
 */
56 56

  
57
#define MISALIGN_OFFSET		16
57
#define MISALIGN_OFFSET     16
58 58
static void *qemu_io_alloc(size_t len, int pattern)
59 59
{
60
	void *buf;
61

  
62
	if (misalign)
63
		len += MISALIGN_OFFSET;
64
	buf = qemu_blockalign(bs, len);
65
	memset(buf, pattern, len);
66
	if (misalign)
67
		buf += MISALIGN_OFFSET;
68
	return buf;
60
    void *buf;
61

  
62
    if (misalign) {
63
        len += MISALIGN_OFFSET;
64
    }
65
    buf = qemu_blockalign(bs, len);
66
    memset(buf, pattern, len);
67
    if (misalign) {
68
        buf += MISALIGN_OFFSET;
69
    }
70
    return buf;
69 71
}
70 72

  
71 73
static void qemu_io_free(void *p)
72 74
{
73
	if (misalign)
74
		p -= MISALIGN_OFFSET;
75
	qemu_vfree(p);
75
    if (misalign) {
76
        p -= MISALIGN_OFFSET;
77
    }
78
    qemu_vfree(p);
76 79
}
77 80

  
78
static void
79
dump_buffer(const void *buffer, int64_t offset, int len)
81
static void dump_buffer(const void *buffer, int64_t offset, int len)
80 82
{
81
	int i, j;
82
	const uint8_t *p;
83

  
84
	for (i = 0, p = buffer; i < len; i += 16) {
85
		const uint8_t *s = p;
86

  
87
                printf("%08" PRIx64 ":  ", offset + i);
88
		for (j = 0; j < 16 && i + j < len; j++, p++)
89
			printf("%02x ", *p);
90
		printf(" ");
91
		for (j = 0; j < 16 && i + j < len; j++, s++) {
92
			if (isalnum(*s))
93
				printf("%c", *s);
94
			else
95
				printf(".");
96
		}
97
		printf("\n");
98
	}
83
    int i, j;
84
    const uint8_t *p;
85

  
86
    for (i = 0, p = buffer; i < len; i += 16) {
87
        const uint8_t *s = p;
88

  
89
        printf("%08" PRIx64 ":  ", offset + i);
90
        for (j = 0; j < 16 && i + j < len; j++, p++) {
91
            printf("%02x ", *p);
92
        }
93
        printf(" ");
94
        for (j = 0; j < 16 && i + j < len; j++, s++) {
95
            if (isalnum(*s)) {
96
                printf("%c", *s);
97
            } else {
98
                printf(".");
99
            }
100
        }
101
        printf("\n");
102
    }
99 103
}
100 104

  
101
static void
102
print_report(const char *op, struct timeval *t, int64_t offset,
103
		int count, int total, int cnt, int Cflag)
105
static void print_report(const char *op, struct timeval *t, int64_t offset,
106
                         int count, int total, int cnt, int Cflag)
104 107
{
105
	char s1[64], s2[64], ts[64];
106

  
107
	timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
108
	if (!Cflag) {
109
		cvtstr((double)total, s1, sizeof(s1));
110
		cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
111
                printf("%s %d/%d bytes at offset %" PRId64 "\n",
112
                       op, total, count, offset);
113
		printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
114
			s1, cnt, ts, s2, tdiv((double)cnt, *t));
115
	} else {/* bytes,ops,time,bytes/sec,ops/sec */
116
		printf("%d,%d,%s,%.3f,%.3f\n",
117
			total, cnt, ts,
118
			tdiv((double)total, *t),
119
			tdiv((double)cnt, *t));
120
	}
108
    char s1[64], s2[64], ts[64];
109

  
110
    timestr(t, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
111
    if (!Cflag) {
112
        cvtstr((double)total, s1, sizeof(s1));
113
        cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
114
        printf("%s %d/%d bytes at offset %" PRId64 "\n",
115
               op, total, count, offset);
116
        printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
117
               s1, cnt, ts, s2, tdiv((double)cnt, *t));
118
    } else {/* bytes,ops,time,bytes/sec,ops/sec */
119
        printf("%d,%d,%s,%.3f,%.3f\n",
120
            total, cnt, ts,
121
            tdiv((double)total, *t),
122
            tdiv((double)cnt, *t));
123
    }
121 124
}
122 125

  
123 126
/*
......
127 130
static void *
128 131
create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern)
129 132
{
130
	size_t *sizes = calloc(nr_iov, sizeof(size_t));
131
	size_t count = 0;
132
	void *buf = NULL;
133
	void *p;
134
	int i;
135

  
136
	for (i = 0; i < nr_iov; i++) {
137
		char *arg = argv[i];
138
                int64_t len;
139

  
140
		len = cvtnum(arg);
141
		if (len < 0) {
142
			printf("non-numeric length argument -- %s\n", arg);
143
			goto fail;
144
		}
145

  
146
		/* should be SIZE_T_MAX, but that doesn't exist */
147
		if (len > INT_MAX) {
148
			printf("too large length argument -- %s\n", arg);
149
			goto fail;
150
		}
151

  
152
		if (len & 0x1ff) {
153
                        printf("length argument %" PRId64
154
                               " is not sector aligned\n", len);
155
			goto fail;
156
		}
157

  
158
		sizes[i] = len;
159
		count += len;
160
	}
161

  
162
	qemu_iovec_init(qiov, nr_iov);
163

  
164
	buf = p = qemu_io_alloc(count, pattern);
165

  
166
	for (i = 0; i < nr_iov; i++) {
167
		qemu_iovec_add(qiov, p, sizes[i]);
168
		p += sizes[i];
169
	}
133
    size_t *sizes = calloc(nr_iov, sizeof(size_t));
134
    size_t count = 0;
135
    void *buf = NULL;
136
    void *p;
137
    int i;
138

  
139
    for (i = 0; i < nr_iov; i++) {
140
        char *arg = argv[i];
141
        int64_t len;
142

  
143
        len = cvtnum(arg);
144
        if (len < 0) {
145
            printf("non-numeric length argument -- %s\n", arg);
146
            goto fail;
147
        }
148

  
149
        /* should be SIZE_T_MAX, but that doesn't exist */
150
        if (len > INT_MAX) {
151
            printf("too large length argument -- %s\n", arg);
152
            goto fail;
153
        }
154

  
155
        if (len & 0x1ff) {
156
            printf("length argument %" PRId64
157
                   " is not sector aligned\n", len);
158
            goto fail;
159
        }
160

  
161
        sizes[i] = len;
162
        count += len;
163
    }
164

  
165
    qemu_iovec_init(qiov, nr_iov);
166

  
167
    buf = p = qemu_io_alloc(count, pattern);
168

  
169
    for (i = 0; i < nr_iov; i++) {
170
        qemu_iovec_add(qiov, p, sizes[i]);
171
        p += sizes[i];
172
    }
170 173

  
171 174
fail:
172
	free(sizes);
173
	return buf;
175
    free(sizes);
176
    return buf;
174 177
}
175 178

  
176 179
static int do_read(char *buf, int64_t offset, int count, int *total)
177 180
{
178
	int ret;
181
    int ret;
179 182

  
180
	ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
181
	if (ret < 0)
182
		return ret;
183
	*total = count;
184
	return 1;
183
    ret = bdrv_read(bs, offset >> 9, (uint8_t *)buf, count >> 9);
184
    if (ret < 0) {
185
        return ret;
186
    }
187
    *total = count;
188
    return 1;
185 189
}
186 190

  
187 191
static int do_write(char *buf, int64_t offset, int count, int *total)
188 192
{
189
	int ret;
193
    int ret;
190 194

  
191
	ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
192
	if (ret < 0)
193
		return ret;
194
	*total = count;
195
	return 1;
195
    ret = bdrv_write(bs, offset >> 9, (uint8_t *)buf, count >> 9);
196
    if (ret < 0) {
197
        return ret;
198
    }
199
    *total = count;
200
    return 1;
196 201
}
197 202

  
198 203
static int do_pread(char *buf, int64_t offset, int count, int *total)
199 204
{
200
	*total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
201
	if (*total < 0)
202
		return *total;
203
	return 1;
205
    *total = bdrv_pread(bs, offset, (uint8_t *)buf, count);
206
    if (*total < 0) {
207
        return *total;
208
    }
209
    return 1;
204 210
}
205 211

  
206 212
static int do_pwrite(char *buf, int64_t offset, int count, int *total)
207 213
{
208
	*total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
209
	if (*total < 0)
210
		return *total;
211
	return 1;
214
    *total = bdrv_pwrite(bs, offset, (uint8_t *)buf, count);
215
    if (*total < 0) {
216
        return *total;
217
    }
218
    return 1;
212 219
}
213 220

  
214 221
static int do_load_vmstate(char *buf, int64_t offset, int count, int *total)
215 222
{
216
	*total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
217
	if (*total < 0)
218
		return *total;
219
	return 1;
223
    *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count);
224
    if (*total < 0) {
225
        return *total;
226
    }
227
    return 1;
220 228
}
221 229

  
222 230
static int do_save_vmstate(char *buf, int64_t offset, int count, int *total)
223 231
{
224
	*total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
225
	if (*total < 0)
226
		return *total;
227
	return 1;
232
    *total = bdrv_save_vmstate(bs, (uint8_t *)buf, offset, count);
233
    if (*total < 0) {
234
        return *total;
235
    }
236
    return 1;
228 237
}
229 238

  
230 239
#define NOT_DONE 0x7fffffff
231 240
static void aio_rw_done(void *opaque, int ret)
232 241
{
233
	*(int *)opaque = ret;
242
    *(int *)opaque = ret;
234 243
}
235 244

  
236 245
static int do_aio_readv(QEMUIOVector *qiov, int64_t offset, int *total)
237 246
{
238
	BlockDriverAIOCB *acb;
239
	int async_ret = NOT_DONE;
247
    BlockDriverAIOCB *acb;
248
    int async_ret = NOT_DONE;
240 249

  
241
	acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
242
			     aio_rw_done, &async_ret);
243
	if (!acb)
244
		return -EIO;
245

  
246
	while (async_ret == NOT_DONE)
247
		qemu_aio_wait();
250
    acb = bdrv_aio_readv(bs, offset >> 9, qiov, qiov->size >> 9,
251
                         aio_rw_done, &async_ret);
252
    if (!acb) {
253
        return -EIO;
254
    }
255
    while (async_ret == NOT_DONE) {
256
        qemu_aio_wait();
257
    }
248 258

  
249
	*total = qiov->size;
250
	return async_ret < 0 ? async_ret : 1;
259
    *total = qiov->size;
260
    return async_ret < 0 ? async_ret : 1;
251 261
}
252 262

  
253 263
static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
254 264
{
255
	BlockDriverAIOCB *acb;
256
	int async_ret = NOT_DONE;
265
    BlockDriverAIOCB *acb;
266
    int async_ret = NOT_DONE;
257 267

  
258
	acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
259
			      aio_rw_done, &async_ret);
260
	if (!acb)
261
		return -EIO;
268
    acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9,
269
                          aio_rw_done, &async_ret);
270
    if (!acb) {
271
        return -EIO;
272
    }
262 273

  
263
	while (async_ret == NOT_DONE)
264
		qemu_aio_wait();
274
    while (async_ret == NOT_DONE) {
275
        qemu_aio_wait();
276
    }
265 277

  
266
	*total = qiov->size;
267
	return async_ret < 0 ? async_ret : 1;
278
    *total = qiov->size;
279
    return async_ret < 0 ? async_ret : 1;
268 280
}
269 281

  
270 282
struct multiwrite_async_ret {
271
	int num_done;
272
	int error;
283
    int num_done;
284
    int error;
273 285
};
274 286

  
275 287
static void multiwrite_cb(void *opaque, int ret)
276 288
{
277
	struct multiwrite_async_ret *async_ret = opaque;
289
    struct multiwrite_async_ret *async_ret = opaque;
278 290

  
279
	async_ret->num_done++;
280
	if (ret < 0) {
281
		async_ret->error = ret;
282
	}
291
    async_ret->num_done++;
292
    if (ret < 0) {
293
        async_ret->error = ret;
294
    }
283 295
}
284 296

  
285 297
static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total)
286 298
{
287
	int i, ret;
288
	struct multiwrite_async_ret async_ret = {
289
		.num_done = 0,
290
		.error = 0,
291
	};
292

  
293
	*total = 0;
294
	for (i = 0; i < num_reqs; i++) {
295
		reqs[i].cb = multiwrite_cb;
296
		reqs[i].opaque = &async_ret;
297
		*total += reqs[i].qiov->size;
298
	}
299

  
300
	ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
301
	if (ret < 0) {
302
		return ret;
303
	}
304

  
305
	while (async_ret.num_done < num_reqs) {
306
		qemu_aio_wait();
307
	}
308

  
309
	return async_ret.error < 0 ? async_ret.error : 1;
299
    int i, ret;
300
    struct multiwrite_async_ret async_ret = {
301
        .num_done = 0,
302
        .error = 0,
303
    };
304

  
305
    *total = 0;
306
    for (i = 0; i < num_reqs; i++) {
307
        reqs[i].cb = multiwrite_cb;
308
        reqs[i].opaque = &async_ret;
309
        *total += reqs[i].qiov->size;
310
    }
311

  
312
    ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
313
    if (ret < 0) {
314
        return ret;
315
    }
316

  
317
    while (async_ret.num_done < num_reqs) {
318
        qemu_aio_wait();
319
    }
320

  
321
    return async_ret.error < 0 ? async_ret.error : 1;
310 322
}
311 323

  
312
static void
313
read_help(void)
324
static void read_help(void)
314 325
{
315
	printf(
326
    printf(
316 327
"\n"
317 328
" reads a range of bytes from the given offset\n"
318 329
"\n"
......
335 346
static int read_f(int argc, char **argv);
336 347

  
337 348
static const cmdinfo_t read_cmd = {
338
	.name		= "read",
339
	.altname	= "r",
340
	.cfunc		= read_f,
341
	.argmin		= 2,
342
	.argmax		= -1,
343
	.args		= "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
344
	.oneline	= "reads a number of bytes at a specified offset",
345
	.help		= read_help,
349
    .name       = "read",
350
    .altname    = "r",
351
    .cfunc      = read_f,
352
    .argmin     = 2,
353
    .argmax     = -1,
354
    .args       = "[-abCpqv] [-P pattern [-s off] [-l len]] off len",
355
    .oneline    = "reads a number of bytes at a specified offset",
356
    .help       = read_help,
346 357
};
347 358

  
348
static int
349
read_f(int argc, char **argv)
359
static int read_f(int argc, char **argv)
350 360
{
351
	struct timeval t1, t2;
352
	int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
353
	int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
354
	int c, cnt;
355
	char *buf;
356
	int64_t offset;
357
	int count;
358
        /* Some compilers get confused and warn if this is not initialized.  */
359
        int total = 0;
360
	int pattern = 0, pattern_offset = 0, pattern_count = 0;
361

  
362
	while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
363
		switch (c) {
364
		case 'b':
365
			bflag = 1;
366
			break;
367
		case 'C':
368
			Cflag = 1;
369
			break;
370
		case 'l':
371
			lflag = 1;
372
			pattern_count = cvtnum(optarg);
373
			if (pattern_count < 0) {
374
				printf("non-numeric length argument -- %s\n", optarg);
375
				return 0;
376
			}
377
			break;
378
		case 'p':
379
			pflag = 1;
380
			break;
381
		case 'P':
382
			Pflag = 1;
383
			pattern = parse_pattern(optarg);
384
			if (pattern < 0)
385
				return 0;
386
			break;
387
		case 'q':
388
			qflag = 1;
389
			break;
390
		case 's':
391
			sflag = 1;
392
			pattern_offset = cvtnum(optarg);
393
			if (pattern_offset < 0) {
394
				printf("non-numeric length argument -- %s\n", optarg);
395
				return 0;
396
			}
397
			break;
398
		case 'v':
399
			vflag = 1;
400
			break;
401
		default:
402
			return command_usage(&read_cmd);
403
		}
404
	}
405

  
406
	if (optind != argc - 2)
407
		return command_usage(&read_cmd);
408

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

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

  
420
	optind++;
421
	count = cvtnum(argv[optind]);
422
	if (count < 0) {
423
		printf("non-numeric length argument -- %s\n", argv[optind]);
424
		return 0;
425
	}
361
    struct timeval t1, t2;
362
    int Cflag = 0, pflag = 0, qflag = 0, vflag = 0;
363
    int Pflag = 0, sflag = 0, lflag = 0, bflag = 0;
364
    int c, cnt;
365
    char *buf;
366
    int64_t offset;
367
    int count;
368
    /* Some compilers get confused and warn if this is not initialized.  */
369
    int total = 0;
370
    int pattern = 0, pattern_offset = 0, pattern_count = 0;
371

  
372
    while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != EOF) {
373
        switch (c) {
374
        case 'b':
375
            bflag = 1;
376
            break;
377
        case 'C':
378
            Cflag = 1;
379
            break;
380
        case 'l':
381
            lflag = 1;
382
            pattern_count = cvtnum(optarg);
383
            if (pattern_count < 0) {
384
                printf("non-numeric length argument -- %s\n", optarg);
385
                return 0;
386
            }
387
            break;
388
        case 'p':
389
            pflag = 1;
390
            break;
391
        case 'P':
392
            Pflag = 1;
393
            pattern = parse_pattern(optarg);
394
            if (pattern < 0) {
395
                return 0;
396
            }
397
            break;
398
        case 'q':
399
            qflag = 1;
400
            break;
401
        case 's':
402
            sflag = 1;
403
            pattern_offset = cvtnum(optarg);
404
            if (pattern_offset < 0) {
405
                printf("non-numeric length argument -- %s\n", optarg);
406
                return 0;
407
            }
408
            break;
409
        case 'v':
410
            vflag = 1;
411
            break;
412
        default:
413
            return command_usage(&read_cmd);
414
        }
415
    }
416

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

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

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

  
432
    optind++;
433
    count = cvtnum(argv[optind]);
434
    if (count < 0) {
435
        printf("non-numeric length argument -- %s\n", argv[optind]);
436
        return 0;
437
    }
426 438

  
427 439
    if (!Pflag && (lflag || sflag)) {
428 440
        return command_usage(&read_cmd);
......
437 449
        return 0;
438 450
    }
439 451

  
440
	if (!pflag)
441
		if (offset & 0x1ff) {
442
                        printf("offset %" PRId64 " is not sector aligned\n",
443
                               offset);
444
			return 0;
445

  
446
		if (count & 0x1ff) {
447
			printf("count %d is not sector aligned\n",
448
				count);
449
			return 0;
450
		}
451
	}
452

  
453
	buf = qemu_io_alloc(count, 0xab);
454

  
455
	gettimeofday(&t1, NULL);
456
	if (pflag)
457
		cnt = do_pread(buf, offset, count, &total);
458
	else if (bflag)
459
		cnt = do_load_vmstate(buf, offset, count, &total);
460
	else
461
		cnt = do_read(buf, offset, count, &total);
462
	gettimeofday(&t2, NULL);
463

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

  
469
	if (Pflag) {
470
		void* cmp_buf = malloc(pattern_count);
471
		memset(cmp_buf, pattern, pattern_count);
472
		if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
473
			printf("Pattern verification failed at offset %"
474
                               PRId64 ", %d bytes\n",
475
                               offset + pattern_offset, pattern_count);
476
		}
477
		free(cmp_buf);
478
	}
479

  
480
	if (qflag)
481
		goto out;
482

  
483
        if (vflag)
484
		dump_buffer(buf, offset, count);
485

  
486
	/* Finally, report back -- -C gives a parsable format */
487
	t2 = tsub(t2, t1);
488
	print_report("read", &t2, offset, count, total, cnt, Cflag);
452
    if (!pflag)
453
        if (offset & 0x1ff) {
454
            printf("offset %" PRId64 " is not sector aligned\n",
455
                   offset);
456
            return 0;
457
        }
458
        if (count & 0x1ff) {
459
            printf("count %d is not sector aligned\n",
460
                   count);
461
            return 0;
462
        }
463

  
464
    buf = qemu_io_alloc(count, 0xab);
465

  
466
    gettimeofday(&t1, NULL);
467
    if (pflag) {
468
        cnt = do_pread(buf, offset, count, &total);
469
    } else if (bflag) {
470
        cnt = do_load_vmstate(buf, offset, count, &total);
471
    } else {
472
        cnt = do_read(buf, offset, count, &total);
473
    }
474
    gettimeofday(&t2, NULL);
475

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

  
481
    if (Pflag) {
482
        void *cmp_buf = malloc(pattern_count);
483
        memset(cmp_buf, pattern, pattern_count);
484
        if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
485
            printf("Pattern verification failed at offset %"
486
                   PRId64 ", %d bytes\n",
487
                   offset + pattern_offset, pattern_count);
488
        }
489
        free(cmp_buf);
490
    }
491

  
492
    if (qflag) {
493
        goto out;
494
    }
495

  
496
    if (vflag) {
497
        dump_buffer(buf, offset, count);
498
    }
499

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

  
490 504
out:
491
	qemu_io_free(buf);
505
    qemu_io_free(buf);
492 506

  
493
	return 0;
507
    return 0;
494 508
}
495 509

  
496
static void
497
readv_help(void)
510
static void readv_help(void)
498 511
{
499
	printf(
512
    printf(
500 513
"\n"
501 514
" reads a range of bytes from the given offset into multiple buffers\n"
502 515
"\n"
......
516 529
static int readv_f(int argc, char **argv);
517 530

  
518 531
static const cmdinfo_t readv_cmd = {
519
	.name		= "readv",
520
	.cfunc		= readv_f,
521
	.argmin		= 2,
522
	.argmax		= -1,
523
	.args		= "[-Cqv] [-P pattern ] off len [len..]",
524
	.oneline	= "reads a number of bytes at a specified offset",
525
	.help		= readv_help,
532
    .name       = "readv",
533
    .cfunc      = readv_f,
534
    .argmin     = 2,
535
    .argmax     = -1,
536
    .args       = "[-Cqv] [-P pattern ] off len [len..]",
537
    .oneline    = "reads a number of bytes at a specified offset",
538
    .help       = readv_help,
526 539
};
527 540

  
528
static int
529
readv_f(int argc, char **argv)
541
static int readv_f(int argc, char **argv)
530 542
{
531
	struct timeval t1, t2;
532
	int Cflag = 0, qflag = 0, vflag = 0;
533
	int c, cnt;
534
	char *buf;
535
	int64_t offset;
536
        /* Some compilers get confused and warn if this is not initialized.  */
537
        int total = 0;
538
	int nr_iov;
539
	QEMUIOVector qiov;
540
	int pattern = 0;
541
	int Pflag = 0;
542

  
543
	while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
544
		switch (c) {
545
		case 'C':
546
			Cflag = 1;
547
			break;
548
		case 'P':
549
			Pflag = 1;
550
			pattern = parse_pattern(optarg);
551
			if (pattern < 0)
552
				return 0;
553
			break;
554
		case 'q':
555
			qflag = 1;
556
			break;
557
		case 'v':
558
			vflag = 1;
559
			break;
560
		default:
561
			return command_usage(&readv_cmd);
562
		}
563
	}
564

  
565
	if (optind > argc - 2)
566
		return command_usage(&readv_cmd);
567

  
568

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

  
576
	if (offset & 0x1ff) {
577
                printf("offset %" PRId64 " is not sector aligned\n",
578
                       offset);
579
		return 0;
580
	}
581

  
582
	nr_iov = argc - optind;
583
	buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
584

  
585
	gettimeofday(&t1, NULL);
586
	cnt = do_aio_readv(&qiov, offset, &total);
587
	gettimeofday(&t2, NULL);
588

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

  
594
	if (Pflag) {
595
		void* cmp_buf = malloc(qiov.size);
596
		memset(cmp_buf, pattern, qiov.size);
597
		if (memcmp(buf, cmp_buf, qiov.size)) {
598
			printf("Pattern verification failed at offset %"
599
                               PRId64 ", %zd bytes\n",
600
                               offset, qiov.size);
601
		}
602
		free(cmp_buf);
603
	}
604

  
605
	if (qflag)
606
		goto out;
607

  
608
        if (vflag)
609
		dump_buffer(buf, offset, qiov.size);
610

  
611
	/* Finally, report back -- -C gives a parsable format */
612
	t2 = tsub(t2, t1);
613
	print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
543
    struct timeval t1, t2;
544
    int Cflag = 0, qflag = 0, vflag = 0;
545
    int c, cnt;
546
    char *buf;
547
    int64_t offset;
548
    /* Some compilers get confused and warn if this is not initialized.  */
549
    int total = 0;
550
    int nr_iov;
551
    QEMUIOVector qiov;
552
    int pattern = 0;
553
    int Pflag = 0;
554

  
555
    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {
556
        switch (c) {
557
        case 'C':
558
            Cflag = 1;
559
            break;
560
        case 'P':
561
            Pflag = 1;
562
            pattern = parse_pattern(optarg);
563
            if (pattern < 0) {
564
                return 0;
565
            }
566
            break;
567
        case 'q':
568
            qflag = 1;
569
            break;
570
        case 'v':
571
            vflag = 1;
572
            break;
573
        default:
574
            return command_usage(&readv_cmd);
575
        }
576
    }
577

  
578
    if (optind > argc - 2) {
579
        return command_usage(&readv_cmd);
580
    }
581

  
582

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

  
590
    if (offset & 0x1ff) {
591
        printf("offset %" PRId64 " is not sector aligned\n",
592
               offset);
593
        return 0;
594
    }
595

  
596
    nr_iov = argc - optind;
597
    buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab);
598

  
599
    gettimeofday(&t1, NULL);
600
    cnt = do_aio_readv(&qiov, offset, &total);
601
    gettimeofday(&t2, NULL);
602

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

  
608
    if (Pflag) {
609
        void *cmp_buf = malloc(qiov.size);
610
        memset(cmp_buf, pattern, qiov.size);
611
        if (memcmp(buf, cmp_buf, qiov.size)) {
612
            printf("Pattern verification failed at offset %"
613
                   PRId64 ", %zd bytes\n", offset, qiov.size);
614
        }
615
        free(cmp_buf);
616
    }
617

  
618
    if (qflag) {
619
        goto out;
620
    }
621

  
622
    if (vflag) {
623
        dump_buffer(buf, offset, qiov.size);
624
    }
625

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

  
615 630
out:
616
	qemu_io_free(buf);
617
	return 0;
631
    qemu_io_free(buf);
632
    return 0;
618 633
}
619 634

  
620
static void
621
write_help(void)
635
static void write_help(void)
622 636
{
623
	printf(
637
    printf(
624 638
"\n"
625 639
" writes a range of bytes from the given offset\n"
626 640
"\n"
......
640 654
static int write_f(int argc, char **argv);
641 655

  
642 656
static const cmdinfo_t write_cmd = {
643
	.name		= "write",
644
	.altname	= "w",
645
	.cfunc		= write_f,
646
	.argmin		= 2,
647
	.argmax		= -1,
648
	.args		= "[-abCpq] [-P pattern ] off len",
649
	.oneline	= "writes a number of bytes at a specified offset",
650
	.help		= write_help,
657
    .name       = "write",
658
    .altname    = "w",
659
    .cfunc      = write_f,
660
    .argmin     = 2,
661
    .argmax     = -1,
662
    .args       = "[-abCpq] [-P pattern ] off len",
663
    .oneline    = "writes a number of bytes at a specified offset",
664
    .help       = write_help,
651 665
};
652 666

  
653
static int
654
write_f(int argc, char **argv)
667
static int write_f(int argc, char **argv)
655 668
{
656
	struct timeval t1, t2;
657
	int Cflag = 0, pflag = 0, qflag = 0, bflag = 0;
658
	int c, cnt;
659
	char *buf;
660
	int64_t offset;
661
	int count;
662
        /* Some compilers get confused and warn if this is not initialized.  */
663
        int total = 0;
664
	int pattern = 0xcd;
665

  
666
	while ((c = getopt(argc, argv, "bCpP:q")) != EOF) {
667
		switch (c) {
668
		case 'b':
669
			bflag = 1;
670
			break;
671
		case 'C':
672
			Cflag = 1;
673
			break;
674
		case 'p':
675
			pflag = 1;
676
			break;
677
		case 'P':
678
			pattern = parse_pattern(optarg);
679
			if (pattern < 0)
680
				return 0;
681
			break;
682
		case 'q':
683
			qflag = 1;
684
			break;
685
		default:
686
			return command_usage(&write_cmd);
687
		}
688
	}
689

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

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

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

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

  
711
	if (!pflag) {
712
		if (offset & 0x1ff) {
713
                        printf("offset %" PRId64 " is not sector aligned\n",
714
                               offset);
715
			return 0;
716
		}
717

  
718
		if (count & 0x1ff) {
719
			printf("count %d is not sector aligned\n",
720
				count);
721
			return 0;
722
		}
723
	}
724

  
725
	buf = qemu_io_alloc(count, pattern);
726

  
727
	gettimeofday(&t1, NULL);
728
	if (pflag)
729
		cnt = do_pwrite(buf, offset, count, &total);
730
	else if (bflag)
731
		cnt = do_save_vmstate(buf, offset, count, &total);
732
	else
733
		cnt = do_write(buf, offset, count, &total);
734
	gettimeofday(&t2, NULL);
735

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

  
741
	if (qflag)
742
		goto out;
743

  
744
	/* Finally, report back -- -C gives a parsable format */
745
	t2 = tsub(t2, t1);
746
	print_report("wrote", &t2, offset, count, total, cnt, Cflag);
669
    struct timeval t1, t2;
670
    int Cflag = 0, pflag = 0, qflag = 0, bflag = 0;
671
    int c, cnt;
672
    char *buf;
673
    int64_t offset;
674
    int count;
675
    /* Some compilers get confused and warn if this is not initialized.  */
676
    int total = 0;
677
    int pattern = 0xcd;
678

  
679
    while ((c = getopt(argc, argv, "bCpP:q")) != EOF) {
680
        switch (c) {
681
        case 'b':
682
            bflag = 1;
683
            break;
684
        case 'C':
685
            Cflag = 1;
686
            break;
687
        case 'p':
688
            pflag = 1;
689
            break;
690
        case 'P':
691
            pattern = parse_pattern(optarg);
692
            if (pattern < 0) {
693
                return 0;
694
            }
695
            break;
696
        case 'q':
697
            qflag = 1;
698
            break;
699
        default:
700
            return command_usage(&write_cmd);
701
        }
702
    }
703

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

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

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

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

  
726
    if (!pflag) {
727
        if (offset & 0x1ff) {
728
            printf("offset %" PRId64 " is not sector aligned\n",
729
                   offset);
730
            return 0;
731
        }
732

  
733
        if (count & 0x1ff) {
734
            printf("count %d is not sector aligned\n",
735
                   count);
736
            return 0;
737
        }
738
    }
739

  
740
    buf = qemu_io_alloc(count, pattern);
741

  
742
    gettimeofday(&t1, NULL);
743
    if (pflag) {
744
        cnt = do_pwrite(buf, offset, count, &total);
745
    } else if (bflag) {
746
        cnt = do_save_vmstate(buf, offset, count, &total);
747
    } else {
748
        cnt = do_write(buf, offset, count, &total);
749
    }
750
    gettimeofday(&t2, NULL);
751

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

  
757
    if (qflag) {
758
        goto out;
759
    }
760

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

  
748 765
out:
749
	qemu_io_free(buf);
766
    qemu_io_free(buf);
750 767

  
751
	return 0;
768
    return 0;
752 769
}
753 770

  
754 771
static void
755 772
writev_help(void)
756 773
{
757
	printf(
774
    printf(
758 775
"\n"
759 776
" writes a range of bytes from the given offset source from multiple buffers\n"
760 777
"\n"
......
772 789
static int writev_f(int argc, char **argv);
773 790

  
774 791
static const cmdinfo_t writev_cmd = {
775
	.name		= "writev",
776
	.cfunc		= writev_f,
777
	.argmin		= 2,
778
	.argmax		= -1,
779
	.args		= "[-Cq] [-P pattern ] off len [len..]",
780
	.oneline	= "writes a number of bytes at a specified offset",
781
	.help		= writev_help,
792
    .name       = "writev",
793
    .cfunc      = writev_f,
794
    .argmin     = 2,
795
    .argmax     = -1,
796
    .args       = "[-Cq] [-P pattern ] off len [len..]",
797
    .oneline    = "writes a number of bytes at a specified offset",
798
    .help       = writev_help,
782 799
};
783 800

  
784
static int
785
writev_f(int argc, char **argv)
801
static int writev_f(int argc, char **argv)
786 802
{
787
	struct timeval t1, t2;
788
	int Cflag = 0, qflag = 0;
789
	int c, cnt;
790
	char *buf;
791
	int64_t offset;
792
        /* Some compilers get confused and warn if this is not initialized.  */
793
        int total = 0;
794
	int nr_iov;
795
	int pattern = 0xcd;
796
	QEMUIOVector qiov;
797

  
798
	while ((c = getopt(argc, argv, "CqP:")) != EOF) {
799
		switch (c) {
800
		case 'C':
801
			Cflag = 1;
802
			break;
803
		case 'q':
804
			qflag = 1;
805
			break;
806
		case 'P':
807
			pattern = parse_pattern(optarg);
808
			if (pattern < 0)
809
				return 0;
810
			break;
811
		default:
812
			return command_usage(&writev_cmd);
813
		}
814
	}
815

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

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

  
826
	if (offset & 0x1ff) {
827
                printf("offset %" PRId64 " is not sector aligned\n",
828
                       offset);
829
		return 0;
830
	}
831

  
832
	nr_iov = argc - optind;
833
	buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
834

  
835
	gettimeofday(&t1, NULL);
836
	cnt = do_aio_writev(&qiov, offset, &total);
837
	gettimeofday(&t2, NULL);
838

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

  
844
	if (qflag)
845
		goto out;
846

  
847
	/* Finally, report back -- -C gives a parsable format */
848
	t2 = tsub(t2, t1);
849
	print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
803
    struct timeval t1, t2;
804
    int Cflag = 0, qflag = 0;
805
    int c, cnt;
806
    char *buf;
807
    int64_t offset;
808
    /* Some compilers get confused and warn if this is not initialized.  */
809
    int total = 0;
810
    int nr_iov;
811
    int pattern = 0xcd;
812
    QEMUIOVector qiov;
813

  
814
    while ((c = getopt(argc, argv, "CqP:")) != EOF) {
815
        switch (c) {
816
        case 'C':
817
            Cflag = 1;
818
            break;
819
        case 'q':
820
            qflag = 1;
821
            break;
822
        case 'P':
823
            pattern = parse_pattern(optarg);
824
            if (pattern < 0) {
825
                return 0;
826
            }
827
            break;
828
        default:
829
            return command_usage(&writev_cmd);
830
        }
831
    }
832

  
833
    if (optind > argc - 2) {
834
        return command_usage(&writev_cmd);
835
    }
836

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

  
844
    if (offset & 0x1ff) {
845
        printf("offset %" PRId64 " is not sector aligned\n",
846
               offset);
847
        return 0;
848
    }
849

  
850
    nr_iov = argc - optind;
851
    buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern);
852

  
853
    gettimeofday(&t1, NULL);
854
    cnt = do_aio_writev(&qiov, offset, &total);
855
    gettimeofday(&t2, NULL);
856

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

  
862
    if (qflag) {
863
        goto out;
864
    }
865

  
866
    /* Finally, report back -- -C gives a parsable format */
867
    t2 = tsub(t2, t1);
868
    print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
850 869
out:
851
	qemu_io_free(buf);
852
	return 0;
870
    qemu_io_free(buf);
871
    return 0;
853 872
}
854 873

  
855
static void
856
multiwrite_help(void)
874
static void multiwrite_help(void)
857 875
{
858
	printf(
876
    printf(
859 877
"\n"
860 878
" writes a range of bytes from the given offset source from multiple buffers,\n"
861 879
" in a batch of requests that may be merged by qemu\n"
......
876 894
static int multiwrite_f(int argc, char **argv);
877 895

  
878 896
static const cmdinfo_t multiwrite_cmd = {
879
	.name		= "multiwrite",
880
	.cfunc		= multiwrite_f,
881
	.argmin		= 2,
882
	.argmax		= -1,
883
	.args		= "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
884
	.oneline	= "issues multiple write requests at once",
885
	.help		= multiwrite_help,
897
    .name       = "multiwrite",
898
    .cfunc      = multiwrite_f,
899
    .argmin     = 2,
900
    .argmax     = -1,
901
    .args       = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
902
    .oneline    = "issues multiple write requests at once",
903
    .help       = multiwrite_help,
886 904
};
887 905

  
888
static int
889
multiwrite_f(int argc, char **argv)
906
static int multiwrite_f(int argc, char **argv)
890 907
{
891
	struct timeval t1, t2;
892
	int Cflag = 0, qflag = 0;
893
	int c, cnt;
894
	char **buf;
895
	int64_t offset, first_offset = 0;
896
	/* Some compilers get confused and warn if this is not initialized.  */
897
	int total = 0;
898
	int nr_iov;
899
	int nr_reqs;
900
	int pattern = 0xcd;
901
	QEMUIOVector *qiovs;
902
	int i;
903
	BlockRequest *reqs;
904

  
905
	while ((c = getopt(argc, argv, "CqP:")) != EOF) {
906
		switch (c) {
907
		case 'C':
908
			Cflag = 1;
909
			break;
910
		case 'q':
911
			qflag = 1;
912
			break;
913
		case 'P':
914
			pattern = parse_pattern(optarg);
915
			if (pattern < 0)
916
				return 0;
917
			break;
918
		default:
919
			return command_usage(&writev_cmd);
920
		}
921
	}
922

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

  
926
	nr_reqs = 1;
927
	for (i = optind; i < argc; i++) {
928
		if (!strcmp(argv[i], ";")) {
929
			nr_reqs++;
930
		}
931
	}
932

  
933
	reqs = qemu_malloc(nr_reqs * sizeof(*reqs));
934
	buf = qemu_malloc(nr_reqs * sizeof(*buf));
935
	qiovs = qemu_malloc(nr_reqs * sizeof(*qiovs));
936

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

  
940
		/* Read the offset of the request */
941
		offset = cvtnum(argv[optind]);
942
		if (offset < 0) {
943
			printf("non-numeric offset argument -- %s\n", argv[optind]);
944
			return 0;
945
		}
946
		optind++;
947

  
948
		if (offset & 0x1ff) {
949
			printf("offset %lld is not sector aligned\n",
950
				(long long)offset);
951
			return 0;
952
		}
908
    struct timeval t1, t2;
909
    int Cflag = 0, qflag = 0;
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff