@@ -196,6 +196,24 @@ xfs_calc_inode_chunk_res(
196196 return res ;
197197}
198198
199+ /*
200+ * Per-extent log reservation for the btree changes involved in freeing or
201+ * allocating a realtime extent. We have to be able to log as many rtbitmap
202+ * blocks as needed to mark inuse MAXEXTLEN blocks' worth of realtime extents,
203+ * as well as the realtime summary block.
204+ */
205+ unsigned int
206+ xfs_rtalloc_log_count (
207+ struct xfs_mount * mp ,
208+ unsigned int num_ops )
209+ {
210+ unsigned int blksz = XFS_FSB_TO_B (mp , 1 );
211+ unsigned int rtbmp_bytes ;
212+
213+ rtbmp_bytes = (MAXEXTLEN / mp -> m_sb .sb_rextsize ) / NBBY ;
214+ return (howmany (rtbmp_bytes , blksz ) + 1 ) * num_ops ;
215+ }
216+
199217/*
200218 * Various log reservation values.
201219 *
@@ -218,13 +236,21 @@ xfs_calc_inode_chunk_res(
218236
219237/*
220238 * In a write transaction we can allocate a maximum of 2
221- * extents. This gives:
239+ * extents. This gives (t1) :
222240 * the inode getting the new extents: inode size
223241 * the inode's bmap btree: max depth * block size
224242 * the agfs of the ags from which the extents are allocated: 2 * sector
225243 * the superblock free block counter: sector size
226244 * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
227- * And the bmap_finish transaction can free bmap blocks in a join:
245+ * Or, if we're writing to a realtime file (t2):
246+ * the inode getting the new extents: inode size
247+ * the inode's bmap btree: max depth * block size
248+ * the agfs of the ags from which the extents are allocated: 2 * sector
249+ * the superblock free block counter: sector size
250+ * the realtime bitmap: ((MAXEXTLEN / rtextsize) / NBBY) bytes
251+ * the realtime summary: 1 block
252+ * the allocation btrees: 2 trees * (2 * max depth - 1) * block size
253+ * And the bmap_finish transaction can free bmap blocks in a join (t3):
228254 * the agfs of the ags containing the blocks: 2 * sector size
229255 * the agfls of the ags containing the blocks: 2 * sector size
230256 * the super block free block counter: sector size
@@ -234,40 +260,72 @@ STATIC uint
234260xfs_calc_write_reservation (
235261 struct xfs_mount * mp )
236262{
237- return XFS_DQUOT_LOGRES (mp ) +
238- max ((xfs_calc_inode_res (mp , 1 ) +
263+ unsigned int t1 , t2 , t3 ;
264+ unsigned int blksz = XFS_FSB_TO_B (mp , 1 );
265+
266+ t1 = xfs_calc_inode_res (mp , 1 ) +
267+ xfs_calc_buf_res (XFS_BM_MAXLEVELS (mp , XFS_DATA_FORK ), blksz ) +
268+ xfs_calc_buf_res (3 , mp -> m_sb .sb_sectsize ) +
269+ xfs_calc_buf_res (xfs_allocfree_log_count (mp , 2 ), blksz );
270+
271+ if (xfs_sb_version_hasrealtime (& mp -> m_sb )) {
272+ t2 = xfs_calc_inode_res (mp , 1 ) +
239273 xfs_calc_buf_res (XFS_BM_MAXLEVELS (mp , XFS_DATA_FORK ),
240- XFS_FSB_TO_B ( mp , 1 ) ) +
274+ blksz ) +
241275 xfs_calc_buf_res (3 , mp -> m_sb .sb_sectsize ) +
242- xfs_calc_buf_res (xfs_allocfree_log_count (mp , 2 ),
243- XFS_FSB_TO_B (mp , 1 ))),
244- (xfs_calc_buf_res (5 , mp -> m_sb .sb_sectsize ) +
245- xfs_calc_buf_res (xfs_allocfree_log_count (mp , 2 ),
246- XFS_FSB_TO_B (mp , 1 ))));
276+ xfs_calc_buf_res (xfs_rtalloc_log_count (mp , 1 ), blksz ) +
277+ xfs_calc_buf_res (xfs_allocfree_log_count (mp , 1 ), blksz );
278+ } else {
279+ t2 = 0 ;
280+ }
281+
282+ t3 = xfs_calc_buf_res (5 , mp -> m_sb .sb_sectsize ) +
283+ xfs_calc_buf_res (xfs_allocfree_log_count (mp , 2 ), blksz );
284+
285+ return XFS_DQUOT_LOGRES (mp ) + max3 (t1 , t2 , t3 );
247286}
248287
249288/*
250- * In truncating a file we free up to two extents at once. We can modify:
289+ * In truncating a file we free up to two extents at once. We can modify (t1) :
251290 * the inode being truncated: inode size
252291 * the inode's bmap btree: (max depth + 1) * block size
253- * And the bmap_finish transaction can free the blocks and bmap blocks:
292+ * And the bmap_finish transaction can free the blocks and bmap blocks (t2) :
254293 * the agf for each of the ags: 4 * sector size
255294 * the agfl for each of the ags: 4 * sector size
256295 * the super block to reflect the freed blocks: sector size
257296 * worst case split in allocation btrees per extent assuming 4 extents:
258297 * 4 exts * 2 trees * (2 * max depth - 1) * block size
298+ * Or, if it's a realtime file (t3):
299+ * the agf for each of the ags: 2 * sector size
300+ * the agfl for each of the ags: 2 * sector size
301+ * the super block to reflect the freed blocks: sector size
302+ * the realtime bitmap: 2 exts * ((MAXEXTLEN / rtextsize) / NBBY) bytes
303+ * the realtime summary: 2 exts * 1 block
304+ * worst case split in allocation btrees per extent assuming 2 extents:
305+ * 2 exts * 2 trees * (2 * max depth - 1) * block size
259306 */
260307STATIC uint
261308xfs_calc_itruncate_reservation (
262309 struct xfs_mount * mp )
263310{
264- return XFS_DQUOT_LOGRES (mp ) +
265- max ((xfs_calc_inode_res (mp , 1 ) +
266- xfs_calc_buf_res (XFS_BM_MAXLEVELS (mp , XFS_DATA_FORK ) + 1 ,
267- XFS_FSB_TO_B (mp , 1 ))),
268- (xfs_calc_buf_res (9 , mp -> m_sb .sb_sectsize ) +
269- xfs_calc_buf_res (xfs_allocfree_log_count (mp , 4 ),
270- XFS_FSB_TO_B (mp , 1 ))));
311+ unsigned int t1 , t2 , t3 ;
312+ unsigned int blksz = XFS_FSB_TO_B (mp , 1 );
313+
314+ t1 = xfs_calc_inode_res (mp , 1 ) +
315+ xfs_calc_buf_res (XFS_BM_MAXLEVELS (mp , XFS_DATA_FORK ) + 1 , blksz );
316+
317+ t2 = xfs_calc_buf_res (9 , mp -> m_sb .sb_sectsize ) +
318+ xfs_calc_buf_res (xfs_allocfree_log_count (mp , 4 ), blksz );
319+
320+ if (xfs_sb_version_hasrealtime (& mp -> m_sb )) {
321+ t3 = xfs_calc_buf_res (5 , mp -> m_sb .sb_sectsize ) +
322+ xfs_calc_buf_res (xfs_rtalloc_log_count (mp , 2 ), blksz ) +
323+ xfs_calc_buf_res (xfs_allocfree_log_count (mp , 2 ), blksz );
324+ } else {
325+ t3 = 0 ;
326+ }
327+
328+ return XFS_DQUOT_LOGRES (mp ) + max3 (t1 , t2 , t3 );
271329}
272330
273331/*
0 commit comments