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 /fs/xfs/xfs_inode.c | |
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
Diffstat (limited to 'fs/xfs/xfs_inode.c')
-rw-r--r-- | fs/xfs/xfs_inode.c | 123 |
1 files changed, 117 insertions, 6 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) |