34
34
xfs_rmap_lookup_le (
35
35
struct xfs_btree_cur * cur ,
36
36
xfs_agblock_t bno ,
37
- xfs_extlen_t len ,
38
37
uint64_t owner ,
39
38
uint64_t offset ,
40
39
unsigned int flags ,
40
+ struct xfs_rmap_irec * irec ,
41
41
int * stat )
42
42
{
43
+ int get_stat = 0 ;
44
+ int error ;
45
+
43
46
cur -> bc_rec .r .rm_startblock = bno ;
44
- cur -> bc_rec .r .rm_blockcount = len ;
47
+ cur -> bc_rec .r .rm_blockcount = 0 ;
45
48
cur -> bc_rec .r .rm_owner = owner ;
46
49
cur -> bc_rec .r .rm_offset = offset ;
47
50
cur -> bc_rec .r .rm_flags = flags ;
48
- return xfs_btree_lookup (cur , XFS_LOOKUP_LE , stat );
51
+
52
+ error = xfs_btree_lookup (cur , XFS_LOOKUP_LE , stat );
53
+ if (error || !(* stat ) || !irec )
54
+ return error ;
55
+
56
+ error = xfs_rmap_get_rec (cur , irec , & get_stat );
57
+ if (error )
58
+ return error ;
59
+ if (!get_stat )
60
+ return - EFSCORRUPTED ;
61
+
62
+ return 0 ;
49
63
}
50
64
51
65
/*
@@ -251,7 +265,6 @@ xfs_rmap_get_rec(
251
265
struct xfs_find_left_neighbor_info {
252
266
struct xfs_rmap_irec high ;
253
267
struct xfs_rmap_irec * irec ;
254
- int * stat ;
255
268
};
256
269
257
270
/* For each rmap given, figure out if it matches the key we want. */
@@ -276,7 +289,6 @@ xfs_rmap_find_left_neighbor_helper(
276
289
return 0 ;
277
290
278
291
* info -> irec = * rec ;
279
- * info -> stat = 1 ;
280
292
return - ECANCELED ;
281
293
}
282
294
@@ -285,7 +297,7 @@ xfs_rmap_find_left_neighbor_helper(
285
297
* return a match with the same owner and adjacent physical and logical
286
298
* block ranges.
287
299
*/
288
- int
300
+ STATIC int
289
301
xfs_rmap_find_left_neighbor (
290
302
struct xfs_btree_cur * cur ,
291
303
xfs_agblock_t bno ,
@@ -296,6 +308,7 @@ xfs_rmap_find_left_neighbor(
296
308
int * stat )
297
309
{
298
310
struct xfs_find_left_neighbor_info info ;
311
+ int found = 0 ;
299
312
int error ;
300
313
301
314
* stat = 0 ;
@@ -313,21 +326,44 @@ xfs_rmap_find_left_neighbor(
313
326
info .high .rm_flags = flags ;
314
327
info .high .rm_blockcount = 0 ;
315
328
info .irec = irec ;
316
- info .stat = stat ;
317
329
318
330
trace_xfs_rmap_find_left_neighbor_query (cur -> bc_mp ,
319
331
cur -> bc_ag .pag -> pag_agno , bno , 0 , owner , offset , flags );
320
332
321
- error = xfs_rmap_query_range (cur , & info .high , & info .high ,
322
- xfs_rmap_find_left_neighbor_helper , & info );
323
- if (error == - ECANCELED )
324
- error = 0 ;
325
- if (* stat )
326
- trace_xfs_rmap_find_left_neighbor_result (cur -> bc_mp ,
327
- cur -> bc_ag .pag -> pag_agno , irec -> rm_startblock ,
328
- irec -> rm_blockcount , irec -> rm_owner ,
329
- irec -> rm_offset , irec -> rm_flags );
330
- return error ;
333
+ /*
334
+ * Historically, we always used the range query to walk every reverse
335
+ * mapping that could possibly overlap the key that the caller asked
336
+ * for, and filter out the ones that don't. That is very slow when
337
+ * there are a lot of records.
338
+ *
339
+ * However, there are two scenarios where the classic btree search can
340
+ * produce correct results -- if the index contains a record that is an
341
+ * exact match for the lookup key; and if there are no other records
342
+ * between the record we want and the key we supplied.
343
+ *
344
+ * As an optimization, try a non-overlapped lookup first. This makes
345
+ * extent conversion and remap operations run a bit faster if the
346
+ * physical extents aren't being shared. If we don't find what we
347
+ * want, we fall back to the overlapped query.
348
+ */
349
+ error = xfs_rmap_lookup_le (cur , bno , owner , offset , flags , irec ,
350
+ & found );
351
+ if (error )
352
+ return error ;
353
+ if (found )
354
+ error = xfs_rmap_find_left_neighbor_helper (cur , irec , & info );
355
+ if (!error )
356
+ error = xfs_rmap_query_range (cur , & info .high , & info .high ,
357
+ xfs_rmap_find_left_neighbor_helper , & info );
358
+ if (error != - ECANCELED )
359
+ return error ;
360
+
361
+ * stat = 1 ;
362
+ trace_xfs_rmap_find_left_neighbor_result (cur -> bc_mp ,
363
+ cur -> bc_ag .pag -> pag_agno , irec -> rm_startblock ,
364
+ irec -> rm_blockcount , irec -> rm_owner , irec -> rm_offset ,
365
+ irec -> rm_flags );
366
+ return 0 ;
331
367
}
332
368
333
369
/* For each rmap given, figure out if it matches the key we want. */
@@ -353,7 +389,6 @@ xfs_rmap_lookup_le_range_helper(
353
389
return 0 ;
354
390
355
391
* info -> irec = * rec ;
356
- * info -> stat = 1 ;
357
392
return - ECANCELED ;
358
393
}
359
394
@@ -374,6 +409,7 @@ xfs_rmap_lookup_le_range(
374
409
int * stat )
375
410
{
376
411
struct xfs_find_left_neighbor_info info ;
412
+ int found = 0 ;
377
413
int error ;
378
414
379
415
info .high .rm_startblock = bno ;
@@ -386,20 +422,44 @@ xfs_rmap_lookup_le_range(
386
422
info .high .rm_blockcount = 0 ;
387
423
* stat = 0 ;
388
424
info .irec = irec ;
389
- info .stat = stat ;
390
425
391
- trace_xfs_rmap_lookup_le_range (cur -> bc_mp ,
392
- cur -> bc_ag .pag -> pag_agno , bno , 0 , owner , offset , flags );
393
- error = xfs_rmap_query_range (cur , & info .high , & info .high ,
394
- xfs_rmap_lookup_le_range_helper , & info );
395
- if (error == - ECANCELED )
396
- error = 0 ;
397
- if (* stat )
398
- trace_xfs_rmap_lookup_le_range_result (cur -> bc_mp ,
399
- cur -> bc_ag .pag -> pag_agno , irec -> rm_startblock ,
400
- irec -> rm_blockcount , irec -> rm_owner ,
401
- irec -> rm_offset , irec -> rm_flags );
402
- return error ;
426
+ trace_xfs_rmap_lookup_le_range (cur -> bc_mp , cur -> bc_ag .pag -> pag_agno ,
427
+ bno , 0 , owner , offset , flags );
428
+
429
+ /*
430
+ * Historically, we always used the range query to walk every reverse
431
+ * mapping that could possibly overlap the key that the caller asked
432
+ * for, and filter out the ones that don't. That is very slow when
433
+ * there are a lot of records.
434
+ *
435
+ * However, there are two scenarios where the classic btree search can
436
+ * produce correct results -- if the index contains a record that is an
437
+ * exact match for the lookup key; and if there are no other records
438
+ * between the record we want and the key we supplied.
439
+ *
440
+ * As an optimization, try a non-overlapped lookup first. This makes
441
+ * scrub run much faster on most filesystems because bmbt records are
442
+ * usually an exact match for rmap records. If we don't find what we
443
+ * want, we fall back to the overlapped query.
444
+ */
445
+ error = xfs_rmap_lookup_le (cur , bno , owner , offset , flags , irec ,
446
+ & found );
447
+ if (error )
448
+ return error ;
449
+ if (found )
450
+ error = xfs_rmap_lookup_le_range_helper (cur , irec , & info );
451
+ if (!error )
452
+ error = xfs_rmap_query_range (cur , & info .high , & info .high ,
453
+ xfs_rmap_lookup_le_range_helper , & info );
454
+ if (error != - ECANCELED )
455
+ return error ;
456
+
457
+ * stat = 1 ;
458
+ trace_xfs_rmap_lookup_le_range_result (cur -> bc_mp ,
459
+ cur -> bc_ag .pag -> pag_agno , irec -> rm_startblock ,
460
+ irec -> rm_blockcount , irec -> rm_owner , irec -> rm_offset ,
461
+ irec -> rm_flags );
462
+ return 0 ;
403
463
}
404
464
405
465
/*
@@ -510,21 +570,14 @@ xfs_rmap_unmap(
510
570
* for the AG headers at rm_startblock == 0 created by mkfs/growfs that
511
571
* will not ever be removed from the tree.
512
572
*/
513
- error = xfs_rmap_lookup_le (cur , bno , len , owner , offset , flags , & i );
573
+ error = xfs_rmap_lookup_le (cur , bno , owner , offset , flags , & ltrec , & i );
514
574
if (error )
515
575
goto out_error ;
516
576
if (XFS_IS_CORRUPT (mp , i != 1 )) {
517
577
error = - EFSCORRUPTED ;
518
578
goto out_error ;
519
579
}
520
580
521
- error = xfs_rmap_get_rec (cur , & ltrec , & i );
522
- if (error )
523
- goto out_error ;
524
- if (XFS_IS_CORRUPT (mp , i != 1 )) {
525
- error = - EFSCORRUPTED ;
526
- goto out_error ;
527
- }
528
581
trace_xfs_rmap_lookup_le_range_result (cur -> bc_mp ,
529
582
cur -> bc_ag .pag -> pag_agno , ltrec .rm_startblock ,
530
583
ltrec .rm_blockcount , ltrec .rm_owner ,
@@ -786,18 +839,11 @@ xfs_rmap_map(
786
839
* record for our insertion point. This will also give us the record for
787
840
* start block contiguity tests.
788
841
*/
789
- error = xfs_rmap_lookup_le (cur , bno , len , owner , offset , flags ,
842
+ error = xfs_rmap_lookup_le (cur , bno , owner , offset , flags , & ltrec ,
790
843
& have_lt );
791
844
if (error )
792
845
goto out_error ;
793
846
if (have_lt ) {
794
- error = xfs_rmap_get_rec (cur , & ltrec , & have_lt );
795
- if (error )
796
- goto out_error ;
797
- if (XFS_IS_CORRUPT (mp , have_lt != 1 )) {
798
- error = - EFSCORRUPTED ;
799
- goto out_error ;
800
- }
801
847
trace_xfs_rmap_lookup_le_range_result (cur -> bc_mp ,
802
848
cur -> bc_ag .pag -> pag_agno , ltrec .rm_startblock ,
803
849
ltrec .rm_blockcount , ltrec .rm_owner ,
@@ -1022,21 +1068,14 @@ xfs_rmap_convert(
1022
1068
* record for our insertion point. This will also give us the record for
1023
1069
* start block contiguity tests.
1024
1070
*/
1025
- error = xfs_rmap_lookup_le (cur , bno , len , owner , offset , oldext , & i );
1071
+ error = xfs_rmap_lookup_le (cur , bno , owner , offset , oldext , & PREV , & i );
1026
1072
if (error )
1027
1073
goto done ;
1028
1074
if (XFS_IS_CORRUPT (mp , i != 1 )) {
1029
1075
error = - EFSCORRUPTED ;
1030
1076
goto done ;
1031
1077
}
1032
1078
1033
- error = xfs_rmap_get_rec (cur , & PREV , & i );
1034
- if (error )
1035
- goto done ;
1036
- if (XFS_IS_CORRUPT (mp , i != 1 )) {
1037
- error = - EFSCORRUPTED ;
1038
- goto done ;
1039
- }
1040
1079
trace_xfs_rmap_lookup_le_range_result (cur -> bc_mp ,
1041
1080
cur -> bc_ag .pag -> pag_agno , PREV .rm_startblock ,
1042
1081
PREV .rm_blockcount , PREV .rm_owner ,
@@ -1140,7 +1179,7 @@ xfs_rmap_convert(
1140
1179
_RET_IP_ );
1141
1180
1142
1181
/* reset the cursor back to PREV */
1143
- error = xfs_rmap_lookup_le (cur , bno , len , owner , offset , oldext , & i );
1182
+ error = xfs_rmap_lookup_le (cur , bno , owner , offset , oldext , NULL , & i );
1144
1183
if (error )
1145
1184
goto done ;
1146
1185
if (XFS_IS_CORRUPT (mp , i != 1 )) {
@@ -2677,7 +2716,7 @@ xfs_rmap_record_exists(
2677
2716
ASSERT (XFS_RMAP_NON_INODE_OWNER (owner ) ||
2678
2717
(flags & XFS_RMAP_BMBT_BLOCK ));
2679
2718
2680
- error = xfs_rmap_lookup_le (cur , bno , len , owner , offset , flags ,
2719
+ error = xfs_rmap_lookup_le (cur , bno , owner , offset , flags , & irec ,
2681
2720
& has_record );
2682
2721
if (error )
2683
2722
return error ;
@@ -2686,14 +2725,6 @@ xfs_rmap_record_exists(
2686
2725
return 0 ;
2687
2726
}
2688
2727
2689
- error = xfs_rmap_get_rec (cur , & irec , & has_record );
2690
- if (error )
2691
- return error ;
2692
- if (!has_record ) {
2693
- * has_rmap = false;
2694
- return 0 ;
2695
- }
2696
-
2697
2728
* has_rmap = (irec .rm_owner == owner && irec .rm_startblock <= bno &&
2698
2729
irec .rm_startblock + irec .rm_blockcount >= bno + len );
2699
2730
return 0 ;
0 commit comments