* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
+#include <sys/time.h>
#include <sys/types.h>
#include <stdarg.h>
#include <stdio.h>
#include <getopt.h>
+#include <libgen.h>
#include "qemu-common.h"
#include "block_int.h"
static int misalign;
/*
+ * Parse the pattern argument to various sub-commands.
+ *
+ * Because the pattern is used as an argument to memset it must evaluate
+ * to an unsigned integer that fits into a single byte.
+ */
+static int parse_pattern(const char *arg)
+{
+ char *endptr = NULL;
+ long pattern;
+
+ pattern = strtol(arg, &endptr, 0);
+ if (pattern < 0 || pattern > UCHAR_MAX || *endptr != '\0') {
+ printf("%s is not a valid pattern byte\n", arg);
+ return -1;
+ }
+
+ return pattern;
+}
+
+/*
* Memory allocation helpers.
*
* Make sure memory is aligned by default, or purposefully misaligned if
break;
case 'P':
Pflag = 1;
- pattern = atoi(optarg);
+ pattern = parse_pattern(optarg);
+ if (pattern < 0)
+ return 0;
break;
case 'q':
qflag = 1;
break;
case 'P':
Pflag = 1;
- pattern = atoi(optarg);
+ pattern = parse_pattern(optarg);
+ if (pattern < 0)
+ return 0;
break;
case 'q':
qflag = 1;
pflag = 1;
break;
case 'P':
- pattern = atoi(optarg);
+ pattern = parse_pattern(optarg);
+ if (pattern < 0)
+ return 0;
break;
case 'q':
qflag = 1;
qflag = 1;
break;
case 'P':
- pattern = atoi(optarg);
+ pattern = parse_pattern(optarg);
+ if (pattern < 0)
+ return 0;
break;
default:
return command_usage(&writev_cmd);
break;
case 'P':
ctx->Pflag = 1;
- ctx->pattern = atoi(optarg);
+ ctx->pattern = parse_pattern(optarg);
+ if (ctx->pattern < 0)
+ return 0;
break;
case 'q':
ctx->qflag = 1;
ctx->qflag = 1;
break;
case 'P':
- pattern = atoi(optarg);
+ pattern = parse_pattern(optarg);
+ if (pattern < 0)
+ return 0;
break;
default:
free(ctx);
alloc_f(int argc, char **argv)
{
int64_t offset;
- int nb_sectors;
+ int nb_sectors, remaining;
char s1[64];
- int num;
+ int num, sum_alloc;
int ret;
- const char *retstr;
offset = cvtnum(argv[1]);
if (offset & 0x1ff) {
else
nb_sectors = 1;
- ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num);
+ remaining = nb_sectors;
+ sum_alloc = 0;
+ while (remaining) {
+ ret = bdrv_is_allocated(bs, offset >> 9, nb_sectors, &num);
+ remaining -= num;
+ if (ret) {
+ sum_alloc += num;
+ }
+ }
cvtstr(offset, s1, sizeof(s1));
- retstr = ret ? "allocated" : "not allocated";
if (nb_sectors == 1)
- printf("sector %s at offset %s\n", retstr, s1);
+ printf("sector allocated at offset %s\n", s1);
else
- printf("%d/%d sectors %s at offset %s\n",
- num, nb_sectors, retstr, s1);
+ printf("%d/%d sectors allocated at offset %s\n",
+ sum_alloc, nb_sectors, s1);
return 0;
}
" -n, --nocache disable host cache\n"
" -g, --growable allow file to grow (only applies to protocols)\n"
" -m, --misalign misalign allocations for O_DIRECT\n"
+" -k, --native-aio use kernel AIO implementation (on Linux only)\n"
" -h, --help display this help and exit\n"
" -V, --version output version information and exit\n"
"\n",
{
int readonly = 0;
int growable = 0;
- const char *sopt = "hVc:Crsnmg";
+ const char *sopt = "hVc:Crsnmgk";
struct option lopt[] = {
- { "help", 0, 0, 'h' },
- { "version", 0, 0, 'V' },
- { "offset", 1, 0, 'o' },
- { "cmd", 1, 0, 'c' },
- { "create", 0, 0, 'C' },
- { "read-only", 0, 0, 'r' },
- { "snapshot", 0, 0, 's' },
- { "nocache", 0, 0, 'n' },
- { "misalign", 0, 0, 'm' },
- { "growable", 0, 0, 'g' },
- { NULL, 0, 0, 0 }
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "offset", 1, NULL, 'o' },
+ { "cmd", 1, NULL, 'c' },
+ { "create", 0, NULL, 'C' },
+ { "read-only", 0, NULL, 'r' },
+ { "snapshot", 0, NULL, 's' },
+ { "nocache", 0, NULL, 'n' },
+ { "misalign", 0, NULL, 'm' },
+ { "growable", 0, NULL, 'g' },
+ { "native-aio", 0, NULL, 'k' },
+ { NULL, 0, NULL, 0 }
};
int c;
int opt_index = 0;
case 'g':
growable = 1;
break;
+ case 'k':
+ flags |= BDRV_O_NATIVE_AIO;
+ break;
case 'V':
printf("%s version %s\n", progname, VERSION);
exit(0);