@@ -160,6 +160,8 @@ struct xfs_getfsmap_info {
160160 struct xfs_buf * agf_bp ; /* AGF, for refcount queries */
161161 struct xfs_perag * pag ; /* AG info, if applicable */
162162 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 ;
163165 u64 missing_owner ; /* owner of holes */
164166 u32 dev ; /* device id */
165167 /*
@@ -250,21 +252,25 @@ xfs_getfsmap_rec_before_start(
250252 const struct xfs_rmap_irec * rec ,
251253 xfs_daddr_t rec_daddr )
252254{
255+ if (info -> low_daddr != -1ULL )
256+ return rec_daddr < info -> low_daddr ;
253257 if (info -> low .rm_blockcount )
254258 return xfs_rmap_compare (rec , & info -> low ) < 0 ;
255259 return false;
256260}
257261
258262/*
259263 * 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.
261266 */
262267STATIC int
263268xfs_getfsmap_helper (
264269 struct xfs_trans * tp ,
265270 struct xfs_getfsmap_info * info ,
266271 const struct xfs_rmap_irec * rec ,
267- xfs_daddr_t rec_daddr )
272+ xfs_daddr_t rec_daddr ,
273+ xfs_daddr_t len_daddr )
268274{
269275 struct xfs_fsmap fmr ;
270276 struct xfs_mount * mp = tp -> t_mountp ;
@@ -274,12 +280,15 @@ xfs_getfsmap_helper(
274280 if (fatal_signal_pending (current ))
275281 return - EINTR ;
276282
283+ if (len_daddr == 0 )
284+ len_daddr = XFS_FSB_TO_BB (mp , rec -> rm_blockcount );
285+
277286 /*
278287 * Filter out records that start before our startpoint, if the
279288 * caller requested that.
280289 */
281290 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 ;
283292 if (info -> next_daddr < rec_daddr )
284293 info -> next_daddr = rec_daddr ;
285294 return 0 ;
@@ -298,7 +307,7 @@ xfs_getfsmap_helper(
298307
299308 info -> head -> fmh_entries ++ ;
300309
301- rec_daddr += XFS_FSB_TO_BB ( mp , rec -> rm_blockcount ) ;
310+ rec_daddr += len_daddr ;
302311 if (info -> next_daddr < rec_daddr )
303312 info -> next_daddr = rec_daddr ;
304313 return 0 ;
@@ -338,7 +347,7 @@ xfs_getfsmap_helper(
338347 if (error )
339348 return error ;
340349 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 ;
342351 if (rec -> rm_flags & XFS_RMAP_UNWRITTEN )
343352 fmr .fmr_flags |= FMR_OF_PREALLOC ;
344353 if (rec -> rm_flags & XFS_RMAP_ATTR_FORK )
@@ -355,7 +364,7 @@ xfs_getfsmap_helper(
355364
356365 xfs_getfsmap_format (mp , & fmr , info );
357366out :
358- rec_daddr += XFS_FSB_TO_BB ( mp , rec -> rm_blockcount ) ;
367+ rec_daddr += len_daddr ;
359368 if (info -> next_daddr < rec_daddr )
360369 info -> next_daddr = rec_daddr ;
361370 return 0 ;
@@ -376,7 +385,7 @@ xfs_getfsmap_datadev_helper(
376385 fsb = XFS_AGB_TO_FSB (mp , cur -> bc_ag .pag -> pag_agno , rec -> rm_startblock );
377386 rec_daddr = XFS_FSB_TO_DADDR (mp , fsb );
378387
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 );
380389}
381390
382391/* Transform a bnobt irec into a fsmap */
@@ -400,7 +409,7 @@ xfs_getfsmap_datadev_bnobt_helper(
400409 irec .rm_offset = 0 ;
401410 irec .rm_flags = 0 ;
402411
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 );
404413}
405414
406415/* Set rmap flags based on the getfsmap flags */
@@ -427,9 +436,13 @@ xfs_getfsmap_logdev(
427436{
428437 struct xfs_mount * mp = tp -> t_mountp ;
429438 struct xfs_rmap_irec rmap ;
439+ xfs_daddr_t rec_daddr , len_daddr ;
440+ xfs_fsblock_t start_fsb ;
430441 int error ;
431442
432443 /* Set up search keys */
444+ start_fsb = XFS_BB_TO_FSBT (mp ,
445+ keys [0 ].fmr_physical + keys [0 ].fmr_length );
433446 info -> low .rm_startblock = XFS_BB_TO_FSBT (mp , keys [0 ].fmr_physical );
434447 info -> low .rm_offset = XFS_BB_TO_FSBT (mp , keys [0 ].fmr_offset );
435448 error = xfs_fsmap_owner_to_rmap (& info -> low , keys );
@@ -438,6 +451,10 @@ xfs_getfsmap_logdev(
438451 info -> low .rm_blockcount = 0 ;
439452 xfs_getfsmap_set_irec_flags (& info -> low , & keys [0 ]);
440453
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+
441458 error = xfs_fsmap_owner_to_rmap (& info -> high , keys + 1 );
442459 if (error )
443460 return error ;
@@ -451,7 +468,7 @@ xfs_getfsmap_logdev(
451468 trace_xfs_fsmap_low_key (mp , info -> dev , NULLAGNUMBER , & info -> low );
452469 trace_xfs_fsmap_high_key (mp , info -> dev , NULLAGNUMBER , & info -> high );
453470
454- if (keys [ 0 ]. fmr_physical > 0 )
471+ if (start_fsb > 0 )
455472 return 0 ;
456473
457474 /* Fabricate an rmap entry for the external log device. */
@@ -461,7 +478,9 @@ xfs_getfsmap_logdev(
461478 rmap .rm_offset = 0 ;
462479 rmap .rm_flags = 0 ;
463480
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 );
465484}
466485
467486#ifdef CONFIG_XFS_RT
@@ -475,16 +494,22 @@ xfs_getfsmap_rtdev_rtbitmap_helper(
475494{
476495 struct xfs_getfsmap_info * info = priv ;
477496 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 ;
479507
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 ;
483508 irec .rm_owner = XFS_RMAP_OWN_NULL ; /* "free" */
484509 irec .rm_offset = 0 ;
485510 irec .rm_flags = 0 ;
486511
487- return xfs_getfsmap_helper (tp , info , & irec , rec_daddr );
512+ return xfs_getfsmap_helper (tp , info , & irec , rec_daddr , len_daddr );
488513}
489514
490515/* Execute a getfsmap query against the realtime device. */
@@ -493,31 +518,41 @@ __xfs_getfsmap_rtdev(
493518 struct xfs_trans * tp ,
494519 const struct xfs_fsmap * keys ,
495520 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 ),
497524 struct xfs_getfsmap_info * info )
498525{
499526 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 ;
502529 uint64_t eofs ;
503530 int error = 0 ;
504531
505532 eofs = XFS_FSB_TO_BB (mp , mp -> m_sb .sb_rblocks );
506533 if (keys [0 ].fmr_physical >= eofs )
507534 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 ));
510538
511539 /* Set up search keys */
512- info -> low .rm_startblock = start_fsb ;
540+ info -> low .rm_startblock = start_rtb ;
513541 error = xfs_fsmap_owner_to_rmap (& info -> low , & keys [0 ]);
514542 if (error )
515543 return error ;
516544 info -> low .rm_offset = XFS_BB_TO_FSBT (mp , keys [0 ].fmr_offset );
517545 info -> low .rm_blockcount = 0 ;
518546 xfs_getfsmap_set_irec_flags (& info -> low , & keys [0 ]);
519547
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 ;
521556 error = xfs_fsmap_owner_to_rmap (& info -> high , & keys [1 ]);
522557 if (error )
523558 return error ;
@@ -528,14 +563,16 @@ __xfs_getfsmap_rtdev(
528563 trace_xfs_fsmap_low_key (mp , info -> dev , NULLAGNUMBER , & info -> low );
529564 trace_xfs_fsmap_high_key (mp , info -> dev , NULLAGNUMBER , & info -> high );
530565
531- return query_fn (tp , info );
566+ return query_fn (tp , info , start_rtb , end_rtb );
532567}
533568
534569/* Actually query the realtime bitmap. */
535570STATIC int
536571xfs_getfsmap_rtdev_rtbitmap_query (
537572 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 )
539576{
540577 struct xfs_rtalloc_rec alow = { 0 };
541578 struct xfs_rtalloc_rec ahigh = { 0 };
@@ -548,8 +585,8 @@ xfs_getfsmap_rtdev_rtbitmap_query(
548585 * Set up query parameters to return free rtextents covering the range
549586 * we want.
550587 */
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 ;
553590 do_div (alow .ar_startext , mp -> m_sb .sb_rextsize );
554591 if (do_div (ahigh .ar_startext , mp -> m_sb .sb_rextsize ))
555592 ahigh .ar_startext ++ ;
@@ -988,6 +1025,7 @@ xfs_getfsmap(
9881025 info .dev = handlers [i ].dev ;
9891026 info .last = false;
9901027 info .pag = NULL ;
1028+ info .low_daddr = -1ULL ;
9911029 info .low .rm_blockcount = 0 ;
9921030 error = handlers [i ].fn (tp , dkeys , & info );
9931031 if (error )
0 commit comments