]> Git Repo - qemu.git/blob - tests/test-block-iothread.c
qcow2: list of bitmaps new test 242
[qemu.git] / tests / test-block-iothread.c
1 /*
2  * Block tests for iothreads
3  *
4  * Copyright (c) 2018 Kevin Wolf <[email protected]>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24
25 #include "qemu/osdep.h"
26 #include "block/block.h"
27 #include "block/blockjob_int.h"
28 #include "sysemu/block-backend.h"
29 #include "qapi/error.h"
30 #include "iothread.h"
31
32 static int coroutine_fn bdrv_test_co_prwv(BlockDriverState *bs,
33                                           uint64_t offset, uint64_t bytes,
34                                           QEMUIOVector *qiov, int flags)
35 {
36     return 0;
37 }
38
39 static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs,
40                                               int64_t offset, int bytes)
41 {
42     return 0;
43 }
44
45 static int coroutine_fn
46 bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset,
47                       PreallocMode prealloc, Error **errp)
48 {
49     return 0;
50 }
51
52 static int coroutine_fn bdrv_test_co_block_status(BlockDriverState *bs,
53                                                   bool want_zero,
54                                                   int64_t offset, int64_t count,
55                                                   int64_t *pnum, int64_t *map,
56                                                   BlockDriverState **file)
57 {
58     *pnum = count;
59     return 0;
60 }
61
62 static BlockDriver bdrv_test = {
63     .format_name            = "test",
64     .instance_size          = 1,
65
66     .bdrv_co_preadv         = bdrv_test_co_prwv,
67     .bdrv_co_pwritev        = bdrv_test_co_prwv,
68     .bdrv_co_pdiscard       = bdrv_test_co_pdiscard,
69     .bdrv_co_truncate       = bdrv_test_co_truncate,
70     .bdrv_co_block_status   = bdrv_test_co_block_status,
71 };
72
73 static void test_sync_op_pread(BdrvChild *c)
74 {
75     uint8_t buf[512];
76     int ret;
77
78     /* Success */
79     ret = bdrv_pread(c, 0, buf, sizeof(buf));
80     g_assert_cmpint(ret, ==, 512);
81
82     /* Early error: Negative offset */
83     ret = bdrv_pread(c, -2, buf, sizeof(buf));
84     g_assert_cmpint(ret, ==, -EIO);
85 }
86
87 static void test_sync_op_pwrite(BdrvChild *c)
88 {
89     uint8_t buf[512];
90     int ret;
91
92     /* Success */
93     ret = bdrv_pwrite(c, 0, buf, sizeof(buf));
94     g_assert_cmpint(ret, ==, 512);
95
96     /* Early error: Negative offset */
97     ret = bdrv_pwrite(c, -2, buf, sizeof(buf));
98     g_assert_cmpint(ret, ==, -EIO);
99 }
100
101 static void test_sync_op_blk_pread(BlockBackend *blk)
102 {
103     uint8_t buf[512];
104     int ret;
105
106     /* Success */
107     ret = blk_pread(blk, 0, buf, sizeof(buf));
108     g_assert_cmpint(ret, ==, 512);
109
110     /* Early error: Negative offset */
111     ret = blk_pread(blk, -2, buf, sizeof(buf));
112     g_assert_cmpint(ret, ==, -EIO);
113 }
114
115 static void test_sync_op_blk_pwrite(BlockBackend *blk)
116 {
117     uint8_t buf[512];
118     int ret;
119
120     /* Success */
121     ret = blk_pwrite(blk, 0, buf, sizeof(buf), 0);
122     g_assert_cmpint(ret, ==, 512);
123
124     /* Early error: Negative offset */
125     ret = blk_pwrite(blk, -2, buf, sizeof(buf), 0);
126     g_assert_cmpint(ret, ==, -EIO);
127 }
128
129 static void test_sync_op_load_vmstate(BdrvChild *c)
130 {
131     uint8_t buf[512];
132     int ret;
133
134     /* Error: Driver does not support snapshots */
135     ret = bdrv_load_vmstate(c->bs, buf, 0, sizeof(buf));
136     g_assert_cmpint(ret, ==, -ENOTSUP);
137 }
138
139 static void test_sync_op_save_vmstate(BdrvChild *c)
140 {
141     uint8_t buf[512];
142     int ret;
143
144     /* Error: Driver does not support snapshots */
145     ret = bdrv_save_vmstate(c->bs, buf, 0, sizeof(buf));
146     g_assert_cmpint(ret, ==, -ENOTSUP);
147 }
148
149 static void test_sync_op_pdiscard(BdrvChild *c)
150 {
151     int ret;
152
153     /* Normal success path */
154     c->bs->open_flags |= BDRV_O_UNMAP;
155     ret = bdrv_pdiscard(c, 0, 512);
156     g_assert_cmpint(ret, ==, 0);
157
158     /* Early success: UNMAP not supported */
159     c->bs->open_flags &= ~BDRV_O_UNMAP;
160     ret = bdrv_pdiscard(c, 0, 512);
161     g_assert_cmpint(ret, ==, 0);
162
163     /* Early error: Negative offset */
164     ret = bdrv_pdiscard(c, -2, 512);
165     g_assert_cmpint(ret, ==, -EIO);
166 }
167
168 static void test_sync_op_blk_pdiscard(BlockBackend *blk)
169 {
170     int ret;
171
172     /* Early success: UNMAP not supported */
173     ret = blk_pdiscard(blk, 0, 512);
174     g_assert_cmpint(ret, ==, 0);
175
176     /* Early error: Negative offset */
177     ret = blk_pdiscard(blk, -2, 512);
178     g_assert_cmpint(ret, ==, -EIO);
179 }
180
181 static void test_sync_op_truncate(BdrvChild *c)
182 {
183     int ret;
184
185     /* Normal success path */
186     ret = bdrv_truncate(c, 65536, PREALLOC_MODE_OFF, NULL);
187     g_assert_cmpint(ret, ==, 0);
188
189     /* Early error: Negative offset */
190     ret = bdrv_truncate(c, -2, PREALLOC_MODE_OFF, NULL);
191     g_assert_cmpint(ret, ==, -EINVAL);
192
193     /* Error: Read-only image */
194     c->bs->read_only = true;
195     c->bs->open_flags &= ~BDRV_O_RDWR;
196
197     ret = bdrv_truncate(c, 65536, PREALLOC_MODE_OFF, NULL);
198     g_assert_cmpint(ret, ==, -EACCES);
199
200     c->bs->read_only = false;
201     c->bs->open_flags |= BDRV_O_RDWR;
202 }
203
204 static void test_sync_op_block_status(BdrvChild *c)
205 {
206     int ret;
207     int64_t n;
208
209     /* Normal success path */
210     ret = bdrv_is_allocated(c->bs, 0, 65536, &n);
211     g_assert_cmpint(ret, ==, 0);
212
213     /* Early success: No driver support */
214     bdrv_test.bdrv_co_block_status = NULL;
215     ret = bdrv_is_allocated(c->bs, 0, 65536, &n);
216     g_assert_cmpint(ret, ==, 1);
217
218     /* Early success: bytes = 0 */
219     ret = bdrv_is_allocated(c->bs, 0, 0, &n);
220     g_assert_cmpint(ret, ==, 0);
221
222     /* Early success: Offset > image size*/
223     ret = bdrv_is_allocated(c->bs, 0x1000000, 0x1000000, &n);
224     g_assert_cmpint(ret, ==, 0);
225 }
226
227 static void test_sync_op_flush(BdrvChild *c)
228 {
229     int ret;
230
231     /* Normal success path */
232     ret = bdrv_flush(c->bs);
233     g_assert_cmpint(ret, ==, 0);
234
235     /* Early success: Read-only image */
236     c->bs->read_only = true;
237     c->bs->open_flags &= ~BDRV_O_RDWR;
238
239     ret = bdrv_flush(c->bs);
240     g_assert_cmpint(ret, ==, 0);
241
242     c->bs->read_only = false;
243     c->bs->open_flags |= BDRV_O_RDWR;
244 }
245
246 static void test_sync_op_blk_flush(BlockBackend *blk)
247 {
248     BlockDriverState *bs = blk_bs(blk);
249     int ret;
250
251     /* Normal success path */
252     ret = blk_flush(blk);
253     g_assert_cmpint(ret, ==, 0);
254
255     /* Early success: Read-only image */
256     bs->read_only = true;
257     bs->open_flags &= ~BDRV_O_RDWR;
258
259     ret = blk_flush(blk);
260     g_assert_cmpint(ret, ==, 0);
261
262     bs->read_only = false;
263     bs->open_flags |= BDRV_O_RDWR;
264 }
265
266 static void test_sync_op_check(BdrvChild *c)
267 {
268     BdrvCheckResult result;
269     int ret;
270
271     /* Error: Driver does not implement check */
272     ret = bdrv_check(c->bs, &result, 0);
273     g_assert_cmpint(ret, ==, -ENOTSUP);
274 }
275
276 static void test_sync_op_invalidate_cache(BdrvChild *c)
277 {
278     /* Early success: Image is not inactive */
279     bdrv_invalidate_cache(c->bs, NULL);
280 }
281
282
283 typedef struct SyncOpTest {
284     const char *name;
285     void (*fn)(BdrvChild *c);
286     void (*blkfn)(BlockBackend *blk);
287 } SyncOpTest;
288
289 const SyncOpTest sync_op_tests[] = {
290     {
291         .name   = "/sync-op/pread",
292         .fn     = test_sync_op_pread,
293         .blkfn  = test_sync_op_blk_pread,
294     }, {
295         .name   = "/sync-op/pwrite",
296         .fn     = test_sync_op_pwrite,
297         .blkfn  = test_sync_op_blk_pwrite,
298     }, {
299         .name   = "/sync-op/load_vmstate",
300         .fn     = test_sync_op_load_vmstate,
301     }, {
302         .name   = "/sync-op/save_vmstate",
303         .fn     = test_sync_op_save_vmstate,
304     }, {
305         .name   = "/sync-op/pdiscard",
306         .fn     = test_sync_op_pdiscard,
307         .blkfn  = test_sync_op_blk_pdiscard,
308     }, {
309         .name   = "/sync-op/truncate",
310         .fn     = test_sync_op_truncate,
311     }, {
312         .name   = "/sync-op/block_status",
313         .fn     = test_sync_op_block_status,
314     }, {
315         .name   = "/sync-op/flush",
316         .fn     = test_sync_op_flush,
317         .blkfn  = test_sync_op_blk_flush,
318     }, {
319         .name   = "/sync-op/check",
320         .fn     = test_sync_op_check,
321     }, {
322         .name   = "/sync-op/invalidate_cache",
323         .fn     = test_sync_op_invalidate_cache,
324     },
325 };
326
327 /* Test synchronous operations that run in a different iothread, so we have to
328  * poll for the coroutine there to return. */
329 static void test_sync_op(const void *opaque)
330 {
331     const SyncOpTest *t = opaque;
332     IOThread *iothread = iothread_new();
333     AioContext *ctx = iothread_get_aio_context(iothread);
334     BlockBackend *blk;
335     BlockDriverState *bs;
336     BdrvChild *c;
337
338     blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
339     bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
340     bs->total_sectors = 65536 / BDRV_SECTOR_SIZE;
341     blk_insert_bs(blk, bs, &error_abort);
342     c = QLIST_FIRST(&bs->parents);
343
344     blk_set_aio_context(blk, ctx);
345     aio_context_acquire(ctx);
346     t->fn(c);
347     if (t->blkfn) {
348         t->blkfn(blk);
349     }
350     aio_context_release(ctx);
351     blk_set_aio_context(blk, qemu_get_aio_context());
352
353     bdrv_unref(bs);
354     blk_unref(blk);
355 }
356
357 int main(int argc, char **argv)
358 {
359     int i;
360
361     bdrv_init();
362     qemu_init_main_loop(&error_abort);
363
364     g_test_init(&argc, &argv, NULL);
365
366     for (i = 0; i < ARRAY_SIZE(sync_op_tests); i++) {
367         const SyncOpTest *t = &sync_op_tests[i];
368         g_test_add_data_func(t->name, t, test_sync_op);
369     }
370
371     return g_test_run();
372 }
This page took 0.044651 seconds and 4 git commands to generate.