diff options
author | Brian Foster <bfoster@redhat.com> | 2014-04-24 02:00:52 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2014-04-24 02:00:52 -0400 |
commit | 9d43b180af67cccd4bd1342f7f54f8131515b0a1 (patch) | |
tree | f4bb0ee658249dc78c5465a850e53add0384b236 | |
parent | aafc3c24652924ea951d215d04a3f42e832e9d7d (diff) |
xfs: update inode allocation/free transaction reservations for finobt
Create the xfs_calc_finobt_res() helper to calculate the finobt log
reservation for inode allocation and free. Update
XFS_IALLOC_SPACE_RES() to reserve blocks for the additional finobt
insertion on inode allocation. Create XFS_IFREE_SPACE_RES() to
reserve blocks for the potential finobt record insertion on inode
free (i.e., if an inode chunk was previously fully allocated).
Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r-- | fs/xfs/xfs_inode.c | 28 | ||||
-rw-r--r-- | fs/xfs/xfs_trans_resv.c | 53 | ||||
-rw-r--r-- | fs/xfs/xfs_trans_space.h | 7 |
3 files changed, 82 insertions, 6 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 5e7a38fa6ee6..a9079c142041 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -1837,9 +1837,33 @@ xfs_inactive_ifree( | |||
1837 | int error; | 1837 | int error; |
1838 | 1838 | ||
1839 | tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); | 1839 | tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); |
1840 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, 0, 0); | 1840 | |
1841 | /* | ||
1842 | * The ifree transaction might need to allocate blocks for record | ||
1843 | * insertion to the finobt. We don't want to fail here at ENOSPC, so | ||
1844 | * allow ifree to dip into the reserved block pool if necessary. | ||
1845 | * | ||
1846 | * Freeing large sets of inodes generally means freeing inode chunks, | ||
1847 | * directory and file data blocks, so this should be relatively safe. | ||
1848 | * Only under severe circumstances should it be possible to free enough | ||
1849 | * inodes to exhaust the reserve block pool via finobt expansion while | ||
1850 | * at the same time not creating free space in the filesystem. | ||
1851 | * | ||
1852 | * Send a warning if the reservation does happen to fail, as the inode | ||
1853 | * now remains allocated and sits on the unlinked list until the fs is | ||
1854 | * repaired. | ||
1855 | */ | ||
1856 | tp->t_flags |= XFS_TRANS_RESERVE; | ||
1857 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ifree, | ||
1858 | XFS_IFREE_SPACE_RES(mp), 0); | ||
1841 | if (error) { | 1859 | if (error) { |
1842 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); | 1860 | if (error == ENOSPC) { |
1861 | xfs_warn_ratelimited(mp, | ||
1862 | "Failed to remove inode(s) from unlinked list. " | ||
1863 | "Please free space, unmount and run xfs_repair."); | ||
1864 | } else { | ||
1865 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); | ||
1866 | } | ||
1843 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES); | 1867 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES); |
1844 | return error; | 1868 | return error; |
1845 | } | 1869 | } |
diff --git a/fs/xfs/xfs_trans_resv.c b/fs/xfs/xfs_trans_resv.c index ae368165244d..52b6c3e3203e 100644 --- a/fs/xfs/xfs_trans_resv.c +++ b/fs/xfs/xfs_trans_resv.c | |||
@@ -106,6 +106,47 @@ xfs_calc_inode_res( | |||
106 | } | 106 | } |
107 | 107 | ||
108 | /* | 108 | /* |
109 | * The free inode btree is a conditional feature and the log reservation | ||
110 | * requirements differ slightly from that of the traditional inode allocation | ||
111 | * btree. The finobt tracks records for inode chunks with at least one free | ||
112 | * inode. A record can be removed from the tree for an inode allocation | ||
113 | * or free and thus the finobt reservation is unconditional across: | ||
114 | * | ||
115 | * - inode allocation | ||
116 | * - inode free | ||
117 | * - inode chunk allocation | ||
118 | * | ||
119 | * The 'modify' param indicates to include the record modification scenario. The | ||
120 | * 'alloc' param indicates to include the reservation for free space btree | ||
121 | * modifications on behalf of finobt modifications. This is required only for | ||
122 | * transactions that do not already account for free space btree modifications. | ||
123 | * | ||
124 | * the free inode btree: max depth * block size | ||
125 | * the allocation btrees: 2 trees * (max depth - 1) * block size | ||
126 | * the free inode btree entry: block size | ||
127 | */ | ||
128 | STATIC uint | ||
129 | xfs_calc_finobt_res( | ||
130 | struct xfs_mount *mp, | ||
131 | int alloc, | ||
132 | int modify) | ||
133 | { | ||
134 | uint res; | ||
135 | |||
136 | if (!xfs_sb_version_hasfinobt(&mp->m_sb)) | ||
137 | return 0; | ||
138 | |||
139 | res = xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)); | ||
140 | if (alloc) | ||
141 | res += xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), | ||
142 | XFS_FSB_TO_B(mp, 1)); | ||
143 | if (modify) | ||
144 | res += (uint)XFS_FSB_TO_B(mp, 1); | ||
145 | |||
146 | return res; | ||
147 | } | ||
148 | |||
149 | /* | ||
109 | * Various log reservation values. | 150 | * Various log reservation values. |
110 | * | 151 | * |
111 | * These are based on the size of the file system block because that is what | 152 | * These are based on the size of the file system block because that is what |
@@ -302,6 +343,7 @@ xfs_calc_remove_reservation( | |||
302 | * the superblock for the nlink flag: sector size | 343 | * the superblock for the nlink flag: sector size |
303 | * the directory btree: (max depth + v2) * dir block size | 344 | * the directory btree: (max depth + v2) * dir block size |
304 | * the directory inode's bmap btree: (max depth + v2) * block size | 345 | * the directory inode's bmap btree: (max depth + v2) * block size |
346 | * the finobt (record modification and allocation btrees) | ||
305 | */ | 347 | */ |
306 | STATIC uint | 348 | STATIC uint |
307 | xfs_calc_create_resv_modify( | 349 | xfs_calc_create_resv_modify( |
@@ -310,7 +352,8 @@ xfs_calc_create_resv_modify( | |||
310 | return xfs_calc_inode_res(mp, 2) + | 352 | return xfs_calc_inode_res(mp, 2) + |
311 | xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + | 353 | xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + |
312 | (uint)XFS_FSB_TO_B(mp, 1) + | 354 | (uint)XFS_FSB_TO_B(mp, 1) + |
313 | xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1)); | 355 | xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1)) + |
356 | xfs_calc_finobt_res(mp, 1, 1); | ||
314 | } | 357 | } |
315 | 358 | ||
316 | /* | 359 | /* |
@@ -348,6 +391,7 @@ __xfs_calc_create_reservation( | |||
348 | * the superblock for the nlink flag: sector size | 391 | * the superblock for the nlink flag: sector size |
349 | * the inode btree: max depth * blocksize | 392 | * the inode btree: max depth * blocksize |
350 | * the allocation btrees: 2 trees * (max depth - 1) * block size | 393 | * the allocation btrees: 2 trees * (max depth - 1) * block size |
394 | * the finobt (record insertion) | ||
351 | */ | 395 | */ |
352 | STATIC uint | 396 | STATIC uint |
353 | xfs_calc_icreate_resv_alloc( | 397 | xfs_calc_icreate_resv_alloc( |
@@ -357,7 +401,8 @@ xfs_calc_icreate_resv_alloc( | |||
357 | mp->m_sb.sb_sectsize + | 401 | mp->m_sb.sb_sectsize + |
358 | xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) + | 402 | xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) + |
359 | xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), | 403 | xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), |
360 | XFS_FSB_TO_B(mp, 1)); | 404 | XFS_FSB_TO_B(mp, 1)) + |
405 | xfs_calc_finobt_res(mp, 0, 0); | ||
361 | } | 406 | } |
362 | 407 | ||
363 | STATIC uint | 408 | STATIC uint |
@@ -425,6 +470,7 @@ xfs_calc_symlink_reservation( | |||
425 | * the on disk inode before ours in the agi hash list: inode cluster size | 470 | * the on disk inode before ours in the agi hash list: inode cluster size |
426 | * the inode btree: max depth * blocksize | 471 | * the inode btree: max depth * blocksize |
427 | * the allocation btrees: 2 trees * (max depth - 1) * block size | 472 | * the allocation btrees: 2 trees * (max depth - 1) * block size |
473 | * the finobt (record insertion, removal or modification) | ||
428 | */ | 474 | */ |
429 | STATIC uint | 475 | STATIC uint |
430 | xfs_calc_ifree_reservation( | 476 | xfs_calc_ifree_reservation( |
@@ -439,7 +485,8 @@ xfs_calc_ifree_reservation( | |||
439 | xfs_calc_buf_res(2 + mp->m_ialloc_blks + | 485 | xfs_calc_buf_res(2 + mp->m_ialloc_blks + |
440 | mp->m_in_maxlevels, 0) + | 486 | mp->m_in_maxlevels, 0) + |
441 | xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), | 487 | xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), |
442 | XFS_FSB_TO_B(mp, 1)); | 488 | XFS_FSB_TO_B(mp, 1)) + |
489 | xfs_calc_finobt_res(mp, 0, 1); | ||
443 | } | 490 | } |
444 | 491 | ||
445 | /* | 492 | /* |
diff --git a/fs/xfs/xfs_trans_space.h b/fs/xfs/xfs_trans_space.h index af5dbe06cb65..df4c1f81884c 100644 --- a/fs/xfs/xfs_trans_space.h +++ b/fs/xfs/xfs_trans_space.h | |||
@@ -47,7 +47,9 @@ | |||
47 | #define XFS_DIRREMOVE_SPACE_RES(mp) \ | 47 | #define XFS_DIRREMOVE_SPACE_RES(mp) \ |
48 | XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK) | 48 | XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK) |
49 | #define XFS_IALLOC_SPACE_RES(mp) \ | 49 | #define XFS_IALLOC_SPACE_RES(mp) \ |
50 | ((mp)->m_ialloc_blks + (mp)->m_in_maxlevels - 1) | 50 | ((mp)->m_ialloc_blks + \ |
51 | (xfs_sb_version_hasfinobt(&mp->m_sb) ? 2 : 1 * \ | ||
52 | ((mp)->m_in_maxlevels - 1))) | ||
51 | 53 | ||
52 | /* | 54 | /* |
53 | * Space reservation values for various transactions. | 55 | * Space reservation values for various transactions. |
@@ -82,5 +84,8 @@ | |||
82 | (XFS_DIRREMOVE_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) | 84 | (XFS_DIRREMOVE_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) |
83 | #define XFS_SYMLINK_SPACE_RES(mp,nl,b) \ | 85 | #define XFS_SYMLINK_SPACE_RES(mp,nl,b) \ |
84 | (XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl) + (b)) | 86 | (XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl) + (b)) |
87 | #define XFS_IFREE_SPACE_RES(mp) \ | ||
88 | (xfs_sb_version_hasfinobt(&mp->m_sb) ? (mp)->m_in_maxlevels : 0) | ||
89 | |||
85 | 90 | ||
86 | #endif /* __XFS_TRANS_SPACE_H__ */ | 91 | #endif /* __XFS_TRANS_SPACE_H__ */ |