Commit d9654a58576dae982458bdb1eb565c9876c24c22
Committed by
Anthony Liguori
1 parent
9dd986cc
qemu-io: Optionally verify only part of read data
There are reasonable test cases where a read must span areas that are not uniformly filled with one pattern but contains several parts. This makes -P useless for them currently. Introducing additional options which determine the part of the read data that should be verified with the given pattern allows to check such reads. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing
1 changed file
with
41 additions
and
10 deletions
qemu-io.c
| ... | ... | @@ -191,11 +191,13 @@ read_help(void) |
| 191 | 191 | "\n" |
| 192 | 192 | " Reads a segment of the currently open file, optionally dumping it to the\n" |
| 193 | 193 | " standard output stream (with -v option) for subsequent inspection.\n" |
| 194 | +" -C, -- report statistics in a machine parsable format\n" | |
| 195 | +" -l, -- length for pattern verification (only with -P)\n" | |
| 194 | 196 | " -p, -- use bdrv_pread to read the file\n" |
| 195 | 197 | " -P, -- use a pattern to verify read data\n" |
| 196 | -" -C, -- report statistics in a machine parsable format\n" | |
| 197 | -" -v, -- dump buffer to standard output\n" | |
| 198 | 198 | " -q, -- quite mode, do not show I/O statistics\n" |
| 199 | +" -s, -- start offset for pattern verification (only with -P)\n" | |
| 200 | +" -v, -- dump buffer to standard output\n" | |
| 199 | 201 | "\n"); |
| 200 | 202 | } |
| 201 | 203 | |
| ... | ... | @@ -204,18 +206,26 @@ read_f(int argc, char **argv) |
| 204 | 206 | { |
| 205 | 207 | struct timeval t1, t2; |
| 206 | 208 | int Cflag = 0, pflag = 0, qflag = 0, vflag = 0; |
| 209 | + int Pflag = 0, sflag = 0, lflag = 0; | |
| 207 | 210 | int c, cnt; |
| 208 | 211 | char *buf; |
| 209 | 212 | int64_t offset; |
| 210 | 213 | int count, total; |
| 211 | - int pattern = 0; | |
| 212 | - int Pflag = 0; | |
| 214 | + int pattern = 0, pattern_offset = 0, pattern_count = 0; | |
| 213 | 215 | |
| 214 | - while ((c = getopt(argc, argv, "CpP:qv")) != EOF) { | |
| 216 | + while ((c = getopt(argc, argv, "Cl:pP:qs:v")) != EOF) { | |
| 215 | 217 | switch (c) { |
| 216 | 218 | case 'C': |
| 217 | 219 | Cflag = 1; |
| 218 | 220 | break; |
| 221 | + case 'l': | |
| 222 | + lflag = 1; | |
| 223 | + pattern_count = cvtnum(optarg); | |
| 224 | + if (pattern_count < 0) { | |
| 225 | + printf("non-numeric length argument -- %s\n", optarg); | |
| 226 | + return 0; | |
| 227 | + } | |
| 228 | + break; | |
| 219 | 229 | case 'p': |
| 220 | 230 | pflag = 1; |
| 221 | 231 | break; |
| ... | ... | @@ -226,6 +236,14 @@ read_f(int argc, char **argv) |
| 226 | 236 | case 'q': |
| 227 | 237 | qflag = 1; |
| 228 | 238 | break; |
| 239 | + case 's': | |
| 240 | + sflag = 1; | |
| 241 | + pattern_offset = cvtnum(optarg); | |
| 242 | + if (pattern_offset < 0) { | |
| 243 | + printf("non-numeric length argument -- %s\n", optarg); | |
| 244 | + return 0; | |
| 245 | + } | |
| 246 | + break; | |
| 229 | 247 | case 'v': |
| 230 | 248 | vflag = 1; |
| 231 | 249 | break; |
| ... | ... | @@ -250,6 +268,19 @@ read_f(int argc, char **argv) |
| 250 | 268 | return 0; |
| 251 | 269 | } |
| 252 | 270 | |
| 271 | + if (!Pflag && (lflag || sflag)) { | |
| 272 | + return command_usage(&read_cmd); | |
| 273 | + } | |
| 274 | + | |
| 275 | + if (!lflag) { | |
| 276 | + pattern_count = count - pattern_offset; | |
| 277 | + } | |
| 278 | + | |
| 279 | + if ((pattern_count < 0) || (pattern_count + pattern_offset > count)) { | |
| 280 | + printf("pattern verfication range exceeds end of read data\n"); | |
| 281 | + return 0; | |
| 282 | + } | |
| 283 | + | |
| 253 | 284 | if (!pflag) |
| 254 | 285 | if (offset & 0x1ff) { |
| 255 | 286 | printf("offset %lld is not sector aligned\n", |
| ... | ... | @@ -278,12 +309,12 @@ read_f(int argc, char **argv) |
| 278 | 309 | } |
| 279 | 310 | |
| 280 | 311 | if (Pflag) { |
| 281 | - void* cmp_buf = malloc(count); | |
| 282 | - memset(cmp_buf, pattern, count); | |
| 283 | - if (memcmp(buf, cmp_buf, count)) { | |
| 312 | + void* cmp_buf = malloc(pattern_count); | |
| 313 | + memset(cmp_buf, pattern, pattern_count); | |
| 314 | + if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) { | |
| 284 | 315 | printf("Pattern verification failed at offset %lld, " |
| 285 | 316 | "%d bytes\n", |
| 286 | - (long long) offset, count); | |
| 317 | + (long long) offset + pattern_offset, pattern_count); | |
| 287 | 318 | } |
| 288 | 319 | free(cmp_buf); |
| 289 | 320 | } |
| ... | ... | @@ -309,7 +340,7 @@ static const cmdinfo_t read_cmd = { |
| 309 | 340 | .cfunc = read_f, |
| 310 | 341 | .argmin = 2, |
| 311 | 342 | .argmax = -1, |
| 312 | - .args = "[-aCpqv] [-P pattern ] off len", | |
| 343 | + .args = "[-aCpqv] [-P pattern [-s off] [-l len]] off len", | |
| 313 | 344 | .oneline = "reads a number of bytes at a specified offset", |
| 314 | 345 | .help = read_help, |
| 315 | 346 | }; | ... | ... |