From: Dave Chinner Date: Thu, 7 Jan 2021 20:59:17 +0000 (-0500) Subject: xfs: introduce xfs_dialloc_roll() X-Git-Tag: v5.11.0-rc0~17 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9543cb30362e14c6c0a4b57f816e970ee9003eae;p=thirdparty%2Fxfsprogs-dev.git xfs: introduce xfs_dialloc_roll() Source kernel commit: aececc9f8dec92a25c84a3378021636ce58d72dc Introduce a helper to make the on-disk inode allocation rolling logic clearer in preparation of the following cleanup. [sandeen: update xfsprogs struct xfs_trans to match] Reviewed-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Dave Chinner Signed-off-by: Gao Xiang Signed-off-by: Darrick J. Wong Signed-off-by: Eric Sandeen --- diff --git a/include/xfs_trans.h b/include/xfs_trans.h index f51e38afd..a2f188998 100644 --- a/include/xfs_trans.h +++ b/include/xfs_trans.h @@ -61,20 +61,21 @@ typedef struct xfs_qoff_logitem { #define XFS_DEFER_OPS_NR_BUFS 2 /* join up to two buffers */ typedef struct xfs_trans { - unsigned int t_log_res; /* amt of log space resvd */ - unsigned int t_log_count; /* count for perm log res */ - unsigned int t_blk_res; /* # of blocks resvd */ - unsigned int t_blk_res_used; /* # of resvd blocks used */ - unsigned int t_rtx_res; /* # of rt extents resvd */ - unsigned int t_rtx_res_used; /* # of resvd rt extents used */ - unsigned int t_flags; /* misc flags */ - xfs_fsblock_t t_firstblock; /* first block allocated */ - struct xfs_mount *t_mountp; /* ptr to fs mount struct */ - long t_icount_delta; /* superblock icount change */ - long t_ifree_delta; /* superblock ifree change */ - long t_fdblocks_delta; /* superblock fdblocks chg */ - long t_frextents_delta; /* superblock freextents chg */ - struct list_head t_items; /* first log item desc chunk */ + unsigned int t_log_res; /* amt of log space resvd */ + unsigned int t_log_count; /* count for perm log res */ + unsigned int t_blk_res; /* # of blocks resvd */ + unsigned int t_blk_res_used; /* # of resvd blocks used */ + unsigned int t_rtx_res; /* # of rt extents resvd */ + unsigned int t_rtx_res_used; /* # of resvd rt extents used */ + unsigned int t_flags; /* misc flags */ + xfs_fsblock_t t_firstblock; /* first block allocated */ + struct xfs_mount *t_mountp; /* ptr to fs mount struct */ + struct xfs_dquot_acct *t_dqinfo; /* acctg info for dquots */ + long t_icount_delta; /* superblock icount change */ + long t_ifree_delta; /* superblock ifree change */ + long t_fdblocks_delta;/* superblock fdblocks chg */ + long t_frextents_delta;/* superblock freextents chg*/ + struct list_head t_items; /* log item descriptors */ struct list_head t_dfops; /* deferred operations */ } xfs_trans_t; diff --git a/libxfs/util.c b/libxfs/util.c index 376c5dac4..a79b650ae 100644 --- a/libxfs/util.c +++ b/libxfs/util.c @@ -560,16 +560,12 @@ libxfs_dir_ialloc( } if (ialloc_context) { - - xfs_trans_bhold(tp, ialloc_context); - - code = xfs_trans_roll(&tp); + code = xfs_dialloc_roll(&tp, ialloc_context); if (code) { fprintf(stderr, _("%s: cannot duplicate transaction: %s\n"), progname, strerror(code)); exit(1); } - xfs_trans_bjoin(tp, ialloc_context); code = libxfs_ialloc(tp, dp, mode, nlink, rdev, cr, fsx, &ialloc_context, &ip); if (!ip) diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c index 6b13f91dc..fcd4529b6 100644 --- a/libxfs/xfs_ialloc.c +++ b/libxfs/xfs_ialloc.c @@ -1677,6 +1677,41 @@ error_cur: return error; } +int +xfs_dialloc_roll( + struct xfs_trans **tpp, + struct xfs_buf *agibp) +{ + struct xfs_trans *tp = *tpp; + struct xfs_dquot_acct *dqinfo; + int error; + + /* + * Hold to on to the agibp across the commit so no other allocation can + * come in and take the free inodes we just allocated for our caller. + */ + xfs_trans_bhold(tp, agibp); + + /* + * We want the quota changes to be associated with the next transaction, + * NOT this one. So, detach the dqinfo from this and attach it to the + * next transaction. + */ + dqinfo = tp->t_dqinfo; + tp->t_dqinfo = NULL; + + error = xfs_trans_roll(&tp); + + /* Re-attach the quota info that we detached from prev trx. */ + tp->t_dqinfo = dqinfo; + + *tpp = tp; + if (error) + return error; + xfs_trans_bjoin(tp, agibp); + return 0; +} + /* * Allocate an inode on disk. * diff --git a/libxfs/xfs_ialloc.h b/libxfs/xfs_ialloc.h index 72b3468b9..bd6e0db9e 100644 --- a/libxfs/xfs_ialloc.h +++ b/libxfs/xfs_ialloc.h @@ -32,6 +32,11 @@ xfs_make_iptr(struct xfs_mount *mp, struct xfs_buf *b, int o) return xfs_buf_offset(b, o << (mp)->m_sb.sb_inodelog); } +int +xfs_dialloc_roll( + struct xfs_trans **tpp, + struct xfs_buf *agibp); + /* * Allocate an inode on disk. * Mode is used to tell whether the new inode will need space, and whether