diff options
author | Liu Bo <bo.li.liu@oracle.com> | 2018-01-05 14:51:14 -0500 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2018-01-22 10:08:22 -0500 |
commit | cd77f4f8363602e5fbee481f38241110e65ff014 (patch) | |
tree | 9a5d1e3f5ab4682253f7abf5a0c69417f28ab4ef | |
parent | fd87526fada701295656b3c695ae20cb037fdd95 (diff) |
Btrfs: extent map selftest: dio write vs dio read
This test case simulates the racy situation of dio write vs dio read,
and see if btrfs_get_extent() would return -EEXIST.
Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
Reviewed-by: Josef Bacik <jbacik@fb.com>
Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r-- | fs/btrfs/tests/extent-map-tests.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/fs/btrfs/tests/extent-map-tests.c b/fs/btrfs/tests/extent-map-tests.c index 16830bf88f46..70c993f01670 100644 --- a/fs/btrfs/tests/extent-map-tests.c +++ b/fs/btrfs/tests/extent-map-tests.c | |||
@@ -255,6 +255,94 @@ static void test_case_3(struct extent_map_tree *em_tree) | |||
255 | __test_case_3(em_tree, (12 * 1024ULL)); | 255 | __test_case_3(em_tree, (12 * 1024ULL)); |
256 | } | 256 | } |
257 | 257 | ||
258 | static void __test_case_4(struct extent_map_tree *em_tree, u64 start) | ||
259 | { | ||
260 | struct extent_map *em; | ||
261 | u64 len = SZ_4K; | ||
262 | int ret; | ||
263 | |||
264 | em = alloc_extent_map(); | ||
265 | if (!em) | ||
266 | /* Skip this test on error. */ | ||
267 | return; | ||
268 | |||
269 | /* Add [0K, 8K) */ | ||
270 | em->start = 0; | ||
271 | em->len = SZ_8K; | ||
272 | em->block_start = 0; | ||
273 | em->block_len = SZ_8K; | ||
274 | ret = add_extent_mapping(em_tree, em, 0); | ||
275 | ASSERT(ret == 0); | ||
276 | free_extent_map(em); | ||
277 | |||
278 | em = alloc_extent_map(); | ||
279 | if (!em) | ||
280 | goto out; | ||
281 | |||
282 | /* Add [8K, 24K) */ | ||
283 | em->start = SZ_8K; | ||
284 | em->len = 24 * 1024ULL; | ||
285 | em->block_start = SZ_16K; /* avoid merging */ | ||
286 | em->block_len = 24 * 1024ULL; | ||
287 | ret = add_extent_mapping(em_tree, em, 0); | ||
288 | ASSERT(ret == 0); | ||
289 | free_extent_map(em); | ||
290 | |||
291 | em = alloc_extent_map(); | ||
292 | if (!em) | ||
293 | goto out; | ||
294 | /* Add [0K, 32K) */ | ||
295 | em->start = 0; | ||
296 | em->len = SZ_32K; | ||
297 | em->block_start = 0; | ||
298 | em->block_len = SZ_32K; | ||
299 | ret = btrfs_add_extent_mapping(em_tree, &em, start, len); | ||
300 | if (ret) | ||
301 | test_msg("case4 [0x%llx 0x%llx): ret %d\n", | ||
302 | start, len, ret); | ||
303 | if (em && | ||
304 | (start < em->start || start + len > extent_map_end(em))) | ||
305 | test_msg( | ||
306 | "case4 [0x%llx 0x%llx): ret %d, added wrong em (start 0x%llx len 0x%llx block_start 0x%llx block_len 0x%llx)\n", | ||
307 | start, len, ret, em->start, em->len, em->block_start, | ||
308 | em->block_len); | ||
309 | free_extent_map(em); | ||
310 | out: | ||
311 | /* free memory */ | ||
312 | free_extent_map_tree(em_tree); | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * Test scenario: | ||
317 | * | ||
318 | * Suppose that no extent map has been loaded into memory yet. | ||
319 | * There is a file extent [0, 32K), two jobs are running concurrently | ||
320 | * against it, t1 is doing dio write to [8K, 32K) and t2 is doing dio | ||
321 | * read from [0, 4K) or [4K, 8K). | ||
322 | * | ||
323 | * t1 goes ahead of t2 and splits em [0, 32K) to em [0K, 8K) and [8K 32K). | ||
324 | * | ||
325 | * t1 t2 | ||
326 | * btrfs_get_blocks_direct() btrfs_get_blocks_direct() | ||
327 | * -> btrfs_get_extent() -> btrfs_get_extent() | ||
328 | * -> lookup_extent_mapping() | ||
329 | * -> add_extent_mapping() -> lookup_extent_mapping() | ||
330 | * # load [0, 32K) | ||
331 | * -> btrfs_new_extent_direct() | ||
332 | * -> btrfs_drop_extent_cache() | ||
333 | * # split [0, 32K) | ||
334 | * -> add_extent_mapping() | ||
335 | * # add [8K, 32K) | ||
336 | * -> add_extent_mapping() | ||
337 | * # handle -EEXIST when adding | ||
338 | * # [0, 32K) | ||
339 | */ | ||
340 | static void test_case_4(struct extent_map_tree *em_tree) | ||
341 | { | ||
342 | __test_case_4(em_tree, 0); | ||
343 | __test_case_4(em_tree, SZ_4K); | ||
344 | } | ||
345 | |||
258 | int btrfs_test_extent_map() | 346 | int btrfs_test_extent_map() |
259 | { | 347 | { |
260 | struct extent_map_tree *em_tree; | 348 | struct extent_map_tree *em_tree; |
@@ -271,6 +359,7 @@ int btrfs_test_extent_map() | |||
271 | test_case_1(em_tree); | 359 | test_case_1(em_tree); |
272 | test_case_2(em_tree); | 360 | test_case_2(em_tree); |
273 | test_case_3(em_tree); | 361 | test_case_3(em_tree); |
362 | test_case_4(em_tree); | ||
274 | 363 | ||
275 | kfree(em_tree); | 364 | kfree(em_tree); |
276 | return 0; | 365 | return 0; |