aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_inode.c10
-rw-r--r--fs/xfs/xfs_trans_resv.c19
2 files changed, 26 insertions, 3 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index ac133ea91c4b..b08b5a84cf0a 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -61,6 +61,8 @@ kmem_zone_t *xfs_inode_zone;
61 61
62STATIC int xfs_iflush_int(xfs_inode_t *, xfs_buf_t *); 62STATIC int xfs_iflush_int(xfs_inode_t *, xfs_buf_t *);
63 63
64STATIC int xfs_iunlink_remove(xfs_trans_t *, xfs_inode_t *);
65
64/* 66/*
65 * helper function to extract extent size hint from inode 67 * helper function to extract extent size hint from inode
66 */ 68 */
@@ -1118,7 +1120,7 @@ xfs_bumplink(
1118{ 1120{
1119 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); 1121 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
1120 1122
1121 ASSERT(ip->i_d.di_nlink > 0); 1123 ASSERT(ip->i_d.di_nlink > 0 || (VFS_I(ip)->i_state & I_LINKABLE));
1122 ip->i_d.di_nlink++; 1124 ip->i_d.di_nlink++;
1123 inc_nlink(VFS_I(ip)); 1125 inc_nlink(VFS_I(ip));
1124 if ((ip->i_d.di_version == 1) && 1126 if ((ip->i_d.di_version == 1) &&
@@ -1504,6 +1506,12 @@ xfs_link(
1504 1506
1505 xfs_bmap_init(&free_list, &first_block); 1507 xfs_bmap_init(&free_list, &first_block);
1506 1508
1509 if (sip->i_d.di_nlink == 0) {
1510 error = xfs_iunlink_remove(tp, sip);
1511 if (error)
1512 goto abort_return;
1513 }
1514
1507 error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino, 1515 error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino,
1508 &first_block, &free_list, resblks); 1516 &first_block, &free_list, resblks);
1509 if (error) 1517 if (error)
diff --git a/fs/xfs/xfs_trans_resv.c b/fs/xfs/xfs_trans_resv.c
index bd3b4b7831b7..76f9a02bc36b 100644
--- a/fs/xfs/xfs_trans_resv.c
+++ b/fs/xfs/xfs_trans_resv.c
@@ -204,6 +204,20 @@ xfs_calc_rename_reservation(
204} 204}
205 205
206/* 206/*
207 * For removing an inode from unlinked list at first, we can modify:
208 * the agi hash list and counters: sector size
209 * the on disk inode before ours in the agi hash list: inode cluster size
210 */
211STATIC uint
212xfs_calc_iunlink_remove_reservation(
213 struct xfs_mount *mp)
214{
215 return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
216 MAX((__uint16_t)XFS_FSB_TO_B(mp, 1),
217 (__uint16_t)XFS_INODE_CLUSTER_SIZE(mp));
218}
219
220/*
207 * For creating a link to an inode: 221 * For creating a link to an inode:
208 * the parent directory inode: inode size 222 * the parent directory inode: inode size
209 * the linked inode: inode size 223 * the linked inode: inode size
@@ -220,6 +234,7 @@ xfs_calc_link_reservation(
220 struct xfs_mount *mp) 234 struct xfs_mount *mp)
221{ 235{
222 return XFS_DQUOT_LOGRES(mp) + 236 return XFS_DQUOT_LOGRES(mp) +
237 xfs_calc_iunlink_remove_reservation(mp) +
223 MAX((xfs_calc_inode_res(mp, 2) + 238 MAX((xfs_calc_inode_res(mp, 2) +
224 xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), 239 xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
225 XFS_FSB_TO_B(mp, 1))), 240 XFS_FSB_TO_B(mp, 1))),
@@ -410,9 +425,9 @@ xfs_calc_ifree_reservation(
410{ 425{
411 return XFS_DQUOT_LOGRES(mp) + 426 return XFS_DQUOT_LOGRES(mp) +
412 xfs_calc_inode_res(mp, 1) + 427 xfs_calc_inode_res(mp, 1) +
413 xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + 428 xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
414 xfs_calc_buf_res(1, XFS_FSB_TO_B(mp, 1)) + 429 xfs_calc_buf_res(1, XFS_FSB_TO_B(mp, 1)) +
415 max_t(uint, XFS_FSB_TO_B(mp, 1), XFS_INODE_CLUSTER_SIZE(mp)) + 430 xfs_calc_iunlink_remove_reservation(mp) +
416 xfs_calc_buf_res(1, 0) + 431 xfs_calc_buf_res(1, 0) +
417 xfs_calc_buf_res(2 + XFS_IALLOC_BLOCKS(mp) + 432 xfs_calc_buf_res(2 + XFS_IALLOC_BLOCKS(mp) +
418 mp->m_in_maxlevels, 0) + 433 mp->m_in_maxlevels, 0) +