@@ -575,6 +575,10 @@ xfs_defer_ops_capture(
dfc->dfc_tpflags = tp->t_flags & XFS_TRANS_LOWMODE;
tp->t_flags &= ~XFS_TRANS_LOWMODE;
+ /* Capture the remaining block reservations along with the dfops. */
+ dfc->dfc_blkres = tp->t_blk_res - tp->t_blk_res_used;
+ dfc->dfc_rtxres = tp->t_rtx_res - tp->t_rtx_res_used;
+
return dfc;
}
@@ -75,6 +75,10 @@ struct xfs_defer_capture {
/* Deferred ops state saved from the transaction. */
struct list_head dfc_dfops;
unsigned int dfc_tpflags;
+
+ /* Block reservations for the data and rt devices. */
+ unsigned int dfc_blkres;
+ unsigned int dfc_rtxres;
};
/*
@@ -2439,27 +2439,12 @@ xlog_finish_defer_ops(
{
struct xfs_defer_capture *dfc, *next;
struct xfs_trans *tp;
- int64_t freeblks;
- uint64_t resblks;
int error = 0;
list_for_each_entry_safe(dfc, next, capture_list, dfc_list) {
- /*
- * We're finishing the defer_ops that accumulated as a result
- * of recovering unfinished intent items during log recovery.
- * We reserve an itruncate transaction because it is the
- * largest permanent transaction type. Since we're the only
- * user of the fs right now, take 93% (15/16) of the available
- * free blocks. Use weird math to avoid a 64-bit division.
- */
- freeblks = percpu_counter_sum(&mp->m_fdblocks);
- if (freeblks <= 0)
- return -ENOSPC;
-
- resblks = min_t(uint64_t, UINT_MAX, freeblks);
- resblks = (resblks * 15) >> 4;
- error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, resblks,
- 0, XFS_TRANS_RESERVE, &tp);
+ error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
+ dfc->dfc_blkres, dfc->dfc_rtxres,
+ XFS_TRANS_RESERVE, &tp);
if (error)
return error;