int libxfs_trans_alloc(struct xfs_mount *mp, struct xfs_trans_res *resp,
uint blocks, uint rtextents, uint flags,
struct xfs_trans **tpp);
+int libxfs_trans_alloc_inode(struct xfs_inode *ip, struct xfs_trans_res *resv,
+ unsigned int dblocks, bool force, struct xfs_trans **tpp);
int libxfs_trans_alloc_rollable(struct xfs_mount *mp, uint blocks,
struct xfs_trans **tpp);
int libxfs_trans_alloc_empty(struct xfs_mount *mp, struct xfs_trans **tpp);
#define xfs_trans_add_item libxfs_trans_add_item
#define xfs_trans_alloc_empty libxfs_trans_alloc_empty
#define xfs_trans_alloc libxfs_trans_alloc
+#define xfs_trans_alloc_inode libxfs_trans_alloc_inode
#define xfs_trans_bhold libxfs_trans_bhold
#define xfs_trans_bhold_release libxfs_trans_bhold_release
#define xfs_trans_binval libxfs_trans_binval
{
return __xfs_trans_commit(tp, false);
}
+
+/*
+ * Allocate an transaction, lock and join the inode to it, and reserve quota.
+ *
+ * The caller must ensure that the on-disk dquots attached to this inode have
+ * already been allocated and initialized. The caller is responsible for
+ * releasing ILOCK_EXCL if a new transaction is returned.
+ */
+int
+libxfs_trans_alloc_inode(
+ struct xfs_inode *ip,
+ struct xfs_trans_res *resv,
+ unsigned int dblocks,
+ bool force,
+ struct xfs_trans **tpp)
+{
+ struct xfs_trans *tp;
+ struct xfs_mount *mp = ip->i_mount;
+ int error;
+
+ error = libxfs_trans_alloc(mp, resv, dblocks, 0,
+ force ? XFS_TRANS_RESERVE : 0, &tp);
+ if (error)
+ return error;
+
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ xfs_trans_ijoin(tp, ip, 0);
+
+ *tpp = tp;
+ return 0;
+}
* Root fork attributes can use reserved data blocks for this
* operation if necessary
*/
- error = xfs_trans_alloc(mp, &tres, total, 0,
- rsvd ? XFS_TRANS_RESERVE : 0, &args->trans);
+ error = xfs_trans_alloc_inode(dp, &tres, total, rsvd, &args->trans);
if (error)
return error;
- xfs_ilock(dp, XFS_ILOCK_EXCL);
- xfs_trans_ijoin(args->trans, dp, 0);
-
if (args->value || xfs_inode_hasattr(dp)) {
error = xfs_iext_count_may_overflow(dp, XFS_ATTR_FORK,
XFS_IEXT_ATTR_MANIP_CNT(rmt_blks));
}
if (args->value) {
- error = xfs_trans_reserve_quota_nblks(args->trans, dp,
- args->total, 0, rsvd);
- if (error)
- goto out_trans_cancel;
-
error = xfs_has_attr(args);
if (error == -EEXIST && (args->attr_flags & XATTR_CREATE))
goto out_trans_cancel;
blks = XFS_ADDAFORK_SPACE_RES(mp);
- error = xfs_trans_alloc(mp, &M_RES(mp)->tr_addafork, blks, 0,
- rsvd ? XFS_TRANS_RESERVE : 0, &tp);
+ error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_addafork, blks,
+ rsvd, &tp);
if (error)
return error;
-
- xfs_ilock(ip, XFS_ILOCK_EXCL);
- error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd);
- if (error)
- goto trans_cancel;
if (XFS_IFORK_Q(ip))
goto trans_cancel;
- xfs_trans_ijoin(tp, ip, 0);
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
error = xfs_bmap_set_attrforkoff(ip, size, &version);
if (error)