qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

block: Remove bdrv_aio_multiwrite()

Since virtio-blk implements request merging itself these days, the only
remaining users are test cases for the function. That doesn't make the
function exactly useful any more.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>

+9 -693
-14
block/block-backend.c
··· 1067 1067 bdrv_aio_cancel_async(acb); 1068 1068 } 1069 1069 1070 - int blk_aio_multiwrite(BlockBackend *blk, BlockRequest *reqs, int num_reqs) 1071 - { 1072 - int i, ret; 1073 - 1074 - for (i = 0; i < num_reqs; i++) { 1075 - ret = blk_check_request(blk, reqs[i].sector, reqs[i].nb_sectors); 1076 - if (ret < 0) { 1077 - return ret; 1078 - } 1079 - } 1080 - 1081 - return bdrv_aio_multiwrite(blk_bs(blk), reqs, num_reqs); 1082 - } 1083 - 1084 1070 int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf) 1085 1071 { 1086 1072 if (!blk_is_available(blk)) {
-194
block/io.c
··· 1878 1878 cb, opaque, true); 1879 1879 } 1880 1880 1881 - 1882 - typedef struct MultiwriteCB { 1883 - int error; 1884 - int num_requests; 1885 - int num_callbacks; 1886 - struct { 1887 - BlockCompletionFunc *cb; 1888 - void *opaque; 1889 - QEMUIOVector *free_qiov; 1890 - } callbacks[]; 1891 - } MultiwriteCB; 1892 - 1893 - static void multiwrite_user_cb(MultiwriteCB *mcb) 1894 - { 1895 - int i; 1896 - 1897 - for (i = 0; i < mcb->num_callbacks; i++) { 1898 - mcb->callbacks[i].cb(mcb->callbacks[i].opaque, mcb->error); 1899 - if (mcb->callbacks[i].free_qiov) { 1900 - qemu_iovec_destroy(mcb->callbacks[i].free_qiov); 1901 - } 1902 - g_free(mcb->callbacks[i].free_qiov); 1903 - } 1904 - } 1905 - 1906 - static void multiwrite_cb(void *opaque, int ret) 1907 - { 1908 - MultiwriteCB *mcb = opaque; 1909 - 1910 - trace_multiwrite_cb(mcb, ret); 1911 - 1912 - if (ret < 0 && !mcb->error) { 1913 - mcb->error = ret; 1914 - } 1915 - 1916 - mcb->num_requests--; 1917 - if (mcb->num_requests == 0) { 1918 - multiwrite_user_cb(mcb); 1919 - g_free(mcb); 1920 - } 1921 - } 1922 - 1923 - static int multiwrite_req_compare(const void *a, const void *b) 1924 - { 1925 - const BlockRequest *req1 = a, *req2 = b; 1926 - 1927 - /* 1928 - * Note that we can't simply subtract req2->sector from req1->sector 1929 - * here as that could overflow the return value. 1930 - */ 1931 - if (req1->sector > req2->sector) { 1932 - return 1; 1933 - } else if (req1->sector < req2->sector) { 1934 - return -1; 1935 - } else { 1936 - return 0; 1937 - } 1938 - } 1939 - 1940 - /* 1941 - * Takes a bunch of requests and tries to merge them. Returns the number of 1942 - * requests that remain after merging. 1943 - */ 1944 - static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs, 1945 - int num_reqs, MultiwriteCB *mcb) 1946 - { 1947 - int i, outidx; 1948 - 1949 - // Sort requests by start sector 1950 - qsort(reqs, num_reqs, sizeof(*reqs), &multiwrite_req_compare); 1951 - 1952 - // Check if adjacent requests touch the same clusters. If so, combine them, 1953 - // filling up gaps with zero sectors. 1954 - outidx = 0; 1955 - for (i = 1; i < num_reqs; i++) { 1956 - int merge = 0; 1957 - int64_t oldreq_last = reqs[outidx].sector + reqs[outidx].nb_sectors; 1958 - 1959 - // Handle exactly sequential writes and overlapping writes. 1960 - if (reqs[i].sector <= oldreq_last) { 1961 - merge = 1; 1962 - } 1963 - 1964 - if (reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1 > 1965 - bs->bl.max_iov) { 1966 - merge = 0; 1967 - } 1968 - 1969 - if (bs->bl.max_transfer_length && reqs[outidx].nb_sectors + 1970 - reqs[i].nb_sectors > bs->bl.max_transfer_length) { 1971 - merge = 0; 1972 - } 1973 - 1974 - if (merge) { 1975 - size_t size; 1976 - QEMUIOVector *qiov = g_malloc0(sizeof(*qiov)); 1977 - qemu_iovec_init(qiov, 1978 - reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1); 1979 - 1980 - // Add the first request to the merged one. If the requests are 1981 - // overlapping, drop the last sectors of the first request. 1982 - size = (reqs[i].sector - reqs[outidx].sector) << 9; 1983 - qemu_iovec_concat(qiov, reqs[outidx].qiov, 0, size); 1984 - 1985 - // We should need to add any zeros between the two requests 1986 - assert (reqs[i].sector <= oldreq_last); 1987 - 1988 - // Add the second request 1989 - qemu_iovec_concat(qiov, reqs[i].qiov, 0, reqs[i].qiov->size); 1990 - 1991 - // Add tail of first request, if necessary 1992 - if (qiov->size < reqs[outidx].qiov->size) { 1993 - qemu_iovec_concat(qiov, reqs[outidx].qiov, qiov->size, 1994 - reqs[outidx].qiov->size - qiov->size); 1995 - } 1996 - 1997 - reqs[outidx].nb_sectors = qiov->size >> 9; 1998 - reqs[outidx].qiov = qiov; 1999 - 2000 - mcb->callbacks[i].free_qiov = reqs[outidx].qiov; 2001 - } else { 2002 - outidx++; 2003 - reqs[outidx].sector = reqs[i].sector; 2004 - reqs[outidx].nb_sectors = reqs[i].nb_sectors; 2005 - reqs[outidx].qiov = reqs[i].qiov; 2006 - } 2007 - } 2008 - 2009 - if (bs->blk) { 2010 - block_acct_merge_done(blk_get_stats(bs->blk), BLOCK_ACCT_WRITE, 2011 - num_reqs - outidx - 1); 2012 - } 2013 - 2014 - return outidx + 1; 2015 - } 2016 - 2017 - /* 2018 - * Submit multiple AIO write requests at once. 2019 - * 2020 - * On success, the function returns 0 and all requests in the reqs array have 2021 - * been submitted. In error case this function returns -1, and any of the 2022 - * requests may or may not be submitted yet. In particular, this means that the 2023 - * callback will be called for some of the requests, for others it won't. The 2024 - * caller must check the error field of the BlockRequest to wait for the right 2025 - * callbacks (if error != 0, no callback will be called). 2026 - * 2027 - * The implementation may modify the contents of the reqs array, e.g. to merge 2028 - * requests. However, the fields opaque and error are left unmodified as they 2029 - * are used to signal failure for a single request to the caller. 2030 - */ 2031 - int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs) 2032 - { 2033 - MultiwriteCB *mcb; 2034 - int i; 2035 - 2036 - /* don't submit writes if we don't have a medium */ 2037 - if (bs->drv == NULL) { 2038 - for (i = 0; i < num_reqs; i++) { 2039 - reqs[i].error = -ENOMEDIUM; 2040 - } 2041 - return -1; 2042 - } 2043 - 2044 - if (num_reqs == 0) { 2045 - return 0; 2046 - } 2047 - 2048 - // Create MultiwriteCB structure 2049 - mcb = g_malloc0(sizeof(*mcb) + num_reqs * sizeof(*mcb->callbacks)); 2050 - mcb->num_requests = 0; 2051 - mcb->num_callbacks = num_reqs; 2052 - 2053 - for (i = 0; i < num_reqs; i++) { 2054 - mcb->callbacks[i].cb = reqs[i].cb; 2055 - mcb->callbacks[i].opaque = reqs[i].opaque; 2056 - } 2057 - 2058 - // Check for mergable requests 2059 - num_reqs = multiwrite_merge(bs, reqs, num_reqs, mcb); 2060 - 2061 - trace_bdrv_aio_multiwrite(mcb, mcb->num_callbacks, num_reqs); 2062 - 2063 - /* Run the aio requests. */ 2064 - mcb->num_requests = num_reqs; 2065 - for (i = 0; i < num_reqs; i++) { 2066 - bdrv_co_aio_rw_vector(bs, reqs[i].sector, reqs[i].qiov, 2067 - reqs[i].nb_sectors, reqs[i].flags, 2068 - multiwrite_cb, mcb, 2069 - true); 2070 - } 2071 - 2072 - return 0; 2073 - } 2074 - 2075 1881 void bdrv_aio_cancel(BlockAIOCB *acb) 2076 1882 { 2077 1883 qemu_aio_ref(acb);
+2 -5
include/block/block.h
··· 329 329 void bdrv_aio_cancel_async(BlockAIOCB *acb); 330 330 331 331 typedef struct BlockRequest { 332 - /* Fields to be filled by multiwrite caller */ 332 + /* Fields to be filled by caller */ 333 333 union { 334 334 struct { 335 335 int64_t sector; ··· 345 345 BlockCompletionFunc *cb; 346 346 void *opaque; 347 347 348 - /* Filled by multiwrite implementation */ 348 + /* Filled by block layer */ 349 349 int error; 350 350 } BlockRequest; 351 - 352 - int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, 353 - int num_reqs); 354 351 355 352 /* sg packet commands */ 356 353 int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf);
-1
include/sysemu/block-backend.h
··· 138 138 BlockCompletionFunc *cb, void *opaque); 139 139 void blk_aio_cancel(BlockAIOCB *acb); 140 140 void blk_aio_cancel_async(BlockAIOCB *acb); 141 - int blk_aio_multiwrite(BlockBackend *blk, BlockRequest *reqs, int num_reqs); 142 141 int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf); 143 142 BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf, 144 143 BlockCompletionFunc *cb, void *opaque);
-203
qemu-io-cmds.c
··· 574 574 return async_ret < 0 ? async_ret : 1; 575 575 } 576 576 577 - struct multiwrite_async_ret { 578 - int num_done; 579 - int error; 580 - }; 581 - 582 - static void multiwrite_cb(void *opaque, int ret) 583 - { 584 - struct multiwrite_async_ret *async_ret = opaque; 585 - 586 - async_ret->num_done++; 587 - if (ret < 0) { 588 - async_ret->error = ret; 589 - } 590 - } 591 - 592 - static int do_aio_multiwrite(BlockBackend *blk, BlockRequest* reqs, 593 - int num_reqs, int *total) 594 - { 595 - int i, ret; 596 - struct multiwrite_async_ret async_ret = { 597 - .num_done = 0, 598 - .error = 0, 599 - }; 600 - 601 - *total = 0; 602 - for (i = 0; i < num_reqs; i++) { 603 - reqs[i].cb = multiwrite_cb; 604 - reqs[i].opaque = &async_ret; 605 - *total += reqs[i].qiov->size; 606 - } 607 - 608 - ret = blk_aio_multiwrite(blk, reqs, num_reqs); 609 - if (ret < 0) { 610 - return ret; 611 - } 612 - 613 - while (async_ret.num_done < num_reqs) { 614 - main_loop_wait(false); 615 - } 616 - 617 - return async_ret.error < 0 ? async_ret.error : 1; 618 - } 619 - 620 577 static void read_help(void) 621 578 { 622 579 printf( ··· 1208 1165 out: 1209 1166 qemu_iovec_destroy(&qiov); 1210 1167 qemu_io_free(buf); 1211 - return 0; 1212 - } 1213 - 1214 - static void multiwrite_help(void) 1215 - { 1216 - printf( 1217 - "\n" 1218 - " writes a range of bytes from the given offset source from multiple buffers,\n" 1219 - " in a batch of requests that may be merged by qemu\n" 1220 - "\n" 1221 - " Example:\n" 1222 - " 'multiwrite 512 1k 1k ; 4k 1k'\n" 1223 - " writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n" 1224 - "\n" 1225 - " Writes into a segment of the currently open file, using a buffer\n" 1226 - " filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n" 1227 - " by one for each request contained in the multiwrite command.\n" 1228 - " -P, -- use different pattern to fill file\n" 1229 - " -C, -- report statistics in a machine parsable format\n" 1230 - " -q, -- quiet mode, do not show I/O statistics\n" 1231 - "\n"); 1232 - } 1233 - 1234 - static int multiwrite_f(BlockBackend *blk, int argc, char **argv); 1235 - 1236 - static const cmdinfo_t multiwrite_cmd = { 1237 - .name = "multiwrite", 1238 - .cfunc = multiwrite_f, 1239 - .argmin = 2, 1240 - .argmax = -1, 1241 - .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]", 1242 - .oneline = "issues multiple write requests at once", 1243 - .help = multiwrite_help, 1244 - }; 1245 - 1246 - static int multiwrite_f(BlockBackend *blk, int argc, char **argv) 1247 - { 1248 - struct timeval t1, t2; 1249 - bool Cflag = false, qflag = false; 1250 - int c, cnt; 1251 - char **buf; 1252 - int64_t offset, first_offset = 0; 1253 - /* Some compilers get confused and warn if this is not initialized. */ 1254 - int total = 0; 1255 - int nr_iov; 1256 - int nr_reqs; 1257 - int pattern = 0xcd; 1258 - QEMUIOVector *qiovs; 1259 - int i; 1260 - BlockRequest *reqs; 1261 - 1262 - while ((c = getopt(argc, argv, "CqP:")) != -1) { 1263 - switch (c) { 1264 - case 'C': 1265 - Cflag = true; 1266 - break; 1267 - case 'q': 1268 - qflag = true; 1269 - break; 1270 - case 'P': 1271 - pattern = parse_pattern(optarg); 1272 - if (pattern < 0) { 1273 - return 0; 1274 - } 1275 - break; 1276 - default: 1277 - return qemuio_command_usage(&writev_cmd); 1278 - } 1279 - } 1280 - 1281 - if (optind > argc - 2) { 1282 - return qemuio_command_usage(&writev_cmd); 1283 - } 1284 - 1285 - nr_reqs = 1; 1286 - for (i = optind; i < argc; i++) { 1287 - if (!strcmp(argv[i], ";")) { 1288 - nr_reqs++; 1289 - } 1290 - } 1291 - 1292 - reqs = g_new0(BlockRequest, nr_reqs); 1293 - buf = g_new0(char *, nr_reqs); 1294 - qiovs = g_new(QEMUIOVector, nr_reqs); 1295 - 1296 - for (i = 0; i < nr_reqs && optind < argc; i++) { 1297 - int j; 1298 - 1299 - /* Read the offset of the request */ 1300 - offset = cvtnum(argv[optind]); 1301 - if (offset < 0) { 1302 - print_cvtnum_err(offset, argv[optind]); 1303 - goto out; 1304 - } 1305 - optind++; 1306 - 1307 - if (offset & 0x1ff) { 1308 - printf("offset %lld is not sector aligned\n", 1309 - (long long)offset); 1310 - goto out; 1311 - } 1312 - 1313 - if (i == 0) { 1314 - first_offset = offset; 1315 - } 1316 - 1317 - /* Read lengths for qiov entries */ 1318 - for (j = optind; j < argc; j++) { 1319 - if (!strcmp(argv[j], ";")) { 1320 - break; 1321 - } 1322 - } 1323 - 1324 - nr_iov = j - optind; 1325 - 1326 - /* Build request */ 1327 - buf[i] = create_iovec(blk, &qiovs[i], &argv[optind], nr_iov, pattern); 1328 - if (buf[i] == NULL) { 1329 - goto out; 1330 - } 1331 - 1332 - reqs[i].qiov = &qiovs[i]; 1333 - reqs[i].sector = offset >> 9; 1334 - reqs[i].nb_sectors = reqs[i].qiov->size >> 9; 1335 - 1336 - optind = j + 1; 1337 - 1338 - pattern++; 1339 - } 1340 - 1341 - /* If there were empty requests at the end, ignore them */ 1342 - nr_reqs = i; 1343 - 1344 - gettimeofday(&t1, NULL); 1345 - cnt = do_aio_multiwrite(blk, reqs, nr_reqs, &total); 1346 - gettimeofday(&t2, NULL); 1347 - 1348 - if (cnt < 0) { 1349 - printf("aio_multiwrite failed: %s\n", strerror(-cnt)); 1350 - goto out; 1351 - } 1352 - 1353 - if (qflag) { 1354 - goto out; 1355 - } 1356 - 1357 - /* Finally, report back -- -C gives a parsable format */ 1358 - t2 = tsub(t2, t1); 1359 - print_report("wrote", &t2, first_offset, total, total, cnt, Cflag); 1360 - out: 1361 - for (i = 0; i < nr_reqs; i++) { 1362 - qemu_io_free(buf[i]); 1363 - if (reqs[i].qiov != NULL) { 1364 - qemu_iovec_destroy(&qiovs[i]); 1365 - } 1366 - } 1367 - g_free(buf); 1368 - g_free(reqs); 1369 - g_free(qiovs); 1370 1168 return 0; 1371 1169 } 1372 1170 ··· 2436 2234 qemuio_add_command(&readv_cmd); 2437 2235 qemuio_add_command(&write_cmd); 2438 2236 qemuio_add_command(&writev_cmd); 2439 - qemuio_add_command(&multiwrite_cmd); 2440 2237 qemuio_add_command(&aio_read_cmd); 2441 2238 qemuio_add_command(&aio_write_cmd); 2442 2239 qemuio_add_command(&aio_flush_cmd);
-152
tests/qemu-iotests/100
··· 1 - #!/bin/bash 2 - # 3 - # Test simple read/write using plain bdrv_read/bdrv_write 4 - # 5 - # Copyright (C) 2014 Red Hat, Inc. 6 - # 7 - # This program is free software; you can redistribute it and/or modify 8 - # it under the terms of the GNU General Public License as published by 9 - # the Free Software Foundation; either version 2 of the License, or 10 - # (at your option) any later version. 11 - # 12 - # This program is distributed in the hope that it will be useful, 13 - # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 - # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 - # GNU General Public License for more details. 16 - # 17 - # You should have received a copy of the GNU General Public License 18 - # along with this program. If not, see <http://www.gnu.org/licenses/>. 19 - # 20 - 21 - # creator 22 - owner=stefanha@redhat.com 23 - 24 - seq=`basename $0` 25 - echo "QA output created by $seq" 26 - 27 - here=`pwd` 28 - status=1 # failure is the default! 29 - 30 - _cleanup() 31 - { 32 - _cleanup_test_img 33 - } 34 - trap "_cleanup; exit \$status" 0 1 2 3 15 35 - 36 - # get standard environment, filters and checks 37 - . ./common.rc 38 - . ./common.filter 39 - 40 - _supported_fmt generic 41 - _supported_proto generic 42 - _supported_os Linux 43 - 44 - 45 - size=128M 46 - 47 - echo 48 - echo "== Single request ==" 49 - _make_test_img $size 50 - $QEMU_IO -c "write -z 0 8k" "$TEST_IMG" | _filter_qemu_io 51 - $QEMU_IO -c "multiwrite 0 4k" "$TEST_IMG" | _filter_qemu_io 52 - 53 - echo 54 - echo "== verify pattern ==" 55 - $QEMU_IO -c "read -P 0xcd 0 4k" "$TEST_IMG" | _filter_qemu_io 56 - $QEMU_IO -c "read -P 0 4k 4k" "$TEST_IMG" | _filter_qemu_io 57 - 58 - _cleanup_test_img 59 - 60 - echo 61 - echo "== Sequential requests ==" 62 - _make_test_img $size 63 - $QEMU_IO -c "write -z 0 12k" "$TEST_IMG" | _filter_qemu_io 64 - $QEMU_IO -c "multiwrite 0 4k ; 4k 4k" "$TEST_IMG" | _filter_qemu_io 65 - 66 - echo 67 - echo "== verify pattern ==" 68 - $QEMU_IO -c "read -P 0xcd 0 4k" "$TEST_IMG" | _filter_qemu_io 69 - $QEMU_IO -c "read -P 0xce 4k 4k" "$TEST_IMG" | _filter_qemu_io 70 - $QEMU_IO -c "read -P 0 8k 4k" "$TEST_IMG" | _filter_qemu_io 71 - 72 - _cleanup_test_img 73 - 74 - echo 75 - echo "== Superset overlapping requests ==" 76 - _make_test_img $size 77 - $QEMU_IO -c "write -z 0 8k" "$TEST_IMG" | _filter_qemu_io 78 - $QEMU_IO -c "multiwrite 0 4k ; 1k 2k" "$TEST_IMG" | _filter_qemu_io 79 - 80 - echo 81 - echo "== verify pattern ==" 82 - # Order of overlapping in-flight requests is not guaranteed so we cannot verify 83 - # [1k, 3k) since it could have either pattern 0xcd or 0xce. 84 - $QEMU_IO -c "read -P 0xcd 0 1k" "$TEST_IMG" | _filter_qemu_io 85 - $QEMU_IO -c "read -P 0xcd 3k 1k" "$TEST_IMG" | _filter_qemu_io 86 - $QEMU_IO -c "read -P 0 4k 4k" "$TEST_IMG" | _filter_qemu_io 87 - 88 - _cleanup_test_img 89 - 90 - echo 91 - echo "== Subset overlapping requests ==" 92 - _make_test_img $size 93 - $QEMU_IO -c "write -z 0 8k" "$TEST_IMG" | _filter_qemu_io 94 - $QEMU_IO -c "multiwrite 1k 2k ; 0k 4k" "$TEST_IMG" | _filter_qemu_io 95 - 96 - echo 97 - echo "== verify pattern ==" 98 - # Order of overlapping in-flight requests is not guaranteed so we cannot verify 99 - # [1k, 3k) since it could have either pattern 0xcd or 0xce. 100 - $QEMU_IO -c "read -P 0xce 0 1k" "$TEST_IMG" | _filter_qemu_io 101 - $QEMU_IO -c "read -P 0xce 3k 1k" "$TEST_IMG" | _filter_qemu_io 102 - $QEMU_IO -c "read -P 0 4k 4k" "$TEST_IMG" | _filter_qemu_io 103 - 104 - _cleanup_test_img 105 - 106 - echo 107 - echo "== Head overlapping requests ==" 108 - _make_test_img $size 109 - $QEMU_IO -c "write -z 0 8k" "$TEST_IMG" | _filter_qemu_io 110 - $QEMU_IO -c "multiwrite 0k 2k ; 0k 4k" "$TEST_IMG" | _filter_qemu_io 111 - 112 - echo 113 - echo "== verify pattern ==" 114 - # Order of overlapping in-flight requests is not guaranteed so we cannot verify 115 - # [0k, 2k) since it could have either pattern 0xcd or 0xce. 116 - $QEMU_IO -c "read -P 0xce 2k 2k" "$TEST_IMG" | _filter_qemu_io 117 - $QEMU_IO -c "read -P 0 4k 4k" "$TEST_IMG" | _filter_qemu_io 118 - 119 - _cleanup_test_img 120 - 121 - echo 122 - echo "== Tail overlapping requests ==" 123 - _make_test_img $size 124 - $QEMU_IO -c "write -z 0 8k" "$TEST_IMG" | _filter_qemu_io 125 - $QEMU_IO -c "multiwrite 2k 2k ; 0k 4k" "$TEST_IMG" | _filter_qemu_io 126 - 127 - echo 128 - echo "== verify pattern ==" 129 - # Order of overlapping in-flight requests is not guaranteed so we cannot verify 130 - # [2k, 4k) since it could have either pattern 0xcd or 0xce. 131 - $QEMU_IO -c "read -P 0xce 0k 2k" "$TEST_IMG" | _filter_qemu_io 132 - $QEMU_IO -c "read -P 0 4k 4k" "$TEST_IMG" | _filter_qemu_io 133 - 134 - _cleanup_test_img 135 - 136 - echo 137 - echo "== Disjoint requests ==" 138 - _make_test_img $size 139 - $QEMU_IO -c "write -z 0 72k" "$TEST_IMG" | _filter_qemu_io 140 - $QEMU_IO -c "multiwrite 0 4k ; 64k 4k" "$TEST_IMG" | _filter_qemu_io 141 - 142 - echo 143 - echo "== verify pattern ==" 144 - $QEMU_IO -c "read -P 0xcd 0 4k" "$TEST_IMG" | _filter_qemu_io 145 - $QEMU_IO -c "read -P 0 4k 60k" "$TEST_IMG" | _filter_qemu_io 146 - $QEMU_IO -c "read -P 0xce 64k 4k" "$TEST_IMG" | _filter_qemu_io 147 - $QEMU_IO -c "read -P 0 68k 4k" "$TEST_IMG" | _filter_qemu_io 148 - 149 - # success, all done 150 - echo "*** done" 151 - rm -f $seq.full 152 - status=0
-103
tests/qemu-iotests/100.out
··· 1 - QA output created by 100 2 - 3 - == Single request == 4 - Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 5 - wrote 8192/8192 bytes at offset 0 6 - 8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 7 - wrote 4096/4096 bytes at offset 0 8 - 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 9 - 10 - == verify pattern == 11 - read 4096/4096 bytes at offset 0 12 - 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 13 - read 4096/4096 bytes at offset 4096 14 - 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 15 - 16 - == Sequential requests == 17 - Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 18 - wrote 12288/12288 bytes at offset 0 19 - 12 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 20 - wrote 8192/8192 bytes at offset 0 21 - 8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 22 - 23 - == verify pattern == 24 - read 4096/4096 bytes at offset 0 25 - 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 26 - read 4096/4096 bytes at offset 4096 27 - 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 28 - read 4096/4096 bytes at offset 8192 29 - 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 30 - 31 - == Superset overlapping requests == 32 - Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 33 - wrote 8192/8192 bytes at offset 0 34 - 8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 35 - wrote 6144/6144 bytes at offset 0 36 - 6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 37 - 38 - == verify pattern == 39 - read 1024/1024 bytes at offset 0 40 - 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 41 - read 1024/1024 bytes at offset 3072 42 - 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 43 - read 4096/4096 bytes at offset 4096 44 - 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 45 - 46 - == Subset overlapping requests == 47 - Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 48 - wrote 8192/8192 bytes at offset 0 49 - 8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 50 - wrote 6144/6144 bytes at offset 1024 51 - 6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 52 - 53 - == verify pattern == 54 - read 1024/1024 bytes at offset 0 55 - 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 56 - read 1024/1024 bytes at offset 3072 57 - 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 58 - read 4096/4096 bytes at offset 4096 59 - 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 60 - 61 - == Head overlapping requests == 62 - Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 63 - wrote 8192/8192 bytes at offset 0 64 - 8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 65 - wrote 6144/6144 bytes at offset 0 66 - 6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 67 - 68 - == verify pattern == 69 - read 2048/2048 bytes at offset 2048 70 - 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 71 - read 4096/4096 bytes at offset 4096 72 - 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 73 - 74 - == Tail overlapping requests == 75 - Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 76 - wrote 8192/8192 bytes at offset 0 77 - 8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 78 - wrote 6144/6144 bytes at offset 2048 79 - 6 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 80 - 81 - == verify pattern == 82 - read 2048/2048 bytes at offset 0 83 - 2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 84 - read 4096/4096 bytes at offset 4096 85 - 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 86 - 87 - == Disjoint requests == 88 - Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 89 - wrote 73728/73728 bytes at offset 0 90 - 72 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 91 - wrote 8192/8192 bytes at offset 0 92 - 8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 93 - 94 - == verify pattern == 95 - read 4096/4096 bytes at offset 0 96 - 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 97 - read 61440/61440 bytes at offset 4096 98 - 60 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 99 - read 4096/4096 bytes at offset 65536 100 - 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 101 - read 4096/4096 bytes at offset 69632 102 - 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) 103 - *** done
+4 -16
tests/qemu-iotests/136
··· 248 248 if failed_wr_ops > 0: 249 249 highest_offset = max(highest_offset, bad_offset + 512) 250 250 251 - for i in range(wr_merged): 252 - first = i * wr_size * 2 253 - second = first + wr_size 254 - ops.append("multiwrite %d %d ; %d %d" % 255 - (first, wr_size, second, wr_size)) 256 - 257 - highest_offset = max(highest_offset, wr_merged * wr_size * 2) 258 - 259 251 # Now perform all operations 260 252 for op in ops: 261 253 self.vm.hmp_qemu_io("drive0", op) ··· 309 301 def test_flush(self): 310 302 self.do_test_stats(flush_ops = 8) 311 303 312 - def test_merged(self): 313 - for i in range(5): 314 - self.do_test_stats(wr_merged = i * 3) 315 - 316 304 def test_all(self): 317 305 # rd_size, rd_ops, wr_size, wr_ops, flush_ops 318 306 # invalid_rd_ops, invalid_wr_ops, 319 307 # failed_rd_ops, failed_wr_ops 320 308 # wr_merged 321 - test_values = [[512, 1, 512, 1, 1, 4, 7, 5, 2, 1], 322 - [65536, 1, 2048, 12, 7, 7, 5, 2, 5, 5], 323 - [32768, 9, 8192, 1, 4, 3, 2, 4, 6, 4], 324 - [16384, 11, 3584, 16, 9, 8, 6, 7, 3, 4]] 309 + test_values = [[512, 1, 512, 1, 1, 4, 7, 5, 2, 0], 310 + [65536, 1, 2048, 12, 7, 7, 5, 2, 5, 0], 311 + [32768, 9, 8192, 1, 4, 3, 2, 4, 6, 0], 312 + [16384, 11, 3584, 16, 9, 8, 6, 7, 3, 0]] 325 313 for i in test_values: 326 314 self.do_test_stats(*i) 327 315
+2 -2
tests/qemu-iotests/136.out
··· 1 - ........................................ 1 + ................................... 2 2 ---------------------------------------------------------------------- 3 - Ran 40 tests 3 + Ran 35 tests 4 4 5 5 OK
+1 -1
tests/qemu-iotests/group
··· 106 106 097 rw auto backing 107 107 098 rw auto backing quick 108 108 099 rw auto quick 109 - 100 rw auto quick 109 + # 100 was removed, do not reuse 110 110 101 rw auto quick 111 111 102 rw auto quick 112 112 103 rw auto quick
-2
trace-events
··· 62 62 bdrv_lock_medium(void *bs, bool locked) "bs %p locked %d" 63 63 64 64 # block/io.c 65 - multiwrite_cb(void *mcb, int ret) "mcb %p ret %d" 66 - bdrv_aio_multiwrite(void *mcb, int num_callbacks, int num_reqs) "mcb %p num_callbacks %d num_reqs %d" 67 65 bdrv_aio_discard(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p" 68 66 bdrv_aio_flush(void *bs, void *opaque) "bs %p opaque %p" 69 67 bdrv_aio_readv(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"