diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2020-02-19 17:02:33 -0800 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2020-06-01 21:16:41 -0700 |
commit | 333a73f8962f3f96898fc8d14a247ea86a78c68e (patch) | |
tree | 7b7bd9dec2cf7d3567d869bb2ac2c819034cd9db /fs/xfs/xfs_inode.c | |
parent | 18124ee9cc649d6b6db6cee5cf856087991454c9 (diff) |
xfs: refactor special inode roll out of xfs_dir_ialloc
In xfs_dir_ialloc, we roll the transaction if we had to allocate a new
inode chunk and before we actually initialize the inode. In the kernel
this requires us to detach the transaction's quota charge information
from the ichunk allocation transaction and to attach it the ialloc
transaction because we don't charge quota for inode chunks. This
doesn't exist in the userspace side of things, so pop it out into a
separately called function.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'fs/xfs/xfs_inode.c')
-rw-r--r-- | fs/xfs/xfs_inode.c | 65 |
1 files changed, 39 insertions, 26 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 87067dbc4a68..d0ac169f1a4d 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -633,6 +633,44 @@ xfs_ialloc_iget( } /* + * Roll the transaction after allocating an inode chunk and before allocating + * the actual inode, moving the quota charge information to the second + * transaction. + */ +int +xfs_dir_ialloc_roll( + struct xfs_trans **tpp) +{ + struct xfs_dquot_acct *dqinfo = NULL; + unsigned int tflags = 0; + int error; + + /* + * 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. + */ + if ((*tpp)->t_dqinfo) { + dqinfo = (*tpp)->t_dqinfo; + (*tpp)->t_dqinfo = NULL; + tflags = (*tpp)->t_flags & XFS_TRANS_DQ_DIRTY; + (*tpp)->t_flags &= ~(XFS_TRANS_DQ_DIRTY); + } + + error = xfs_trans_roll(tpp); + + /* + * Re-attach the quota info that we detached from prev trx. + */ + if (dqinfo) { + (*tpp)->t_dqinfo = dqinfo; + (*tpp)->t_flags |= tflags; + } + + return error; +} + +/* * Allocates a new inode from disk and return a pointer to the * incore copy. This routine will internally commit the current * transaction and allocate a new one if the Space Manager needed @@ -651,8 +689,6 @@ xfs_dir_ialloc( struct xfs_trans *tp; struct xfs_inode *ip; struct xfs_buf *ialloc_context = NULL; - void *dqinfo; - uint tflags; int code; tp = *tpp; @@ -705,30 +741,7 @@ xfs_dir_ialloc( */ xfs_trans_bhold(tp, ialloc_context); - /* - * 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 = NULL; - tflags = 0; - if (tp->t_dqinfo) { - dqinfo = (void *)tp->t_dqinfo; - tp->t_dqinfo = NULL; - tflags = tp->t_flags & XFS_TRANS_DQ_DIRTY; - tp->t_flags &= ~(XFS_TRANS_DQ_DIRTY); - } - - code = xfs_trans_roll(&tp); - - /* - * Re-attach the quota info that we detached from prev trx. - */ - if (dqinfo) { - tp->t_dqinfo = dqinfo; - tp->t_flags |= tflags; - } - + code = xfs_dir_ialloc_roll(&tp); if (code) { xfs_buf_relse(ialloc_context); *tpp = tp; |