#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;
}
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)
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.
*
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