Skip to content

Commit 42852fe

Browse files
Christoph Hellwigcmaiolino
authored andcommitted
xfs: track the number of blocks in each buftarg
Add a bt_nr_sectors to track the number of sector in each buftarg, and replace the check that hard codes sb_dblock in xfs_buf_map_verify with this new value so that it is correct for non-ddev buftargs. The RT buftarg only has a superblock in the first block, so it is unlikely to trigger this, or are we likely to ever have enough blocks in the in-memory buftargs, but we might as well get the check right. Fixes: 10616b8 ("xfs: fix _xfs_buf_find oops on blocks beyond the filesystem end") Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Carlos Maiolino <cem@kernel.org>
1 parent 3c54e60 commit 42852fe

5 files changed

Lines changed: 52 additions & 34 deletions

File tree

fs/xfs/xfs_buf.c

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -387,8 +387,6 @@ xfs_buf_map_verify(
387387
struct xfs_buftarg *btp,
388388
struct xfs_buf_map *map)
389389
{
390-
xfs_daddr_t eofs;
391-
392390
/* Check for IOs smaller than the sector size / not sector aligned */
393391
ASSERT(!(BBTOB(map->bm_len) < btp->bt_meta_sectorsize));
394392
ASSERT(!(BBTOB(map->bm_bn) & (xfs_off_t)btp->bt_meta_sectormask));
@@ -397,11 +395,10 @@ xfs_buf_map_verify(
397395
* Corrupted block numbers can get through to here, unfortunately, so we
398396
* have to check that the buffer falls within the filesystem bounds.
399397
*/
400-
eofs = XFS_FSB_TO_BB(btp->bt_mount, btp->bt_mount->m_sb.sb_dblocks);
401-
if (map->bm_bn < 0 || map->bm_bn >= eofs) {
398+
if (map->bm_bn < 0 || map->bm_bn >= btp->bt_nr_sectors) {
402399
xfs_alert(btp->bt_mount,
403400
"%s: daddr 0x%llx out of range, EOFS 0x%llx",
404-
__func__, map->bm_bn, eofs);
401+
__func__, map->bm_bn, btp->bt_nr_sectors);
405402
WARN_ON(1);
406403
return -EFSCORRUPTED;
407404
}
@@ -1720,26 +1717,30 @@ xfs_configure_buftarg_atomic_writes(
17201717
int
17211718
xfs_configure_buftarg(
17221719
struct xfs_buftarg *btp,
1723-
unsigned int sectorsize)
1720+
unsigned int sectorsize,
1721+
xfs_rfsblock_t nr_blocks)
17241722
{
1725-
int error;
1723+
struct xfs_mount *mp = btp->bt_mount;
17261724

1727-
ASSERT(btp->bt_bdev != NULL);
1725+
if (btp->bt_bdev) {
1726+
int error;
17281727

1729-
/* Set up metadata sector size info */
1730-
btp->bt_meta_sectorsize = sectorsize;
1731-
btp->bt_meta_sectormask = sectorsize - 1;
1728+
error = bdev_validate_blocksize(btp->bt_bdev, sectorsize);
1729+
if (error) {
1730+
xfs_warn(mp,
1731+
"Cannot use blocksize %u on device %pg, err %d",
1732+
sectorsize, btp->bt_bdev, error);
1733+
return -EINVAL;
1734+
}
17321735

1733-
error = bdev_validate_blocksize(btp->bt_bdev, sectorsize);
1734-
if (error) {
1735-
xfs_warn(btp->bt_mount,
1736-
"Cannot use blocksize %u on device %pg, err %d",
1737-
sectorsize, btp->bt_bdev, error);
1738-
return -EINVAL;
1736+
if (bdev_can_atomic_write(btp->bt_bdev))
1737+
xfs_configure_buftarg_atomic_writes(btp);
17391738
}
17401739

1741-
if (bdev_can_atomic_write(btp->bt_bdev))
1742-
xfs_configure_buftarg_atomic_writes(btp);
1740+
btp->bt_meta_sectorsize = sectorsize;
1741+
btp->bt_meta_sectormask = sectorsize - 1;
1742+
/* m_blkbb_log is not set up yet */
1743+
btp->bt_nr_sectors = nr_blocks << (mp->m_sb.sb_blocklog - BBSHIFT);
17431744
return 0;
17441745
}
17451746

@@ -1749,6 +1750,9 @@ xfs_init_buftarg(
17491750
size_t logical_sectorsize,
17501751
const char *descr)
17511752
{
1753+
/* The maximum size of the buftarg is only known once the sb is read. */
1754+
btp->bt_nr_sectors = (xfs_daddr_t)-1;
1755+
17521756
/* Set up device logical sector size mask */
17531757
btp->bt_logical_sectorsize = logical_sectorsize;
17541758
btp->bt_logical_sectormask = logical_sectorsize - 1;

fs/xfs/xfs_buf.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ struct xfs_buftarg {
103103
size_t bt_meta_sectormask;
104104
size_t bt_logical_sectorsize;
105105
size_t bt_logical_sectormask;
106+
xfs_daddr_t bt_nr_sectors;
106107

107108
/* LRU control structures */
108109
struct shrinker *bt_shrinker;
@@ -372,7 +373,8 @@ struct xfs_buftarg *xfs_alloc_buftarg(struct xfs_mount *mp,
372373
extern void xfs_free_buftarg(struct xfs_buftarg *);
373374
extern void xfs_buftarg_wait(struct xfs_buftarg *);
374375
extern void xfs_buftarg_drain(struct xfs_buftarg *);
375-
int xfs_configure_buftarg(struct xfs_buftarg *btp, unsigned int sectorsize);
376+
int xfs_configure_buftarg(struct xfs_buftarg *btp, unsigned int sectorsize,
377+
xfs_fsblock_t nr_blocks);
376378

377379
#define xfs_readonly_buftarg(buftarg) bdev_read_only((buftarg)->bt_bdev)
378380

fs/xfs/xfs_buf_item_recover.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,16 @@ xlog_recover_do_primary_sb_buffer(
736736
*/
737737
xfs_sb_from_disk(&mp->m_sb, dsb);
738738

739+
/*
740+
* Grow can change the device size. Mirror that into the buftarg.
741+
*/
742+
mp->m_ddev_targp->bt_nr_sectors =
743+
XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
744+
if (mp->m_rtdev_targp && mp->m_rtdev_targp != mp->m_ddev_targp) {
745+
mp->m_rtdev_targp->bt_nr_sectors =
746+
XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
747+
}
748+
739749
if (mp->m_sb.sb_agcount < orig_agcount) {
740750
xfs_alert(mp, "Shrinking AG count in log recovery not supported");
741751
return -EFSCORRUPTED;

fs/xfs/xfs_super.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,8 @@ xfs_setup_devices(
535535
{
536536
int error;
537537

538-
error = xfs_configure_buftarg(mp->m_ddev_targp, mp->m_sb.sb_sectsize);
538+
error = xfs_configure_buftarg(mp->m_ddev_targp, mp->m_sb.sb_sectsize,
539+
mp->m_sb.sb_dblocks);
539540
if (error)
540541
return error;
541542

@@ -545,7 +546,7 @@ xfs_setup_devices(
545546
if (xfs_has_sector(mp))
546547
log_sector_size = mp->m_sb.sb_logsectsize;
547548
error = xfs_configure_buftarg(mp->m_logdev_targp,
548-
log_sector_size);
549+
log_sector_size, mp->m_sb.sb_logblocks);
549550
if (error)
550551
return error;
551552
}
@@ -559,7 +560,7 @@ xfs_setup_devices(
559560
mp->m_rtdev_targp = mp->m_ddev_targp;
560561
} else if (mp->m_rtname) {
561562
error = xfs_configure_buftarg(mp->m_rtdev_targp,
562-
mp->m_sb.sb_sectsize);
563+
mp->m_sb.sb_sectsize, mp->m_sb.sb_rblocks);
563564
if (error)
564565
return error;
565566
}

fs/xfs/xfs_trans.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -452,19 +452,17 @@ xfs_trans_mod_sb(
452452
*/
453453
STATIC void
454454
xfs_trans_apply_sb_deltas(
455-
xfs_trans_t *tp)
455+
struct xfs_trans *tp)
456456
{
457-
struct xfs_dsb *sbp;
458-
struct xfs_buf *bp;
459-
int whole = 0;
460-
461-
bp = xfs_trans_getsb(tp);
462-
sbp = bp->b_addr;
457+
struct xfs_mount *mp = tp->t_mountp;
458+
struct xfs_buf *bp = xfs_trans_getsb(tp);
459+
struct xfs_dsb *sbp = bp->b_addr;
460+
int whole = 0;
463461

464462
/*
465463
* Only update the superblock counters if we are logging them
466464
*/
467-
if (!xfs_has_lazysbcount((tp->t_mountp))) {
465+
if (!xfs_has_lazysbcount(mp)) {
468466
if (tp->t_icount_delta)
469467
be64_add_cpu(&sbp->sb_icount, tp->t_icount_delta);
470468
if (tp->t_ifree_delta)
@@ -491,8 +489,7 @@ xfs_trans_apply_sb_deltas(
491489
* write the correct value ondisk.
492490
*/
493491
if ((tp->t_frextents_delta || tp->t_res_frextents_delta) &&
494-
!xfs_has_rtgroups(tp->t_mountp)) {
495-
struct xfs_mount *mp = tp->t_mountp;
492+
!xfs_has_rtgroups(mp)) {
496493
int64_t rtxdelta;
497494

498495
rtxdelta = tp->t_frextents_delta + tp->t_res_frextents_delta;
@@ -505,6 +502,8 @@ xfs_trans_apply_sb_deltas(
505502

506503
if (tp->t_dblocks_delta) {
507504
be64_add_cpu(&sbp->sb_dblocks, tp->t_dblocks_delta);
505+
mp->m_ddev_targp->bt_nr_sectors +=
506+
XFS_FSB_TO_BB(mp, tp->t_dblocks_delta);
508507
whole = 1;
509508
}
510509
if (tp->t_agcount_delta) {
@@ -524,7 +523,7 @@ xfs_trans_apply_sb_deltas(
524523
* recompute the ondisk rtgroup block log. The incore values
525524
* will be recomputed in xfs_trans_unreserve_and_mod_sb.
526525
*/
527-
if (xfs_has_rtgroups(tp->t_mountp)) {
526+
if (xfs_has_rtgroups(mp)) {
528527
sbp->sb_rgblklog = xfs_compute_rgblklog(
529528
be32_to_cpu(sbp->sb_rgextents),
530529
be32_to_cpu(sbp->sb_rextsize));
@@ -537,6 +536,8 @@ xfs_trans_apply_sb_deltas(
537536
}
538537
if (tp->t_rblocks_delta) {
539538
be64_add_cpu(&sbp->sb_rblocks, tp->t_rblocks_delta);
539+
mp->m_rtdev_targp->bt_nr_sectors +=
540+
XFS_FSB_TO_BB(mp, tp->t_rblocks_delta);
540541
whole = 1;
541542
}
542543
if (tp->t_rextents_delta) {

0 commit comments

Comments
 (0)