@@ -160,6 +160,8 @@ struct xfs_getfsmap_info {
160
160
struct xfs_buf * agf_bp ; /* AGF, for refcount queries */
161
161
struct xfs_perag * pag ; /* AG info, if applicable */
162
162
xfs_daddr_t next_daddr ; /* next daddr we expect */
163
+ /* daddr of low fsmap key when we're using the rtbitmap */
164
+ xfs_daddr_t low_daddr ;
163
165
u64 missing_owner ; /* owner of holes */
164
166
u32 dev ; /* device id */
165
167
/*
@@ -250,21 +252,25 @@ xfs_getfsmap_rec_before_start(
250
252
const struct xfs_rmap_irec * rec ,
251
253
xfs_daddr_t rec_daddr )
252
254
{
255
+ if (info -> low_daddr != -1ULL )
256
+ return rec_daddr < info -> low_daddr ;
253
257
if (info -> low .rm_blockcount )
254
258
return xfs_rmap_compare (rec , & info -> low ) < 0 ;
255
259
return false;
256
260
}
257
261
258
262
/*
259
263
* Format a reverse mapping for getfsmap, having translated rm_startblock
260
- * into the appropriate daddr units.
264
+ * into the appropriate daddr units. Pass in a nonzero @len_daddr if the
265
+ * length could be larger than rm_blockcount in struct xfs_rmap_irec.
261
266
*/
262
267
STATIC int
263
268
xfs_getfsmap_helper (
264
269
struct xfs_trans * tp ,
265
270
struct xfs_getfsmap_info * info ,
266
271
const struct xfs_rmap_irec * rec ,
267
- xfs_daddr_t rec_daddr )
272
+ xfs_daddr_t rec_daddr ,
273
+ xfs_daddr_t len_daddr )
268
274
{
269
275
struct xfs_fsmap fmr ;
270
276
struct xfs_mount * mp = tp -> t_mountp ;
@@ -274,12 +280,15 @@ xfs_getfsmap_helper(
274
280
if (fatal_signal_pending (current ))
275
281
return - EINTR ;
276
282
283
+ if (len_daddr == 0 )
284
+ len_daddr = XFS_FSB_TO_BB (mp , rec -> rm_blockcount );
285
+
277
286
/*
278
287
* Filter out records that start before our startpoint, if the
279
288
* caller requested that.
280
289
*/
281
290
if (xfs_getfsmap_rec_before_start (info , rec , rec_daddr )) {
282
- rec_daddr += XFS_FSB_TO_BB ( mp , rec -> rm_blockcount ) ;
291
+ rec_daddr += len_daddr ;
283
292
if (info -> next_daddr < rec_daddr )
284
293
info -> next_daddr = rec_daddr ;
285
294
return 0 ;
@@ -298,7 +307,7 @@ xfs_getfsmap_helper(
298
307
299
308
info -> head -> fmh_entries ++ ;
300
309
301
- rec_daddr += XFS_FSB_TO_BB ( mp , rec -> rm_blockcount ) ;
310
+ rec_daddr += len_daddr ;
302
311
if (info -> next_daddr < rec_daddr )
303
312
info -> next_daddr = rec_daddr ;
304
313
return 0 ;
@@ -338,7 +347,7 @@ xfs_getfsmap_helper(
338
347
if (error )
339
348
return error ;
340
349
fmr .fmr_offset = XFS_FSB_TO_BB (mp , rec -> rm_offset );
341
- fmr .fmr_length = XFS_FSB_TO_BB ( mp , rec -> rm_blockcount ) ;
350
+ fmr .fmr_length = len_daddr ;
342
351
if (rec -> rm_flags & XFS_RMAP_UNWRITTEN )
343
352
fmr .fmr_flags |= FMR_OF_PREALLOC ;
344
353
if (rec -> rm_flags & XFS_RMAP_ATTR_FORK )
@@ -355,7 +364,7 @@ xfs_getfsmap_helper(
355
364
356
365
xfs_getfsmap_format (mp , & fmr , info );
357
366
out :
358
- rec_daddr += XFS_FSB_TO_BB ( mp , rec -> rm_blockcount ) ;
367
+ rec_daddr += len_daddr ;
359
368
if (info -> next_daddr < rec_daddr )
360
369
info -> next_daddr = rec_daddr ;
361
370
return 0 ;
@@ -376,7 +385,7 @@ xfs_getfsmap_datadev_helper(
376
385
fsb = XFS_AGB_TO_FSB (mp , cur -> bc_ag .pag -> pag_agno , rec -> rm_startblock );
377
386
rec_daddr = XFS_FSB_TO_DADDR (mp , fsb );
378
387
379
- return xfs_getfsmap_helper (cur -> bc_tp , info , rec , rec_daddr );
388
+ return xfs_getfsmap_helper (cur -> bc_tp , info , rec , rec_daddr , 0 );
380
389
}
381
390
382
391
/* Transform a bnobt irec into a fsmap */
@@ -400,7 +409,7 @@ xfs_getfsmap_datadev_bnobt_helper(
400
409
irec .rm_offset = 0 ;
401
410
irec .rm_flags = 0 ;
402
411
403
- return xfs_getfsmap_helper (cur -> bc_tp , info , & irec , rec_daddr );
412
+ return xfs_getfsmap_helper (cur -> bc_tp , info , & irec , rec_daddr , 0 );
404
413
}
405
414
406
415
/* Set rmap flags based on the getfsmap flags */
@@ -427,9 +436,13 @@ xfs_getfsmap_logdev(
427
436
{
428
437
struct xfs_mount * mp = tp -> t_mountp ;
429
438
struct xfs_rmap_irec rmap ;
439
+ xfs_daddr_t rec_daddr , len_daddr ;
440
+ xfs_fsblock_t start_fsb ;
430
441
int error ;
431
442
432
443
/* Set up search keys */
444
+ start_fsb = XFS_BB_TO_FSBT (mp ,
445
+ keys [0 ].fmr_physical + keys [0 ].fmr_length );
433
446
info -> low .rm_startblock = XFS_BB_TO_FSBT (mp , keys [0 ].fmr_physical );
434
447
info -> low .rm_offset = XFS_BB_TO_FSBT (mp , keys [0 ].fmr_offset );
435
448
error = xfs_fsmap_owner_to_rmap (& info -> low , keys );
@@ -438,6 +451,10 @@ xfs_getfsmap_logdev(
438
451
info -> low .rm_blockcount = 0 ;
439
452
xfs_getfsmap_set_irec_flags (& info -> low , & keys [0 ]);
440
453
454
+ /* Adjust the low key if we are continuing from where we left off. */
455
+ if (keys [0 ].fmr_length > 0 )
456
+ info -> low_daddr = XFS_FSB_TO_BB (mp , start_fsb );
457
+
441
458
error = xfs_fsmap_owner_to_rmap (& info -> high , keys + 1 );
442
459
if (error )
443
460
return error ;
@@ -451,7 +468,7 @@ xfs_getfsmap_logdev(
451
468
trace_xfs_fsmap_low_key (mp , info -> dev , NULLAGNUMBER , & info -> low );
452
469
trace_xfs_fsmap_high_key (mp , info -> dev , NULLAGNUMBER , & info -> high );
453
470
454
- if (keys [ 0 ]. fmr_physical > 0 )
471
+ if (start_fsb > 0 )
455
472
return 0 ;
456
473
457
474
/* Fabricate an rmap entry for the external log device. */
@@ -461,7 +478,9 @@ xfs_getfsmap_logdev(
461
478
rmap .rm_offset = 0 ;
462
479
rmap .rm_flags = 0 ;
463
480
464
- return xfs_getfsmap_helper (tp , info , & rmap , 0 );
481
+ rec_daddr = XFS_FSB_TO_BB (mp , rmap .rm_startblock );
482
+ len_daddr = XFS_FSB_TO_BB (mp , rmap .rm_blockcount );
483
+ return xfs_getfsmap_helper (tp , info , & rmap , rec_daddr , len_daddr );
465
484
}
466
485
467
486
#ifdef CONFIG_XFS_RT
@@ -475,16 +494,22 @@ xfs_getfsmap_rtdev_rtbitmap_helper(
475
494
{
476
495
struct xfs_getfsmap_info * info = priv ;
477
496
struct xfs_rmap_irec irec ;
478
- xfs_daddr_t rec_daddr ;
497
+ xfs_rtblock_t rtbno ;
498
+ xfs_daddr_t rec_daddr , len_daddr ;
499
+
500
+ rtbno = rec -> ar_startext * mp -> m_sb .sb_rextsize ;
501
+ rec_daddr = XFS_FSB_TO_BB (mp , rtbno );
502
+ irec .rm_startblock = rtbno ;
503
+
504
+ rtbno = rec -> ar_extcount * mp -> m_sb .sb_rextsize ;
505
+ len_daddr = XFS_FSB_TO_BB (mp , rtbno );
506
+ irec .rm_blockcount = rtbno ;
479
507
480
- irec .rm_startblock = rec -> ar_startext * mp -> m_sb .sb_rextsize ;
481
- rec_daddr = XFS_FSB_TO_BB (mp , irec .rm_startblock );
482
- irec .rm_blockcount = rec -> ar_extcount * mp -> m_sb .sb_rextsize ;
483
508
irec .rm_owner = XFS_RMAP_OWN_NULL ; /* "free" */
484
509
irec .rm_offset = 0 ;
485
510
irec .rm_flags = 0 ;
486
511
487
- return xfs_getfsmap_helper (tp , info , & irec , rec_daddr );
512
+ return xfs_getfsmap_helper (tp , info , & irec , rec_daddr , len_daddr );
488
513
}
489
514
490
515
/* Execute a getfsmap query against the realtime device. */
@@ -493,31 +518,41 @@ __xfs_getfsmap_rtdev(
493
518
struct xfs_trans * tp ,
494
519
const struct xfs_fsmap * keys ,
495
520
int (* query_fn )(struct xfs_trans * ,
496
- struct xfs_getfsmap_info * ),
521
+ struct xfs_getfsmap_info * ,
522
+ xfs_rtblock_t start_rtb ,
523
+ xfs_rtblock_t end_rtb ),
497
524
struct xfs_getfsmap_info * info )
498
525
{
499
526
struct xfs_mount * mp = tp -> t_mountp ;
500
- xfs_fsblock_t start_fsb ;
501
- xfs_fsblock_t end_fsb ;
527
+ xfs_rtblock_t start_rtb ;
528
+ xfs_rtblock_t end_rtb ;
502
529
uint64_t eofs ;
503
530
int error = 0 ;
504
531
505
532
eofs = XFS_FSB_TO_BB (mp , mp -> m_sb .sb_rblocks );
506
533
if (keys [0 ].fmr_physical >= eofs )
507
534
return 0 ;
508
- start_fsb = XFS_BB_TO_FSBT (mp , keys [0 ].fmr_physical );
509
- end_fsb = XFS_BB_TO_FSB (mp , min (eofs - 1 , keys [1 ].fmr_physical ));
535
+ start_rtb = XFS_BB_TO_FSBT (mp ,
536
+ keys [0 ].fmr_physical + keys [0 ].fmr_length );
537
+ end_rtb = XFS_BB_TO_FSB (mp , min (eofs - 1 , keys [1 ].fmr_physical ));
510
538
511
539
/* Set up search keys */
512
- info -> low .rm_startblock = start_fsb ;
540
+ info -> low .rm_startblock = start_rtb ;
513
541
error = xfs_fsmap_owner_to_rmap (& info -> low , & keys [0 ]);
514
542
if (error )
515
543
return error ;
516
544
info -> low .rm_offset = XFS_BB_TO_FSBT (mp , keys [0 ].fmr_offset );
517
545
info -> low .rm_blockcount = 0 ;
518
546
xfs_getfsmap_set_irec_flags (& info -> low , & keys [0 ]);
519
547
520
- info -> high .rm_startblock = end_fsb ;
548
+ /* Adjust the low key if we are continuing from where we left off. */
549
+ if (keys [0 ].fmr_length > 0 ) {
550
+ info -> low_daddr = XFS_FSB_TO_BB (mp , start_rtb );
551
+ if (info -> low_daddr >= eofs )
552
+ return 0 ;
553
+ }
554
+
555
+ info -> high .rm_startblock = end_rtb ;
521
556
error = xfs_fsmap_owner_to_rmap (& info -> high , & keys [1 ]);
522
557
if (error )
523
558
return error ;
@@ -528,14 +563,16 @@ __xfs_getfsmap_rtdev(
528
563
trace_xfs_fsmap_low_key (mp , info -> dev , NULLAGNUMBER , & info -> low );
529
564
trace_xfs_fsmap_high_key (mp , info -> dev , NULLAGNUMBER , & info -> high );
530
565
531
- return query_fn (tp , info );
566
+ return query_fn (tp , info , start_rtb , end_rtb );
532
567
}
533
568
534
569
/* Actually query the realtime bitmap. */
535
570
STATIC int
536
571
xfs_getfsmap_rtdev_rtbitmap_query (
537
572
struct xfs_trans * tp ,
538
- struct xfs_getfsmap_info * info )
573
+ struct xfs_getfsmap_info * info ,
574
+ xfs_rtblock_t start_rtb ,
575
+ xfs_rtblock_t end_rtb )
539
576
{
540
577
struct xfs_rtalloc_rec alow = { 0 };
541
578
struct xfs_rtalloc_rec ahigh = { 0 };
@@ -548,8 +585,8 @@ xfs_getfsmap_rtdev_rtbitmap_query(
548
585
* Set up query parameters to return free rtextents covering the range
549
586
* we want.
550
587
*/
551
- alow .ar_startext = info -> low . rm_startblock ;
552
- ahigh .ar_startext = info -> high . rm_startblock ;
588
+ alow .ar_startext = start_rtb ;
589
+ ahigh .ar_startext = end_rtb ;
553
590
do_div (alow .ar_startext , mp -> m_sb .sb_rextsize );
554
591
if (do_div (ahigh .ar_startext , mp -> m_sb .sb_rextsize ))
555
592
ahigh .ar_startext ++ ;
@@ -988,6 +1025,7 @@ xfs_getfsmap(
988
1025
info .dev = handlers [i ].dev ;
989
1026
info .last = false;
990
1027
info .pag = NULL ;
1028
+ info .low_daddr = -1ULL ;
991
1029
info .low .rm_blockcount = 0 ;
992
1030
error = handlers [i ].fn (tp , dkeys , & info );
993
1031
if (error )
0 commit comments