|
20 | 20 | #include "xfs_trace.h" |
21 | 21 | #include "xfs_error.h" |
22 | 22 | #include "xfs_defer.h" |
| 23 | +#include "xfs_inode.h" |
23 | 24 |
|
24 | 25 | kmem_zone_t *xfs_trans_zone; |
25 | 26 |
|
@@ -1024,3 +1025,50 @@ xfs_trans_roll( |
1024 | 1025 | tres.tr_logflags = XFS_TRANS_PERM_LOG_RES; |
1025 | 1026 | return xfs_trans_reserve(*tpp, &tres, 0, 0); |
1026 | 1027 | } |
| 1028 | + |
| 1029 | +/* |
| 1030 | + * Allocate an transaction, lock and join the inode to it, and reserve quota. |
| 1031 | + * |
| 1032 | + * The caller must ensure that the on-disk dquots attached to this inode have |
| 1033 | + * already been allocated and initialized. The caller is responsible for |
| 1034 | + * releasing ILOCK_EXCL if a new transaction is returned. |
| 1035 | + */ |
| 1036 | +int |
| 1037 | +xfs_trans_alloc_inode( |
| 1038 | + struct xfs_inode *ip, |
| 1039 | + struct xfs_trans_res *resv, |
| 1040 | + unsigned int dblocks, |
| 1041 | + bool force, |
| 1042 | + struct xfs_trans **tpp) |
| 1043 | +{ |
| 1044 | + struct xfs_trans *tp; |
| 1045 | + struct xfs_mount *mp = ip->i_mount; |
| 1046 | + int error; |
| 1047 | + |
| 1048 | + error = xfs_trans_alloc(mp, resv, dblocks, 0, |
| 1049 | + force ? XFS_TRANS_RESERVE : 0, &tp); |
| 1050 | + if (error) |
| 1051 | + return error; |
| 1052 | + |
| 1053 | + xfs_ilock(ip, XFS_ILOCK_EXCL); |
| 1054 | + xfs_trans_ijoin(tp, ip, 0); |
| 1055 | + |
| 1056 | + error = xfs_qm_dqattach_locked(ip, false); |
| 1057 | + if (error) { |
| 1058 | + /* Caller should have allocated the dquots! */ |
| 1059 | + ASSERT(error != -ENOENT); |
| 1060 | + goto out_cancel; |
| 1061 | + } |
| 1062 | + |
| 1063 | + error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, 0, force); |
| 1064 | + if (error) |
| 1065 | + goto out_cancel; |
| 1066 | + |
| 1067 | + *tpp = tp; |
| 1068 | + return 0; |
| 1069 | + |
| 1070 | +out_cancel: |
| 1071 | + xfs_trans_cancel(tp); |
| 1072 | + xfs_iunlock(ip, XFS_ILOCK_EXCL); |
| 1073 | + return error; |
| 1074 | +} |
0 commit comments