On Thu, Feb 24, 2022 at 06:32:08PM +0530, Chandan Babu R wrote: > This commit upgrades inodes to use 64-bit extent counters when they are read > from disk. Inodes are upgraded only when the filesystem instance has > XFS_SB_FEAT_INCOMPAT_NREXT64 incompat flag set. > > Signed-off-by: Chandan Babu R <chandan.babu@xxxxxxxxxx> Yay! Reviewed-by: Darrick J. Wong <djwong@xxxxxxxxxx> --D > --- > fs/xfs/libxfs/xfs_attr.c | 3 ++- > fs/xfs/libxfs/xfs_bmap.c | 5 ++--- > fs/xfs/libxfs/xfs_inode_fork.c | 37 ++++++++++++++++++++++++++++++++++ > fs/xfs/libxfs/xfs_inode_fork.h | 2 ++ > fs/xfs/xfs_bmap_item.c | 3 ++- > fs/xfs/xfs_bmap_util.c | 10 ++++----- > fs/xfs/xfs_dquot.c | 2 +- > fs/xfs/xfs_iomap.c | 5 +++-- > fs/xfs/xfs_reflink.c | 5 +++-- > fs/xfs/xfs_rtalloc.c | 2 +- > 10 files changed, 58 insertions(+), 16 deletions(-) > > diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c > index 23523b802539..03a358930d74 100644 > --- a/fs/xfs/libxfs/xfs_attr.c > +++ b/fs/xfs/libxfs/xfs_attr.c > @@ -774,7 +774,8 @@ xfs_attr_set( > return error; > > if (args->value || xfs_inode_hasattr(dp)) { > - error = xfs_iext_count_may_overflow(dp, XFS_ATTR_FORK, > + error = xfs_trans_inode_ensure_nextents(&args->trans, dp, > + XFS_ATTR_FORK, > XFS_IEXT_ATTR_MANIP_CNT(rmt_blks)); > if (error) > goto out_trans_cancel; > diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c > index be7f8ebe3cd5..3a3c99ef7f13 100644 > --- a/fs/xfs/libxfs/xfs_bmap.c > +++ b/fs/xfs/libxfs/xfs_bmap.c > @@ -4523,14 +4523,13 @@ xfs_bmapi_convert_delalloc( > return error; > > xfs_ilock(ip, XFS_ILOCK_EXCL); > + xfs_trans_ijoin(tp, ip, 0); > > - error = xfs_iext_count_may_overflow(ip, whichfork, > + error = xfs_trans_inode_ensure_nextents(&tp, ip, whichfork, > XFS_IEXT_ADD_NOSPLIT_CNT); > if (error) > goto out_trans_cancel; > > - xfs_trans_ijoin(tp, ip, 0); > - > if (!xfs_iext_lookup_extent(ip, ifp, offset_fsb, &bma.icur, &bma.got) || > bma.got.br_startoff > offset_fsb) { > /* > diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c > index a3a3b54f9c55..d1d065abeac3 100644 > --- a/fs/xfs/libxfs/xfs_inode_fork.c > +++ b/fs/xfs/libxfs/xfs_inode_fork.c > @@ -757,3 +757,40 @@ xfs_iext_count_may_overflow( > > return 0; > } > + > +/* > + * Ensure that the inode has the ability to add the specified number of > + * extents. Caller must hold ILOCK_EXCL and have joined the inode to > + * the transaction. Upon return, the inode will still be in this state > + * upon return and the transaction will be clean. > + */ > +int > +xfs_trans_inode_ensure_nextents( > + struct xfs_trans **tpp, > + struct xfs_inode *ip, > + int whichfork, > + int nr_to_add) > +{ > + int error; > + > + error = xfs_iext_count_may_overflow(ip, whichfork, nr_to_add); > + if (!error) > + return 0; > + > + /* > + * Try to upgrade if the extent count fields aren't large > + * enough. > + */ > + if (!xfs_has_nrext64(ip->i_mount) || > + (ip->i_diflags2 & XFS_DIFLAG2_NREXT64)) > + return error; > + > + ip->i_diflags2 |= XFS_DIFLAG2_NREXT64; > + xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE); > + > + error = xfs_trans_roll(tpp); > + if (error) > + return error; > + > + return xfs_iext_count_may_overflow(ip, whichfork, nr_to_add); > +} > diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h > index 8e6221e32660..65265ca51b0d 100644 > --- a/fs/xfs/libxfs/xfs_inode_fork.h > +++ b/fs/xfs/libxfs/xfs_inode_fork.h > @@ -286,6 +286,8 @@ int xfs_ifork_verify_local_data(struct xfs_inode *ip); > int xfs_ifork_verify_local_attr(struct xfs_inode *ip); > int xfs_iext_count_may_overflow(struct xfs_inode *ip, int whichfork, > int nr_to_add); > +int xfs_trans_inode_ensure_nextents(struct xfs_trans **tpp, > + struct xfs_inode *ip, int whichfork, int nr_to_add); > > /* returns true if the fork has extents but they are not read in yet. */ > static inline bool xfs_need_iread_extents(struct xfs_ifork *ifp) > diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c > index e1f4d7d5a011..27bc16a2b09b 100644 > --- a/fs/xfs/xfs_bmap_item.c > +++ b/fs/xfs/xfs_bmap_item.c > @@ -505,7 +505,8 @@ xfs_bui_item_recover( > else > iext_delta = XFS_IEXT_PUNCH_HOLE_CNT; > > - error = xfs_iext_count_may_overflow(ip, whichfork, iext_delta); > + error = xfs_trans_inode_ensure_nextents(&tp, ip, whichfork, > + iext_delta); > if (error) > goto err_cancel; > > diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c > index eb2e387ba528..8d86d8d5ad88 100644 > --- a/fs/xfs/xfs_bmap_util.c > +++ b/fs/xfs/xfs_bmap_util.c > @@ -855,7 +855,7 @@ xfs_alloc_file_space( > if (error) > break; > > - error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK, > + error = xfs_trans_inode_ensure_nextents(&tp, ip, XFS_DATA_FORK, > XFS_IEXT_ADD_NOSPLIT_CNT); > if (error) > goto error; > @@ -910,7 +910,7 @@ xfs_unmap_extent( > if (error) > return error; > > - error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK, > + error = xfs_trans_inode_ensure_nextents(&tp, ip, XFS_DATA_FORK, > XFS_IEXT_PUNCH_HOLE_CNT); > if (error) > goto out_trans_cancel; > @@ -1191,7 +1191,7 @@ xfs_insert_file_space( > xfs_ilock(ip, XFS_ILOCK_EXCL); > xfs_trans_ijoin(tp, ip, 0); > > - error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK, > + error = xfs_trans_inode_ensure_nextents(&tp, ip, XFS_DATA_FORK, > XFS_IEXT_PUNCH_HOLE_CNT); > if (error) > goto out_trans_cancel; > @@ -1418,7 +1418,7 @@ xfs_swap_extent_rmap( > trace_xfs_swap_extent_rmap_remap_piece(tip, &uirec); > > if (xfs_bmap_is_real_extent(&uirec)) { > - error = xfs_iext_count_may_overflow(ip, > + error = xfs_trans_inode_ensure_nextents(&tp, ip, > XFS_DATA_FORK, > XFS_IEXT_SWAP_RMAP_CNT); > if (error) > @@ -1426,7 +1426,7 @@ xfs_swap_extent_rmap( > } > > if (xfs_bmap_is_real_extent(&irec)) { > - error = xfs_iext_count_may_overflow(tip, > + error = xfs_trans_inode_ensure_nextents(&tp, tip, > XFS_DATA_FORK, > XFS_IEXT_SWAP_RMAP_CNT); > if (error) > diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c > index 5afedcbc78c7..193a2e66efc7 100644 > --- a/fs/xfs/xfs_dquot.c > +++ b/fs/xfs/xfs_dquot.c > @@ -320,7 +320,7 @@ xfs_dquot_disk_alloc( > goto err_cancel; > } > > - error = xfs_iext_count_may_overflow(quotip, XFS_DATA_FORK, > + error = xfs_trans_inode_ensure_nextents(&tp, quotip, XFS_DATA_FORK, > XFS_IEXT_ADD_NOSPLIT_CNT); > if (error) > goto err_cancel; > diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c > index e552ce541ec2..4078d5324090 100644 > --- a/fs/xfs/xfs_iomap.c > +++ b/fs/xfs/xfs_iomap.c > @@ -250,7 +250,8 @@ xfs_iomap_write_direct( > if (error) > return error; > > - error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK, nr_exts); > + error = xfs_trans_inode_ensure_nextents(&tp, ip, XFS_DATA_FORK, > + nr_exts); > if (error) > goto out_trans_cancel; > > @@ -553,7 +554,7 @@ xfs_iomap_write_unwritten( > if (error) > return error; > > - error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK, > + error = xfs_trans_inode_ensure_nextents(&tp, ip, XFS_DATA_FORK, > XFS_IEXT_WRITE_UNWRITTEN_CNT); > if (error) > goto error_on_bmapi_transaction; > diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c > index db70060e7bf6..9d4fd2b160ff 100644 > --- a/fs/xfs/xfs_reflink.c > +++ b/fs/xfs/xfs_reflink.c > @@ -615,7 +615,7 @@ xfs_reflink_end_cow_extent( > xfs_ilock(ip, XFS_ILOCK_EXCL); > xfs_trans_ijoin(tp, ip, 0); > > - error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK, > + error = xfs_trans_inode_ensure_nextents(&tp, ip, XFS_DATA_FORK, > XFS_IEXT_REFLINK_END_COW_CNT); > if (error) > goto out_cancel; > @@ -1117,7 +1117,8 @@ xfs_reflink_remap_extent( > if (dmap_written) > ++iext_delta; > > - error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK, iext_delta); > + error = xfs_trans_inode_ensure_nextents(&tp, ip, XFS_DATA_FORK, > + iext_delta); > if (error) > goto out_cancel; > > diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c > index 379ef99722c5..4d24977d6a47 100644 > --- a/fs/xfs/xfs_rtalloc.c > +++ b/fs/xfs/xfs_rtalloc.c > @@ -806,7 +806,7 @@ xfs_growfs_rt_alloc( > xfs_trans_ijoin(tp, ip, 0); > unlock_inode = true; > > - error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK, > + error = xfs_trans_inode_ensure_nextents(&tp, ip, XFS_DATA_FORK, > XFS_IEXT_ADD_NOSPLIT_CNT); > if (error) > goto out_trans_cancel; > -- > 2.30.2 >