diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/xfs_inode.c | 10 | ||||
-rw-r--r-- | fs/xfs/xfs_trans_resv.c | 19 |
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 | ||
62 | STATIC int xfs_iflush_int(xfs_inode_t *, xfs_buf_t *); | 62 | STATIC int xfs_iflush_int(xfs_inode_t *, xfs_buf_t *); |
63 | 63 | ||
64 | STATIC 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 | */ | ||
211 | STATIC uint | ||
212 | xfs_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) + |