Skip to content

Commit f2f7b9f

Browse files
author
Darrick J. Wong
committed
xfs: refactor inode creation transaction/inode/quota allocation idiom
For file creation, create a new helper xfs_trans_alloc_icreate that allocates a transaction and reserves the appropriate amount of quota against that transction. Replace all the open-coded idioms with a single call to this helper so that we can contain the retry loops in the next patchset. This changes the locking behavior for non-tempfile creation slightly, in that we now make the quota reservation without holding the directory ILOCK. While the dquots chosen for inode creation are based on the directory state at a given point in time, the directory ILOCK was released as soon as the dquot references are picked up. Hence it was never necessary to hold the directory ILOCK for the quota reservation. Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Brian Foster <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>
1 parent f273387 commit f2f7b9f

File tree

4 files changed

+53
-28
lines changed

4 files changed

+53
-28
lines changed

fs/xfs/xfs_inode.c

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,25 +1022,20 @@ xfs_create(
10221022
* the case we'll drop the one we have and get a more
10231023
* appropriate transaction later.
10241024
*/
1025-
error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp);
1025+
error = xfs_trans_alloc_icreate(mp, tres, udqp, gdqp, pdqp, resblks,
1026+
&tp);
10261027
if (error == -ENOSPC) {
10271028
/* flush outstanding delalloc blocks and retry */
10281029
xfs_flush_inodes(mp);
1029-
error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp);
1030+
error = xfs_trans_alloc_icreate(mp, tres, udqp, gdqp, pdqp,
1031+
resblks, &tp);
10301032
}
10311033
if (error)
1032-
goto out_release_inode;
1034+
goto out_release_dquots;
10331035

10341036
xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
10351037
unlock_dp_on_error = true;
10361038

1037-
/*
1038-
* Reserve disk quota and the inode.
1039-
*/
1040-
error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, resblks);
1041-
if (error)
1042-
goto out_trans_cancel;
1043-
10441039
error = xfs_iext_count_may_overflow(dp, XFS_DATA_FORK,
10451040
XFS_IEXT_DIR_MANIP_CNT(mp));
10461041
if (error)
@@ -1120,7 +1115,7 @@ xfs_create(
11201115
xfs_finish_inode_setup(ip);
11211116
xfs_irele(ip);
11221117
}
1123-
1118+
out_release_dquots:
11241119
xfs_qm_dqrele(udqp);
11251120
xfs_qm_dqrele(gdqp);
11261121
xfs_qm_dqrele(pdqp);
@@ -1164,13 +1159,10 @@ xfs_create_tmpfile(
11641159
resblks = XFS_IALLOC_SPACE_RES(mp);
11651160
tres = &M_RES(mp)->tr_create_tmpfile;
11661161

1167-
error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp);
1168-
if (error)
1169-
goto out_release_inode;
1170-
1171-
error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, resblks);
1162+
error = xfs_trans_alloc_icreate(mp, tres, udqp, gdqp, pdqp, resblks,
1163+
&tp);
11721164
if (error)
1173-
goto out_trans_cancel;
1165+
goto out_release_dquots;
11741166

11751167
error = xfs_dir_ialloc(&tp, dp, mode, 0, 0, prid, &ip);
11761168
if (error)
@@ -1213,7 +1205,7 @@ xfs_create_tmpfile(
12131205
xfs_finish_inode_setup(ip);
12141206
xfs_irele(ip);
12151207
}
1216-
1208+
out_release_dquots:
12171209
xfs_qm_dqrele(udqp);
12181210
xfs_qm_dqrele(gdqp);
12191211
xfs_qm_dqrele(pdqp);

fs/xfs/xfs_symlink.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,10 @@ xfs_symlink(
197197
fs_blocks = xfs_symlink_blocks(mp, pathlen);
198198
resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
199199

200-
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_symlink, resblks, 0, 0, &tp);
200+
error = xfs_trans_alloc_icreate(mp, &M_RES(mp)->tr_symlink, udqp, gdqp,
201+
pdqp, resblks, &tp);
201202
if (error)
202-
goto out_release_inode;
203+
goto out_release_dquots;
203204

204205
xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
205206
unlock_dp_on_error = true;
@@ -212,13 +213,6 @@ xfs_symlink(
212213
goto out_trans_cancel;
213214
}
214215

215-
/*
216-
* Reserve disk quota : blocks and inode.
217-
*/
218-
error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, resblks);
219-
if (error)
220-
goto out_trans_cancel;
221-
222216
error = xfs_iext_count_may_overflow(dp, XFS_DATA_FORK,
223217
XFS_IEXT_DIR_MANIP_CNT(mp));
224218
if (error)
@@ -347,7 +341,7 @@ xfs_symlink(
347341
xfs_finish_inode_setup(ip);
348342
xfs_irele(ip);
349343
}
350-
344+
out_release_dquots:
351345
xfs_qm_dqrele(udqp);
352346
xfs_qm_dqrele(gdqp);
353347
xfs_qm_dqrele(pdqp);

fs/xfs/xfs_trans.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "xfs_error.h"
2222
#include "xfs_defer.h"
2323
#include "xfs_inode.h"
24+
#include "xfs_dquot_item.h"
25+
#include "xfs_dquot.h"
2426

2527
kmem_zone_t *xfs_trans_zone;
2628

@@ -1074,3 +1076,34 @@ xfs_trans_alloc_inode(
10741076
xfs_iunlock(ip, XFS_ILOCK_EXCL);
10751077
return error;
10761078
}
1079+
1080+
/*
1081+
* Allocate an transaction in preparation for inode creation by reserving quota
1082+
* against the given dquots. Callers are not required to hold any inode locks.
1083+
*/
1084+
int
1085+
xfs_trans_alloc_icreate(
1086+
struct xfs_mount *mp,
1087+
struct xfs_trans_res *resv,
1088+
struct xfs_dquot *udqp,
1089+
struct xfs_dquot *gdqp,
1090+
struct xfs_dquot *pdqp,
1091+
unsigned int dblocks,
1092+
struct xfs_trans **tpp)
1093+
{
1094+
struct xfs_trans *tp;
1095+
int error;
1096+
1097+
error = xfs_trans_alloc(mp, resv, dblocks, 0, 0, &tp);
1098+
if (error)
1099+
return error;
1100+
1101+
error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, dblocks);
1102+
if (error) {
1103+
xfs_trans_cancel(tp);
1104+
return error;
1105+
}
1106+
1107+
*tpp = tp;
1108+
return 0;
1109+
}

fs/xfs/xfs_trans.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,14 @@ xfs_trans_item_relog(
268268
return lip->li_ops->iop_relog(lip, tp);
269269
}
270270

271+
struct xfs_dquot;
272+
271273
int xfs_trans_alloc_inode(struct xfs_inode *ip, struct xfs_trans_res *resv,
272274
unsigned int dblocks, unsigned int rblocks, bool force,
273275
struct xfs_trans **tpp);
276+
int xfs_trans_alloc_icreate(struct xfs_mount *mp, struct xfs_trans_res *resv,
277+
struct xfs_dquot *udqp, struct xfs_dquot *gdqp,
278+
struct xfs_dquot *pdqp, unsigned int dblocks,
279+
struct xfs_trans **tpp);
274280

275281
#endif /* __XFS_TRANS_H__ */

0 commit comments

Comments
 (0)