diff options
| author | Dave Chinner <david@fromorbit.com> | 2014-03-13 04:14:43 -0400 |
|---|---|---|
| committer | Dave Chinner <david@fromorbit.com> | 2014-03-13 04:14:43 -0400 |
| commit | fe986f9d88ab8079c91669b7f175081f15491a80 (patch) | |
| tree | 73be54e2c5378750dee0ebc0720af5143d2c4dc6 | |
| parent | 5f44e4c185ec5a4a438841cbd4983d0c4a106a4a (diff) | |
| parent | ab29743117f9f4c22ac44c13c1647fb24fb2bafe (diff) | |
Merge branch 'xfs-O_TMPFILE-support' into for-next
Conflicts:
fs/xfs/xfs_trans_resv.c
- fix for XFS_INODE_CLUSTER_SIZE macro removal
| -rw-r--r-- | fs/xfs/xfs_inode.c | 123 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.h | 12 | ||||
| -rw-r--r-- | fs/xfs/xfs_iops.c | 16 | ||||
| -rw-r--r-- | fs/xfs/xfs_shared.h | 4 | ||||
| -rw-r--r-- | fs/xfs/xfs_symlink.c | 5 | ||||
| -rw-r--r-- | fs/xfs/xfs_trans_resv.c | 54 | ||||
| -rw-r--r-- | fs/xfs/xfs_trans_resv.h | 2 |
7 files changed, 201 insertions, 15 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 3a137e9f9a7d..5e7a38fa6ee6 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
| @@ -42,7 +42,6 @@ | |||
| 42 | #include "xfs_bmap_util.h" | 42 | #include "xfs_bmap_util.h" |
| 43 | #include "xfs_error.h" | 43 | #include "xfs_error.h" |
| 44 | #include "xfs_quota.h" | 44 | #include "xfs_quota.h" |
| 45 | #include "xfs_dinode.h" | ||
| 46 | #include "xfs_filestream.h" | 45 | #include "xfs_filestream.h" |
| 47 | #include "xfs_cksum.h" | 46 | #include "xfs_cksum.h" |
| 48 | #include "xfs_trace.h" | 47 | #include "xfs_trace.h" |
| @@ -62,6 +61,8 @@ kmem_zone_t *xfs_inode_zone; | |||
| 62 | 61 | ||
| 63 | STATIC int xfs_iflush_int(xfs_inode_t *, xfs_buf_t *); | 62 | STATIC int xfs_iflush_int(xfs_inode_t *, xfs_buf_t *); |
| 64 | 63 | ||
| 64 | STATIC int xfs_iunlink_remove(xfs_trans_t *, xfs_inode_t *); | ||
| 65 | |||
| 65 | /* | 66 | /* |
| 66 | * helper function to extract extent size hint from inode | 67 | * helper function to extract extent size hint from inode |
| 67 | */ | 68 | */ |
| @@ -1115,7 +1116,7 @@ xfs_bumplink( | |||
| 1115 | { | 1116 | { |
| 1116 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); | 1117 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); |
| 1117 | 1118 | ||
| 1118 | ASSERT(ip->i_d.di_nlink > 0); | 1119 | ASSERT(ip->i_d.di_nlink > 0 || (VFS_I(ip)->i_state & I_LINKABLE)); |
| 1119 | ip->i_d.di_nlink++; | 1120 | ip->i_d.di_nlink++; |
| 1120 | inc_nlink(VFS_I(ip)); | 1121 | inc_nlink(VFS_I(ip)); |
| 1121 | if ((ip->i_d.di_version == 1) && | 1122 | if ((ip->i_d.di_version == 1) && |
| @@ -1165,10 +1166,7 @@ xfs_create( | |||
| 1165 | if (XFS_FORCED_SHUTDOWN(mp)) | 1166 | if (XFS_FORCED_SHUTDOWN(mp)) |
| 1166 | return XFS_ERROR(EIO); | 1167 | return XFS_ERROR(EIO); |
| 1167 | 1168 | ||
| 1168 | if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) | 1169 | prid = xfs_get_initial_prid(dp); |
| 1169 | prid = xfs_get_projid(dp); | ||
| 1170 | else | ||
| 1171 | prid = XFS_PROJID_DEFAULT; | ||
| 1172 | 1170 | ||
| 1173 | /* | 1171 | /* |
| 1174 | * Make sure that we have allocated dquot(s) on disk. | 1172 | * Make sure that we have allocated dquot(s) on disk. |
| @@ -1333,6 +1331,113 @@ xfs_create( | |||
| 1333 | } | 1331 | } |
| 1334 | 1332 | ||
| 1335 | int | 1333 | int |
| 1334 | xfs_create_tmpfile( | ||
| 1335 | struct xfs_inode *dp, | ||
| 1336 | struct dentry *dentry, | ||
| 1337 | umode_t mode) | ||
| 1338 | { | ||
| 1339 | struct xfs_mount *mp = dp->i_mount; | ||
| 1340 | struct xfs_inode *ip = NULL; | ||
| 1341 | struct xfs_trans *tp = NULL; | ||
| 1342 | int error; | ||
| 1343 | uint cancel_flags = XFS_TRANS_RELEASE_LOG_RES; | ||
| 1344 | prid_t prid; | ||
| 1345 | struct xfs_dquot *udqp = NULL; | ||
| 1346 | struct xfs_dquot *gdqp = NULL; | ||
| 1347 | struct xfs_dquot *pdqp = NULL; | ||
| 1348 | struct xfs_trans_res *tres; | ||
| 1349 | uint resblks; | ||
| 1350 | |||
| 1351 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
| 1352 | return XFS_ERROR(EIO); | ||
| 1353 | |||
| 1354 | prid = xfs_get_initial_prid(dp); | ||
| 1355 | |||
| 1356 | /* | ||
| 1357 | * Make sure that we have allocated dquot(s) on disk. | ||
| 1358 | */ | ||
| 1359 | error = xfs_qm_vop_dqalloc(dp, xfs_kuid_to_uid(current_fsuid()), | ||
| 1360 | xfs_kgid_to_gid(current_fsgid()), prid, | ||
| 1361 | XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, | ||
| 1362 | &udqp, &gdqp, &pdqp); | ||
| 1363 | if (error) | ||
| 1364 | return error; | ||
| 1365 | |||
| 1366 | resblks = XFS_IALLOC_SPACE_RES(mp); | ||
| 1367 | tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE_TMPFILE); | ||
| 1368 | |||
| 1369 | tres = &M_RES(mp)->tr_create_tmpfile; | ||
| 1370 | error = xfs_trans_reserve(tp, tres, resblks, 0); | ||
| 1371 | if (error == ENOSPC) { | ||
| 1372 | /* No space at all so try a "no-allocation" reservation */ | ||
| 1373 | resblks = 0; | ||
| 1374 | error = xfs_trans_reserve(tp, tres, 0, 0); | ||
| 1375 | } | ||
| 1376 | if (error) { | ||
| 1377 | cancel_flags = 0; | ||
| 1378 | goto out_trans_cancel; | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, | ||
| 1382 | pdqp, resblks, 1, 0); | ||
| 1383 | if (error) | ||
| 1384 | goto out_trans_cancel; | ||
| 1385 | |||
| 1386 | error = xfs_dir_ialloc(&tp, dp, mode, 1, 0, | ||
| 1387 | prid, resblks > 0, &ip, NULL); | ||
| 1388 | if (error) { | ||
| 1389 | if (error == ENOSPC) | ||
| 1390 | goto out_trans_cancel; | ||
| 1391 | goto out_trans_abort; | ||
| 1392 | } | ||
| 1393 | |||
| 1394 | if (mp->m_flags & XFS_MOUNT_WSYNC) | ||
| 1395 | xfs_trans_set_sync(tp); | ||
| 1396 | |||
| 1397 | /* | ||
| 1398 | * Attach the dquot(s) to the inodes and modify them incore. | ||
| 1399 | * These ids of the inode couldn't have changed since the new | ||
| 1400 | * inode has been locked ever since it was created. | ||
| 1401 | */ | ||
| 1402 | xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); | ||
| 1403 | |||
| 1404 | ip->i_d.di_nlink--; | ||
| 1405 | d_tmpfile(dentry, VFS_I(ip)); | ||
| 1406 | error = xfs_iunlink(tp, ip); | ||
| 1407 | if (error) | ||
| 1408 | goto out_trans_abort; | ||
| 1409 | |||
| 1410 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | ||
| 1411 | if (error) | ||
| 1412 | goto out_release_inode; | ||
| 1413 | |||
| 1414 | xfs_qm_dqrele(udqp); | ||
| 1415 | xfs_qm_dqrele(gdqp); | ||
| 1416 | xfs_qm_dqrele(pdqp); | ||
| 1417 | |||
| 1418 | return 0; | ||
| 1419 | |||
| 1420 | out_trans_abort: | ||
| 1421 | cancel_flags |= XFS_TRANS_ABORT; | ||
| 1422 | out_trans_cancel: | ||
| 1423 | xfs_trans_cancel(tp, cancel_flags); | ||
| 1424 | out_release_inode: | ||
| 1425 | /* | ||
| 1426 | * Wait until after the current transaction is aborted to | ||
| 1427 | * release the inode. This prevents recursive transactions | ||
| 1428 | * and deadlocks from xfs_inactive. | ||
| 1429 | */ | ||
| 1430 | if (ip) | ||
| 1431 | IRELE(ip); | ||
| 1432 | |||
| 1433 | xfs_qm_dqrele(udqp); | ||
| 1434 | xfs_qm_dqrele(gdqp); | ||
| 1435 | xfs_qm_dqrele(pdqp); | ||
| 1436 | |||
| 1437 | return error; | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | int | ||
| 1336 | xfs_link( | 1441 | xfs_link( |
| 1337 | xfs_inode_t *tdp, | 1442 | xfs_inode_t *tdp, |
| 1338 | xfs_inode_t *sip, | 1443 | xfs_inode_t *sip, |
| @@ -1397,6 +1502,12 @@ xfs_link( | |||
| 1397 | 1502 | ||
| 1398 | xfs_bmap_init(&free_list, &first_block); | 1503 | xfs_bmap_init(&free_list, &first_block); |
| 1399 | 1504 | ||
| 1505 | if (sip->i_d.di_nlink == 0) { | ||
| 1506 | error = xfs_iunlink_remove(tp, sip); | ||
| 1507 | if (error) | ||
| 1508 | goto abort_return; | ||
| 1509 | } | ||
| 1510 | |||
| 1400 | error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino, | 1511 | error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino, |
| 1401 | &first_block, &free_list, resblks); | 1512 | &first_block, &free_list, resblks); |
| 1402 | if (error) | 1513 | if (error) |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 65e2350f449c..396cc1fafd0d 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | #include "xfs_inode_buf.h" | 21 | #include "xfs_inode_buf.h" |
| 22 | #include "xfs_inode_fork.h" | 22 | #include "xfs_inode_fork.h" |
| 23 | #include "xfs_dinode.h" | ||
| 23 | 24 | ||
| 24 | /* | 25 | /* |
| 25 | * Kernel only inode definitions | 26 | * Kernel only inode definitions |
| @@ -192,6 +193,15 @@ xfs_set_projid(struct xfs_inode *ip, | |||
| 192 | ip->i_d.di_projid_lo = (__uint16_t) (projid & 0xffff); | 193 | ip->i_d.di_projid_lo = (__uint16_t) (projid & 0xffff); |
| 193 | } | 194 | } |
| 194 | 195 | ||
| 196 | static inline prid_t | ||
| 197 | xfs_get_initial_prid(struct xfs_inode *dp) | ||
| 198 | { | ||
| 199 | if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) | ||
| 200 | return xfs_get_projid(dp); | ||
| 201 | |||
| 202 | return XFS_PROJID_DEFAULT; | ||
| 203 | } | ||
| 204 | |||
| 195 | /* | 205 | /* |
| 196 | * In-core inode flags. | 206 | * In-core inode flags. |
| 197 | */ | 207 | */ |
| @@ -323,6 +333,8 @@ int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name, | |||
| 323 | struct xfs_inode **ipp, struct xfs_name *ci_name); | 333 | struct xfs_inode **ipp, struct xfs_name *ci_name); |
| 324 | int xfs_create(struct xfs_inode *dp, struct xfs_name *name, | 334 | int xfs_create(struct xfs_inode *dp, struct xfs_name *name, |
| 325 | umode_t mode, xfs_dev_t rdev, struct xfs_inode **ipp); | 335 | umode_t mode, xfs_dev_t rdev, struct xfs_inode **ipp); |
| 336 | int xfs_create_tmpfile(struct xfs_inode *dp, struct dentry *dentry, | ||
| 337 | umode_t mode); | ||
| 326 | int xfs_remove(struct xfs_inode *dp, struct xfs_name *name, | 338 | int xfs_remove(struct xfs_inode *dp, struct xfs_name *name, |
| 327 | struct xfs_inode *ip); | 339 | struct xfs_inode *ip); |
| 328 | int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip, | 340 | int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip, |
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index bb3bb658e39c..89b07e43ca28 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include "xfs_da_btree.h" | 39 | #include "xfs_da_btree.h" |
| 40 | #include "xfs_dir2_priv.h" | 40 | #include "xfs_dir2_priv.h" |
| 41 | #include "xfs_dinode.h" | 41 | #include "xfs_dinode.h" |
| 42 | #include "xfs_trans_space.h" | ||
| 42 | 43 | ||
| 43 | #include <linux/capability.h> | 44 | #include <linux/capability.h> |
| 44 | #include <linux/xattr.h> | 45 | #include <linux/xattr.h> |
| @@ -1046,6 +1047,19 @@ xfs_vn_fiemap( | |||
| 1046 | return 0; | 1047 | return 0; |
| 1047 | } | 1048 | } |
| 1048 | 1049 | ||
| 1050 | STATIC int | ||
| 1051 | xfs_vn_tmpfile( | ||
| 1052 | struct inode *dir, | ||
| 1053 | struct dentry *dentry, | ||
| 1054 | umode_t mode) | ||
| 1055 | { | ||
| 1056 | int error; | ||
| 1057 | |||
| 1058 | error = xfs_create_tmpfile(XFS_I(dir), dentry, mode); | ||
| 1059 | |||
| 1060 | return -error; | ||
| 1061 | } | ||
| 1062 | |||
| 1049 | static const struct inode_operations xfs_inode_operations = { | 1063 | static const struct inode_operations xfs_inode_operations = { |
| 1050 | .get_acl = xfs_get_acl, | 1064 | .get_acl = xfs_get_acl, |
| 1051 | .set_acl = xfs_set_acl, | 1065 | .set_acl = xfs_set_acl, |
| @@ -1084,6 +1098,7 @@ static const struct inode_operations xfs_dir_inode_operations = { | |||
| 1084 | .removexattr = generic_removexattr, | 1098 | .removexattr = generic_removexattr, |
| 1085 | .listxattr = xfs_vn_listxattr, | 1099 | .listxattr = xfs_vn_listxattr, |
| 1086 | .update_time = xfs_vn_update_time, | 1100 | .update_time = xfs_vn_update_time, |
| 1101 | .tmpfile = xfs_vn_tmpfile, | ||
| 1087 | }; | 1102 | }; |
| 1088 | 1103 | ||
| 1089 | static const struct inode_operations xfs_dir_ci_inode_operations = { | 1104 | static const struct inode_operations xfs_dir_ci_inode_operations = { |
| @@ -1111,6 +1126,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = { | |||
| 1111 | .removexattr = generic_removexattr, | 1126 | .removexattr = generic_removexattr, |
| 1112 | .listxattr = xfs_vn_listxattr, | 1127 | .listxattr = xfs_vn_listxattr, |
| 1113 | .update_time = xfs_vn_update_time, | 1128 | .update_time = xfs_vn_update_time, |
| 1129 | .tmpfile = xfs_vn_tmpfile, | ||
| 1114 | }; | 1130 | }; |
| 1115 | 1131 | ||
| 1116 | static const struct inode_operations xfs_symlink_inode_operations = { | 1132 | static const struct inode_operations xfs_symlink_inode_operations = { |
diff --git a/fs/xfs/xfs_shared.h b/fs/xfs/xfs_shared.h index 8c5035a13df1..4484e5151395 100644 --- a/fs/xfs/xfs_shared.h +++ b/fs/xfs/xfs_shared.h | |||
| @@ -104,7 +104,8 @@ extern const struct xfs_buf_ops xfs_symlink_buf_ops; | |||
| 104 | #define XFS_TRANS_SB_COUNT 41 | 104 | #define XFS_TRANS_SB_COUNT 41 |
| 105 | #define XFS_TRANS_CHECKPOINT 42 | 105 | #define XFS_TRANS_CHECKPOINT 42 |
| 106 | #define XFS_TRANS_ICREATE 43 | 106 | #define XFS_TRANS_ICREATE 43 |
| 107 | #define XFS_TRANS_TYPE_MAX 43 | 107 | #define XFS_TRANS_CREATE_TMPFILE 44 |
| 108 | #define XFS_TRANS_TYPE_MAX 44 | ||
| 108 | /* new transaction types need to be reflected in xfs_logprint(8) */ | 109 | /* new transaction types need to be reflected in xfs_logprint(8) */ |
| 109 | 110 | ||
| 110 | #define XFS_TRANS_TYPES \ | 111 | #define XFS_TRANS_TYPES \ |
| @@ -112,6 +113,7 @@ extern const struct xfs_buf_ops xfs_symlink_buf_ops; | |||
| 112 | { XFS_TRANS_SETATTR_SIZE, "SETATTR_SIZE" }, \ | 113 | { XFS_TRANS_SETATTR_SIZE, "SETATTR_SIZE" }, \ |
| 113 | { XFS_TRANS_INACTIVE, "INACTIVE" }, \ | 114 | { XFS_TRANS_INACTIVE, "INACTIVE" }, \ |
| 114 | { XFS_TRANS_CREATE, "CREATE" }, \ | 115 | { XFS_TRANS_CREATE, "CREATE" }, \ |
| 116 | { XFS_TRANS_CREATE_TMPFILE, "CREATE_TMPFILE" }, \ | ||
| 115 | { XFS_TRANS_CREATE_TRUNC, "CREATE_TRUNC" }, \ | 117 | { XFS_TRANS_CREATE_TRUNC, "CREATE_TRUNC" }, \ |
| 116 | { XFS_TRANS_TRUNCATE_FILE, "TRUNCATE_FILE" }, \ | 118 | { XFS_TRANS_TRUNCATE_FILE, "TRUNCATE_FILE" }, \ |
| 117 | { XFS_TRANS_REMOVE, "REMOVE" }, \ | 119 | { XFS_TRANS_REMOVE, "REMOVE" }, \ |
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index 5fda18919d3b..52979aa90986 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c | |||
| @@ -212,10 +212,7 @@ xfs_symlink( | |||
| 212 | return XFS_ERROR(ENAMETOOLONG); | 212 | return XFS_ERROR(ENAMETOOLONG); |
| 213 | 213 | ||
| 214 | udqp = gdqp = NULL; | 214 | udqp = gdqp = NULL; |
| 215 | if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) | 215 | prid = xfs_get_initial_prid(dp); |
| 216 | prid = xfs_get_projid(dp); | ||
| 217 | else | ||
| 218 | prid = XFS_PROJID_DEFAULT; | ||
| 219 | 216 | ||
| 220 | /* | 217 | /* |
| 221 | * Make sure that we have allocated dquot(s) on disk. | 218 | * Make sure that we have allocated dquot(s) on disk. |
diff --git a/fs/xfs/xfs_trans_resv.c b/fs/xfs/xfs_trans_resv.c index d2c8e4a6ee2a..ae368165244d 100644 --- a/fs/xfs/xfs_trans_resv.c +++ b/fs/xfs/xfs_trans_resv.c | |||
| @@ -212,6 +212,19 @@ xfs_calc_rename_reservation( | |||
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | /* | 214 | /* |
| 215 | * For removing an inode from unlinked list at first, we can modify: | ||
| 216 | * the agi hash list and counters: sector size | ||
| 217 | * the on disk inode before ours in the agi hash list: inode cluster size | ||
| 218 | */ | ||
| 219 | STATIC uint | ||
| 220 | xfs_calc_iunlink_remove_reservation( | ||
| 221 | struct xfs_mount *mp) | ||
| 222 | { | ||
| 223 | return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + | ||
| 224 | max_t(uint, XFS_FSB_TO_B(mp, 1), mp->m_inode_cluster_size); | ||
| 225 | } | ||
| 226 | |||
| 227 | /* | ||
| 215 | * For creating a link to an inode: | 228 | * For creating a link to an inode: |
| 216 | * the parent directory inode: inode size | 229 | * the parent directory inode: inode size |
| 217 | * the linked inode: inode size | 230 | * the linked inode: inode size |
| @@ -228,6 +241,7 @@ xfs_calc_link_reservation( | |||
| 228 | struct xfs_mount *mp) | 241 | struct xfs_mount *mp) |
| 229 | { | 242 | { |
| 230 | return XFS_DQUOT_LOGRES(mp) + | 243 | return XFS_DQUOT_LOGRES(mp) + |
| 244 | xfs_calc_iunlink_remove_reservation(mp) + | ||
| 231 | MAX((xfs_calc_inode_res(mp, 2) + | 245 | MAX((xfs_calc_inode_res(mp, 2) + |
| 232 | xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), | 246 | xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), |
| 233 | XFS_FSB_TO_B(mp, 1))), | 247 | XFS_FSB_TO_B(mp, 1))), |
| @@ -237,6 +251,18 @@ xfs_calc_link_reservation( | |||
| 237 | } | 251 | } |
| 238 | 252 | ||
| 239 | /* | 253 | /* |
| 254 | * For adding an inode to unlinked list we can modify: | ||
| 255 | * the agi hash list: sector size | ||
| 256 | * the unlinked inode: inode size | ||
| 257 | */ | ||
| 258 | STATIC uint | ||
| 259 | xfs_calc_iunlink_add_reservation(xfs_mount_t *mp) | ||
| 260 | { | ||
| 261 | return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + | ||
| 262 | xfs_calc_inode_res(mp, 1); | ||
| 263 | } | ||
| 264 | |||
| 265 | /* | ||
| 240 | * For removing a directory entry we can modify: | 266 | * For removing a directory entry we can modify: |
| 241 | * the parent directory inode: inode size | 267 | * the parent directory inode: inode size |
| 242 | * the removed inode: inode size | 268 | * the removed inode: inode size |
| @@ -253,10 +279,11 @@ xfs_calc_remove_reservation( | |||
| 253 | struct xfs_mount *mp) | 279 | struct xfs_mount *mp) |
| 254 | { | 280 | { |
| 255 | return XFS_DQUOT_LOGRES(mp) + | 281 | return XFS_DQUOT_LOGRES(mp) + |
| 256 | MAX((xfs_calc_inode_res(mp, 2) + | 282 | xfs_calc_iunlink_add_reservation(mp) + |
| 283 | MAX((xfs_calc_inode_res(mp, 1) + | ||
| 257 | xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), | 284 | xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), |
| 258 | XFS_FSB_TO_B(mp, 1))), | 285 | XFS_FSB_TO_B(mp, 1))), |
| 259 | (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) + | 286 | (xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) + |
| 260 | xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2), | 287 | xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2), |
| 261 | XFS_FSB_TO_B(mp, 1)))); | 288 | XFS_FSB_TO_B(mp, 1)))); |
| 262 | } | 289 | } |
| @@ -351,6 +378,20 @@ xfs_calc_create_reservation( | |||
| 351 | 378 | ||
| 352 | } | 379 | } |
| 353 | 380 | ||
| 381 | STATIC uint | ||
| 382 | xfs_calc_create_tmpfile_reservation( | ||
| 383 | struct xfs_mount *mp) | ||
| 384 | { | ||
| 385 | uint res = XFS_DQUOT_LOGRES(mp); | ||
| 386 | |||
| 387 | if (xfs_sb_version_hascrc(&mp->m_sb)) | ||
| 388 | res += xfs_calc_icreate_resv_alloc(mp); | ||
| 389 | else | ||
| 390 | res += xfs_calc_create_resv_alloc(mp); | ||
| 391 | |||
| 392 | return res + xfs_calc_iunlink_add_reservation(mp); | ||
| 393 | } | ||
| 394 | |||
| 354 | /* | 395 | /* |
| 355 | * Making a new directory is the same as creating a new file. | 396 | * Making a new directory is the same as creating a new file. |
| 356 | */ | 397 | */ |
| @@ -391,9 +432,9 @@ xfs_calc_ifree_reservation( | |||
| 391 | { | 432 | { |
| 392 | return XFS_DQUOT_LOGRES(mp) + | 433 | return XFS_DQUOT_LOGRES(mp) + |
| 393 | xfs_calc_inode_res(mp, 1) + | 434 | xfs_calc_inode_res(mp, 1) + |
| 394 | xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + | 435 | xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + |
| 395 | xfs_calc_buf_res(1, XFS_FSB_TO_B(mp, 1)) + | 436 | xfs_calc_buf_res(1, XFS_FSB_TO_B(mp, 1)) + |
| 396 | max_t(uint, XFS_FSB_TO_B(mp, 1), mp->m_inode_cluster_size) + | 437 | xfs_calc_iunlink_remove_reservation(mp) + |
| 397 | xfs_calc_buf_res(1, 0) + | 438 | xfs_calc_buf_res(1, 0) + |
| 398 | xfs_calc_buf_res(2 + mp->m_ialloc_blks + | 439 | xfs_calc_buf_res(2 + mp->m_ialloc_blks + |
| 399 | mp->m_in_maxlevels, 0) + | 440 | mp->m_in_maxlevels, 0) + |
| @@ -736,6 +777,11 @@ xfs_trans_resv_calc( | |||
| 736 | resp->tr_create.tr_logcount = XFS_CREATE_LOG_COUNT; | 777 | resp->tr_create.tr_logcount = XFS_CREATE_LOG_COUNT; |
| 737 | resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES; | 778 | resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES; |
| 738 | 779 | ||
| 780 | resp->tr_create_tmpfile.tr_logres = | ||
| 781 | xfs_calc_create_tmpfile_reservation(mp); | ||
| 782 | resp->tr_create_tmpfile.tr_logcount = XFS_CREATE_TMPFILE_LOG_COUNT; | ||
| 783 | resp->tr_create_tmpfile.tr_logflags |= XFS_TRANS_PERM_LOG_RES; | ||
| 784 | |||
| 739 | resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp); | 785 | resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp); |
| 740 | resp->tr_mkdir.tr_logcount = XFS_MKDIR_LOG_COUNT; | 786 | resp->tr_mkdir.tr_logcount = XFS_MKDIR_LOG_COUNT; |
| 741 | resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES; | 787 | resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES; |
diff --git a/fs/xfs/xfs_trans_resv.h b/fs/xfs/xfs_trans_resv.h index f76c1297b83f..1097d14cd583 100644 --- a/fs/xfs/xfs_trans_resv.h +++ b/fs/xfs/xfs_trans_resv.h | |||
| @@ -38,6 +38,7 @@ struct xfs_trans_resv { | |||
| 38 | struct xfs_trans_res tr_remove; /* unlink trans */ | 38 | struct xfs_trans_res tr_remove; /* unlink trans */ |
| 39 | struct xfs_trans_res tr_symlink; /* symlink trans */ | 39 | struct xfs_trans_res tr_symlink; /* symlink trans */ |
| 40 | struct xfs_trans_res tr_create; /* create trans */ | 40 | struct xfs_trans_res tr_create; /* create trans */ |
| 41 | struct xfs_trans_res tr_create_tmpfile; /* create O_TMPFILE trans */ | ||
| 41 | struct xfs_trans_res tr_mkdir; /* mkdir trans */ | 42 | struct xfs_trans_res tr_mkdir; /* mkdir trans */ |
| 42 | struct xfs_trans_res tr_ifree; /* inode free trans */ | 43 | struct xfs_trans_res tr_ifree; /* inode free trans */ |
| 43 | struct xfs_trans_res tr_ichange; /* inode update trans */ | 44 | struct xfs_trans_res tr_ichange; /* inode update trans */ |
| @@ -99,6 +100,7 @@ struct xfs_trans_resv { | |||
| 99 | #define XFS_ITRUNCATE_LOG_COUNT 2 | 100 | #define XFS_ITRUNCATE_LOG_COUNT 2 |
| 100 | #define XFS_INACTIVE_LOG_COUNT 2 | 101 | #define XFS_INACTIVE_LOG_COUNT 2 |
| 101 | #define XFS_CREATE_LOG_COUNT 2 | 102 | #define XFS_CREATE_LOG_COUNT 2 |
| 103 | #define XFS_CREATE_TMPFILE_LOG_COUNT 2 | ||
| 102 | #define XFS_MKDIR_LOG_COUNT 3 | 104 | #define XFS_MKDIR_LOG_COUNT 3 |
| 103 | #define XFS_SYMLINK_LOG_COUNT 3 | 105 | #define XFS_SYMLINK_LOG_COUNT 3 |
| 104 | #define XFS_REMOVE_LOG_COUNT 2 | 106 | #define XFS_REMOVE_LOG_COUNT 2 |
