Message ID | 160125008731.174438.2552492068404088327.stgit@magnolia (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | xfs: fix how we deal with new intents during recovery | expand |
On Sun, Sep 27, 2020 at 04:41:27PM -0700, Darrick J. Wong wrote: > From: Darrick J. Wong <darrick.wong@oracle.com> > > When xfs_defer_capture extracts the deferred ops and transaction state > from a transaction, it should absorb the remaining block reservation so > that when we continue the dfops chain, we still have those blocks to > use. > > This adds the requirement that every log intent item recovery function > must be careful to reserve enough blocks to handle both itself and all > defer ops that it can queue. On the other hand, this enables us to do > away with the handwaving block estimation nonsense that was going on in > xlog_finish_defer_ops. > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > Reviewed-by: Christoph Hellwig <hch@lst.de> > --- > fs/xfs/libxfs/xfs_defer.c | 4 ++++ > fs/xfs/libxfs/xfs_defer.h | 1 + > fs/xfs/xfs_log_recover.c | 18 +----------------- > 3 files changed, 6 insertions(+), 17 deletions(-) > > > diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c > index 0de7672fe63d..85d70f1edc1c 100644 > --- a/fs/xfs/libxfs/xfs_defer.c > +++ b/fs/xfs/libxfs/xfs_defer.c > @@ -574,6 +574,8 @@ xfs_defer_capture( > list_splice_init(&tp->t_dfops, &dfc->dfc_dfops); > dfc->dfc_tpflags = tp->t_flags & XFS_TRANS_LOWMODE; > tp->t_flags &= ~XFS_TRANS_LOWMODE; > + dfc->dfc_blkres = tp->t_blk_res - tp->t_blk_res_used; > + tp->t_blk_res = tp->t_blk_res_used; > > return dfc; > } I think this needs an explanation in the function/API comment to explain why it is being done. Otherwise looks good. Reviewed-by: Dave Chinner <dchinner@redhat.com>
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 0de7672fe63d..85d70f1edc1c 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -574,6 +574,8 @@ xfs_defer_capture( list_splice_init(&tp->t_dfops, &dfc->dfc_dfops); dfc->dfc_tpflags = tp->t_flags & XFS_TRANS_LOWMODE; tp->t_flags &= ~XFS_TRANS_LOWMODE; + dfc->dfc_blkres = tp->t_blk_res - tp->t_blk_res_used; + tp->t_blk_res = tp->t_blk_res_used; return dfc; } @@ -591,6 +593,8 @@ xfs_defer_continue( list_splice_init(&dfc->dfc_dfops, &tp->t_dfops); tp->t_flags |= dfc->dfc_tpflags; dfc->dfc_tpflags = 0; + tp->t_blk_res += dfc->dfc_blkres; + dfc->dfc_blkres = 0; } /* Release all resources that we used to capture deferred ops. */ diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index bc7493bf4542..999adbb8c449 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -76,6 +76,7 @@ struct xfs_defer_capture { /* Deferred ops state saved from the transaction. */ struct list_head dfc_dfops; unsigned int dfc_tpflags; + unsigned int dfc_blkres; }; /* diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 107965acc57e..60670ac4e5ae 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -2484,26 +2484,10 @@ 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, + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, XFS_TRANS_RESERVE, &tp); if (error) return error;