From 6aa6718439ac6907b3c34cbe7ac2c71408f84f6e Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 11 Jul 2018 22:26:07 -0700 Subject: xfs: rename xfs_trans ->t_agfl_dfops to ->t_dfops The ->t_agfl_dfops field is currently used to defer agfl block frees from associated transaction contexts. While all known problematic contexts have already been updated to use ->t_agfl_dfops, the broader goal is defer agfl frees from all callers that already use a deferred operations structure. Further, the transaction field facilitates a good amount of code clean up where the transaction and dfops have historically been passed down through the stack separately. Rename the field to something more generic to prepare to use it as such throughout XFS. This patch does not change behavior. Signed-off-by: Brian Foster Reviewed-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_defer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index c3e5bffda4f5..560a7d178c1e 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -350,9 +350,9 @@ xfs_defer_finish( * Note that this code can go away once all dfops users attach to the * associated tp. */ - ASSERT(!(*tp)->t_agfl_dfops || ((*tp)->t_agfl_dfops == dop)); - orig_dop = (*tp)->t_agfl_dfops; - (*tp)->t_agfl_dfops = dop; + ASSERT(!(*tp)->t_dfops || ((*tp)->t_dfops == dop)); + orig_dop = (*tp)->t_dfops; + (*tp)->t_dfops = dop; /* Until we run out of pending work to finish... */ while (xfs_defer_has_unfinished_work(dop)) { @@ -425,7 +425,7 @@ xfs_defer_finish( } out: - (*tp)->t_agfl_dfops = orig_dop; + (*tp)->t_dfops = orig_dop; if (error) trace_xfs_defer_finish_error((*tp)->t_mountp, dop, error); else -- cgit v1.2.3 From bcd2c9f33559764e0d306e226a8aa88bc2e1e6fb Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 11 Jul 2018 22:26:19 -0700 Subject: xfs: refactor dfops init to attach to transaction Most callers of xfs_defer_init() immediately attach the dfops structure to a transaction. Add a transaction parameter to eliminate much of this boilerplate code. This also helps self-document the fact that many codepaths now expect a dfops pointer implicitly via xfs_trans->t_dfops. Signed-off-by: Brian Foster Reviewed-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 26 ++++++++++++++------------ fs/xfs/libxfs/xfs_attr_remote.c | 6 +++--- fs/xfs/libxfs/xfs_bmap.c | 6 ++---- fs/xfs/libxfs/xfs_defer.c | 9 ++++++++- fs/xfs/libxfs/xfs_defer.h | 3 ++- fs/xfs/libxfs/xfs_refcount.c | 3 +-- fs/xfs/xfs_bmap_util.c | 17 ++++++----------- fs/xfs/xfs_dquot.c | 5 ++--- fs/xfs/xfs_inode.c | 18 ++++++------------ fs/xfs/xfs_iomap.c | 9 +++------ fs/xfs/xfs_log_recover.c | 2 +- fs/xfs/xfs_reflink.c | 12 ++++-------- fs/xfs/xfs_rtalloc.c | 3 +-- fs/xfs/xfs_symlink.c | 6 ++---- 14 files changed, 55 insertions(+), 70 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index a14ab9b2669e..8a7e2c0308c4 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -253,8 +253,7 @@ xfs_attr_set( rsvd ? XFS_TRANS_RESERVE : 0, &args.trans); if (error) return error; - xfs_defer_init(&dfops, &firstblock); - args.trans->t_dfops = &dfops; + xfs_defer_init(args.trans, &dfops, &firstblock); xfs_ilock(dp, XFS_ILOCK_EXCL); error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0, @@ -428,8 +427,7 @@ xfs_attr_remove( &args.trans); if (error) return error; - xfs_defer_init(&dfops, &firstblock); - args.trans->t_dfops = &dfops; + xfs_defer_init(args.trans, &dfops, &firstblock); xfs_ilock(dp, XFS_ILOCK_EXCL); /* @@ -600,7 +598,7 @@ xfs_attr_leaf_addname( * Commit that transaction so that the node_addname() call * can manage its own transactions. */ - xfs_defer_init(args->trans->t_dfops, args->firstblock); + xfs_defer_init(NULL, args->trans->t_dfops, args->firstblock); error = xfs_attr3_leaf_to_node(args); if (error) goto out_defer_cancel; @@ -689,7 +687,8 @@ xfs_attr_leaf_addname( * If the result is small enough, shrink it all into the inode. */ if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_defer_init(args->trans->t_dfops, args->firstblock); + xfs_defer_init(NULL, args->trans->t_dfops, + args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (error) @@ -754,7 +753,7 @@ xfs_attr_leaf_removename( * If the result is small enough, shrink it all into the inode. */ if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_defer_init(args->trans->t_dfops, args->firstblock); + xfs_defer_init(NULL, args->trans->t_dfops, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (error) @@ -883,7 +882,8 @@ restart: */ xfs_da_state_free(state); state = NULL; - xfs_defer_init(args->trans->t_dfops, args->firstblock); + xfs_defer_init(NULL, args->trans->t_dfops, + args->firstblock); error = xfs_attr3_leaf_to_node(args); if (error) goto out_defer_cancel; @@ -910,7 +910,7 @@ restart: * in the index/blkno/rmtblkno/rmtblkcnt fields and * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields. */ - xfs_defer_init(args->trans->t_dfops, args->firstblock); + xfs_defer_init(NULL, args->trans->t_dfops, args->firstblock); error = xfs_da3_split(state); if (error) goto out_defer_cancel; @@ -1008,7 +1008,8 @@ restart: * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active > 1)) { - xfs_defer_init(args->trans->t_dfops, args->firstblock); + xfs_defer_init(NULL, args->trans->t_dfops, + args->firstblock); error = xfs_da3_join(state); if (error) goto out_defer_cancel; @@ -1133,7 +1134,7 @@ xfs_attr_node_removename( * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active > 1)) { - xfs_defer_init(args->trans->t_dfops, args->firstblock); + xfs_defer_init(NULL, args->trans->t_dfops, args->firstblock); error = xfs_da3_join(state); if (error) goto out_defer_cancel; @@ -1165,7 +1166,8 @@ xfs_attr_node_removename( goto out; if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_defer_init(args->trans->t_dfops, args->firstblock); + xfs_defer_init(NULL, args->trans->t_dfops, + args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (error) diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index 179259fd1b5e..ab7c2755ad8c 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c @@ -480,7 +480,7 @@ xfs_attr_rmtval_set( * extent and then crash then the block may not contain the * correct metadata after log recovery occurs. */ - xfs_defer_init(args->trans->t_dfops, args->firstblock); + xfs_defer_init(NULL, args->trans->t_dfops, args->firstblock); nmap = 1; error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno, blkcnt, XFS_BMAPI_ATTRFORK, args->firstblock, @@ -522,7 +522,7 @@ xfs_attr_rmtval_set( ASSERT(blkcnt > 0); - xfs_defer_init(args->trans->t_dfops, args->firstblock); + xfs_defer_init(NULL, args->trans->t_dfops, args->firstblock); nmap = 1; error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno, blkcnt, &map, &nmap, @@ -626,7 +626,7 @@ xfs_attr_rmtval_remove( blkcnt = args->rmtblkcnt; done = 0; while (!done) { - xfs_defer_init(args->trans->t_dfops, args->firstblock); + xfs_defer_init(NULL, args->trans->t_dfops, args->firstblock); error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, XFS_BMAPI_ATTRFORK, 1, args->firstblock, &done); diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 32d8d87b7582..dfff840c79f9 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -1050,8 +1050,7 @@ xfs_bmap_add_attrfork( rsvd ? XFS_TRANS_RESERVE : 0, &tp); if (error) return error; - xfs_defer_init(&dfops, &firstblock); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &firstblock); xfs_ilock(ip, XFS_ILOCK_EXCL); error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd ? @@ -6025,8 +6024,7 @@ xfs_bmap_split_extent( XFS_DIOSTRAT_SPACE_RES(mp, 0), 0, 0, &tp); if (error) return error; - xfs_defer_init(&dfops, &firstfsb); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &firstfsb); xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 560a7d178c1e..6b25a9436829 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -523,12 +523,19 @@ xfs_defer_init_op_type( /* Initialize a deferred operation. */ void xfs_defer_init( + struct xfs_trans *tp, struct xfs_defer_ops *dop, xfs_fsblock_t *fbp) { + struct xfs_mount *mp = NULL; + memset(dop, 0, sizeof(struct xfs_defer_ops)); *fbp = NULLFSBLOCK; INIT_LIST_HEAD(&dop->dop_intake); INIT_LIST_HEAD(&dop->dop_pending); - trace_xfs_defer_init(NULL, dop, _RET_IP_); + if (tp) { + tp->t_dfops = dop; + mp = tp->t_mountp; + } + trace_xfs_defer_init(mp, dop, _RET_IP_); } diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index a02b2b748b6d..56eaaac31df5 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -63,7 +63,8 @@ void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, struct list_head *h); int xfs_defer_finish(struct xfs_trans **tp, struct xfs_defer_ops *dop); void xfs_defer_cancel(struct xfs_defer_ops *dop); -void xfs_defer_init(struct xfs_defer_ops *dop, xfs_fsblock_t *fbp); +void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop, + xfs_fsblock_t *fbp); bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip); int xfs_defer_bjoin(struct xfs_defer_ops *dop, struct xfs_buf *bp); diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index df67821fb5f4..8dc380574cd8 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -1691,8 +1691,7 @@ xfs_refcount_recover_cow_leftovers( trace_xfs_refcount_recover_extent(mp, agno, &rr->rr_rrec); /* Free the orphan record */ - xfs_defer_init(&dfops, &fsb); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &fsb); agbno = rr->rr_rrec.rc_startblock - XFS_REFC_COW_START; fsb = XFS_AGB_TO_FSB(mp, agno, agbno); error = xfs_refcount_free_cow_extent(mp, tp->t_dfops, fsb, diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 6bea8df348bc..1259e599158d 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -972,8 +972,7 @@ xfs_alloc_file_space( xfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(&dfops, &firstfsb); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &firstfsb); error = xfs_bmapi_write(tp, ip, startoffset_fsb, allocatesize_fsb, alloc_type, &firstfsb, resblks, imapp, &nimaps); @@ -1043,8 +1042,7 @@ xfs_unmap_extent( xfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(&dfops, &firstfsb); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &firstfsb); error = xfs_bunmapi(tp, ip, startoffset_fsb, len_fsb, 0, 2, &firstfsb, done); if (error) @@ -1347,8 +1345,7 @@ xfs_collapse_file_space( goto out_trans_cancel; xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_defer_init(&dfops, &first_block); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &first_block); error = xfs_bmap_collapse_extents(tp, ip, &next_fsb, shift_fsb, &done, &first_block); if (error) @@ -1427,8 +1424,7 @@ xfs_insert_file_space( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_defer_init(&dfops, &first_block); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &first_block); error = xfs_bmap_insert_extents(tp, ip, &next_fsb, shift_fsb, &done, stop_fsb, &first_block); if (error) @@ -1615,7 +1611,7 @@ xfs_swap_extent_rmap( /* Unmap the old blocks in the source file. */ while (tirec.br_blockcount) { - xfs_defer_init(tp->t_dfops, &firstfsb); + xfs_defer_init(tp, tp->t_dfops, &firstfsb); trace_xfs_swap_extent_rmap_remap_piece(tip, &tirec); /* Read extent from the source file */ @@ -1920,8 +1916,7 @@ xfs_swap_extents( error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp); if (error) goto out_unlock; - xfs_defer_init(&dfops, &firstfsb); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &firstfsb); /* * Lock and join the inodes to the tansaction so that transaction commit diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 1ef38e1df679..c698e7f6f744 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -296,7 +296,7 @@ xfs_dquot_disk_alloc( trace_xfs_dqalloc(dqp); - xfs_defer_init(tp->t_dfops, &firstblock); + xfs_defer_init(tp, tp->t_dfops, &firstblock); xfs_ilock(quotip, XFS_ILOCK_EXCL); if (!xfs_this_quota_on(dqp->q_mount, dqp->dq_flags)) { @@ -549,8 +549,7 @@ xfs_qm_dqread_alloc( XFS_QM_DQALLOC_SPACE_RES(mp), 0, 0, &tp); if (error) goto err; - xfs_defer_init(&dfops, &firstblock); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &firstblock); error = xfs_dquot_disk_alloc(&tp, dqp, &bp); if (error) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index f456df2e1394..04e17234e5d7 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1195,8 +1195,7 @@ xfs_create( xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); unlock_dp_on_error = true; - xfs_defer_init(&dfops, &first_block); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &first_block); /* * Reserve disk quota and the inode. @@ -1451,8 +1450,7 @@ xfs_link( goto error_return; } - xfs_defer_init(&dfops, &first_block); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &first_block); /* * Handle initial link state of O_TMPFILE inode @@ -1584,8 +1582,7 @@ xfs_itruncate_extents_flags( ASSERT(first_unmap_block < last_block); unmap_len = last_block - first_unmap_block + 1; while (!done) { - xfs_defer_init(&dfops, &first_block); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &first_block); error = xfs_bunmapi(tp, ip, first_unmap_block, unmap_len, flags, XFS_ITRUNC_MAX_EXTENTS, &first_block, &done); @@ -1816,8 +1813,7 @@ xfs_inactive_ifree( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(&dfops, &first_block); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &first_block); error = xfs_ifree(tp, ip); if (error) { /* @@ -2661,8 +2657,7 @@ xfs_remove( if (error) goto out_trans_cancel; - xfs_defer_init(&dfops, &first_block); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &first_block); error = xfs_dir_removename(tp, dp, name, ip->i_ino, &first_block, resblks); if (error) { @@ -3026,8 +3021,7 @@ xfs_rename( goto out_trans_cancel; } - xfs_defer_init(&dfops, &first_block); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &first_block); /* RENAME_EXCHANGE is unique from here on. */ if (flags & RENAME_EXCHANGE) diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 0c736c938f52..777c349607b3 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -254,8 +254,7 @@ xfs_iomap_write_direct( * From this point onwards we overwrite the imap pointer that the * caller gave to us. */ - xfs_defer_init(&dfops, &firstfsb); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &firstfsb); nimaps = 1; error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, bmapi_flags, &firstfsb, resblks, imap, @@ -717,8 +716,7 @@ xfs_iomap_write_allocate( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(&dfops, &first_block); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &first_block); /* * it is possible that the extents have changed since @@ -878,8 +876,7 @@ xfs_iomap_write_unwritten( /* * Modify the unwritten extent state of the buffer. */ - xfs_defer_init(&dfops, &firstfsb); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &firstfsb); nimaps = 1; error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, XFS_BMAPI_CONVERT, &firstfsb, resblks, diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index b181b5f57a19..940eb30e0271 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -4902,7 +4902,7 @@ xlog_recover_process_intents( #if defined(DEBUG) || defined(XFS_WARN) last_lsn = xlog_assign_lsn(log->l_curr_cycle, log->l_curr_block); #endif - xfs_defer_init(&dfops, &firstfsb); + xfs_defer_init(NULL, &dfops, &firstfsb); while (lip != NULL) { /* * We're done when we see something other than an intent. diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 8ea4ba0e45d8..bef780171962 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -428,8 +428,7 @@ retry: xfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(&dfops, &first_block); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &first_block); nimaps = 1; /* Allocate the entire reservation as unwritten blocks. */ @@ -517,8 +516,7 @@ xfs_reflink_cancel_cow_blocks( if (error) break; } else if (del.br_state == XFS_EXT_UNWRITTEN || cancel_real) { - xfs_defer_init(&dfops, &firstfsb); - (*tpp)->t_dfops = &dfops; + xfs_defer_init(*tpp, &dfops, &firstfsb); /* Free the CoW orphan record. */ error = xfs_refcount_free_cow_extent(ip->i_mount, @@ -701,8 +699,7 @@ xfs_reflink_end_cow( goto prev_extent; /* Unmap the old blocks in the data fork. */ - xfs_defer_init(&dfops, &firstfsb); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &firstfsb); rlen = del.br_blockcount; error = __xfs_bunmapi(tp, ip, del.br_startoff, &rlen, 0, 1, &firstfsb); @@ -1052,8 +1049,7 @@ xfs_reflink_remap_extent( /* Unmap the old blocks in the data fork. */ rlen = unmap_len; while (rlen) { - xfs_defer_init(&dfops, &firstfsb); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &firstfsb); error = __xfs_bunmapi(tp, ip, destoff, &rlen, 0, 1, &firstfsb); if (error) goto out_defer; diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 1c7d1238ff3b..c102b0d26bc1 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -787,8 +787,7 @@ xfs_growfs_rt_alloc( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_defer_init(&dfops, &firstblock); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &firstblock); /* * Allocate blocks to the bitmap file. */ diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index a54f095c1409..e50e97308f81 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -246,8 +246,7 @@ xfs_symlink( * Initialize the bmap freelist prior to calling either * bmapi or the directory create code. */ - xfs_defer_init(&dfops, &first_block); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &first_block); /* * Allocate an inode for the symlink. @@ -443,8 +442,7 @@ xfs_inactive_symlink_rmt( * Find the block(s) so we can inval and unmap them. */ done = 0; - xfs_defer_init(&dfops, &first_block); - tp->t_dfops = &dfops; + xfs_defer_init(tp, &dfops, &first_block); nmaps = ARRAY_SIZE(mval); error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size), mval, &nmaps, 0); -- cgit v1.2.3 From 5fdd97944ee5ae0fcdd88227224d0c2c87aa6db9 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 11 Jul 2018 22:26:33 -0700 Subject: xfs: remove xfs_defer_init() firstblock param All but one caller of xfs_defer_init() passes in the ->t_firstblock of the associated transaction. The one outlier is xlog_recover_process_intents(), which simply passes a dummy value because a valid pointer is required. This firstblock variable can simply be removed. At this point we could remove the xfs_defer_init() firstblock parameter and initialize ->t_firstblock directly. Even that is not necessary, however, because ->t_firstblock is automatically reinitialized in the new transaction on a transaction roll. Since xfs_defer_init() should never occur more than once on a particular transaction (since the corresponding finish will roll it), replace the reinit from xfs_defer_init() with an assert that verifies the transaction has a NULLFSBLOCK firstblock. Signed-off-by: Brian Foster Reviewed-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 28 ++++++++++------------------ fs/xfs/libxfs/xfs_attr_remote.c | 9 +++------ fs/xfs/libxfs/xfs_bmap.c | 4 ++-- fs/xfs/libxfs/xfs_defer.c | 5 ++--- fs/xfs/libxfs/xfs_defer.h | 3 +-- fs/xfs/libxfs/xfs_refcount.c | 2 +- fs/xfs/xfs_bmap_util.c | 12 ++++++------ fs/xfs/xfs_dquot.c | 4 ++-- fs/xfs/xfs_inode.c | 12 ++++++------ fs/xfs/xfs_iomap.c | 6 +++--- fs/xfs/xfs_log_recover.c | 3 +-- fs/xfs/xfs_reflink.c | 8 ++++---- fs/xfs/xfs_rtalloc.c | 2 +- fs/xfs/xfs_symlink.c | 4 ++-- 14 files changed, 44 insertions(+), 58 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 153d2e29f872..927d4c968f9a 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -251,7 +251,7 @@ xfs_attr_set( rsvd ? XFS_TRANS_RESERVE : 0, &args.trans); if (error) return error; - xfs_defer_init(args.trans, &dfops, &args.trans->t_firstblock); + xfs_defer_init(args.trans, &dfops); xfs_ilock(dp, XFS_ILOCK_EXCL); error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0, @@ -422,7 +422,7 @@ xfs_attr_remove( &args.trans); if (error) return error; - xfs_defer_init(args.trans, &dfops, &args.trans->t_firstblock); + xfs_defer_init(args.trans, &dfops); xfs_ilock(dp, XFS_ILOCK_EXCL); /* @@ -593,8 +593,7 @@ xfs_attr_leaf_addname( * Commit that transaction so that the node_addname() call * can manage its own transactions. */ - xfs_defer_init(args->trans, args->trans->t_dfops, - &args->trans->t_firstblock); + xfs_defer_init(args->trans, args->trans->t_dfops); error = xfs_attr3_leaf_to_node(args); if (error) goto out_defer_cancel; @@ -683,8 +682,7 @@ xfs_attr_leaf_addname( * If the result is small enough, shrink it all into the inode. */ if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_defer_init(args->trans, args->trans->t_dfops, - &args->trans->t_firstblock); + xfs_defer_init(args->trans, args->trans->t_dfops); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (error) @@ -749,8 +747,7 @@ xfs_attr_leaf_removename( * If the result is small enough, shrink it all into the inode. */ if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_defer_init(args->trans, args->trans->t_dfops, - &args->trans->t_firstblock); + xfs_defer_init(args->trans, args->trans->t_dfops); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (error) @@ -879,8 +876,7 @@ restart: */ xfs_da_state_free(state); state = NULL; - xfs_defer_init(args->trans, args->trans->t_dfops, - &args->trans->t_firstblock); + xfs_defer_init(args->trans, args->trans->t_dfops); error = xfs_attr3_leaf_to_node(args); if (error) goto out_defer_cancel; @@ -907,8 +903,7 @@ restart: * in the index/blkno/rmtblkno/rmtblkcnt fields and * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields. */ - xfs_defer_init(args->trans, args->trans->t_dfops, - &args->trans->t_firstblock); + xfs_defer_init(args->trans, args->trans->t_dfops); error = xfs_da3_split(state); if (error) goto out_defer_cancel; @@ -1006,8 +1001,7 @@ restart: * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active > 1)) { - xfs_defer_init(args->trans, args->trans->t_dfops, - &args->trans->t_firstblock); + xfs_defer_init(args->trans, args->trans->t_dfops); error = xfs_da3_join(state); if (error) goto out_defer_cancel; @@ -1132,8 +1126,7 @@ xfs_attr_node_removename( * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active > 1)) { - xfs_defer_init(args->trans, args->trans->t_dfops, - &args->trans->t_firstblock); + xfs_defer_init(args->trans, args->trans->t_dfops); error = xfs_da3_join(state); if (error) goto out_defer_cancel; @@ -1165,8 +1158,7 @@ xfs_attr_node_removename( goto out; if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_defer_init(args->trans, args->trans->t_dfops, - &args->trans->t_firstblock); + xfs_defer_init(args->trans, args->trans->t_dfops); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (error) diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index f02c705965ff..7841e6255129 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c @@ -480,8 +480,7 @@ xfs_attr_rmtval_set( * extent and then crash then the block may not contain the * correct metadata after log recovery occurs. */ - xfs_defer_init(args->trans, args->trans->t_dfops, - &args->trans->t_firstblock); + xfs_defer_init(args->trans, args->trans->t_dfops); nmap = 1; error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno, blkcnt, XFS_BMAPI_ATTRFORK, args->total, &map, @@ -523,8 +522,7 @@ xfs_attr_rmtval_set( ASSERT(blkcnt > 0); - xfs_defer_init(args->trans, args->trans->t_dfops, - &args->trans->t_firstblock); + xfs_defer_init(args->trans, args->trans->t_dfops); nmap = 1; error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno, blkcnt, &map, &nmap, @@ -628,8 +626,7 @@ xfs_attr_rmtval_remove( blkcnt = args->rmtblkcnt; done = 0; while (!done) { - xfs_defer_init(args->trans, args->trans->t_dfops, - &args->trans->t_firstblock); + xfs_defer_init(args->trans, args->trans->t_dfops); error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, XFS_BMAPI_ATTRFORK, 1, &done); if (error) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 12be9ad888c3..7b93b1e16ad9 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -1038,7 +1038,7 @@ xfs_bmap_add_attrfork( rsvd ? XFS_TRANS_RESERVE : 0, &tp); if (error) return error; - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); xfs_ilock(ip, XFS_ILOCK_EXCL); error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd ? @@ -5968,7 +5968,7 @@ xfs_bmap_split_extent( XFS_DIOSTRAT_SPACE_RES(mp, 0), 0, 0, &tp); if (error) return error; - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 6b25a9436829..2713e2d808a7 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -524,16 +524,15 @@ xfs_defer_init_op_type( void xfs_defer_init( struct xfs_trans *tp, - struct xfs_defer_ops *dop, - xfs_fsblock_t *fbp) + struct xfs_defer_ops *dop) { struct xfs_mount *mp = NULL; memset(dop, 0, sizeof(struct xfs_defer_ops)); - *fbp = NULLFSBLOCK; INIT_LIST_HEAD(&dop->dop_intake); INIT_LIST_HEAD(&dop->dop_pending); if (tp) { + ASSERT(tp->t_firstblock == NULLFSBLOCK); tp->t_dfops = dop; mp = tp->t_mountp; } diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 56eaaac31df5..c17c9deda995 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -63,8 +63,7 @@ void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, struct list_head *h); int xfs_defer_finish(struct xfs_trans **tp, struct xfs_defer_ops *dop); void xfs_defer_cancel(struct xfs_defer_ops *dop); -void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop, - xfs_fsblock_t *fbp); +void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop); bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip); int xfs_defer_bjoin(struct xfs_defer_ops *dop, struct xfs_buf *bp); diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index d81c17aac710..2ecfb0518580 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -1691,7 +1691,7 @@ xfs_refcount_recover_cow_leftovers( trace_xfs_refcount_recover_extent(mp, agno, &rr->rr_rrec); /* Free the orphan record */ - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); agbno = rr->rr_rrec.rc_startblock - XFS_REFC_COW_START; fsb = XFS_AGB_TO_FSB(mp, agno, agbno); error = xfs_refcount_free_cow_extent(mp, tp->t_dfops, fsb, diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 765859843606..d3a314fd721f 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -971,7 +971,7 @@ xfs_alloc_file_space( xfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); error = xfs_bmapi_write(tp, ip, startoffset_fsb, allocatesize_fsb, alloc_type, resblks, imapp, &nimaps); @@ -1040,7 +1040,7 @@ xfs_unmap_extent( xfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); error = xfs_bunmapi(tp, ip, startoffset_fsb, len_fsb, 0, 2, done); if (error) goto out_bmap_cancel; @@ -1341,7 +1341,7 @@ xfs_collapse_file_space( goto out_trans_cancel; xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); error = xfs_bmap_collapse_extents(tp, ip, &next_fsb, shift_fsb, &done); if (error) @@ -1419,7 +1419,7 @@ xfs_insert_file_space( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); error = xfs_bmap_insert_extents(tp, ip, &next_fsb, shift_fsb, &done, stop_fsb); if (error) @@ -1605,7 +1605,7 @@ xfs_swap_extent_rmap( /* Unmap the old blocks in the source file. */ while (tirec.br_blockcount) { - xfs_defer_init(tp, tp->t_dfops, &tp->t_firstblock); + xfs_defer_init(tp, tp->t_dfops); trace_xfs_swap_extent_rmap_remap_piece(tip, &tirec); /* Read extent from the source file */ @@ -1909,7 +1909,7 @@ xfs_swap_extents( error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp); if (error) goto out_unlock; - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); /* * Lock and join the inodes to the tansaction so that transaction commit diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 3b61b4d266b4..c53de34c9ae5 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -295,7 +295,7 @@ xfs_dquot_disk_alloc( trace_xfs_dqalloc(dqp); - xfs_defer_init(tp, tp->t_dfops, &tp->t_firstblock); + xfs_defer_init(tp, tp->t_dfops); xfs_ilock(quotip, XFS_ILOCK_EXCL); if (!xfs_this_quota_on(dqp->q_mount, dqp->dq_flags)) { @@ -546,7 +546,7 @@ xfs_qm_dqread_alloc( XFS_QM_DQALLOC_SPACE_RES(mp), 0, 0, &tp); if (error) goto err; - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); error = xfs_dquot_disk_alloc(&tp, dqp, &bp); if (error) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 48d22134b06f..7b2694d3901a 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1194,7 +1194,7 @@ xfs_create( xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); unlock_dp_on_error = true; - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); /* * Reserve disk quota and the inode. @@ -1448,7 +1448,7 @@ xfs_link( goto error_return; } - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); /* * Handle initial link state of O_TMPFILE inode @@ -1579,7 +1579,7 @@ xfs_itruncate_extents_flags( ASSERT(first_unmap_block < last_block); unmap_len = last_block - first_unmap_block + 1; while (!done) { - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); error = xfs_bunmapi(tp, ip, first_unmap_block, unmap_len, flags, XFS_ITRUNC_MAX_EXTENTS, &done); if (error) @@ -1808,7 +1808,7 @@ xfs_inactive_ifree( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); error = xfs_ifree(tp, ip); if (error) { /* @@ -2651,7 +2651,7 @@ xfs_remove( if (error) goto out_trans_cancel; - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); error = xfs_dir_removename(tp, dp, name, ip->i_ino, resblks); if (error) { ASSERT(error != -ENOENT); @@ -3008,7 +3008,7 @@ xfs_rename( goto out_trans_cancel; } - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); /* RENAME_EXCHANGE is unique from here on. */ if (flags & RENAME_EXCHANGE) diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 0ae822538a63..756694219f77 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -253,7 +253,7 @@ xfs_iomap_write_direct( * From this point onwards we overwrite the imap pointer that the * caller gave to us. */ - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); nimaps = 1; error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, bmapi_flags, resblks, imap, &nimaps); @@ -713,7 +713,7 @@ xfs_iomap_write_allocate( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); /* * it is possible that the extents have changed since @@ -872,7 +872,7 @@ xfs_iomap_write_unwritten( /* * Modify the unwritten extent state of the buffer. */ - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); nimaps = 1; error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, XFS_BMAPI_CONVERT, resblks, &imap, diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 940eb30e0271..8317023293a5 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -4890,7 +4890,6 @@ xlog_recover_process_intents( struct xfs_ail_cursor cur; struct xfs_log_item *lip; struct xfs_ail *ailp; - xfs_fsblock_t firstfsb; int error = 0; #if defined(DEBUG) || defined(XFS_WARN) xfs_lsn_t last_lsn; @@ -4902,7 +4901,7 @@ xlog_recover_process_intents( #if defined(DEBUG) || defined(XFS_WARN) last_lsn = xlog_assign_lsn(log->l_curr_cycle, log->l_curr_block); #endif - xfs_defer_init(NULL, &dfops, &firstfsb); + xfs_defer_init(NULL, &dfops); while (lip != NULL) { /* * We're done when we see something other than an intent. diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 891214242118..3143889097f1 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -424,7 +424,7 @@ retry: xfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); nimaps = 1; /* Allocate the entire reservation as unwritten blocks. */ @@ -511,7 +511,7 @@ xfs_reflink_cancel_cow_blocks( if (error) break; } else if (del.br_state == XFS_EXT_UNWRITTEN || cancel_real) { - xfs_defer_init(*tpp, &dfops, &(*tpp)->t_firstblock); + xfs_defer_init(*tpp, &dfops); /* Free the CoW orphan record. */ error = xfs_refcount_free_cow_extent(ip->i_mount, @@ -693,7 +693,7 @@ xfs_reflink_end_cow( goto prev_extent; /* Unmap the old blocks in the data fork. */ - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); rlen = del.br_blockcount; error = __xfs_bunmapi(tp, ip, del.br_startoff, &rlen, 0, 1); if (error) @@ -1041,7 +1041,7 @@ xfs_reflink_remap_extent( /* Unmap the old blocks in the data fork. */ rlen = unmap_len; while (rlen) { - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); error = __xfs_bunmapi(tp, ip, destoff, &rlen, 0, 1); if (error) goto out_defer; diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index edd949376a51..bc471d42a968 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -786,7 +786,7 @@ xfs_growfs_rt_alloc( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); /* * Allocate blocks to the bitmap file. */ diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index a3dc552a5b97..d1ab0afa2723 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -245,7 +245,7 @@ xfs_symlink( * Initialize the bmap freelist prior to calling either * bmapi or the directory create code. */ - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); /* * Allocate an inode for the symlink. @@ -438,7 +438,7 @@ xfs_inactive_symlink_rmt( * Find the block(s) so we can inval and unmap them. */ done = 0; - xfs_defer_init(tp, &dfops, &tp->t_firstblock); + xfs_defer_init(tp, &dfops); nmaps = ARRAY_SIZE(mval); error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size), mval, &nmaps, 0); -- cgit v1.2.3 From 81b549aa626b650bbf00423c084c0fd5581169b9 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 19 Jul 2018 12:25:47 -0700 Subject: xfs: return from _defer_finish with a clean transaction The following assertion was seen on generic/051: XFS: Assertion failed: tp->t_firstblock == NULLFSBLOCK, file: fs/xfs/libxfs5 ------------[ cut here ]------------ kernel BUG at fs/xfs/xfs_message.c:102! invalid opcode: 0000 [#1] SMP PTI CPU: 2 PID: 20757 Comm: fsstress Not tainted 4.18.0-rc4+ #3969 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.1-1 04/01/4 RIP: 0010:assfail+0x23/0x30 Code: c3 66 0f 1f 44 00 00 48 89 f1 41 89 d0 48 c7 c6 88 e0 8c 82 48 89 fa RSP: 0018:ffff88012dc43c08 EFLAGS: 00010202 RAX: 0000000000000000 RBX: ffff88012dc43ca0 RCX: 0000000000000000 RDX: 00000000ffffffc0 RSI: 000000000000000a RDI: ffffffff828480eb RBP: ffff88012aa92758 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: f000000000000000 R12: 0000000000000000 R13: ffff88012dc43d48 R14: ffff88013092e7e8 R15: 0000000000000014 FS: 00007f8d689b8e80(0000) GS:ffff88013fd00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f8d689c7000 CR3: 000000012ba6a000 CR4: 00000000000006e0 Call Trace: xfs_defer_init+0xff/0x160 xfs_reflink_remap_extent+0x31b/0xa00 xfs_reflink_remap_blocks+0xec/0x4a0 xfs_reflink_remap_range+0x3a1/0x650 xfs_file_dedupe_range+0x39/0x50 vfs_dedupe_file_range+0x218/0x260 do_vfs_ioctl+0x262/0x6a0 ? __se_sys_newfstat+0x3c/0x60 ksys_ioctl+0x35/0x60 __x64_sys_ioctl+0x11/0x20 do_syscall_64+0x4b/0x190 entry_SYSCALL_64_after_hwframe+0x49/0xbe The root cause of the assertion failure is that xfs_defer_finish doesn't roll the transaction after processing all the deferred items. Therefore it returns a dirty transaction to the caller, which leaves the caller at risk of exceeding the transaction reservation if it logs more items. Brian Foster's patchset to move the defer_ops firstblock into the transaction requires t_firstblock == NULLFSBLOCK upon defer_ops initialization, which is how this was noticed at all. Reported-by: Christoph Hellwig Signed-off-by: Darrick J. Wong Reviewed-by: Brian Foster Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_defer.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 2713e2d808a7..c4b0eaeb5190 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -424,6 +424,12 @@ xfs_defer_finish( cleanup_fn(*tp, state, error); } + /* + * Roll the transaction once more to avoid returning to the caller + * with a dirty transaction. + */ + if ((*tp)->t_flags & XFS_TRANS_DIRTY) + error = xfs_defer_trans_roll(tp, dop); out: (*tp)->t_dfops = orig_dop; if (error) -- cgit v1.2.3 From 03f4e4b26cd5f6eed728f82d90039a19d1b51ce3 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Tue, 24 Jul 2018 13:43:09 -0700 Subject: xfs: make deferred processing safe for embedded dfops xfs_defer_finish() has a couple quirks that are not safe with respect to the upcoming internal dfops functionality. First, xfs_defer_finish() attaches the passed in dfops structure to ->t_dfops and caches and restores the original value. Second, it continues to use the initial dfops reference before and after the transaction roll. These behaviors assume that dop is an independent memory allocation from the transaction itself, which may not always be true once transactions begin to use an embedded dfops structure. In the latter model, dfops processing creates a new xfs_defer_ops structure with each transaction and the associated state is migrated across to the new transaction. Fix up xfs_defer_finish() to handle the possibility of the current dfops changing after a transaction roll. Since ->t_dfops is used unconditionally in this path, it is no longer necessary to attach/restore ->t_dfops and pass it explicitly down to xfs_defer_trans_roll(). Update dop in the latter function and the caller to ensure that it always refers to the current dfops structure. Signed-off-by: Brian Foster Reviewed-by: Christoph Hellwig Reviewed-by: Bill O'Donnell Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_defer.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index c4b0eaeb5190..ee734a8b3fa9 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -225,9 +225,9 @@ xfs_defer_trans_abort( /* Roll a transaction so we can do some deferred op processing. */ STATIC int xfs_defer_trans_roll( - struct xfs_trans **tp, - struct xfs_defer_ops *dop) + struct xfs_trans **tp) { + struct xfs_defer_ops *dop = (*tp)->t_dfops; int i; int error; @@ -243,6 +243,7 @@ xfs_defer_trans_roll( /* Roll the transaction. */ error = xfs_trans_roll(tp); + dop = (*tp)->t_dfops; if (error) { trace_xfs_defer_trans_roll_error((*tp)->t_mountp, dop, error); xfs_defer_trans_abort(*tp, dop, error); @@ -338,31 +339,25 @@ xfs_defer_finish( void *state; int error = 0; void (*cleanup_fn)(struct xfs_trans *, void *, int); - struct xfs_defer_ops *orig_dop; ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); + ASSERT((*tp)->t_dfops == dop); trace_xfs_defer_finish((*tp)->t_mountp, dop, _RET_IP_); - /* - * Attach dfops to the transaction during deferred ops processing. This - * explicitly causes calls into the allocator to defer AGFL block frees. - * Note that this code can go away once all dfops users attach to the - * associated tp. - */ - ASSERT(!(*tp)->t_dfops || ((*tp)->t_dfops == dop)); - orig_dop = (*tp)->t_dfops; - (*tp)->t_dfops = dop; - /* Until we run out of pending work to finish... */ while (xfs_defer_has_unfinished_work(dop)) { /* Log intents for work items sitting in the intake. */ xfs_defer_intake_work(*tp, dop); - /* Roll the transaction. */ - error = xfs_defer_trans_roll(tp, dop); + /* + * Roll the transaction and update dop in case dfops was + * embedded in the transaction. + */ + error = xfs_defer_trans_roll(tp); if (error) goto out; + dop = (*tp)->t_dfops; /* Log an intent-done item for the first pending item. */ dfp = list_first_entry(&dop->dop_pending, @@ -428,10 +423,11 @@ xfs_defer_finish( * Roll the transaction once more to avoid returning to the caller * with a dirty transaction. */ - if ((*tp)->t_flags & XFS_TRANS_DIRTY) - error = xfs_defer_trans_roll(tp, dop); + if ((*tp)->t_flags & XFS_TRANS_DIRTY) { + error = xfs_defer_trans_roll(tp); + dop = (*tp)->t_dfops; + } out: - (*tp)->t_dfops = orig_dop; if (error) trace_xfs_defer_finish_error((*tp)->t_mountp, dop, error); else -- cgit v1.2.3 From 83200bfac6082a46cc962366478d050052e50450 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Tue, 24 Jul 2018 13:43:09 -0700 Subject: xfs: remove unused deferred ops committed field dop_committed is set when deferred item processing rolls the transaction at least once, but is only ever accessed in tracepoints. The transaction roll/commit events are already available via independent tracepoints, so remove the otherwise unused field. Signed-off-by: Brian Foster Reviewed-by: Christoph Hellwig Reviewed-by: Bill O'Donnell Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_defer.c | 1 - fs/xfs/libxfs/xfs_defer.h | 1 - fs/xfs/xfs_trace.h | 8 ++------ 3 files changed, 2 insertions(+), 8 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index ee734a8b3fa9..0df09c094e42 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -249,7 +249,6 @@ xfs_defer_trans_roll( xfs_defer_trans_abort(*tp, dop, error); return error; } - dop->dop_committed = true; /* Rejoin the joined inodes. */ for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index c17c9deda995..58c979c9f3fa 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -49,7 +49,6 @@ enum xfs_defer_ops_type { #define XFS_DEFER_OPS_NR_BUFS 2 /* join up to two buffers */ struct xfs_defer_ops { - bool dop_committed; /* did any trans commit? */ bool dop_low; /* alloc in low mode */ struct list_head dop_intake; /* unlogged pending work */ struct list_head dop_pending; /* logged pending work */ diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index b668fc127aa7..cc6995cfce66 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2229,14 +2229,12 @@ DECLARE_EVENT_CLASS(xfs_defer_class, TP_fast_assign( __entry->dev = mp ? mp->m_super->s_dev : 0; __entry->dop = dop; - __entry->committed = dop->dop_committed; __entry->low = dop->dop_low; __entry->caller_ip = caller_ip; ), - TP_printk("dev %d:%d ops %p committed %d low %d, caller %pS", + TP_printk("dev %d:%d ops %p low %d, caller %pS", MAJOR(__entry->dev), MINOR(__entry->dev), __entry->dop, - __entry->committed, __entry->low, (char *)__entry->caller_ip) ) @@ -2259,14 +2257,12 @@ DECLARE_EVENT_CLASS(xfs_defer_error_class, TP_fast_assign( __entry->dev = mp ? mp->m_super->s_dev : 0; __entry->dop = dop; - __entry->committed = dop->dop_committed; __entry->low = dop->dop_low; __entry->error = error; ), - TP_printk("dev %d:%d ops %p committed %d low %d err %d", + TP_printk("dev %d:%d ops %p low %d err %d", MAJOR(__entry->dev), MINOR(__entry->dev), __entry->dop, - __entry->committed, __entry->low, __entry->error) ) -- cgit v1.2.3 From 509308b413c9e4e3140b4bc524522255d126787e Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Tue, 24 Jul 2018 13:43:10 -0700 Subject: xfs: reset dfops to initial state after finish xfs_defer_init() is currently used in two particular situations. The first and most obvious case is raw initialization of an xfs_defer_ops struct. The other case is partial reinit of xfs_defer_ops on reuse due to iteration. Most instances of the first case will be replaced by a single init of a dfops embedded in the transaction. Init calls are still technically required for the second case because the dfops may have low space mode enabled or have joined items that need to be reset before the dfops should be reused. Since the current dfops usage expects either a final transaction commit after xfs_defer_finish() or xfs_defer_init() if dfops is to be reused, we can shift some of the init logic into xfs_defer_finish() such that the latter returns with a reinitialized dfops. This eliminates the second dependency noted above such that a dfops is immediately ready for reuse after an xfs_defer_finish() without the need to change any calling code. Signed-off-by: Brian Foster Reviewed-by: Christoph Hellwig Reviewed-by: Bill O'Donnell Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_defer.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 0df09c094e42..23f2a52b088e 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -319,6 +319,19 @@ xfs_defer_bjoin( return -EFSCORRUPTED; } +/* + * Reset an already used dfops after finish. + */ +static void +xfs_defer_reset( + struct xfs_defer_ops *dop) +{ + ASSERT(!xfs_defer_has_unfinished_work(dop)); + dop->dop_low = false; + memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes)); + memset(dop->dop_bufs, 0, sizeof(dop->dop_bufs)); +} + /* * Finish all the pending work. This involves logging intent items for * any work items that wandered in since the last transaction roll (if @@ -427,10 +440,13 @@ xfs_defer_finish( dop = (*tp)->t_dfops; } out: - if (error) + if (error) { trace_xfs_defer_finish_error((*tp)->t_mountp, dop, error); - else + } else { trace_xfs_defer_finish_done((*tp)->t_mountp, dop, _RET_IP_); + xfs_defer_reset(dop); + } + return error; } -- cgit v1.2.3 From e021a2e5fc520d930f949f303e7307038e258645 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Tue, 24 Jul 2018 13:43:11 -0700 Subject: xfs: support embedded dfops in transaction The dfops structure used by multi-transaction operations is typically stored on the stack and carried around by the associated transaction. The lifecycle of dfops does not quite match that of the transaction, but they are tightly related in that the former depends on the latter. The relationship of these objects is tight enough that we can avoid the cumbersome boilerplate code required in most cases to manage them separately by just embedding an xfs_defer_ops in the transaction itself. This means that a transaction allocation returns with an initialized dfops, a transaction commit finishes pending deferred items before the tx commit, a transaction cancel cancels the dfops before the transaction and a transaction dup operation transfers the current dfops state to the new transaction. The dup operation is slightly complicated by the fact that we can no longer just copy a dfops pointer from the old transaction to the new transaction. This is solved through a dfops move helper that transfers the pending items and other dfops state across the transactions. This also requires that transaction rolling code always refer to the transaction for the current dfops reference. Finally, to facilitate incremental conversion to the internal dfops and continue to support the current external dfops mode of operation, create the new ->t_dfops_internal field with a layer of indirection. On allocation, ->t_dfops points to the internal dfops. This state is overridden by callers who re-init a local dfops on the transaction. Once ->t_dfops is overridden, the external dfops reference is maintained as the transaction rolls. This patch adds the fundamental ability to support an internal dfops. All codepaths that perform deferred processing continue to override the internal dfops until they are converted over in subsequent patches. Signed-off-by: Brian Foster Reviewed-by: Bill O'Donnell Reviewed-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_defer.c | 22 ++++++++++++++++++++++ fs/xfs/libxfs/xfs_defer.h | 16 ++-------------- fs/xfs/xfs_trans.c | 30 ++++++++++++++++++++++++++---- fs/xfs/xfs_trans.h | 17 ++++++++++++++++- 4 files changed, 66 insertions(+), 19 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 23f2a52b088e..b63cc9e730da 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -555,3 +555,25 @@ xfs_defer_init( } trace_xfs_defer_init(mp, dop, _RET_IP_); } + +/* + * Move state from one xfs_defer_ops to another and reset the source to initial + * state. This is primarily used to carry state forward across transaction rolls + * with internal dfops. + */ +void +xfs_defer_move( + struct xfs_defer_ops *dst, + struct xfs_defer_ops *src) +{ + ASSERT(dst != src); + + list_splice_init(&src->dop_intake, &dst->dop_intake); + list_splice_init(&src->dop_pending, &dst->dop_pending); + + memcpy(dst->dop_inodes, src->dop_inodes, sizeof(dst->dop_inodes)); + memcpy(dst->dop_bufs, src->dop_bufs, sizeof(dst->dop_bufs)); + dst->dop_low = src->dop_low; + + xfs_defer_reset(src); +} diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 8f58f217fdff..35507ca9a148 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -7,6 +7,7 @@ #define __XFS_DEFER_H__ struct xfs_defer_op_type; +struct xfs_defer_ops; /* * Save a log intent item and a list of extents, so that we can replay @@ -45,20 +46,6 @@ enum xfs_defer_ops_type { XFS_DEFER_OPS_TYPE_MAX, }; -#define XFS_DEFER_OPS_NR_INODES 2 /* join up to two inodes */ -#define XFS_DEFER_OPS_NR_BUFS 2 /* join up to two buffers */ - -struct xfs_defer_ops { - struct list_head dop_intake; /* unlogged pending work */ - struct list_head dop_pending; /* logged pending work */ - - /* relog these with each roll */ - struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES]; - struct xfs_buf *dop_bufs[XFS_DEFER_OPS_NR_BUFS]; - - bool dop_low; /* alloc in low mode */ -}; - void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, struct list_head *h); int xfs_defer_finish(struct xfs_trans **tp, struct xfs_defer_ops *dop); @@ -67,6 +54,7 @@ void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop); bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip); int xfs_defer_bjoin(struct xfs_defer_ops *dop, struct xfs_buf *bp); +void xfs_defer_move(struct xfs_defer_ops *dst, struct xfs_defer_ops *src); /* Description of a deferred type. */ struct xfs_defer_op_type { diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index de00f79ff698..412c8d236c71 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -119,7 +119,13 @@ xfs_trans_dup( ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used; tp->t_rtx_res = tp->t_rtx_res_used; ntp->t_pflags = tp->t_pflags; - ntp->t_dfops = tp->t_dfops; + + /* copy the dfops pointer if it's external, otherwise move it */ + xfs_defer_init(ntp, &ntp->t_dfops_internal); + if (tp->t_dfops != &tp->t_dfops_internal) + ntp->t_dfops = tp->t_dfops; + else + xfs_defer_move(ntp->t_dfops, tp->t_dfops); xfs_trans_dup_dqinfo(tp, ntp); @@ -275,6 +281,13 @@ xfs_trans_alloc( INIT_LIST_HEAD(&tp->t_items); INIT_LIST_HEAD(&tp->t_busy); tp->t_firstblock = NULLFSBLOCK; + /* + * We only roll transactions with permanent log reservation. Don't init + * ->t_dfops to skip attempts to finish or cancel an empty dfops with a + * non-permanent res. + */ + if (resp->tr_logflags & XFS_TRANS_PERM_LOG_RES) + xfs_defer_init(tp, &tp->t_dfops_internal); error = xfs_trans_reserve(tp, resp, blocks, rtextents); if (error) { @@ -916,11 +929,17 @@ __xfs_trans_commit( int error = 0; int sync = tp->t_flags & XFS_TRANS_SYNC; - ASSERT(!tp->t_dfops || - !xfs_defer_has_unfinished_work(tp->t_dfops) || regrant); - trace_xfs_trans_commit(tp, _RET_IP_); + /* finish deferred items on final commit */ + if (!regrant && tp->t_dfops) { + error = xfs_defer_finish(&tp, tp->t_dfops); + if (error) { + xfs_defer_cancel(tp->t_dfops); + goto out_unreserve; + } + } + /* * If there is nothing to be logged by the transaction, * then unlock all of the items associated with the @@ -1010,6 +1029,9 @@ xfs_trans_cancel( trace_xfs_trans_cancel(tp, _RET_IP_); + if (tp->t_dfops) + xfs_defer_cancel(tp->t_dfops); + /* * See if the caller is relying on us to shut down the * filesystem. This happens in paths where we detect diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 6f857af61455..dc79e3c1d3e8 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -24,7 +24,6 @@ struct xfs_rui_log_item; struct xfs_btree_cur; struct xfs_cui_log_item; struct xfs_cud_log_item; -struct xfs_defer_ops; struct xfs_bui_log_item; struct xfs_bud_log_item; @@ -90,6 +89,21 @@ void xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *item, #define XFS_ITEM_LOCKED 2 #define XFS_ITEM_FLUSHING 3 +/* + * Deferred operations tracking structure. + */ +#define XFS_DEFER_OPS_NR_INODES 2 /* join up to two inodes */ +#define XFS_DEFER_OPS_NR_BUFS 2 /* join up to two buffers */ +struct xfs_defer_ops { + struct list_head dop_intake; /* unlogged pending work */ + struct list_head dop_pending; /* logged pending work */ + + /* relog these with each roll */ + struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES]; + struct xfs_buf *dop_bufs[XFS_DEFER_OPS_NR_BUFS]; + + bool dop_low; /* alloc in low mode */ +}; /* * This is the structure maintained for every active transaction. @@ -130,6 +144,7 @@ typedef struct xfs_trans { struct list_head t_items; /* log item descriptors */ struct list_head t_busy; /* list of busy extents */ unsigned long t_pflags; /* saved process flags state */ + struct xfs_defer_ops t_dfops_internal; } xfs_trans_t; /* -- cgit v1.2.3 From 9e28a242be65b8274742425ca5d146f366205a90 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Tue, 24 Jul 2018 13:43:15 -0700 Subject: xfs: drop unnecessary xfs_defer_finish() dfops parameter Every caller of xfs_defer_finish() now passes the transaction and its associated ->t_dfops. The xfs_defer_ops parameter is therefore no longer necessary and can be removed. Since most xfs_defer_finish() callers also have to consider xfs_defer_cancel() on error, update the latter to also receive the transaction for consistency. The log recovery code contains an outlier case that cancels a dfops directly without an available transaction. Retain an internal wrapper to support this outlier case for the time being. Signed-off-by: Brian Foster Reviewed-by: Bill O'Donnell Reviewed-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 27 +++++++++++++-------------- fs/xfs/libxfs/xfs_attr_remote.c | 8 ++++---- fs/xfs/libxfs/xfs_defer.c | 7 +++---- fs/xfs/libxfs/xfs_defer.h | 4 ++-- fs/xfs/xfs_bmap_util.c | 4 ++-- fs/xfs/xfs_dquot.c | 4 ++-- fs/xfs/xfs_inode.c | 4 ++-- fs/xfs/xfs_log_recover.c | 2 +- fs/xfs/xfs_reflink.c | 8 ++++---- fs/xfs/xfs_trans.c | 13 ++++++++++--- fs/xfs/xfs_trans.h | 3 +++ 11 files changed, 46 insertions(+), 38 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 3e98f0af389c..3deb5cdadf08 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -322,7 +322,7 @@ xfs_attr_set( xfs_trans_bhold(args.trans, leaf_bp); xfs_defer_bjoin(args.trans->t_dfops, leaf_bp); xfs_defer_ijoin(args.trans->t_dfops, dp); - error = xfs_defer_finish(&args.trans, args.trans->t_dfops); + error = xfs_defer_finish(&args.trans); if (error) goto out; @@ -591,7 +591,7 @@ xfs_attr_leaf_addname( if (error) goto out_defer_cancel; xfs_defer_ijoin(args->trans->t_dfops, dp); - error = xfs_defer_finish(&args->trans, args->trans->t_dfops); + error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; @@ -680,7 +680,7 @@ xfs_attr_leaf_addname( if (error) goto out_defer_cancel; xfs_defer_ijoin(args->trans->t_dfops, dp); - error = xfs_defer_finish(&args->trans, args->trans->t_dfops); + error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; } @@ -698,7 +698,7 @@ xfs_attr_leaf_addname( } return error; out_defer_cancel: - xfs_defer_cancel(args->trans->t_dfops); + xfs_defer_cancel(args->trans); return error; } @@ -744,13 +744,13 @@ xfs_attr_leaf_removename( if (error) goto out_defer_cancel; xfs_defer_ijoin(args->trans->t_dfops, dp); - error = xfs_defer_finish(&args->trans, args->trans->t_dfops); + error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; } return 0; out_defer_cancel: - xfs_defer_cancel(args->trans->t_dfops); + xfs_defer_cancel(args->trans); return error; } @@ -871,8 +871,7 @@ restart: if (error) goto out_defer_cancel; xfs_defer_ijoin(args->trans->t_dfops, dp); - error = xfs_defer_finish(&args->trans, - args->trans->t_dfops); + error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; @@ -897,7 +896,7 @@ restart: if (error) goto out_defer_cancel; xfs_defer_ijoin(args->trans->t_dfops, dp); - error = xfs_defer_finish(&args->trans, args->trans->t_dfops); + error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; } else { @@ -994,7 +993,7 @@ restart: if (error) goto out_defer_cancel; xfs_defer_ijoin(args->trans->t_dfops, dp); - error = xfs_defer_finish(&args->trans, args->trans->t_dfops); + error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; } @@ -1023,7 +1022,7 @@ out: return error; return retval; out_defer_cancel: - xfs_defer_cancel(args->trans->t_dfops); + xfs_defer_cancel(args->trans); goto out; } @@ -1118,7 +1117,7 @@ xfs_attr_node_removename( if (error) goto out_defer_cancel; xfs_defer_ijoin(args->trans->t_dfops, dp); - error = xfs_defer_finish(&args->trans, args->trans->t_dfops); + error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; /* @@ -1150,7 +1149,7 @@ xfs_attr_node_removename( if (error) goto out_defer_cancel; xfs_defer_ijoin(args->trans->t_dfops, dp); - error = xfs_defer_finish(&args->trans, args->trans->t_dfops); + error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; } else @@ -1162,7 +1161,7 @@ out: xfs_da_state_free(state); return error; out_defer_cancel: - xfs_defer_cancel(args->trans->t_dfops); + xfs_defer_cancel(args->trans); goto out; } diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index 0fbfb740949e..77ca38586913 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c @@ -487,7 +487,7 @@ xfs_attr_rmtval_set( if (error) goto out_defer_cancel; xfs_defer_ijoin(args->trans->t_dfops, dp); - error = xfs_defer_finish(&args->trans, args->trans->t_dfops); + error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; @@ -555,7 +555,7 @@ xfs_attr_rmtval_set( ASSERT(valuelen == 0); return 0; out_defer_cancel: - xfs_defer_cancel(args->trans->t_dfops); + xfs_defer_cancel(args->trans); return error; } @@ -628,7 +628,7 @@ xfs_attr_rmtval_remove( if (error) goto out_defer_cancel; xfs_defer_ijoin(args->trans->t_dfops, args->dp); - error = xfs_defer_finish(&args->trans, args->trans->t_dfops); + error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; @@ -641,6 +641,6 @@ xfs_attr_rmtval_remove( } return 0; out_defer_cancel: - xfs_defer_cancel(args->trans->t_dfops); + xfs_defer_cancel(args->trans); return error; } diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index b63cc9e730da..cbee0a86c978 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -342,9 +342,9 @@ xfs_defer_reset( */ int xfs_defer_finish( - struct xfs_trans **tp, - struct xfs_defer_ops *dop) + struct xfs_trans **tp) { + struct xfs_defer_ops *dop = (*tp)->t_dfops; struct xfs_defer_pending *dfp; struct list_head *li; struct list_head *n; @@ -353,7 +353,6 @@ xfs_defer_finish( void (*cleanup_fn)(struct xfs_trans *, void *, int); ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); - ASSERT((*tp)->t_dfops == dop); trace_xfs_defer_finish((*tp)->t_mountp, dop, _RET_IP_); @@ -454,7 +453,7 @@ out: * Free up any items left in the list. */ void -xfs_defer_cancel( +__xfs_defer_cancel( struct xfs_defer_ops *dop) { struct xfs_defer_pending *dfp; diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 35507ca9a148..56f927803940 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -48,8 +48,8 @@ enum xfs_defer_ops_type { void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, struct list_head *h); -int xfs_defer_finish(struct xfs_trans **tp, struct xfs_defer_ops *dop); -void xfs_defer_cancel(struct xfs_defer_ops *dop); +int xfs_defer_finish(struct xfs_trans **tp); +void __xfs_defer_cancel(struct xfs_defer_ops *dop); void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop); bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip); diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index ddb5f1200d3d..c32ec17048f5 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1624,7 +1624,7 @@ xfs_swap_extent_rmap( goto out_defer; xfs_defer_ijoin(tp->t_dfops, ip); - error = xfs_defer_finish(tpp, tp->t_dfops); + error = xfs_defer_finish(tpp); tp = *tpp; if (error) goto out_defer; @@ -1645,7 +1645,7 @@ xfs_swap_extent_rmap( return 0; out_defer: - xfs_defer_cancel(tp->t_dfops); + xfs_defer_cancel(tp); out: trace_xfs_swap_extent_rmap_error(ip, error, _RET_IP_); tip->i_d.di_flags2 = tip_flags2; diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index a57d5e8c3118..da5c55cec966 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -368,7 +368,7 @@ xfs_dquot_disk_alloc( xfs_trans_brelse(tp, bp); goto error1; } - error = xfs_defer_finish(tpp, tp->t_dfops); + error = xfs_defer_finish(tpp); tp = *tpp; if (error) { xfs_buf_relse(bp); @@ -378,7 +378,7 @@ xfs_dquot_disk_alloc( return 0; error1: - xfs_defer_cancel(tp->t_dfops); + xfs_defer_cancel(tp); error0: return error; } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index c47183a2f167..0e4bd559a6a7 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1570,7 +1570,7 @@ xfs_itruncate_extents_flags( * reservation and commit the old transaction. */ xfs_defer_ijoin(tp->t_dfops, ip); - error = xfs_defer_finish(&tp, tp->t_dfops); + error = xfs_defer_finish(&tp); if (error) goto out_bmap_cancel; @@ -1606,7 +1606,7 @@ out_bmap_cancel: * the transaction can be properly aborted. We just need to make sure * we're not holding any resources that we were not when we came in. */ - xfs_defer_cancel(tp->t_dfops); + xfs_defer_cancel(tp); goto out; } diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 265e1f561157..94908a4019e1 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -4946,7 +4946,7 @@ out: xfs_trans_ail_cursor_done(&cur); spin_unlock(&ailp->ail_lock); if (error) - xfs_defer_cancel(&dfops); + __xfs_defer_cancel(&dfops); else error = xlog_finish_defer_ops(log->l_mp, &dfops); diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index a653739c9fb2..68b6921dc3f6 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -518,9 +518,9 @@ xfs_reflink_cancel_cow_blocks( /* Roll the transaction */ xfs_defer_ijoin((*tpp)->t_dfops, ip); - error = xfs_defer_finish(tpp, (*tpp)->t_dfops); + error = xfs_defer_finish(tpp); if (error) { - xfs_defer_cancel((*tpp)->t_dfops); + xfs_defer_cancel(*tpp); break; } @@ -716,7 +716,7 @@ xfs_reflink_end_cow( xfs_bmap_del_extent_cow(ip, &icur, &got, &del); xfs_defer_ijoin(tp->t_dfops, ip); - error = xfs_defer_finish(&tp, tp->t_dfops); + error = xfs_defer_finish(&tp); if (error) goto out_cancel; if (!xfs_iext_get_extent(ifp, &icur, &got)) @@ -1077,7 +1077,7 @@ xfs_reflink_remap_extent( next_extent: /* Process all the deferred stuff. */ xfs_defer_ijoin(tp->t_dfops, ip); - error = xfs_defer_finish(&tp, tp->t_dfops); + error = xfs_defer_finish(&tp); if (error) goto out_cancel; } diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 412c8d236c71..cd553aa9ecb0 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -933,9 +933,9 @@ __xfs_trans_commit( /* finish deferred items on final commit */ if (!regrant && tp->t_dfops) { - error = xfs_defer_finish(&tp, tp->t_dfops); + error = xfs_defer_finish(&tp); if (error) { - xfs_defer_cancel(tp->t_dfops); + xfs_defer_cancel(tp); goto out_unreserve; } } @@ -1030,7 +1030,7 @@ xfs_trans_cancel( trace_xfs_trans_cancel(tp, _RET_IP_); if (tp->t_dfops) - xfs_defer_cancel(tp->t_dfops); + xfs_defer_cancel(tp); /* * See if the caller is relying on us to shut down the @@ -1111,3 +1111,10 @@ xfs_trans_roll( tres.tr_logflags = XFS_TRANS_PERM_LOG_RES; return xfs_trans_reserve(*tpp, &tres, 0, 0); } + +void +xfs_defer_cancel( + struct xfs_trans *tp) +{ + __xfs_defer_cancel(tp->t_dfops); +} diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index dc79e3c1d3e8..5170e89bec02 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -214,6 +214,9 @@ xfs_trans_read_buf( flags, bpp, ops); } +/* cancel dfops associated with a transaction */ +void xfs_defer_cancel(struct xfs_trans *); + struct xfs_buf *xfs_trans_getsb(xfs_trans_t *, struct xfs_mount *, int); void xfs_trans_brelse(xfs_trans_t *, struct xfs_buf *); -- cgit v1.2.3 From b277c37f43dd387f7430a2186deda0e58c943087 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Tue, 24 Jul 2018 13:43:15 -0700 Subject: xfs: bypass final dfops roll in trans commit path Once xfs_defer_finish() has completed all deferred operations, it checks the dirty state of the transaction and rolls it once more to return a clean transaction for the caller. This primarily to cover the case where repeated xfs_defer_finish() calls are made in a loop and we need to make sure that the caller starts the next iteration with a clean transaction. Otherwise we risk transaction reservation overrun. This final transaction roll is not required in the transaction commit path, however, because the transaction is immediately committed and freed after dfops completion. Refactor the final roll into a separate helper such that we can avoid it in the transaction commit path. Lift the dfops reset as well so dfops remains valid until after the last call to xfs_defer_trans_roll(). The reset is also unnecessary in the transaction commit path because the transaction is about to complete. This eliminates unnecessary regrants of transactions where the associated transaction roll can be replaced by a transaction commit. Signed-off-by: Brian Foster Reviewed-by: Bill O'Donnell Reviewed-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_defer.c | 38 +++++++++++++++++++++++++------------- fs/xfs/libxfs/xfs_defer.h | 1 + fs/xfs/xfs_trans.c | 2 +- 3 files changed, 27 insertions(+), 14 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index cbee0a86c978..a5f7dc18a62f 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -341,7 +341,7 @@ xfs_defer_reset( * If an inode is provided, relog it to the new transaction. */ int -xfs_defer_finish( +xfs_defer_finish_noroll( struct xfs_trans **tp) { struct xfs_defer_ops *dop = (*tp)->t_dfops; @@ -430,25 +430,37 @@ xfs_defer_finish( cleanup_fn(*tp, state, error); } - /* - * Roll the transaction once more to avoid returning to the caller - * with a dirty transaction. - */ - if ((*tp)->t_flags & XFS_TRANS_DIRTY) { - error = xfs_defer_trans_roll(tp); - dop = (*tp)->t_dfops; - } out: - if (error) { + if (error) trace_xfs_defer_finish_error((*tp)->t_mountp, dop, error); - } else { + else trace_xfs_defer_finish_done((*tp)->t_mountp, dop, _RET_IP_); - xfs_defer_reset(dop); - } return error; } +int +xfs_defer_finish( + struct xfs_trans **tp) +{ + int error; + + /* + * Finish and roll the transaction once more to avoid returning to the + * caller with a dirty transaction. + */ + error = xfs_defer_finish_noroll(tp); + if (error) + return error; + if ((*tp)->t_flags & XFS_TRANS_DIRTY) { + error = xfs_defer_trans_roll(tp); + if (error) + return error; + } + xfs_defer_reset((*tp)->t_dfops); + return 0; +} + /* * Free up any items left in the list. */ diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 56f927803940..85c41fe4dbae 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -48,6 +48,7 @@ enum xfs_defer_ops_type { void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, struct list_head *h); +int xfs_defer_finish_noroll(struct xfs_trans **tp); int xfs_defer_finish(struct xfs_trans **tp); void __xfs_defer_cancel(struct xfs_defer_ops *dop); void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop); diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index cd553aa9ecb0..7bf5c1202719 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -933,7 +933,7 @@ __xfs_trans_commit( /* finish deferred items on final commit */ if (!regrant && tp->t_dfops) { - error = xfs_defer_finish(&tp); + error = xfs_defer_finish_noroll(&tp); if (error) { xfs_defer_cancel(tp); goto out_unreserve; -- cgit v1.2.3 From 7279aa13b8fb954f50073a672f912898198efd14 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 1 Aug 2018 07:20:30 -0700 Subject: xfs: remove unused __xfs_defer_cancel() internal helper With no more external dfops users, there is no need for an xfs_defer_ops cancel wrapper. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Reviewed-by: Christoph Hellwig Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_defer.c | 5 +++-- fs/xfs/libxfs/xfs_defer.h | 2 +- fs/xfs/xfs_trans.c | 7 ------- fs/xfs/xfs_trans.h | 3 --- 4 files changed, 4 insertions(+), 13 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index a5f7dc18a62f..ebead781613f 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -465,9 +465,10 @@ xfs_defer_finish( * Free up any items left in the list. */ void -__xfs_defer_cancel( - struct xfs_defer_ops *dop) +xfs_defer_cancel( + struct xfs_trans *tp) { + struct xfs_defer_ops *dop = tp->t_dfops; struct xfs_defer_pending *dfp; struct xfs_defer_pending *pli; struct list_head *pwi; diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 85c41fe4dbae..da145fc04ae1 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -50,7 +50,7 @@ void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, struct list_head *h); int xfs_defer_finish_noroll(struct xfs_trans **tp); int xfs_defer_finish(struct xfs_trans **tp); -void __xfs_defer_cancel(struct xfs_defer_ops *dop); +void xfs_defer_cancel(struct xfs_trans *); void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop); bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip); diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 12b6ad1558e6..0d07cdcc5c7d 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -1110,10 +1110,3 @@ xfs_trans_roll( tres.tr_logflags = XFS_TRANS_PERM_LOG_RES; return xfs_trans_reserve(*tpp, &tres, 0, 0); } - -void -xfs_defer_cancel( - struct xfs_trans *tp) -{ - __xfs_defer_cancel(tp->t_dfops); -} diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 5170e89bec02..dc79e3c1d3e8 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -214,9 +214,6 @@ xfs_trans_read_buf( flags, bpp, ops); } -/* cancel dfops associated with a transaction */ -void xfs_defer_cancel(struct xfs_trans *); - struct xfs_buf *xfs_trans_getsb(xfs_trans_t *, struct xfs_mount *, int); void xfs_trans_brelse(xfs_trans_t *, struct xfs_buf *); -- cgit v1.2.3 From ce356d64772f920f26cd6c1b02878a737a275638 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 1 Aug 2018 07:20:30 -0700 Subject: xfs: pass transaction to dfops reset/move helpers All callers pass ->t_dfops of the associated transactions. Refactor the helpers to receive the transactions and facilitate further cleanups between xfs_defer_ops and xfs_trans. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Reviewed-by: Christoph Hellwig Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_defer.c | 15 ++++++++++----- fs/xfs/libxfs/xfs_defer.h | 2 +- fs/xfs/xfs_bmap_item.c | 6 +++--- fs/xfs/xfs_log_recover.c | 2 +- fs/xfs/xfs_refcount_item.c | 6 +++--- fs/xfs/xfs_trans.c | 2 +- 6 files changed, 19 insertions(+), 14 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index ebead781613f..e3517a53c525 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -324,9 +324,12 @@ xfs_defer_bjoin( */ static void xfs_defer_reset( - struct xfs_defer_ops *dop) + struct xfs_trans *tp) { + struct xfs_defer_ops *dop = tp->t_dfops; + ASSERT(!xfs_defer_has_unfinished_work(dop)); + dop->dop_low = false; memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes)); memset(dop->dop_bufs, 0, sizeof(dop->dop_bufs)); @@ -457,7 +460,7 @@ xfs_defer_finish( if (error) return error; } - xfs_defer_reset((*tp)->t_dfops); + xfs_defer_reset(*tp); return 0; } @@ -575,9 +578,11 @@ xfs_defer_init( */ void xfs_defer_move( - struct xfs_defer_ops *dst, - struct xfs_defer_ops *src) + struct xfs_trans *dtp, + struct xfs_trans *stp) { + struct xfs_defer_ops *dst = dtp->t_dfops; + struct xfs_defer_ops *src = stp->t_dfops; ASSERT(dst != src); list_splice_init(&src->dop_intake, &dst->dop_intake); @@ -587,5 +592,5 @@ xfs_defer_move( memcpy(dst->dop_bufs, src->dop_bufs, sizeof(dst->dop_bufs)); dst->dop_low = src->dop_low; - xfs_defer_reset(src); + xfs_defer_reset(stp); } diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index da145fc04ae1..d60c50498fdf 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -55,7 +55,7 @@ void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop); bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip); int xfs_defer_bjoin(struct xfs_defer_ops *dop, struct xfs_buf *bp); -void xfs_defer_move(struct xfs_defer_ops *dst, struct xfs_defer_ops *src); +void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp); /* Description of a deferred type. */ struct xfs_defer_op_type { diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c index 57429055e608..b8a6be036cd7 100644 --- a/fs/xfs/xfs_bmap_item.c +++ b/fs/xfs/xfs_bmap_item.c @@ -446,7 +446,7 @@ xfs_bui_recover( * finishes them on completion. Transfer current dfops state to this * transaction and transfer the result back before we return. */ - xfs_defer_move(tp->t_dfops, parent_tp->t_dfops); + xfs_defer_move(tp, parent_tp); budp = xfs_trans_get_bud(tp, buip); /* Grab the inode. */ @@ -494,7 +494,7 @@ xfs_bui_recover( } set_bit(XFS_BUI_RECOVERED, &buip->bui_flags); - xfs_defer_move(parent_tp->t_dfops, tp->t_dfops); + xfs_defer_move(parent_tp, tp); error = xfs_trans_commit(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); xfs_irele(ip); @@ -502,7 +502,7 @@ xfs_bui_recover( return error; err_inode: - xfs_defer_move(parent_tp->t_dfops, tp->t_dfops); + xfs_defer_move(parent_tp, tp); xfs_trans_cancel(tp); if (ip) { xfs_iunlock(ip, XFS_ILOCK_EXCL); diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index fc1ce9a644e3..a21dc61ec09e 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -4853,7 +4853,7 @@ xlog_finish_defer_ops( if (error) return error; /* transfer all collected dfops to this transaction */ - xfs_defer_move(tp->t_dfops, parent_tp->t_dfops); + xfs_defer_move(tp, parent_tp); return xfs_trans_commit(tp); } diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c index 011e1d0640fb..4a417daae781 100644 --- a/fs/xfs/xfs_refcount_item.c +++ b/fs/xfs/xfs_refcount_item.c @@ -457,7 +457,7 @@ xfs_cui_recover( * finishes them on completion. Transfer current dfops state to this * transaction and transfer the result back before we return. */ - xfs_defer_move(tp->t_dfops, parent_tp->t_dfops); + xfs_defer_move(tp, parent_tp); cudp = xfs_trans_get_cud(tp, cuip); for (i = 0; i < cuip->cui_format.cui_nextents; i++) { @@ -522,13 +522,13 @@ xfs_cui_recover( xfs_refcount_finish_one_cleanup(tp, rcur, error); set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags); - xfs_defer_move(parent_tp->t_dfops, tp->t_dfops); + xfs_defer_move(parent_tp, tp); error = xfs_trans_commit(tp); return error; abort_error: xfs_refcount_finish_one_cleanup(tp, rcur, error); - xfs_defer_move(parent_tp->t_dfops, tp->t_dfops); + xfs_defer_move(parent_tp, tp); xfs_trans_cancel(tp); return error; } diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 0d07cdcc5c7d..ae3c875a14e5 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -125,7 +125,7 @@ xfs_trans_dup( if (tp->t_dfops != &tp->t_dfops_internal) ntp->t_dfops = tp->t_dfops; else - xfs_defer_move(ntp->t_dfops, tp->t_dfops); + xfs_defer_move(ntp, tp); xfs_trans_dup_dqinfo(tp, ntp); -- cgit v1.2.3 From 1214f1cf663b0939fbb8f1bccdc74c1d1e452d53 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 1 Aug 2018 07:20:31 -0700 Subject: xfs: replace dop_low with transaction flag The dop_low field enables the low free space allocation mode when a previous allocation has detected difficulty allocating blocks. It has historically been part of the xfs_defer_ops structure, which means if enabled, it remains enabled across a set of transactions until the deferred operations have completed and the dfops is reset. Now that the dfops is embedded in the transaction, we can save a bit more space by using a transaction flag rather than a standalone boolean. Drop the ->dop_low field and replace it with a transaction flag that is set at the same points, carried across rolling transactions and cleared on completion of deferred operations. This essentially emulates the behavior of ->dop_low and so should not change behavior. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Reviewed-by: Christoph Hellwig Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 8 ++++---- fs/xfs/libxfs/xfs_bmap_btree.c | 4 ++-- fs/xfs/libxfs/xfs_defer.c | 16 ++++++++++++++-- fs/xfs/libxfs/xfs_defer.h | 11 ----------- fs/xfs/libxfs/xfs_shared.h | 12 ++++++++++++ fs/xfs/xfs_filestream.c | 3 ++- fs/xfs/xfs_trace.h | 10 ++-------- fs/xfs/xfs_trans.h | 2 -- 8 files changed, 36 insertions(+), 30 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index a85c0445b38f..8edf7522aaff 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -700,7 +700,7 @@ xfs_bmap_extents_to_btree( if (tp->t_firstblock == NULLFSBLOCK) { args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); - } else if (tp->t_dfops->dop_low) { + } else if (tp->t_flags & XFS_TRANS_LOWMODE) { args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = tp->t_firstblock; } else { @@ -3449,7 +3449,7 @@ xfs_bmap_btalloc( error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); if (error) return error; - } else if (ap->tp->t_dfops->dop_low) { + } else if (ap->tp->t_flags & XFS_TRANS_LOWMODE) { if (xfs_inode_is_filestream(ap->ip)) args.type = XFS_ALLOCTYPE_FIRST_AG; else @@ -3484,7 +3484,7 @@ xfs_bmap_btalloc( * is >= the stripe unit and the allocation offset is * at the end of file. */ - if (!ap->tp->t_dfops->dop_low && ap->aeof) { + if (!(ap->tp->t_flags & XFS_TRANS_LOWMODE) && ap->aeof) { if (!ap->offset) { args.alignment = stripe_align; atype = args.type; @@ -3576,7 +3576,7 @@ xfs_bmap_btalloc( args.total = ap->minlen; if ((error = xfs_alloc_vextent(&args))) return error; - ap->tp->t_dfops->dop_low = true; + ap->tp->t_flags |= XFS_TRANS_LOWMODE; } if (args.fsbno != NULLFSBLOCK) { /* diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index 01489714a253..955e29de8cae 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c @@ -226,7 +226,7 @@ xfs_bmbt_alloc_block( * block allocation here and corrupt the filesystem. */ args.minleft = args.tp->t_blk_res; - } else if (cur->bc_tp->t_dfops->dop_low) { + } else if (cur->bc_tp->t_flags & XFS_TRANS_LOWMODE) { args.type = XFS_ALLOCTYPE_START_BNO; } else { args.type = XFS_ALLOCTYPE_NEAR_BNO; @@ -253,7 +253,7 @@ xfs_bmbt_alloc_block( error = xfs_alloc_vextent(&args); if (error) goto error0; - cur->bc_tp->t_dfops->dop_low = true; + cur->bc_tp->t_flags |= XFS_TRANS_LOWMODE; } if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) { *stat = 0; diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index e3517a53c525..64e1abc60edc 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -330,9 +330,14 @@ xfs_defer_reset( ASSERT(!xfs_defer_has_unfinished_work(dop)); - dop->dop_low = false; memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes)); memset(dop->dop_bufs, 0, sizeof(dop->dop_bufs)); + + /* + * Low mode state transfers across transaction rolls to mirror dfops + * lifetime. Clear it now that dfops is reset. + */ + tp->t_flags &= ~XFS_TRANS_LOWMODE; } /* @@ -590,7 +595,14 @@ xfs_defer_move( memcpy(dst->dop_inodes, src->dop_inodes, sizeof(dst->dop_inodes)); memcpy(dst->dop_bufs, src->dop_bufs, sizeof(dst->dop_bufs)); - dst->dop_low = src->dop_low; + + /* + * Low free space mode was historically controlled by a dfops field. + * This meant that low mode state potentially carried across multiple + * transaction rolls. Transfer low mode on a dfops move to preserve + * that behavior. + */ + dtp->t_flags |= (stp->t_flags & XFS_TRANS_LOWMODE); xfs_defer_reset(stp); } diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index d60c50498fdf..8908a2716774 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -25,17 +25,6 @@ struct xfs_defer_pending { /* * Header for deferred operation list. - * - * dop_low is used by the allocator to activate the lowspace algorithm - - * when free space is running low the extent allocator may choose to - * allocate an extent from an AG without leaving sufficient space for - * a btree split when inserting the new extent. In this case the allocator - * will enable the lowspace algorithm which is supposed to allow further - * allocations (such as btree splits and newroots) to allocate from - * sequential AGs. In order to avoid locking AGs out of order the lowspace - * algorithm will start searching for free space from AG 0. If the correct - * transaction reservations have been made then this algorithm will eventually - * find all the space it needs. */ enum xfs_defer_ops_type { XFS_DEFER_OPS_TYPE_BMAP, diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 22089f1c880a..1c5debe748f0 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h @@ -64,6 +64,18 @@ void xfs_log_get_max_trans_res(struct xfs_mount *mp, #define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */ #define XFS_TRANS_NO_WRITECOUNT 0x40 /* do not elevate SB writecount */ #define XFS_TRANS_NOFS 0x80 /* pass KM_NOFS to kmem_alloc */ +/* + * LOWMODE is used by the allocator to activate the lowspace algorithm - when + * free space is running low the extent allocator may choose to allocate an + * extent from an AG without leaving sufficient space for a btree split when + * inserting the new extent. In this case the allocator will enable the + * lowspace algorithm which is supposed to allow further allocations (such as + * btree splits and newroots) to allocate from sequential AGs. In order to + * avoid locking AGs out of order the lowspace algorithm will start searching + * for free space from AG 0. If the correct transaction reservations have been + * made then this algorithm will eventually find all the space it needs. + */ +#define XFS_TRANS_LOWMODE 0x100 /* allocate in low space mode */ /* * Field values for xfs_trans_mod_sb. diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index 212173c62588..182501373af2 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c @@ -20,6 +20,7 @@ #include "xfs_trace.h" #include "xfs_ag_resv.h" #include "xfs_trans.h" +#include "xfs_shared.h" struct xfs_fstrm_item { struct xfs_mru_cache_elem mru; @@ -378,7 +379,7 @@ xfs_filestream_new_ag( if (xfs_alloc_is_userdata(ap->datatype)) flags |= XFS_PICK_USERDATA; - if (ap->tp->t_dfops->dop_low) + if (ap->tp->t_flags & XFS_TRANS_LOWMODE) flags |= XFS_PICK_LOWSPACE; err = xfs_filestream_pick_ag(pip, startag, agp, flags, minlen); diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index cc6995cfce66..8807f1bb814a 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2223,19 +2223,16 @@ DECLARE_EVENT_CLASS(xfs_defer_class, __field(dev_t, dev) __field(void *, dop) __field(char, committed) - __field(char, low) __field(unsigned long, caller_ip) ), TP_fast_assign( __entry->dev = mp ? mp->m_super->s_dev : 0; __entry->dop = dop; - __entry->low = dop->dop_low; __entry->caller_ip = caller_ip; ), - TP_printk("dev %d:%d ops %p low %d, caller %pS", + TP_printk("dev %d:%d ops %p caller %pS", MAJOR(__entry->dev), MINOR(__entry->dev), __entry->dop, - __entry->low, (char *)__entry->caller_ip) ) #define DEFINE_DEFER_EVENT(name) \ @@ -2251,19 +2248,16 @@ DECLARE_EVENT_CLASS(xfs_defer_error_class, __field(dev_t, dev) __field(void *, dop) __field(char, committed) - __field(char, low) __field(int, error) ), TP_fast_assign( __entry->dev = mp ? mp->m_super->s_dev : 0; __entry->dop = dop; - __entry->low = dop->dop_low; __entry->error = error; ), - TP_printk("dev %d:%d ops %p low %d err %d", + TP_printk("dev %d:%d ops %p err %d", MAJOR(__entry->dev), MINOR(__entry->dev), __entry->dop, - __entry->low, __entry->error) ) #define DEFINE_DEFER_ERROR_EVENT(name) \ diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index dc79e3c1d3e8..7e493221160e 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -101,8 +101,6 @@ struct xfs_defer_ops { /* relog these with each roll */ struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES]; struct xfs_buf *dop_bufs[XFS_DEFER_OPS_NR_BUFS]; - - bool dop_low; /* alloc in low mode */ }; /* -- cgit v1.2.3 From 82ff27bc52a88cb5cc400bfa64e210d3ec8dfebd Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 1 Aug 2018 07:20:32 -0700 Subject: xfs: automatic dfops buffer relogging Buffers that are held across deferred operations are explicitly joined to the dfops structure to ensure appropriate relogging. While buffers are currently joined explicitly, we can detect the conditions that require relogging at dfops finish time by inspecting the transaction item list for held buffers. Replace the xfs_defer_bjoin() infrastructure with such detection and automatic relogging of held buffers. This eliminates the need for the per-dfops buffer list, replaced by an on-stack variant in xfs_defer_trans_roll(). Signed-off-by: Brian Foster Reviewed-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 1 - fs/xfs/libxfs/xfs_defer.c | 58 +++++++++++++++++++++-------------------------- fs/xfs/libxfs/xfs_defer.h | 1 - fs/xfs/xfs_dquot.c | 1 - fs/xfs/xfs_trans.h | 1 - 5 files changed, 26 insertions(+), 36 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 3deb5cdadf08..227887bee00d 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -320,7 +320,6 @@ xfs_attr_set( * buffer and run into problems with the write verifier. */ xfs_trans_bhold(args.trans, leaf_bp); - xfs_defer_bjoin(args.trans->t_dfops, leaf_bp); xfs_defer_ijoin(args.trans->t_dfops, dp); error = xfs_defer_finish(&args.trans); if (error) diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 64e1abc60edc..e9b7671d289a 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -14,6 +14,7 @@ #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_trans.h" +#include "xfs_buf_item.h" #include "xfs_trace.h" /* @@ -228,6 +229,10 @@ xfs_defer_trans_roll( struct xfs_trans **tp) { struct xfs_defer_ops *dop = (*tp)->t_dfops; + struct xfs_buf_log_item *bli; + struct xfs_log_item *lip; + struct xfs_buf *bplist[XFS_DEFER_OPS_NR_BUFS]; + int bpcount = 0; int i; int error; @@ -235,9 +240,24 @@ xfs_defer_trans_roll( for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE); - /* Hold the (previously bjoin'd) buffer locked across the roll. */ - for (i = 0; i < XFS_DEFER_OPS_NR_BUFS && dop->dop_bufs[i]; i++) - xfs_trans_dirty_buf(*tp, dop->dop_bufs[i]); + list_for_each_entry(lip, &(*tp)->t_items, li_trans) { + switch (lip->li_type) { + case XFS_LI_BUF: + bli = container_of(lip, struct xfs_buf_log_item, + bli_item); + if (bli->bli_flags & XFS_BLI_HOLD) { + if (bpcount >= XFS_DEFER_OPS_NR_BUFS) { + ASSERT(0); + return -EFSCORRUPTED; + } + xfs_trans_dirty_buf(*tp, bli->bli_buf); + bplist[bpcount++] = bli->bli_buf; + } + break; + default: + break; + } + } trace_xfs_defer_trans_roll((*tp)->t_mountp, dop, _RET_IP_); @@ -255,9 +275,9 @@ xfs_defer_trans_roll( xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0); /* Rejoin the buffers and dirty them so the log moves forward. */ - for (i = 0; i < XFS_DEFER_OPS_NR_BUFS && dop->dop_bufs[i]; i++) { - xfs_trans_bjoin(*tp, dop->dop_bufs[i]); - xfs_trans_bhold(*tp, dop->dop_bufs[i]); + for (i = 0; i < bpcount; i++) { + xfs_trans_bjoin(*tp, bplist[i]); + xfs_trans_bhold(*tp, bplist[i]); } return error; @@ -295,30 +315,6 @@ xfs_defer_ijoin( return -EFSCORRUPTED; } -/* - * Add this buffer to the deferred op. Each joined buffer is relogged - * each time we roll the transaction. - */ -int -xfs_defer_bjoin( - struct xfs_defer_ops *dop, - struct xfs_buf *bp) -{ - int i; - - for (i = 0; i < XFS_DEFER_OPS_NR_BUFS; i++) { - if (dop->dop_bufs[i] == bp) - return 0; - else if (dop->dop_bufs[i] == NULL) { - dop->dop_bufs[i] = bp; - return 0; - } - } - - ASSERT(0); - return -EFSCORRUPTED; -} - /* * Reset an already used dfops after finish. */ @@ -331,7 +327,6 @@ xfs_defer_reset( ASSERT(!xfs_defer_has_unfinished_work(dop)); memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes)); - memset(dop->dop_bufs, 0, sizeof(dop->dop_bufs)); /* * Low mode state transfers across transaction rolls to mirror dfops @@ -594,7 +589,6 @@ xfs_defer_move( list_splice_init(&src->dop_pending, &dst->dop_pending); memcpy(dst->dop_inodes, src->dop_inodes, sizeof(dst->dop_inodes)); - memcpy(dst->dop_bufs, src->dop_bufs, sizeof(dst->dop_bufs)); /* * Low free space mode was historically controlled by a dfops field. diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 8908a2716774..4a8bb838adf2 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -43,7 +43,6 @@ void xfs_defer_cancel(struct xfs_trans *); void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop); bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip); -int xfs_defer_bjoin(struct xfs_defer_ops *dop, struct xfs_buf *bp); void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp); /* Description of a deferred type. */ diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index da5c55cec966..e1196854dbcd 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -362,7 +362,6 @@ xfs_dquot_disk_alloc( * manually or by committing the transaction. */ xfs_trans_bhold(tp, bp); - error = xfs_defer_bjoin(tp->t_dfops, bp); if (error) { xfs_trans_bhold_release(tp, bp); xfs_trans_brelse(tp, bp); diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 7e493221160e..581456c79197 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -100,7 +100,6 @@ struct xfs_defer_ops { /* relog these with each roll */ struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES]; - struct xfs_buf *dop_bufs[XFS_DEFER_OPS_NR_BUFS]; }; /* -- cgit v1.2.3 From a8198666fb755e129c2fe92819774256ec26c79c Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 1 Aug 2018 07:20:32 -0700 Subject: xfs: automatic dfops inode relogging Inodes that are held across deferred operations are explicitly joined to the dfops structure to ensure appropriate relogging. While inodes are currently joined explicitly, we can detect the conditions that require relogging at dfops finish time by inspecting the transaction item list for inodes with ili_lock_flags == 0. Replace the xfs_defer_ijoin() infrastructure with such detection and automatic relogging of held inodes. This eliminates the need for the per-dfops inode list, replaced by an on-stack variant in xfs_defer_trans_roll(). Signed-off-by: Brian Foster Reviewed-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 9 ------- fs/xfs/libxfs/xfs_attr_remote.c | 2 -- fs/xfs/libxfs/xfs_bmap.c | 8 ------ fs/xfs/libxfs/xfs_defer.c | 59 +++++++++++++++-------------------------- fs/xfs/libxfs/xfs_defer.h | 1 - fs/xfs/xfs_bmap_util.c | 4 --- fs/xfs/xfs_inode.c | 2 -- fs/xfs/xfs_iomap.c | 3 --- fs/xfs/xfs_reflink.c | 4 --- fs/xfs/xfs_symlink.c | 1 - fs/xfs/xfs_trans.h | 3 --- 11 files changed, 21 insertions(+), 75 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 227887bee00d..3190dfc21b60 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -320,7 +320,6 @@ xfs_attr_set( * buffer and run into problems with the write verifier. */ xfs_trans_bhold(args.trans, leaf_bp); - xfs_defer_ijoin(args.trans->t_dfops, dp); error = xfs_defer_finish(&args.trans); if (error) goto out; @@ -589,7 +588,6 @@ xfs_attr_leaf_addname( error = xfs_attr3_leaf_to_node(args); if (error) goto out_defer_cancel; - xfs_defer_ijoin(args->trans->t_dfops, dp); error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; @@ -678,7 +676,6 @@ xfs_attr_leaf_addname( /* bp is gone due to xfs_da_shrink_inode */ if (error) goto out_defer_cancel; - xfs_defer_ijoin(args->trans->t_dfops, dp); error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; @@ -742,7 +739,6 @@ xfs_attr_leaf_removename( /* bp is gone due to xfs_da_shrink_inode */ if (error) goto out_defer_cancel; - xfs_defer_ijoin(args->trans->t_dfops, dp); error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; @@ -869,7 +865,6 @@ restart: error = xfs_attr3_leaf_to_node(args); if (error) goto out_defer_cancel; - xfs_defer_ijoin(args->trans->t_dfops, dp); error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; @@ -894,7 +889,6 @@ restart: error = xfs_da3_split(state); if (error) goto out_defer_cancel; - xfs_defer_ijoin(args->trans->t_dfops, dp); error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; @@ -991,7 +985,6 @@ restart: error = xfs_da3_join(state); if (error) goto out_defer_cancel; - xfs_defer_ijoin(args->trans->t_dfops, dp); error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; @@ -1115,7 +1108,6 @@ xfs_attr_node_removename( error = xfs_da3_join(state); if (error) goto out_defer_cancel; - xfs_defer_ijoin(args->trans->t_dfops, dp); error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; @@ -1147,7 +1139,6 @@ xfs_attr_node_removename( /* bp is gone due to xfs_da_shrink_inode */ if (error) goto out_defer_cancel; - xfs_defer_ijoin(args->trans->t_dfops, dp); error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index 77ca38586913..f52552313773 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c @@ -486,7 +486,6 @@ xfs_attr_rmtval_set( &nmap); if (error) goto out_defer_cancel; - xfs_defer_ijoin(args->trans->t_dfops, dp); error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; @@ -627,7 +626,6 @@ xfs_attr_rmtval_remove( XFS_BMAPI_ATTRFORK, 1, &done); if (error) goto out_defer_cancel; - xfs_defer_ijoin(args->trans->t_dfops, args->dp); error = xfs_defer_finish(&args->trans); if (error) goto out_defer_cancel; diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 71687d805f79..5cd490dc891a 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -1119,7 +1119,6 @@ xfs_bmap_add_attrfork( xfs_log_sb(tp); } - xfs_defer_ijoin(tp->t_dfops, ip); error = xfs_trans_commit(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); return error; @@ -5987,7 +5986,6 @@ __xfs_bmap_add( int whichfork, struct xfs_bmbt_irec *bmap) { - int error; struct xfs_bmap_intent *bi; trace_xfs_bmap_defer(mp, @@ -6006,12 +6004,6 @@ __xfs_bmap_add( bi->bi_whichfork = whichfork; bi->bi_bmap = *bmap; - error = xfs_defer_ijoin(dfops, bi->bi_owner); - if (error) { - kmem_free(bi); - return error; - } - xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_BMAP, &bi->bi_list); return 0; } diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index e9b7671d289a..1e7073252a5e 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -15,6 +15,8 @@ #include "xfs_defer.h" #include "xfs_trans.h" #include "xfs_buf_item.h" +#include "xfs_inode.h" +#include "xfs_inode_item.h" #include "xfs_trace.h" /* @@ -230,16 +232,14 @@ xfs_defer_trans_roll( { struct xfs_defer_ops *dop = (*tp)->t_dfops; struct xfs_buf_log_item *bli; + struct xfs_inode_log_item *ili; struct xfs_log_item *lip; struct xfs_buf *bplist[XFS_DEFER_OPS_NR_BUFS]; - int bpcount = 0; + struct xfs_inode *iplist[XFS_DEFER_OPS_NR_INODES]; + int bpcount = 0, ipcount = 0; int i; int error; - /* Log all the joined inodes. */ - for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) - xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE); - list_for_each_entry(lip, &(*tp)->t_items, li_trans) { switch (lip->li_type) { case XFS_LI_BUF: @@ -254,6 +254,19 @@ xfs_defer_trans_roll( bplist[bpcount++] = bli->bli_buf; } break; + case XFS_LI_INODE: + ili = container_of(lip, struct xfs_inode_log_item, + ili_item); + if (ili->ili_lock_flags == 0) { + if (ipcount >= XFS_DEFER_OPS_NR_INODES) { + ASSERT(0); + return -EFSCORRUPTED; + } + xfs_trans_log_inode(*tp, ili->ili_inode, + XFS_ILOG_CORE); + iplist[ipcount++] = ili->ili_inode; + } + break; default: break; } @@ -271,8 +284,8 @@ xfs_defer_trans_roll( } /* Rejoin the joined inodes. */ - for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) - xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0); + for (i = 0; i < ipcount; i++) + xfs_trans_ijoin(*tp, iplist[i], 0); /* Rejoin the buffers and dirty them so the log moves forward. */ for (i = 0; i < bpcount; i++) { @@ -291,30 +304,6 @@ xfs_defer_has_unfinished_work( return !list_empty(&dop->dop_pending) || !list_empty(&dop->dop_intake); } -/* - * Add this inode to the deferred op. Each joined inode is relogged - * each time we roll the transaction. - */ -int -xfs_defer_ijoin( - struct xfs_defer_ops *dop, - struct xfs_inode *ip) -{ - int i; - - for (i = 0; i < XFS_DEFER_OPS_NR_INODES; i++) { - if (dop->dop_inodes[i] == ip) - return 0; - else if (dop->dop_inodes[i] == NULL) { - dop->dop_inodes[i] = ip; - return 0; - } - } - - ASSERT(0); - return -EFSCORRUPTED; -} - /* * Reset an already used dfops after finish. */ @@ -322,11 +311,7 @@ static void xfs_defer_reset( struct xfs_trans *tp) { - struct xfs_defer_ops *dop = tp->t_dfops; - - ASSERT(!xfs_defer_has_unfinished_work(dop)); - - memset(dop->dop_inodes, 0, sizeof(dop->dop_inodes)); + ASSERT(!xfs_defer_has_unfinished_work(tp->t_dfops)); /* * Low mode state transfers across transaction rolls to mirror dfops @@ -588,8 +573,6 @@ xfs_defer_move( list_splice_init(&src->dop_intake, &dst->dop_intake); list_splice_init(&src->dop_pending, &dst->dop_pending); - memcpy(dst->dop_inodes, src->dop_inodes, sizeof(dst->dop_inodes)); - /* * Low free space mode was historically controlled by a dfops field. * This meant that low mode state potentially carried across multiple diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 4a8bb838adf2..bf1e9f78561e 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -42,7 +42,6 @@ int xfs_defer_finish(struct xfs_trans **tp); void xfs_defer_cancel(struct xfs_trans *); void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop); bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); -int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip); void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp); /* Description of a deferred type. */ diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 0c58a66b39e5..30ac1300dc49 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -979,7 +979,6 @@ xfs_alloc_file_space( /* * Complete the transaction */ - xfs_defer_ijoin(tp->t_dfops, ip); error = xfs_trans_commit(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); if (error) @@ -1037,8 +1036,6 @@ xfs_unmap_extent( if (error) goto out_trans_cancel; - xfs_defer_ijoin(tp->t_dfops, ip); - error = xfs_trans_commit(tp); out_unlock: xfs_iunlock(ip, XFS_ILOCK_EXCL); @@ -1624,7 +1621,6 @@ xfs_swap_extent_rmap( if (error) goto out_defer; - xfs_defer_ijoin(tp->t_dfops, ip); error = xfs_defer_finish(tpp); tp = *tpp; if (error) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 441c8593cfd7..7bb46a0eecfc 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1569,7 +1569,6 @@ xfs_itruncate_extents_flags( * Duplicate the transaction that has the permanent * reservation and commit the old transaction. */ - xfs_defer_ijoin(tp->t_dfops, ip); error = xfs_defer_finish(&tp); if (error) goto out_bmap_cancel; @@ -1810,7 +1809,6 @@ xfs_inactive_ifree( * Just ignore errors at this point. There is nothing we can do except * to try to keep going. Make sure it's not a silent error. */ - xfs_defer_ijoin(tp->t_dfops, ip); error = xfs_trans_commit(tp); if (error) xfs_notice(mp, "%s: xfs_trans_commit returned error %d", diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 8093a01fcf9e..3282575e2df4 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -261,7 +261,6 @@ xfs_iomap_write_direct( /* * Complete the transaction */ - xfs_defer_ijoin(tp->t_dfops, ip); error = xfs_trans_commit(tp); if (error) goto out_unlock; @@ -764,7 +763,6 @@ xfs_iomap_write_allocate( if (error) goto trans_cancel; - xfs_defer_ijoin(tp->t_dfops, ip); error = xfs_trans_commit(tp); if (error) goto error0; @@ -884,7 +882,6 @@ xfs_iomap_write_unwritten( xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); } - xfs_defer_ijoin(tp->t_dfops, ip); error = xfs_trans_commit(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); if (error) diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index e986fcf928e5..dce8ba8ab681 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -435,7 +435,6 @@ retry: xfs_inode_set_cowblocks_tag(ip); /* Finish up. */ - xfs_defer_ijoin(tp->t_dfops, ip); error = xfs_trans_commit(tp); if (error) return error; @@ -518,7 +517,6 @@ xfs_reflink_cancel_cow_blocks( NULL); /* Roll the transaction */ - xfs_defer_ijoin((*tpp)->t_dfops, ip); error = xfs_defer_finish(tpp); if (error) { xfs_defer_cancel(*tpp); @@ -716,7 +714,6 @@ xfs_reflink_end_cow( /* Remove the mapping from the CoW fork. */ xfs_bmap_del_extent_cow(ip, &icur, &got, &del); - xfs_defer_ijoin(tp->t_dfops, ip); error = xfs_defer_finish(&tp); if (error) goto out_cancel; @@ -1077,7 +1074,6 @@ xfs_reflink_remap_extent( next_extent: /* Process all the deferred stuff. */ - xfs_defer_ijoin(tp->t_dfops, ip); error = xfs_defer_finish(&tp); if (error) goto out_cancel; diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index 2bfe7fbbedb2..a3e98c64b6e3 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -454,7 +454,6 @@ xfs_inactive_symlink_rmt( * Commit the transaction. This first logs the EFI and the inode, then * rolls and commits the transaction that frees the extents. */ - xfs_defer_ijoin(tp->t_dfops, ip); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); error = xfs_trans_commit(tp); if (error) { diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 581456c79197..8665d45b82c6 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -97,9 +97,6 @@ void xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *item, struct xfs_defer_ops { struct list_head dop_intake; /* unlogged pending work */ struct list_head dop_pending; /* logged pending work */ - - /* relog these with each roll */ - struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES]; }; /* -- cgit v1.2.3 From 7dbddbaccd189e63c39c9e22c728c4548b9893bb Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 1 Aug 2018 07:20:32 -0700 Subject: xfs: drop dop param from xfs_defer_op_type ->finish_item() callback The dfops infrastructure ->finish_item() callback passes the transaction and dfops as separate parameters. Since dfops is always part of a transaction, the latter parameter is no longer necessary. Remove it from the various callbacks. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Reviewed-by: Christoph Hellwig Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 2 -- fs/xfs/libxfs/xfs_bmap.h | 6 +++--- fs/xfs/libxfs/xfs_defer.c | 2 +- fs/xfs/libxfs/xfs_defer.h | 4 ++-- fs/xfs/libxfs/xfs_refcount.c | 2 +- fs/xfs/libxfs/xfs_refcount.h | 7 +++---- fs/xfs/xfs_bmap_item.c | 5 ++--- fs/xfs/xfs_refcount_item.c | 4 ++-- fs/xfs/xfs_trans.h | 10 +++++----- fs/xfs/xfs_trans_bmap.c | 6 ++---- fs/xfs/xfs_trans_extfree.c | 2 -- fs/xfs/xfs_trans_refcount.c | 6 ++---- fs/xfs/xfs_trans_rmap.c | 1 - 13 files changed, 23 insertions(+), 34 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 5cd490dc891a..d20f541b7061 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -6045,7 +6045,6 @@ xfs_bmap_unmap_extent( int xfs_bmap_finish_one( struct xfs_trans *tp, - struct xfs_defer_ops *dfops, struct xfs_inode *ip, enum xfs_bmap_intent_type type, int whichfork, @@ -6072,7 +6071,6 @@ xfs_bmap_finish_one( switch (type) { case XFS_BMAP_MAP: - ASSERT(dfops == tp->t_dfops); error = xfs_bmapi_remap(tp, ip, startoff, *blockcount, startblock, 0); *blockcount = 0; diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 2e8555c1229a..9165a878edcd 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -252,9 +252,9 @@ struct xfs_bmap_intent { struct xfs_bmbt_irec bi_bmap; }; -int xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_defer_ops *dfops, - struct xfs_inode *ip, enum xfs_bmap_intent_type type, - int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock, +int xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_inode *ip, + enum xfs_bmap_intent_type type, int whichfork, + xfs_fileoff_t startoff, xfs_fsblock_t startblock, xfs_filblks_t *blockcount, xfs_exntst_t state); int xfs_bmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, struct xfs_inode *ip, struct xfs_bmbt_irec *imap); diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 1e7073252a5e..66ef9341813b 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -371,7 +371,7 @@ xfs_defer_finish_noroll( list_for_each_safe(li, n, &dfp->dfp_work) { list_del(li); dfp->dfp_count--; - error = dfp->dfp_type->finish_item(*tp, dop, li, + error = dfp->dfp_type->finish_item(*tp, li, dfp->dfp_done, &state); if (error == -EAGAIN) { /* diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index bf1e9f78561e..0de7504e5651 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -50,8 +50,8 @@ struct xfs_defer_op_type { unsigned int max_items; void (*abort_intent)(void *); void *(*create_done)(struct xfs_trans *, void *, unsigned int); - int (*finish_item)(struct xfs_trans *, struct xfs_defer_ops *, - struct list_head *, void *, void **); + int (*finish_item)(struct xfs_trans *, struct list_head *, void *, + void **); void (*finish_cleanup)(struct xfs_trans *, void *, int); void (*cancel_item)(struct list_head *); int (*diff_items)(void *, struct list_head *, struct list_head *); diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index 4cbc2efb099e..86f297ca90cd 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -1082,7 +1082,6 @@ xfs_refcount_finish_one_cleanup( int xfs_refcount_finish_one( struct xfs_trans *tp, - struct xfs_defer_ops *dfops, enum xfs_refcount_intent_type type, xfs_fsblock_t startblock, xfs_extlen_t blockcount, @@ -1091,6 +1090,7 @@ xfs_refcount_finish_one( struct xfs_btree_cur **pcur) { struct xfs_mount *mp = tp->t_mountp; + struct xfs_defer_ops *dfops = tp->t_dfops; struct xfs_btree_cur *rcur; struct xfs_buf *agbp = NULL; int error = 0; diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h index 5fef74412727..3b72c6dbf6ad 100644 --- a/fs/xfs/libxfs/xfs_refcount.h +++ b/fs/xfs/libxfs/xfs_refcount.h @@ -37,10 +37,9 @@ extern int xfs_refcount_decrease_extent(struct xfs_mount *mp, extern void xfs_refcount_finish_one_cleanup(struct xfs_trans *tp, struct xfs_btree_cur *rcur, int error); extern int xfs_refcount_finish_one(struct xfs_trans *tp, - struct xfs_defer_ops *dfops, enum xfs_refcount_intent_type type, - xfs_fsblock_t startblock, xfs_extlen_t blockcount, - xfs_fsblock_t *new_fsb, xfs_extlen_t *new_len, - struct xfs_btree_cur **pcur); + enum xfs_refcount_intent_type type, xfs_fsblock_t startblock, + xfs_extlen_t blockcount, xfs_fsblock_t *new_fsb, + xfs_extlen_t *new_len, struct xfs_btree_cur **pcur); extern int xfs_refcount_find_shared(struct xfs_btree_cur *cur, xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno, diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c index b8a6be036cd7..e828e0b51814 100644 --- a/fs/xfs/xfs_bmap_item.c +++ b/fs/xfs/xfs_bmap_item.c @@ -475,9 +475,8 @@ xfs_bui_recover( xfs_trans_ijoin(tp, ip, 0); count = bmap->me_len; - error = xfs_trans_log_finish_bmap_update(tp, budp, tp->t_dfops, type, - ip, whichfork, bmap->me_startoff, - bmap->me_startblock, &count, state); + error = xfs_trans_log_finish_bmap_update(tp, budp, type, ip, whichfork, + bmap->me_startoff, bmap->me_startblock, &count, state); if (error) goto err_inode; diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c index 4a417daae781..43c4ac374cba 100644 --- a/fs/xfs/xfs_refcount_item.c +++ b/fs/xfs/xfs_refcount_item.c @@ -479,8 +479,8 @@ xfs_cui_recover( new_len = refc->pe_len; } else error = xfs_trans_log_finish_refcount_update(tp, cudp, - tp->t_dfops, type, refc->pe_startblock, - refc->pe_len, &new_fsb, &new_len, &rcur); + type, refc->pe_startblock, refc->pe_len, + &new_fsb, &new_len, &rcur); if (error) goto abort_error; diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 8665d45b82c6..299656dbf324 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -268,7 +268,7 @@ void xfs_refcount_update_init_defer_op(void); struct xfs_cud_log_item *xfs_trans_get_cud(struct xfs_trans *tp, struct xfs_cui_log_item *cuip); int xfs_trans_log_finish_refcount_update(struct xfs_trans *tp, - struct xfs_cud_log_item *cudp, struct xfs_defer_ops *dfops, + struct xfs_cud_log_item *cudp, enum xfs_refcount_intent_type type, xfs_fsblock_t startblock, xfs_extlen_t blockcount, xfs_fsblock_t *new_fsb, xfs_extlen_t *new_len, struct xfs_btree_cur **pcur); @@ -280,9 +280,9 @@ void xfs_bmap_update_init_defer_op(void); struct xfs_bud_log_item *xfs_trans_get_bud(struct xfs_trans *tp, struct xfs_bui_log_item *buip); int xfs_trans_log_finish_bmap_update(struct xfs_trans *tp, - struct xfs_bud_log_item *rudp, struct xfs_defer_ops *dfops, - enum xfs_bmap_intent_type type, struct xfs_inode *ip, - int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock, - xfs_filblks_t *blockcount, xfs_exntst_t state); + struct xfs_bud_log_item *rudp, enum xfs_bmap_intent_type type, + struct xfs_inode *ip, int whichfork, xfs_fileoff_t startoff, + xfs_fsblock_t startblock, xfs_filblks_t *blockcount, + xfs_exntst_t state); #endif /* __XFS_TRANS_H__ */ diff --git a/fs/xfs/xfs_trans_bmap.c b/fs/xfs/xfs_trans_bmap.c index a15a5cd867f9..741c558b2179 100644 --- a/fs/xfs/xfs_trans_bmap.c +++ b/fs/xfs/xfs_trans_bmap.c @@ -43,7 +43,6 @@ int xfs_trans_log_finish_bmap_update( struct xfs_trans *tp, struct xfs_bud_log_item *budp, - struct xfs_defer_ops *dop, enum xfs_bmap_intent_type type, struct xfs_inode *ip, int whichfork, @@ -54,7 +53,7 @@ xfs_trans_log_finish_bmap_update( { int error; - error = xfs_bmap_finish_one(tp, dop, ip, type, whichfork, startoff, + error = xfs_bmap_finish_one(tp, ip, type, whichfork, startoff, startblock, blockcount, state); /* @@ -176,7 +175,6 @@ xfs_bmap_update_create_done( STATIC int xfs_bmap_update_finish_item( struct xfs_trans *tp, - struct xfs_defer_ops *dop, struct list_head *item, void *done_item, void **state) @@ -187,7 +185,7 @@ xfs_bmap_update_finish_item( bmap = container_of(item, struct xfs_bmap_intent, bi_list); count = bmap->bi_bmap.br_blockcount; - error = xfs_trans_log_finish_bmap_update(tp, done_item, dop, + error = xfs_trans_log_finish_bmap_update(tp, done_item, bmap->bi_type, bmap->bi_owner, bmap->bi_whichfork, bmap->bi_bmap.br_startoff, diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c index bd66c76f55e6..855c0b651fd4 100644 --- a/fs/xfs/xfs_trans_extfree.c +++ b/fs/xfs/xfs_trans_extfree.c @@ -171,7 +171,6 @@ xfs_extent_free_create_done( STATIC int xfs_extent_free_finish_item( struct xfs_trans *tp, - struct xfs_defer_ops *dop, struct list_head *item, void *done_item, void **state) @@ -226,7 +225,6 @@ static const struct xfs_defer_op_type xfs_extent_free_defer_type = { STATIC int xfs_agfl_free_finish_item( struct xfs_trans *tp, - struct xfs_defer_ops *dop, struct list_head *item, void *done_item, void **state) diff --git a/fs/xfs/xfs_trans_refcount.c b/fs/xfs/xfs_trans_refcount.c index 46dd4fca8aa7..523c55663954 100644 --- a/fs/xfs/xfs_trans_refcount.c +++ b/fs/xfs/xfs_trans_refcount.c @@ -42,7 +42,6 @@ int xfs_trans_log_finish_refcount_update( struct xfs_trans *tp, struct xfs_cud_log_item *cudp, - struct xfs_defer_ops *dop, enum xfs_refcount_intent_type type, xfs_fsblock_t startblock, xfs_extlen_t blockcount, @@ -52,7 +51,7 @@ xfs_trans_log_finish_refcount_update( { int error; - error = xfs_refcount_finish_one(tp, dop, type, startblock, + error = xfs_refcount_finish_one(tp, type, startblock, blockcount, new_fsb, new_len, pcur); /* @@ -169,7 +168,6 @@ xfs_refcount_update_create_done( STATIC int xfs_refcount_update_finish_item( struct xfs_trans *tp, - struct xfs_defer_ops *dop, struct list_head *item, void *done_item, void **state) @@ -180,7 +178,7 @@ xfs_refcount_update_finish_item( int error; refc = container_of(item, struct xfs_refcount_intent, ri_list); - error = xfs_trans_log_finish_refcount_update(tp, done_item, dop, + error = xfs_trans_log_finish_refcount_update(tp, done_item, refc->ri_type, refc->ri_startblock, refc->ri_blockcount, diff --git a/fs/xfs/xfs_trans_rmap.c b/fs/xfs/xfs_trans_rmap.c index 726d8e2c0558..05b00e40251f 100644 --- a/fs/xfs/xfs_trans_rmap.c +++ b/fs/xfs/xfs_trans_rmap.c @@ -193,7 +193,6 @@ xfs_rmap_update_create_done( STATIC int xfs_rmap_update_finish_item( struct xfs_trans *tp, - struct xfs_defer_ops *dop, struct list_head *item, void *done_item, void **state) -- cgit v1.2.3 From 60f31a609ed3d28791acb2bc24188cb7e2259176 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 1 Aug 2018 07:20:33 -0700 Subject: xfs: clean out superfluous dfops dop params/vars The dfops code still passes around the xfs_defer_ops pointer superfluously in a few places. Clean this up wherever the transaction will suffice. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Reviewed-by: Christoph Hellwig Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_defer.c | 43 +++++++++++++++++++++---------------------- fs/xfs/libxfs/xfs_defer.h | 2 +- fs/xfs/xfs_trans.c | 2 +- 3 files changed, 23 insertions(+), 24 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 66ef9341813b..7079f534c735 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -181,9 +181,9 @@ static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX]; */ STATIC void xfs_defer_intake_work( - struct xfs_trans *tp, - struct xfs_defer_ops *dop) + struct xfs_trans *tp) { + struct xfs_defer_ops *dop = tp->t_dfops; struct list_head *li; struct xfs_defer_pending *dfp; @@ -204,9 +204,9 @@ xfs_defer_intake_work( STATIC void xfs_defer_trans_abort( struct xfs_trans *tp, - struct xfs_defer_ops *dop, int error) { + struct xfs_defer_ops *dop = tp->t_dfops; struct xfs_defer_pending *dfp; trace_xfs_defer_trans_abort(tp->t_mountp, dop, _RET_IP_); @@ -230,7 +230,6 @@ STATIC int xfs_defer_trans_roll( struct xfs_trans **tp) { - struct xfs_defer_ops *dop = (*tp)->t_dfops; struct xfs_buf_log_item *bli; struct xfs_inode_log_item *ili; struct xfs_log_item *lip; @@ -272,14 +271,14 @@ xfs_defer_trans_roll( } } - trace_xfs_defer_trans_roll((*tp)->t_mountp, dop, _RET_IP_); + trace_xfs_defer_trans_roll((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_); /* Roll the transaction. */ error = xfs_trans_roll(tp); - dop = (*tp)->t_dfops; if (error) { - trace_xfs_defer_trans_roll_error((*tp)->t_mountp, dop, error); - xfs_defer_trans_abort(*tp, dop, error); + trace_xfs_defer_trans_roll_error((*tp)->t_mountp, + (*tp)->t_dfops, error); + xfs_defer_trans_abort(*tp, error); return error; } @@ -299,9 +298,10 @@ xfs_defer_trans_roll( /* Do we have any work items to finish? */ bool xfs_defer_has_unfinished_work( - struct xfs_defer_ops *dop) + struct xfs_trans *tp) { - return !list_empty(&dop->dop_pending) || !list_empty(&dop->dop_intake); + return !list_empty(&tp->t_dfops->dop_pending) || + !list_empty(&tp->t_dfops->dop_intake); } /* @@ -311,7 +311,7 @@ static void xfs_defer_reset( struct xfs_trans *tp) { - ASSERT(!xfs_defer_has_unfinished_work(tp->t_dfops)); + ASSERT(!xfs_defer_has_unfinished_work(tp)); /* * Low mode state transfers across transaction rolls to mirror dfops @@ -332,7 +332,6 @@ int xfs_defer_finish_noroll( struct xfs_trans **tp) { - struct xfs_defer_ops *dop = (*tp)->t_dfops; struct xfs_defer_pending *dfp; struct list_head *li; struct list_head *n; @@ -342,24 +341,22 @@ xfs_defer_finish_noroll( ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); - trace_xfs_defer_finish((*tp)->t_mountp, dop, _RET_IP_); + trace_xfs_defer_finish((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_); /* Until we run out of pending work to finish... */ - while (xfs_defer_has_unfinished_work(dop)) { + while (xfs_defer_has_unfinished_work(*tp)) { /* Log intents for work items sitting in the intake. */ - xfs_defer_intake_work(*tp, dop); + xfs_defer_intake_work(*tp); /* - * Roll the transaction and update dop in case dfops was - * embedded in the transaction. + * Roll the transaction. */ error = xfs_defer_trans_roll(tp); if (error) goto out; - dop = (*tp)->t_dfops; /* Log an intent-done item for the first pending item. */ - dfp = list_first_entry(&dop->dop_pending, + dfp = list_first_entry(&(*tp)->t_dfops->dop_pending, struct xfs_defer_pending, dfp_list); trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp); dfp->dfp_done = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, @@ -390,7 +387,7 @@ xfs_defer_finish_noroll( */ if (cleanup_fn) cleanup_fn(*tp, state, error); - xfs_defer_trans_abort(*tp, dop, error); + xfs_defer_trans_abort(*tp, error); goto out; } } @@ -420,9 +417,11 @@ xfs_defer_finish_noroll( out: if (error) - trace_xfs_defer_finish_error((*tp)->t_mountp, dop, error); + trace_xfs_defer_finish_error((*tp)->t_mountp, (*tp)->t_dfops, + error); else - trace_xfs_defer_finish_done((*tp)->t_mountp, dop, _RET_IP_); + trace_xfs_defer_finish_done((*tp)->t_mountp, (*tp)->t_dfops, + _RET_IP_); return error; } diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 0de7504e5651..f051c8056141 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -41,7 +41,7 @@ int xfs_defer_finish_noroll(struct xfs_trans **tp); int xfs_defer_finish(struct xfs_trans **tp); void xfs_defer_cancel(struct xfs_trans *); void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop); -bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); +bool xfs_defer_has_unfinished_work(struct xfs_trans *tp); void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp); /* Description of a deferred type. */ diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index ae3c875a14e5..b0130b21f4de 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -929,7 +929,7 @@ __xfs_trans_commit( * Finish deferred items on final commit. Only permanent transactions * should ever have deferred ops. */ - WARN_ON_ONCE(xfs_defer_has_unfinished_work(tp->t_dfops) && + WARN_ON_ONCE(xfs_defer_has_unfinished_work(tp) && !(tp->t_flags & XFS_TRANS_PERM_LOG_RES)); if (!regrant && (tp->t_flags & XFS_TRANS_PERM_LOG_RES)) { error = xfs_defer_finish_noroll(&tp); -- cgit v1.2.3 From 9b1f4e9831df29776031e86e112e68784f1fc079 Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 1 Aug 2018 07:20:33 -0700 Subject: xfs: cancel dfops on xfs_defer_finish() error The current semantics of xfs_defer_finish() require the caller to call xfs_defer_cancel() on error. This is slightly inconsistent with transaction commit error handling where a failed commit cleans up the transaction before returning. More significantly, the only requirement for exposure of ->dop_pending outside of xfs_defer_finish() is so that xfs_defer_cancel() can drain it on error. Since the only recourse of xfs_defer_finish() errors is cancellation, mirror the transaction logic and cancel remaining dfops before returning from xfs_defer_finish() with an error. Beside simplifying xfs_defer_finish() semantics, this ensures that xfs_defer_finish() always returns with an empty ->dop_pending and thus facilitates removal of the list from xfs_defer_ops. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Reviewed-by: Christoph Hellwig Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 16 ++++++++-------- fs/xfs/libxfs/xfs_attr_remote.c | 4 ++-- fs/xfs/libxfs/xfs_defer.c | 11 ++++++----- fs/xfs/xfs_bmap_util.c | 2 +- fs/xfs/xfs_dquot.c | 2 +- fs/xfs/xfs_inode.c | 2 +- fs/xfs/xfs_reflink.c | 4 +--- fs/xfs/xfs_trans.c | 4 +--- 8 files changed, 21 insertions(+), 24 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 3190dfc21b60..1e671d4eb6fa 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -590,7 +590,7 @@ xfs_attr_leaf_addname( goto out_defer_cancel; error = xfs_defer_finish(&args->trans); if (error) - goto out_defer_cancel; + return error; /* * Commit the current trans (including the inode) and start @@ -678,7 +678,7 @@ xfs_attr_leaf_addname( goto out_defer_cancel; error = xfs_defer_finish(&args->trans); if (error) - goto out_defer_cancel; + return error; } /* @@ -741,7 +741,7 @@ xfs_attr_leaf_removename( goto out_defer_cancel; error = xfs_defer_finish(&args->trans); if (error) - goto out_defer_cancel; + return error; } return 0; out_defer_cancel: @@ -867,7 +867,7 @@ restart: goto out_defer_cancel; error = xfs_defer_finish(&args->trans); if (error) - goto out_defer_cancel; + goto out; /* * Commit the node conversion and start the next @@ -891,7 +891,7 @@ restart: goto out_defer_cancel; error = xfs_defer_finish(&args->trans); if (error) - goto out_defer_cancel; + goto out; } else { /* * Addition succeeded, update Btree hashvals. @@ -987,7 +987,7 @@ restart: goto out_defer_cancel; error = xfs_defer_finish(&args->trans); if (error) - goto out_defer_cancel; + goto out; } /* @@ -1110,7 +1110,7 @@ xfs_attr_node_removename( goto out_defer_cancel; error = xfs_defer_finish(&args->trans); if (error) - goto out_defer_cancel; + goto out; /* * Commit the Btree join operation and start a new trans. */ @@ -1141,7 +1141,7 @@ xfs_attr_node_removename( goto out_defer_cancel; error = xfs_defer_finish(&args->trans); if (error) - goto out_defer_cancel; + goto out; } else xfs_trans_brelse(args->trans, bp); } diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index f52552313773..af094063e402 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c @@ -488,7 +488,7 @@ xfs_attr_rmtval_set( goto out_defer_cancel; error = xfs_defer_finish(&args->trans); if (error) - goto out_defer_cancel; + return error; ASSERT(nmap == 1); ASSERT((map.br_startblock != DELAYSTARTBLOCK) && @@ -628,7 +628,7 @@ xfs_attr_rmtval_remove( goto out_defer_cancel; error = xfs_defer_finish(&args->trans); if (error) - goto out_defer_cancel; + return error; /* * Close out trans and start the next one in the chain. diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 7079f534c735..b656a399cd71 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -416,14 +416,15 @@ xfs_defer_finish_noroll( } out: - if (error) + if (error) { trace_xfs_defer_finish_error((*tp)->t_mountp, (*tp)->t_dfops, error); - else - trace_xfs_defer_finish_done((*tp)->t_mountp, (*tp)->t_dfops, - _RET_IP_); + xfs_defer_cancel(*tp); + return error; + } - return error; + trace_xfs_defer_finish_done((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_); + return 0; } int diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 30ac1300dc49..d9dad399440a 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1624,7 +1624,7 @@ xfs_swap_extent_rmap( error = xfs_defer_finish(tpp); tp = *tpp; if (error) - goto out_defer; + goto out; tirec.br_startoff += rlen; if (tirec.br_startblock != HOLESTARTBLOCK && diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index e1196854dbcd..70a76ac41f01 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -371,7 +371,7 @@ xfs_dquot_disk_alloc( tp = *tpp; if (error) { xfs_buf_relse(bp); - goto error1; + goto error0; } *bpp = bp; return 0; diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 7bb46a0eecfc..d957a46dc1cb 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1571,7 +1571,7 @@ xfs_itruncate_extents_flags( */ error = xfs_defer_finish(&tp); if (error) - goto out_bmap_cancel; + goto out; error = xfs_trans_roll_inode(&tp, ip); if (error) diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index dce8ba8ab681..2ec562d75494 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -518,10 +518,8 @@ xfs_reflink_cancel_cow_blocks( /* Roll the transaction */ error = xfs_defer_finish(tpp); - if (error) { - xfs_defer_cancel(*tpp); + if (error) break; - } /* Remove the mapping from the CoW fork. */ xfs_bmap_del_extent_cow(ip, &icur, &got, &del); diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index b0130b21f4de..b050663c2a70 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -933,10 +933,8 @@ __xfs_trans_commit( !(tp->t_flags & XFS_TRANS_PERM_LOG_RES)); if (!regrant && (tp->t_flags & XFS_TRANS_PERM_LOG_RES)) { error = xfs_defer_finish_noroll(&tp); - if (error) { - xfs_defer_cancel(tp); + if (error) goto out_unreserve; - } } /* -- cgit v1.2.3 From 1ae093cbea3d1ef04e1344b9e3996a9e1763a91b Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 1 Aug 2018 07:20:34 -0700 Subject: xfs: replace xfs_defer_ops ->dop_pending with on-stack list The xfs_defer_ops ->dop_pending list is used to track active deferred operations once intents are logged. These items must be aborted in the event of an error. The list is populated as intents are logged and items are removed as they complete (or are aborted). Now that xfs_defer_finish() cancels on error, there is no need to ever access ->dop_pending outside of xfs_defer_finish(). The list is only ever populated after xfs_defer_finish() begins and is either completed or cancelled before it returns. Remove ->dop_pending from xfs_defer_ops and replace it with a local list in the xfs_defer_finish() path. Pass the local list to the various helpers now that it is not accessible via dfops. Note that we have to check for NULL in the abort case as the final tx roll occurs outside of the scope of the new local list (once the dfops has completed and thus drained the list). Signed-off-by: Brian Foster Reviewed-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_defer.c | 146 +++++++++++++++++++++------------------------- fs/xfs/libxfs/xfs_defer.h | 1 - fs/xfs/xfs_trace.h | 5 +- fs/xfs/xfs_trans.c | 2 +- fs/xfs/xfs_trans.h | 1 - 5 files changed, 71 insertions(+), 84 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index b656a399cd71..1cbddcf539da 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -180,7 +180,7 @@ static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX]; * the pending list. */ STATIC void -xfs_defer_intake_work( +xfs_defer_create_intents( struct xfs_trans *tp) { struct xfs_defer_ops *dop = tp->t_dfops; @@ -190,21 +190,19 @@ xfs_defer_intake_work( list_for_each_entry(dfp, &dop->dop_intake, dfp_list) { dfp->dfp_intent = dfp->dfp_type->create_intent(tp, dfp->dfp_count); - trace_xfs_defer_intake_work(tp->t_mountp, dfp); + trace_xfs_defer_create_intent(tp->t_mountp, dfp); list_sort(tp->t_mountp, &dfp->dfp_work, dfp->dfp_type->diff_items); list_for_each(li, &dfp->dfp_work) dfp->dfp_type->log_item(tp, dfp->dfp_intent, li); } - - list_splice_tail_init(&dop->dop_intake, &dop->dop_pending); } /* Abort all the intents that were committed. */ STATIC void xfs_defer_trans_abort( struct xfs_trans *tp, - int error) + struct list_head *dop_pending) { struct xfs_defer_ops *dop = tp->t_dfops; struct xfs_defer_pending *dfp; @@ -212,24 +210,21 @@ xfs_defer_trans_abort( trace_xfs_defer_trans_abort(tp->t_mountp, dop, _RET_IP_); /* Abort intent items that don't have a done item. */ - list_for_each_entry(dfp, &dop->dop_pending, dfp_list) { + list_for_each_entry(dfp, dop_pending, dfp_list) { trace_xfs_defer_pending_abort(tp->t_mountp, dfp); if (dfp->dfp_intent && !dfp->dfp_done) { dfp->dfp_type->abort_intent(dfp->dfp_intent); dfp->dfp_intent = NULL; } } - - /* Shut down FS. */ - xfs_force_shutdown(tp->t_mountp, (error == -EFSCORRUPTED) ? - SHUTDOWN_CORRUPT_INCORE : SHUTDOWN_META_IO_ERROR); } /* Roll a transaction so we can do some deferred op processing. */ STATIC int xfs_defer_trans_roll( - struct xfs_trans **tp) + struct xfs_trans **tpp) { + struct xfs_trans *tp = *tpp; struct xfs_buf_log_item *bli; struct xfs_inode_log_item *ili; struct xfs_log_item *lip; @@ -239,7 +234,7 @@ xfs_defer_trans_roll( int i; int error; - list_for_each_entry(lip, &(*tp)->t_items, li_trans) { + list_for_each_entry(lip, &tp->t_items, li_trans) { switch (lip->li_type) { case XFS_LI_BUF: bli = container_of(lip, struct xfs_buf_log_item, @@ -249,7 +244,7 @@ xfs_defer_trans_roll( ASSERT(0); return -EFSCORRUPTED; } - xfs_trans_dirty_buf(*tp, bli->bli_buf); + xfs_trans_dirty_buf(tp, bli->bli_buf); bplist[bpcount++] = bli->bli_buf; } break; @@ -261,7 +256,7 @@ xfs_defer_trans_roll( ASSERT(0); return -EFSCORRUPTED; } - xfs_trans_log_inode(*tp, ili->ili_inode, + xfs_trans_log_inode(tp, ili->ili_inode, XFS_ILOG_CORE); iplist[ipcount++] = ili->ili_inode; } @@ -271,39 +266,30 @@ xfs_defer_trans_roll( } } - trace_xfs_defer_trans_roll((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_); + trace_xfs_defer_trans_roll(tp->t_mountp, tp->t_dfops, _RET_IP_); /* Roll the transaction. */ - error = xfs_trans_roll(tp); + error = xfs_trans_roll(tpp); + tp = *tpp; if (error) { - trace_xfs_defer_trans_roll_error((*tp)->t_mountp, - (*tp)->t_dfops, error); - xfs_defer_trans_abort(*tp, error); + trace_xfs_defer_trans_roll_error(tp->t_mountp, + tp->t_dfops, error); return error; } /* Rejoin the joined inodes. */ for (i = 0; i < ipcount; i++) - xfs_trans_ijoin(*tp, iplist[i], 0); + xfs_trans_ijoin(tp, iplist[i], 0); /* Rejoin the buffers and dirty them so the log moves forward. */ for (i = 0; i < bpcount; i++) { - xfs_trans_bjoin(*tp, bplist[i]); - xfs_trans_bhold(*tp, bplist[i]); + xfs_trans_bjoin(tp, bplist[i]); + xfs_trans_bhold(tp, bplist[i]); } return error; } -/* Do we have any work items to finish? */ -bool -xfs_defer_has_unfinished_work( - struct xfs_trans *tp) -{ - return !list_empty(&tp->t_dfops->dop_pending) || - !list_empty(&tp->t_dfops->dop_intake); -} - /* * Reset an already used dfops after finish. */ @@ -311,7 +297,7 @@ static void xfs_defer_reset( struct xfs_trans *tp) { - ASSERT(!xfs_defer_has_unfinished_work(tp)); + ASSERT(list_empty(&tp->t_dfops->dop_intake)); /* * Low mode state transfers across transaction rolls to mirror dfops @@ -320,6 +306,36 @@ xfs_defer_reset( tp->t_flags &= ~XFS_TRANS_LOWMODE; } +/* + * Free up any items left in the list. + */ +static void +xfs_defer_cancel_list( + struct xfs_mount *mp, + struct list_head *dop_list) +{ + struct xfs_defer_pending *dfp; + struct xfs_defer_pending *pli; + struct list_head *pwi; + struct list_head *n; + + /* + * Free the pending items. Caller should already have arranged + * for the intent items to be released. + */ + list_for_each_entry_safe(dfp, pli, dop_list, dfp_list) { + trace_xfs_defer_cancel_list(mp, dfp); + list_del(&dfp->dfp_list); + list_for_each_safe(pwi, n, &dfp->dfp_work) { + list_del(pwi); + dfp->dfp_count--; + dfp->dfp_type->cancel_item(pwi); + } + ASSERT(dfp->dfp_count == 0); + kmem_free(dfp); + } +} + /* * Finish all the pending work. This involves logging intent items for * any work items that wandered in since the last transaction roll (if @@ -338,15 +354,19 @@ xfs_defer_finish_noroll( void *state; int error = 0; void (*cleanup_fn)(struct xfs_trans *, void *, int); + LIST_HEAD(dop_pending); ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); trace_xfs_defer_finish((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_); /* Until we run out of pending work to finish... */ - while (xfs_defer_has_unfinished_work(*tp)) { - /* Log intents for work items sitting in the intake. */ - xfs_defer_intake_work(*tp); + while (!list_empty(&dop_pending) || + !list_empty(&(*tp)->t_dfops->dop_intake)) { + /* log intents and pull in intake items */ + xfs_defer_create_intents(*tp); + list_splice_tail_init(&(*tp)->t_dfops->dop_intake, + &dop_pending); /* * Roll the transaction. @@ -356,8 +376,8 @@ xfs_defer_finish_noroll( goto out; /* Log an intent-done item for the first pending item. */ - dfp = list_first_entry(&(*tp)->t_dfops->dop_pending, - struct xfs_defer_pending, dfp_list); + dfp = list_first_entry(&dop_pending, struct xfs_defer_pending, + dfp_list); trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp); dfp->dfp_done = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, dfp->dfp_count); @@ -387,7 +407,6 @@ xfs_defer_finish_noroll( */ if (cleanup_fn) cleanup_fn(*tp, state, error); - xfs_defer_trans_abort(*tp, error); goto out; } } @@ -417,8 +436,11 @@ xfs_defer_finish_noroll( out: if (error) { + xfs_defer_trans_abort(*tp, &dop_pending); + xfs_force_shutdown((*tp)->t_mountp, SHUTDOWN_CORRUPT_INCORE); trace_xfs_defer_finish_error((*tp)->t_mountp, (*tp)->t_dfops, error); + xfs_defer_cancel_list((*tp)->t_mountp, &dop_pending); xfs_defer_cancel(*tp); return error; } @@ -442,54 +464,24 @@ xfs_defer_finish( return error; if ((*tp)->t_flags & XFS_TRANS_DIRTY) { error = xfs_defer_trans_roll(tp); - if (error) + if (error) { + xfs_force_shutdown((*tp)->t_mountp, + SHUTDOWN_CORRUPT_INCORE); return error; + } } xfs_defer_reset(*tp); return 0; } -/* - * Free up any items left in the list. - */ void xfs_defer_cancel( - struct xfs_trans *tp) + struct xfs_trans *tp) { - struct xfs_defer_ops *dop = tp->t_dfops; - struct xfs_defer_pending *dfp; - struct xfs_defer_pending *pli; - struct list_head *pwi; - struct list_head *n; + struct xfs_mount *mp = tp->t_mountp; - trace_xfs_defer_cancel(NULL, dop, _RET_IP_); - - /* - * Free the pending items. Caller should already have arranged - * for the intent items to be released. - */ - list_for_each_entry_safe(dfp, pli, &dop->dop_intake, dfp_list) { - trace_xfs_defer_intake_cancel(NULL, dfp); - list_del(&dfp->dfp_list); - list_for_each_safe(pwi, n, &dfp->dfp_work) { - list_del(pwi); - dfp->dfp_count--; - dfp->dfp_type->cancel_item(pwi); - } - ASSERT(dfp->dfp_count == 0); - kmem_free(dfp); - } - list_for_each_entry_safe(dfp, pli, &dop->dop_pending, dfp_list) { - trace_xfs_defer_pending_cancel(NULL, dfp); - list_del(&dfp->dfp_list); - list_for_each_safe(pwi, n, &dfp->dfp_work) { - list_del(pwi); - dfp->dfp_count--; - dfp->dfp_type->cancel_item(pwi); - } - ASSERT(dfp->dfp_count == 0); - kmem_free(dfp); - } + trace_xfs_defer_cancel(mp, tp->t_dfops, _RET_IP_); + xfs_defer_cancel_list(mp, &tp->t_dfops->dop_intake); } /* Add an item for later deferred processing. */ @@ -547,7 +539,6 @@ xfs_defer_init( memset(dop, 0, sizeof(struct xfs_defer_ops)); INIT_LIST_HEAD(&dop->dop_intake); - INIT_LIST_HEAD(&dop->dop_pending); if (tp) { ASSERT(tp->t_firstblock == NULLFSBLOCK); tp->t_dfops = dop; @@ -571,7 +562,6 @@ xfs_defer_move( ASSERT(dst != src); list_splice_init(&src->dop_intake, &dst->dop_intake); - list_splice_init(&src->dop_pending, &dst->dop_pending); /* * Low free space mode was historically controlled by a dfops field. diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index f051c8056141..f091bf3abeaf 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -41,7 +41,6 @@ int xfs_defer_finish_noroll(struct xfs_trans **tp); int xfs_defer_finish(struct xfs_trans **tp); void xfs_defer_cancel(struct xfs_trans *); void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop); -bool xfs_defer_has_unfinished_work(struct xfs_trans *tp); void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp); /* Description of a deferred type. */ diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 8807f1bb814a..fec9cfe3dfb4 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2392,9 +2392,8 @@ DEFINE_DEFER_EVENT(xfs_defer_finish_done); DEFINE_DEFER_ERROR_EVENT(xfs_defer_trans_roll_error); DEFINE_DEFER_ERROR_EVENT(xfs_defer_finish_error); -DEFINE_DEFER_PENDING_EVENT(xfs_defer_intake_work); -DEFINE_DEFER_PENDING_EVENT(xfs_defer_intake_cancel); -DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_cancel); +DEFINE_DEFER_PENDING_EVENT(xfs_defer_create_intent); +DEFINE_DEFER_PENDING_EVENT(xfs_defer_cancel_list); DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_finish); DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_abort); diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index b050663c2a70..413e4138357f 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -929,7 +929,7 @@ __xfs_trans_commit( * Finish deferred items on final commit. Only permanent transactions * should ever have deferred ops. */ - WARN_ON_ONCE(xfs_defer_has_unfinished_work(tp) && + WARN_ON_ONCE(!list_empty(&tp->t_dfops->dop_intake) && !(tp->t_flags & XFS_TRANS_PERM_LOG_RES)); if (!regrant && (tp->t_flags & XFS_TRANS_PERM_LOG_RES)) { error = xfs_defer_finish_noroll(&tp); diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 299656dbf324..1cdc7c0ebeac 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -96,7 +96,6 @@ void xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *item, #define XFS_DEFER_OPS_NR_BUFS 2 /* join up to two buffers */ struct xfs_defer_ops { struct list_head dop_intake; /* unlogged pending work */ - struct list_head dop_pending; /* logged pending work */ }; /* -- cgit v1.2.3 From 0f37d1780c3d864599fb377dcb47ad1aa0686b4e Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 1 Aug 2018 07:20:34 -0700 Subject: xfs: pass transaction to xfs_defer_add() The majority of remaining references to struct xfs_defer_ops in XFS are associated with xfs_defer_add(). At this point, there are no more external xfs_defer_ops users left. All instances of xfs_defer_ops are embedded in the transaction, which means we can safely pass the transaction down to the dfops add interface. Update xfs_defer_add() to receive the transaction as a parameter. Various subsystems implement wrappers to allocate and construct the context specific data structures for the associated deferred operation type. Update these to also carry the transaction down as needed and clean up unused dfops parameters along the way. This removes most of the remaining references to struct xfs_defer_ops throughout the code and facilitates removal of the structure. Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Reviewed-by: Christoph Hellwig [darrick: fix unused variable warnings with ftrace disabled] Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 9 ++--- fs/xfs/libxfs/xfs_bmap.c | 89 +++++++++++++++++++----------------------- fs/xfs/libxfs/xfs_bmap.h | 19 +++++---- fs/xfs/libxfs/xfs_bmap_btree.c | 2 +- fs/xfs/libxfs/xfs_defer.c | 5 ++- fs/xfs/libxfs/xfs_defer.h | 2 +- fs/xfs/libxfs/xfs_ialloc.c | 25 ++++++------ fs/xfs/libxfs/xfs_refcount.c | 80 ++++++++++++++++--------------------- fs/xfs/libxfs/xfs_refcount.h | 18 ++++----- fs/xfs/libxfs/xfs_rmap.c | 57 +++++++++++++-------------- fs/xfs/libxfs/xfs_rmap.h | 22 +++++------ fs/xfs/xfs_bmap_item.c | 3 +- fs/xfs/xfs_bmap_util.c | 13 ++---- fs/xfs/xfs_refcount_item.c | 14 ++----- fs/xfs/xfs_reflink.c | 21 +++++----- 15 files changed, 169 insertions(+), 210 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 9847c1632712..5580b6e23bb3 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2198,12 +2198,12 @@ xfs_agfl_reset( */ STATIC void xfs_defer_agfl_block( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, xfs_agnumber_t agno, xfs_fsblock_t agbno, struct xfs_owner_info *oinfo) { + struct xfs_mount *mp = tp->t_mountp; struct xfs_extent_free_item *new; /* new element */ ASSERT(xfs_bmap_free_item_zone != NULL); @@ -2216,7 +2216,7 @@ xfs_defer_agfl_block( trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1); - xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_AGFL_FREE, &new->xefi_list); + xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_AGFL_FREE, &new->xefi_list); } /* @@ -2325,8 +2325,7 @@ xfs_alloc_fix_freelist( /* defer agfl frees if dfops is provided */ if (tp->t_dfops) { - xfs_defer_agfl_block(mp, tp->t_dfops, args->agno, - bno, &targs.oinfo); + xfs_defer_agfl_block(tp, args->agno, bno, &targs.oinfo); } else { error = xfs_free_agfl_block(tp, args->agno, bno, agbp, &targs.oinfo); diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index d20f541b7061..c9fec0443f38 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -533,8 +533,7 @@ xfs_bmap_validate_ret( */ void __xfs_bmap_add_free( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, xfs_fsblock_t bno, xfs_filblks_t len, struct xfs_owner_info *oinfo, @@ -542,8 +541,9 @@ __xfs_bmap_add_free( { struct xfs_extent_free_item *new; /* new element */ #ifdef DEBUG - xfs_agnumber_t agno; - xfs_agblock_t agbno; + struct xfs_mount *mp = tp->t_mountp; + xfs_agnumber_t agno; + xfs_agblock_t agbno; ASSERT(bno != NULLFSBLOCK); ASSERT(len > 0); @@ -566,9 +566,10 @@ __xfs_bmap_add_free( else xfs_rmap_skip_owner_update(&new->xefi_oinfo); new->xefi_skip_discard = skip_discard; - trace_xfs_bmap_free_defer(mp, XFS_FSB_TO_AGNO(mp, bno), 0, - XFS_FSB_TO_AGBNO(mp, bno), len); - xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xefi_list); + trace_xfs_bmap_free_defer(tp->t_mountp, + XFS_FSB_TO_AGNO(tp->t_mountp, bno), 0, + XFS_FSB_TO_AGBNO(tp->t_mountp, bno), len); + xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_FREE, &new->xefi_list); } /* @@ -624,7 +625,7 @@ xfs_bmap_btree_to_extents( if ((error = xfs_btree_check_block(cur, cblock, 0, cbp))) return error; xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork); - xfs_bmap_add_free(mp, cur->bc_tp->t_dfops, cbno, 1, &oinfo); + xfs_bmap_add_free(cur->bc_tp, cbno, 1, &oinfo); ip->i_d.di_nblocks--; xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L); xfs_trans_binval(tp, cbp); @@ -1961,8 +1962,7 @@ xfs_bmap_add_extent_delay_real( /* add reverse mapping unless caller opted out */ if (!(bma->flags & XFS_BMAPI_NORMAP)) { - error = xfs_rmap_map_extent(mp, bma->tp->t_dfops, bma->ip, - whichfork, new); + error = xfs_rmap_map_extent(bma->tp, bma->ip, whichfork, new); if (error) goto done; } @@ -2026,7 +2026,6 @@ xfs_bmap_add_extent_unwritten_real( int state = xfs_bmap_fork_to_state(whichfork); struct xfs_mount *mp = ip->i_mount; struct xfs_bmbt_irec old; - struct xfs_defer_ops *dfops = tp ? tp->t_dfops : NULL; *logflagsp = 0; @@ -2445,7 +2444,7 @@ xfs_bmap_add_extent_unwritten_real( } /* update reverse mappings */ - error = xfs_rmap_convert_extent(mp, dfops, ip, whichfork, new); + error = xfs_rmap_convert_extent(mp, tp, ip, whichfork, new); if (error) goto done; @@ -2806,8 +2805,7 @@ xfs_bmap_add_extent_hole_real( /* add reverse mapping unless caller opted out */ if (!(flags & XFS_BMAPI_NORMAP)) { - error = xfs_rmap_map_extent(mp, tp->t_dfops, ip, whichfork, - new); + error = xfs_rmap_map_extent(tp, ip, whichfork, new); if (error) goto done; } @@ -4364,9 +4362,8 @@ xfs_bmapi_write( * the refcount btree for orphan recovery. */ if (whichfork == XFS_COW_FORK) { - error = xfs_refcount_alloc_cow_extent(mp, - tp->t_dfops, bma.blkno, - bma.length); + error = xfs_refcount_alloc_cow_extent(tp, + bma.blkno, bma.length); if (error) goto error0; } @@ -4852,7 +4849,6 @@ xfs_bmap_del_extent_real( uint qfield; /* quota field to update */ int state = xfs_bmap_fork_to_state(whichfork); struct xfs_bmbt_irec old; - struct xfs_defer_ops *dfops = tp ? tp->t_dfops : NULL; mp = ip->i_mount; XFS_STATS_INC(mp, xs_del_exlist); @@ -5036,7 +5032,7 @@ xfs_bmap_del_extent_real( } /* remove reverse mapping */ - error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, del); + error = xfs_rmap_unmap_extent(tp, ip, whichfork, del); if (error) goto done; @@ -5045,11 +5041,11 @@ xfs_bmap_del_extent_real( */ if (do_fx && !(bflags & XFS_BMAPI_REMAP)) { if (xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK) { - error = xfs_refcount_decrease_extent(mp, dfops, del); + error = xfs_refcount_decrease_extent(tp, del); if (error) goto done; } else { - __xfs_bmap_add_free(mp, dfops, del->br_startblock, + __xfs_bmap_add_free(tp, del->br_startblock, del->br_blockcount, NULL, (bflags & XFS_BMAPI_NODISCARD) || del->br_state == XFS_EXT_UNWRITTEN); @@ -5489,6 +5485,7 @@ xfs_bmse_can_merge( */ STATIC int xfs_bmse_merge( + struct xfs_trans *tp, struct xfs_inode *ip, int whichfork, xfs_fileoff_t shift, /* shift fsb */ @@ -5496,8 +5493,7 @@ xfs_bmse_merge( struct xfs_bmbt_irec *got, /* extent to shift */ struct xfs_bmbt_irec *left, /* preceding extent */ struct xfs_btree_cur *cur, - int *logflags, /* output */ - struct xfs_defer_ops *dfops) + int *logflags) /* output */ { struct xfs_bmbt_irec new; xfs_filblks_t blockcount; @@ -5553,23 +5549,23 @@ done: &new); /* update reverse mapping. rmap functions merge the rmaps for us */ - error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, got); + error = xfs_rmap_unmap_extent(tp, ip, whichfork, got); if (error) return error; memcpy(&new, got, sizeof(new)); new.br_startoff = left->br_startoff + left->br_blockcount; - return xfs_rmap_map_extent(mp, dfops, ip, whichfork, &new); + return xfs_rmap_map_extent(tp, ip, whichfork, &new); } static int xfs_bmap_shift_update_extent( + struct xfs_trans *tp, struct xfs_inode *ip, int whichfork, struct xfs_iext_cursor *icur, struct xfs_bmbt_irec *got, struct xfs_btree_cur *cur, int *logflags, - struct xfs_defer_ops *dfops, xfs_fileoff_t startoff) { struct xfs_mount *mp = ip->i_mount; @@ -5597,10 +5593,10 @@ xfs_bmap_shift_update_extent( got); /* update reverse mapping */ - error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, &prev); + error = xfs_rmap_unmap_extent(tp, ip, whichfork, &prev); if (error) return error; - return xfs_rmap_map_extent(mp, dfops, ip, whichfork, got); + return xfs_rmap_map_extent(tp, ip, whichfork, got); } int @@ -5660,9 +5656,9 @@ xfs_bmap_collapse_extents( } if (xfs_bmse_can_merge(&prev, &got, offset_shift_fsb)) { - error = xfs_bmse_merge(ip, whichfork, offset_shift_fsb, - &icur, &got, &prev, cur, &logflags, - tp->t_dfops); + error = xfs_bmse_merge(tp, ip, whichfork, + offset_shift_fsb, &icur, &got, &prev, + cur, &logflags); if (error) goto del_cursor; goto done; @@ -5674,8 +5670,8 @@ xfs_bmap_collapse_extents( } } - error = xfs_bmap_shift_update_extent(ip, whichfork, &icur, &got, cur, - &logflags, tp->t_dfops, new_startoff); + error = xfs_bmap_shift_update_extent(tp, ip, whichfork, &icur, &got, + cur, &logflags, new_startoff); if (error) goto del_cursor; @@ -5801,8 +5797,8 @@ xfs_bmap_insert_extents( WARN_ON_ONCE(1); } - error = xfs_bmap_shift_update_extent(ip, whichfork, &icur, &got, cur, - &logflags, tp->t_dfops, new_startoff); + error = xfs_bmap_shift_update_extent(tp, ip, whichfork, &icur, &got, + cur, &logflags, new_startoff); if (error) goto del_cursor; @@ -5979,8 +5975,7 @@ xfs_bmap_is_update_needed( /* Record a bmap intent. */ static int __xfs_bmap_add( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, enum xfs_bmap_intent_type type, struct xfs_inode *ip, int whichfork, @@ -5988,10 +5983,10 @@ __xfs_bmap_add( { struct xfs_bmap_intent *bi; - trace_xfs_bmap_defer(mp, - XFS_FSB_TO_AGNO(mp, bmap->br_startblock), + trace_xfs_bmap_defer(tp->t_mountp, + XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock), type, - XFS_FSB_TO_AGBNO(mp, bmap->br_startblock), + XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock), ip->i_ino, whichfork, bmap->br_startoff, bmap->br_blockcount, @@ -6004,38 +5999,34 @@ __xfs_bmap_add( bi->bi_whichfork = whichfork; bi->bi_bmap = *bmap; - xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_BMAP, &bi->bi_list); + xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_BMAP, &bi->bi_list); return 0; } /* Map an extent into a file. */ int xfs_bmap_map_extent( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, struct xfs_inode *ip, struct xfs_bmbt_irec *PREV) { if (!xfs_bmap_is_update_needed(PREV)) return 0; - return __xfs_bmap_add(mp, dfops, XFS_BMAP_MAP, ip, - XFS_DATA_FORK, PREV); + return __xfs_bmap_add(tp, XFS_BMAP_MAP, ip, XFS_DATA_FORK, PREV); } /* Unmap an extent out of a file. */ int xfs_bmap_unmap_extent( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, struct xfs_inode *ip, struct xfs_bmbt_irec *PREV) { if (!xfs_bmap_is_update_needed(PREV)) return 0; - return __xfs_bmap_add(mp, dfops, XFS_BMAP_UNMAP, ip, - XFS_DATA_FORK, PREV); + return __xfs_bmap_add(tp, XFS_BMAP_UNMAP, ip, XFS_DATA_FORK, PREV); } /* diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 9165a878edcd..b6e9b639e731 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -184,9 +184,9 @@ void xfs_trim_extent(struct xfs_bmbt_irec *irec, xfs_fileoff_t bno, void xfs_trim_extent_eof(struct xfs_bmbt_irec *, struct xfs_inode *); int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); -void __xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops, - xfs_fsblock_t bno, xfs_filblks_t len, - struct xfs_owner_info *oinfo, bool skip_discard); +void __xfs_bmap_add_free(struct xfs_trans *tp, xfs_fsblock_t bno, + xfs_filblks_t len, struct xfs_owner_info *oinfo, + bool skip_discard); void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork); int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork); @@ -230,13 +230,12 @@ int xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork, static inline void xfs_bmap_add_free( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, xfs_fsblock_t bno, xfs_filblks_t len, struct xfs_owner_info *oinfo) { - __xfs_bmap_add_free(mp, dfops, bno, len, oinfo, false); + __xfs_bmap_add_free(tp, bno, len, oinfo, false); } enum xfs_bmap_intent_type { @@ -256,10 +255,10 @@ int xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_inode *ip, enum xfs_bmap_intent_type type, int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock, xfs_filblks_t *blockcount, xfs_exntst_t state); -int xfs_bmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, - struct xfs_inode *ip, struct xfs_bmbt_irec *imap); -int xfs_bmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, - struct xfs_inode *ip, struct xfs_bmbt_irec *imap); +int xfs_bmap_map_extent(struct xfs_trans *tp, struct xfs_inode *ip, + struct xfs_bmbt_irec *imap); +int xfs_bmap_unmap_extent(struct xfs_trans *tp, struct xfs_inode *ip, + struct xfs_bmbt_irec *imap); static inline int xfs_bmap_fork_to_state(int whichfork) { diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index 955e29de8cae..cdb74d2e2a43 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c @@ -289,7 +289,7 @@ xfs_bmbt_free_block( struct xfs_owner_info oinfo; xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_private.b.whichfork); - xfs_bmap_add_free(mp, cur->bc_tp->t_dfops, fsbno, 1, &oinfo); + xfs_bmap_add_free(cur->bc_tp, fsbno, 1, &oinfo); ip->i_d.di_nblocks--; xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 1cbddcf539da..ce2286763531 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -487,12 +487,15 @@ xfs_defer_cancel( /* Add an item for later deferred processing. */ void xfs_defer_add( - struct xfs_defer_ops *dop, + struct xfs_trans *tp, enum xfs_defer_ops_type type, struct list_head *li) { + struct xfs_defer_ops *dop = tp->t_dfops; struct xfs_defer_pending *dfp = NULL; + ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); + /* * Add the item to a pending item at the end of the intake list. * If the last pending item has the same type, reuse it. Else, diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index f091bf3abeaf..b2675f1ca909 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -35,7 +35,7 @@ enum xfs_defer_ops_type { XFS_DEFER_OPS_TYPE_MAX, }; -void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, +void xfs_defer_add(struct xfs_trans *tp, enum xfs_defer_ops_type type, struct list_head *h); int xfs_defer_finish_noroll(struct xfs_trans **tp); int xfs_defer_finish(struct xfs_trans **tp); diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index 295304ad1bc1..a8f6db735d5d 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -1838,23 +1838,24 @@ out_error: */ STATIC void xfs_difree_inode_chunk( - struct xfs_mount *mp, + struct xfs_trans *tp, xfs_agnumber_t agno, - struct xfs_inobt_rec_incore *rec, - struct xfs_defer_ops *dfops) + struct xfs_inobt_rec_incore *rec) { - xfs_agblock_t sagbno = XFS_AGINO_TO_AGBNO(mp, rec->ir_startino); - int startidx, endidx; - int nextbit; - xfs_agblock_t agbno; - int contigblk; - struct xfs_owner_info oinfo; + struct xfs_mount *mp = tp->t_mountp; + xfs_agblock_t sagbno = XFS_AGINO_TO_AGBNO(mp, + rec->ir_startino); + int startidx, endidx; + int nextbit; + xfs_agblock_t agbno; + int contigblk; + struct xfs_owner_info oinfo; DECLARE_BITMAP(holemask, XFS_INOBT_HOLEMASK_BITS); xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES); if (!xfs_inobt_issparse(rec->ir_holemask)) { /* not sparse, calculate extent info directly */ - xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, sagbno), + xfs_bmap_add_free(tp, XFS_AGB_TO_FSB(mp, agno, sagbno), mp->m_ialloc_blks, &oinfo); return; } @@ -1898,7 +1899,7 @@ xfs_difree_inode_chunk( ASSERT(agbno % mp->m_sb.sb_spino_align == 0); ASSERT(contigblk % mp->m_sb.sb_spino_align == 0); - xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, agbno), + xfs_bmap_add_free(tp, XFS_AGB_TO_FSB(mp, agno, agbno), contigblk, &oinfo); /* reset range to current bit and carry on... */ @@ -2002,7 +2003,7 @@ xfs_difree_inobt( goto error0; } - xfs_difree_inode_chunk(mp, agno, &rec, tp->t_dfops); + xfs_difree_inode_chunk(tp, agno, &rec); } else { xic->deleted = false; diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index 86f297ca90cd..542aa1475b5f 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -34,11 +34,9 @@ enum xfs_refc_adjust_op { }; STATIC int __xfs_refcount_cow_alloc(struct xfs_btree_cur *rcur, - xfs_agblock_t agbno, xfs_extlen_t aglen, - struct xfs_defer_ops *dfops); + xfs_agblock_t agbno, xfs_extlen_t aglen); STATIC int __xfs_refcount_cow_free(struct xfs_btree_cur *rcur, - xfs_agblock_t agbno, xfs_extlen_t aglen, - struct xfs_defer_ops *dfops); + xfs_agblock_t agbno, xfs_extlen_t aglen); /* * Look up the first record less than or equal to [bno, len] in the btree @@ -870,7 +868,6 @@ xfs_refcount_adjust_extents( xfs_agblock_t *agbno, xfs_extlen_t *aglen, enum xfs_refc_adjust_op adj, - struct xfs_defer_ops *dfops, struct xfs_owner_info *oinfo) { struct xfs_refcount_irec ext, tmp; @@ -925,8 +922,8 @@ xfs_refcount_adjust_extents( fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_private.a.agno, tmp.rc_startblock); - xfs_bmap_add_free(cur->bc_mp, dfops, fsbno, - tmp.rc_blockcount, oinfo); + xfs_bmap_add_free(cur->bc_tp, fsbno, + tmp.rc_blockcount, oinfo); } (*agbno) += tmp.rc_blockcount; @@ -968,8 +965,8 @@ xfs_refcount_adjust_extents( fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_private.a.agno, ext.rc_startblock); - xfs_bmap_add_free(cur->bc_mp, dfops, fsbno, - ext.rc_blockcount, oinfo); + xfs_bmap_add_free(cur->bc_tp, fsbno, ext.rc_blockcount, + oinfo); } skip: @@ -998,7 +995,6 @@ xfs_refcount_adjust( xfs_agblock_t *new_agbno, xfs_extlen_t *new_aglen, enum xfs_refc_adjust_op adj, - struct xfs_defer_ops *dfops, struct xfs_owner_info *oinfo) { bool shape_changed; @@ -1043,7 +1039,7 @@ xfs_refcount_adjust( /* Now that we've taken care of the ends, adjust the middle extents */ error = xfs_refcount_adjust_extents(cur, new_agbno, new_aglen, - adj, dfops, oinfo); + adj, oinfo); if (error) goto out_error; @@ -1090,7 +1086,6 @@ xfs_refcount_finish_one( struct xfs_btree_cur **pcur) { struct xfs_mount *mp = tp->t_mountp; - struct xfs_defer_ops *dfops = tp->t_dfops; struct xfs_btree_cur *rcur; struct xfs_buf *agbp = NULL; int error = 0; @@ -1145,23 +1140,23 @@ xfs_refcount_finish_one( switch (type) { case XFS_REFCOUNT_INCREASE: error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno, - new_len, XFS_REFCOUNT_ADJUST_INCREASE, dfops, NULL); + new_len, XFS_REFCOUNT_ADJUST_INCREASE, NULL); *new_fsb = XFS_AGB_TO_FSB(mp, agno, new_agbno); break; case XFS_REFCOUNT_DECREASE: error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno, - new_len, XFS_REFCOUNT_ADJUST_DECREASE, dfops, NULL); + new_len, XFS_REFCOUNT_ADJUST_DECREASE, NULL); *new_fsb = XFS_AGB_TO_FSB(mp, agno, new_agbno); break; case XFS_REFCOUNT_ALLOC_COW: *new_fsb = startblock + blockcount; *new_len = 0; - error = __xfs_refcount_cow_alloc(rcur, bno, blockcount, dfops); + error = __xfs_refcount_cow_alloc(rcur, bno, blockcount); break; case XFS_REFCOUNT_FREE_COW: *new_fsb = startblock + blockcount; *new_len = 0; - error = __xfs_refcount_cow_free(rcur, bno, blockcount, dfops); + error = __xfs_refcount_cow_free(rcur, bno, blockcount); break; default: ASSERT(0); @@ -1183,16 +1178,16 @@ out_cur: */ static int __xfs_refcount_add( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, enum xfs_refcount_intent_type type, xfs_fsblock_t startblock, xfs_extlen_t blockcount) { struct xfs_refcount_intent *ri; - trace_xfs_refcount_defer(mp, XFS_FSB_TO_AGNO(mp, startblock), - type, XFS_FSB_TO_AGBNO(mp, startblock), + trace_xfs_refcount_defer(tp->t_mountp, + XFS_FSB_TO_AGNO(tp->t_mountp, startblock), + type, XFS_FSB_TO_AGBNO(tp->t_mountp, startblock), blockcount); ri = kmem_alloc(sizeof(struct xfs_refcount_intent), @@ -1202,7 +1197,7 @@ __xfs_refcount_add( ri->ri_startblock = startblock; ri->ri_blockcount = blockcount; - xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_REFCOUNT, &ri->ri_list); + xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_REFCOUNT, &ri->ri_list); return 0; } @@ -1211,14 +1206,13 @@ __xfs_refcount_add( */ int xfs_refcount_increase_extent( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, struct xfs_bmbt_irec *PREV) { - if (!xfs_sb_version_hasreflink(&mp->m_sb)) + if (!xfs_sb_version_hasreflink(&tp->t_mountp->m_sb)) return 0; - return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_INCREASE, + return __xfs_refcount_add(tp, XFS_REFCOUNT_INCREASE, PREV->br_startblock, PREV->br_blockcount); } @@ -1227,14 +1221,13 @@ xfs_refcount_increase_extent( */ int xfs_refcount_decrease_extent( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, struct xfs_bmbt_irec *PREV) { - if (!xfs_sb_version_hasreflink(&mp->m_sb)) + if (!xfs_sb_version_hasreflink(&tp->t_mountp->m_sb)) return 0; - return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_DECREASE, + return __xfs_refcount_add(tp, XFS_REFCOUNT_DECREASE, PREV->br_startblock, PREV->br_blockcount); } @@ -1522,8 +1515,7 @@ STATIC int __xfs_refcount_cow_alloc( struct xfs_btree_cur *rcur, xfs_agblock_t agbno, - xfs_extlen_t aglen, - struct xfs_defer_ops *dfops) + xfs_extlen_t aglen) { trace_xfs_refcount_cow_increase(rcur->bc_mp, rcur->bc_private.a.agno, agbno, aglen); @@ -1540,8 +1532,7 @@ STATIC int __xfs_refcount_cow_free( struct xfs_btree_cur *rcur, xfs_agblock_t agbno, - xfs_extlen_t aglen, - struct xfs_defer_ops *dfops) + xfs_extlen_t aglen) { trace_xfs_refcount_cow_decrease(rcur->bc_mp, rcur->bc_private.a.agno, agbno, aglen); @@ -1554,47 +1545,45 @@ __xfs_refcount_cow_free( /* Record a CoW staging extent in the refcount btree. */ int xfs_refcount_alloc_cow_extent( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, xfs_fsblock_t fsb, xfs_extlen_t len) { + struct xfs_mount *mp = tp->t_mountp; int error; if (!xfs_sb_version_hasreflink(&mp->m_sb)) return 0; - error = __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_ALLOC_COW, - fsb, len); + error = __xfs_refcount_add(tp, XFS_REFCOUNT_ALLOC_COW, fsb, len); if (error) return error; /* Add rmap entry */ - return xfs_rmap_alloc_extent(mp, dfops, XFS_FSB_TO_AGNO(mp, fsb), + return xfs_rmap_alloc_extent(tp, XFS_FSB_TO_AGNO(mp, fsb), XFS_FSB_TO_AGBNO(mp, fsb), len, XFS_RMAP_OWN_COW); } /* Forget a CoW staging event in the refcount btree. */ int xfs_refcount_free_cow_extent( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, xfs_fsblock_t fsb, xfs_extlen_t len) { + struct xfs_mount *mp = tp->t_mountp; int error; if (!xfs_sb_version_hasreflink(&mp->m_sb)) return 0; /* Remove rmap entry */ - error = xfs_rmap_free_extent(mp, dfops, XFS_FSB_TO_AGNO(mp, fsb), + error = xfs_rmap_free_extent(tp, XFS_FSB_TO_AGNO(mp, fsb), XFS_FSB_TO_AGBNO(mp, fsb), len, XFS_RMAP_OWN_COW); if (error) return error; - return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_FREE_COW, - fsb, len); + return __xfs_refcount_add(tp, XFS_REFCOUNT_FREE_COW, fsb, len); } struct xfs_refcount_recovery { @@ -1692,14 +1681,13 @@ xfs_refcount_recover_cow_leftovers( /* Free the orphan record */ agbno = rr->rr_rrec.rc_startblock - XFS_REFC_COW_START; fsb = XFS_AGB_TO_FSB(mp, agno, agbno); - error = xfs_refcount_free_cow_extent(mp, tp->t_dfops, fsb, + error = xfs_refcount_free_cow_extent(tp, fsb, rr->rr_rrec.rc_blockcount); if (error) goto out_trans; /* Free the block. */ - xfs_bmap_add_free(mp, tp->t_dfops, fsb, - rr->rr_rrec.rc_blockcount, NULL); + xfs_bmap_add_free(tp, fsb, rr->rr_rrec.rc_blockcount, NULL); error = xfs_trans_commit(tp); if (error) diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h index 3b72c6dbf6ad..1d9c518575e7 100644 --- a/fs/xfs/libxfs/xfs_refcount.h +++ b/fs/xfs/libxfs/xfs_refcount.h @@ -29,10 +29,10 @@ struct xfs_refcount_intent { xfs_extlen_t ri_blockcount; }; -extern int xfs_refcount_increase_extent(struct xfs_mount *mp, - struct xfs_defer_ops *dfops, struct xfs_bmbt_irec *irec); -extern int xfs_refcount_decrease_extent(struct xfs_mount *mp, - struct xfs_defer_ops *dfops, struct xfs_bmbt_irec *irec); +extern int xfs_refcount_increase_extent(struct xfs_trans *tp, + struct xfs_bmbt_irec *irec); +extern int xfs_refcount_decrease_extent(struct xfs_trans *tp, + struct xfs_bmbt_irec *irec); extern void xfs_refcount_finish_one_cleanup(struct xfs_trans *tp, struct xfs_btree_cur *rcur, int error); @@ -45,12 +45,10 @@ extern int xfs_refcount_find_shared(struct xfs_btree_cur *cur, xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno, xfs_extlen_t *flen, bool find_end_of_shared); -extern int xfs_refcount_alloc_cow_extent(struct xfs_mount *mp, - struct xfs_defer_ops *dfops, xfs_fsblock_t fsb, - xfs_extlen_t len); -extern int xfs_refcount_free_cow_extent(struct xfs_mount *mp, - struct xfs_defer_ops *dfops, xfs_fsblock_t fsb, - xfs_extlen_t len); +extern int xfs_refcount_alloc_cow_extent(struct xfs_trans *tp, + xfs_fsblock_t fsb, xfs_extlen_t len); +extern int xfs_refcount_free_cow_extent(struct xfs_trans *tp, + xfs_fsblock_t fsb, xfs_extlen_t len); extern int xfs_refcount_recover_cow_leftovers(struct xfs_mount *mp, xfs_agnumber_t agno); diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index fb266fa2cc45..245af452840e 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -2277,18 +2277,18 @@ xfs_rmap_update_is_needed( */ static int __xfs_rmap_add( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, enum xfs_rmap_intent_type type, uint64_t owner, int whichfork, struct xfs_bmbt_irec *bmap) { - struct xfs_rmap_intent *ri; + struct xfs_rmap_intent *ri; - trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock), + trace_xfs_rmap_defer(tp->t_mountp, + XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock), type, - XFS_FSB_TO_AGBNO(mp, bmap->br_startblock), + XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock), owner, whichfork, bmap->br_startoff, bmap->br_blockcount, @@ -2301,23 +2301,22 @@ __xfs_rmap_add( ri->ri_whichfork = whichfork; ri->ri_bmap = *bmap; - xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list); + xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list); return 0; } /* Map an extent into a file. */ int xfs_rmap_map_extent( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *PREV) { - if (!xfs_rmap_update_is_needed(mp, whichfork)) + if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork)) return 0; - return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ? + return __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ? XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino, whichfork, PREV); } @@ -2325,25 +2324,29 @@ xfs_rmap_map_extent( /* Unmap an extent out of a file. */ int xfs_rmap_unmap_extent( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *PREV) { - if (!xfs_rmap_update_is_needed(mp, whichfork)) + if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork)) return 0; - return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ? + return __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ? XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino, whichfork, PREV); } -/* Convert a data fork extent from unwritten to real or vice versa. */ +/* + * Convert a data fork extent from unwritten to real or vice versa. + * + * Note that tp can be NULL here as no transaction is used for COW fork + * unwritten conversion. + */ int xfs_rmap_convert_extent( struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *PREV) @@ -2351,7 +2354,7 @@ xfs_rmap_convert_extent( if (!xfs_rmap_update_is_needed(mp, whichfork)) return 0; - return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ? + return __xfs_rmap_add(tp, xfs_is_reflink_inode(ip) ? XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino, whichfork, PREV); } @@ -2359,8 +2362,7 @@ xfs_rmap_convert_extent( /* Schedule the creation of an rmap for non-file data. */ int xfs_rmap_alloc_extent( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, @@ -2368,23 +2370,21 @@ xfs_rmap_alloc_extent( { struct xfs_bmbt_irec bmap; - if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK)) + if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK)) return 0; - bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno); + bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno); bmap.br_blockcount = len; bmap.br_startoff = 0; bmap.br_state = XFS_EXT_NORM; - return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner, - XFS_DATA_FORK, &bmap); + return __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap); } /* Schedule the deletion of an rmap for non-file data. */ int xfs_rmap_free_extent( - struct xfs_mount *mp, - struct xfs_defer_ops *dfops, + struct xfs_trans *tp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, @@ -2392,16 +2392,15 @@ xfs_rmap_free_extent( { struct xfs_bmbt_irec bmap; - if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK)) + if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK)) return 0; - bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno); + bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno); bmap.br_blockcount = len; bmap.br_startoff = 0; bmap.br_state = XFS_EXT_NORM; - return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner, - XFS_DATA_FORK, &bmap); + return __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap); } /* Compare rmap records. Returns -1 if a < b, 1 if a > b, and 0 if equal. */ diff --git a/fs/xfs/libxfs/xfs_rmap.h b/fs/xfs/libxfs/xfs_rmap.h index 9f19454768b2..157dc722ad35 100644 --- a/fs/xfs/libxfs/xfs_rmap.h +++ b/fs/xfs/libxfs/xfs_rmap.h @@ -185,21 +185,17 @@ struct xfs_rmap_intent { }; /* functions for updating the rmapbt based on bmbt map/unmap operations */ -int xfs_rmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, +int xfs_rmap_map_extent(struct xfs_trans *tp, struct xfs_inode *ip, + int whichfork, struct xfs_bmbt_irec *imap); +int xfs_rmap_unmap_extent(struct xfs_trans *tp, struct xfs_inode *ip, + int whichfork, struct xfs_bmbt_irec *imap); +int xfs_rmap_convert_extent(struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *imap); -int xfs_rmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, - struct xfs_inode *ip, int whichfork, - struct xfs_bmbt_irec *imap); -int xfs_rmap_convert_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, - struct xfs_inode *ip, int whichfork, - struct xfs_bmbt_irec *imap); -int xfs_rmap_alloc_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, - xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, - uint64_t owner); -int xfs_rmap_free_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, - xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, - uint64_t owner); +int xfs_rmap_alloc_extent(struct xfs_trans *tp, xfs_agnumber_t agno, + xfs_agblock_t bno, xfs_extlen_t len, uint64_t owner); +int xfs_rmap_free_extent(struct xfs_trans *tp, xfs_agnumber_t agno, + xfs_agblock_t bno, xfs_extlen_t len, uint64_t owner); void xfs_rmap_finish_one_cleanup(struct xfs_trans *tp, struct xfs_btree_cur *rcur, int error); diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c index e828e0b51814..ce45f066995e 100644 --- a/fs/xfs/xfs_bmap_item.c +++ b/fs/xfs/xfs_bmap_item.c @@ -486,8 +486,7 @@ xfs_bui_recover( irec.br_blockcount = count; irec.br_startoff = bmap->me_startoff; irec.br_state = state; - error = xfs_bmap_unmap_extent(tp->t_mountp, tp->t_dfops, ip, - &irec); + error = xfs_bmap_unmap_extent(tp, ip, &irec); if (error) goto err_inode; } diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index d9dad399440a..addbd74ecd8e 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1534,7 +1534,6 @@ xfs_swap_extent_rmap( struct xfs_inode *tip) { struct xfs_trans *tp = *tpp; - struct xfs_mount *mp = tp->t_mountp; struct xfs_bmbt_irec irec; struct xfs_bmbt_irec uirec; struct xfs_bmbt_irec tirec; @@ -1598,26 +1597,22 @@ xfs_swap_extent_rmap( trace_xfs_swap_extent_rmap_remap_piece(tip, &uirec); /* Remove the mapping from the donor file. */ - error = xfs_bmap_unmap_extent(mp, tp->t_dfops, tip, - &uirec); + error = xfs_bmap_unmap_extent(tp, tip, &uirec); if (error) goto out_defer; /* Remove the mapping from the source file. */ - error = xfs_bmap_unmap_extent(mp, tp->t_dfops, ip, - &irec); + error = xfs_bmap_unmap_extent(tp, ip, &irec); if (error) goto out_defer; /* Map the donor file's blocks into the source file. */ - error = xfs_bmap_map_extent(mp, tp->t_dfops, ip, - &uirec); + error = xfs_bmap_map_extent(tp, ip, &uirec); if (error) goto out_defer; /* Map the source file's blocks into the donor file. */ - error = xfs_bmap_map_extent(mp, tp->t_dfops, tip, - &irec); + error = xfs_bmap_map_extent(tp, tip, &irec); if (error) goto out_defer; diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c index 43c4ac374cba..fce38b56b962 100644 --- a/fs/xfs/xfs_refcount_item.c +++ b/fs/xfs/xfs_refcount_item.c @@ -490,24 +490,18 @@ xfs_cui_recover( irec.br_blockcount = new_len; switch (type) { case XFS_REFCOUNT_INCREASE: - error = xfs_refcount_increase_extent( - tp->t_mountp, tp->t_dfops, - &irec); + error = xfs_refcount_increase_extent(tp, &irec); break; case XFS_REFCOUNT_DECREASE: - error = xfs_refcount_decrease_extent( - tp->t_mountp, tp->t_dfops, - &irec); + error = xfs_refcount_decrease_extent(tp, &irec); break; case XFS_REFCOUNT_ALLOC_COW: - error = xfs_refcount_alloc_cow_extent( - tp->t_mountp, tp->t_dfops, + error = xfs_refcount_alloc_cow_extent(tp, irec.br_startblock, irec.br_blockcount); break; case XFS_REFCOUNT_FREE_COW: - error = xfs_refcount_free_cow_extent( - tp->t_mountp, tp->t_dfops, + error = xfs_refcount_free_cow_extent(tp, irec.br_startblock, irec.br_blockcount); break; diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 2ec562d75494..cbceb320a2e7 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -506,15 +506,13 @@ xfs_reflink_cancel_cow_blocks( ASSERT((*tpp)->t_firstblock == NULLFSBLOCK); /* Free the CoW orphan record. */ - error = xfs_refcount_free_cow_extent(ip->i_mount, - (*tpp)->t_dfops, del.br_startblock, - del.br_blockcount); + error = xfs_refcount_free_cow_extent(*tpp, + del.br_startblock, del.br_blockcount); if (error) break; - xfs_bmap_add_free(ip->i_mount, (*tpp)->t_dfops, - del.br_startblock, del.br_blockcount, - NULL); + xfs_bmap_add_free(*tpp, del.br_startblock, + del.br_blockcount, NULL); /* Roll the transaction */ error = xfs_defer_finish(tpp); @@ -694,14 +692,13 @@ xfs_reflink_end_cow( trace_xfs_reflink_cow_remap(ip, &del); /* Free the CoW orphan record. */ - error = xfs_refcount_free_cow_extent(tp->t_mountp, tp->t_dfops, - del.br_startblock, del.br_blockcount); + error = xfs_refcount_free_cow_extent(tp, del.br_startblock, + del.br_blockcount); if (error) goto out_cancel; /* Map the new blocks into the data fork. */ - error = xfs_bmap_map_extent(tp->t_mountp, tp->t_dfops, ip, - &del); + error = xfs_bmap_map_extent(tp, ip, &del); if (error) goto out_cancel; @@ -1046,12 +1043,12 @@ xfs_reflink_remap_extent( uirec.br_blockcount, uirec.br_startblock); /* Update the refcount tree */ - error = xfs_refcount_increase_extent(mp, tp->t_dfops, &uirec); + error = xfs_refcount_increase_extent(tp, &uirec); if (error) goto out_cancel; /* Map the new blocks into the data fork. */ - error = xfs_bmap_map_extent(mp, tp->t_dfops, ip, &uirec); + error = xfs_bmap_map_extent(tp, ip, &uirec); if (error) goto out_cancel; -- cgit v1.2.3 From 9d9e6233859706875c392707efd6d516cfb764fb Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Wed, 1 Aug 2018 07:20:35 -0700 Subject: xfs: fold dfops into the transaction struct xfs_defer_ops has now been reduced to a single list_head. The external dfops mechanism is unused and thus everywhere a (permanent) transaction is accessible the associated dfops structure is as well. Remove the xfs_defer_ops structure and fold the list_head into the transaction. Also remove the last remnant of external dfops in xfs_trans_dup(). Signed-off-by: Brian Foster Reviewed-by: Darrick J. Wong Reviewed-by: Christoph Hellwig Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 1 - fs/xfs/libxfs/xfs_btree.h | 1 - fs/xfs/libxfs/xfs_da_btree.h | 1 - fs/xfs/libxfs/xfs_defer.c | 67 +++++++++++++------------------------------- fs/xfs/libxfs/xfs_defer.h | 2 -- fs/xfs/libxfs/xfs_dir2.c | 2 -- fs/xfs/libxfs/xfs_dir2.h | 1 - fs/xfs/xfs_inode.h | 1 - fs/xfs/xfs_reflink.c | 5 ++-- fs/xfs/xfs_trace.h | 40 ++++++++++++-------------- fs/xfs/xfs_trans.c | 13 ++++----- fs/xfs/xfs_trans.h | 8 ++---- 12 files changed, 46 insertions(+), 96 deletions(-) (limited to 'fs/xfs/libxfs/xfs_defer.c') diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index c9fec0443f38..5648a177e0ac 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -4286,7 +4286,6 @@ xfs_bmapi_write( bma.ip = ip; bma.total = total; bma.datatype = 0; - ASSERT(!tp || tp->t_dfops); while (bno < end && n < *nmap) { bool need_alloc = false, wasdelay = false; diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index 503615f4d729..e3b3e9dce5da 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -7,7 +7,6 @@ #define __XFS_BTREE_H__ struct xfs_buf; -struct xfs_defer_ops; struct xfs_inode; struct xfs_mount; struct xfs_trans; diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h index 59e290ef334f..84dd865b6c3d 100644 --- a/fs/xfs/libxfs/xfs_da_btree.h +++ b/fs/xfs/libxfs/xfs_da_btree.h @@ -7,7 +7,6 @@ #ifndef __XFS_DA_BTREE_H__ #define __XFS_DA_BTREE_H__ -struct xfs_defer_ops; struct xfs_inode; struct xfs_trans; struct zone; diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index ce2286763531..e792b167150a 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -183,11 +183,10 @@ STATIC void xfs_defer_create_intents( struct xfs_trans *tp) { - struct xfs_defer_ops *dop = tp->t_dfops; struct list_head *li; struct xfs_defer_pending *dfp; - list_for_each_entry(dfp, &dop->dop_intake, dfp_list) { + list_for_each_entry(dfp, &tp->t_dfops, dfp_list) { dfp->dfp_intent = dfp->dfp_type->create_intent(tp, dfp->dfp_count); trace_xfs_defer_create_intent(tp->t_mountp, dfp); @@ -204,10 +203,9 @@ xfs_defer_trans_abort( struct xfs_trans *tp, struct list_head *dop_pending) { - struct xfs_defer_ops *dop = tp->t_dfops; struct xfs_defer_pending *dfp; - trace_xfs_defer_trans_abort(tp->t_mountp, dop, _RET_IP_); + trace_xfs_defer_trans_abort(tp, _RET_IP_); /* Abort intent items that don't have a done item. */ list_for_each_entry(dfp, dop_pending, dfp_list) { @@ -266,14 +264,13 @@ xfs_defer_trans_roll( } } - trace_xfs_defer_trans_roll(tp->t_mountp, tp->t_dfops, _RET_IP_); + trace_xfs_defer_trans_roll(tp, _RET_IP_); /* Roll the transaction. */ error = xfs_trans_roll(tpp); tp = *tpp; if (error) { - trace_xfs_defer_trans_roll_error(tp->t_mountp, - tp->t_dfops, error); + trace_xfs_defer_trans_roll_error(tp, error); return error; } @@ -297,7 +294,7 @@ static void xfs_defer_reset( struct xfs_trans *tp) { - ASSERT(list_empty(&tp->t_dfops->dop_intake)); + ASSERT(list_empty(&tp->t_dfops)); /* * Low mode state transfers across transaction rolls to mirror dfops @@ -358,15 +355,13 @@ xfs_defer_finish_noroll( ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); - trace_xfs_defer_finish((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_); + trace_xfs_defer_finish(*tp, _RET_IP_); /* Until we run out of pending work to finish... */ - while (!list_empty(&dop_pending) || - !list_empty(&(*tp)->t_dfops->dop_intake)) { + while (!list_empty(&dop_pending) || !list_empty(&(*tp)->t_dfops)) { /* log intents and pull in intake items */ xfs_defer_create_intents(*tp); - list_splice_tail_init(&(*tp)->t_dfops->dop_intake, - &dop_pending); + list_splice_tail_init(&(*tp)->t_dfops, &dop_pending); /* * Roll the transaction. @@ -438,14 +433,13 @@ out: if (error) { xfs_defer_trans_abort(*tp, &dop_pending); xfs_force_shutdown((*tp)->t_mountp, SHUTDOWN_CORRUPT_INCORE); - trace_xfs_defer_finish_error((*tp)->t_mountp, (*tp)->t_dfops, - error); + trace_xfs_defer_finish_error(*tp, error); xfs_defer_cancel_list((*tp)->t_mountp, &dop_pending); xfs_defer_cancel(*tp); return error; } - trace_xfs_defer_finish_done((*tp)->t_mountp, (*tp)->t_dfops, _RET_IP_); + trace_xfs_defer_finish_done(*tp, _RET_IP_); return 0; } @@ -480,8 +474,8 @@ xfs_defer_cancel( { struct xfs_mount *mp = tp->t_mountp; - trace_xfs_defer_cancel(mp, tp->t_dfops, _RET_IP_); - xfs_defer_cancel_list(mp, &tp->t_dfops->dop_intake); + trace_xfs_defer_cancel(tp, _RET_IP_); + xfs_defer_cancel_list(mp, &tp->t_dfops); } /* Add an item for later deferred processing. */ @@ -491,7 +485,6 @@ xfs_defer_add( enum xfs_defer_ops_type type, struct list_head *li) { - struct xfs_defer_ops *dop = tp->t_dfops; struct xfs_defer_pending *dfp = NULL; ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); @@ -501,8 +494,8 @@ xfs_defer_add( * If the last pending item has the same type, reuse it. Else, * create a new pending item at the end of the intake list. */ - if (!list_empty(&dop->dop_intake)) { - dfp = list_last_entry(&dop->dop_intake, + if (!list_empty(&tp->t_dfops)) { + dfp = list_last_entry(&tp->t_dfops, struct xfs_defer_pending, dfp_list); if (dfp->dfp_type->type != type || (dfp->dfp_type->max_items && @@ -517,7 +510,7 @@ xfs_defer_add( dfp->dfp_done = NULL; dfp->dfp_count = 0; INIT_LIST_HEAD(&dfp->dfp_work); - list_add_tail(&dfp->dfp_list, &dop->dop_intake); + list_add_tail(&dfp->dfp_list, &tp->t_dfops); } list_add_tail(li, &dfp->dfp_work); @@ -532,39 +525,17 @@ xfs_defer_init_op_type( defer_op_types[type->type] = type; } -/* Initialize a deferred operation. */ -void -xfs_defer_init( - struct xfs_trans *tp, - struct xfs_defer_ops *dop) -{ - struct xfs_mount *mp = NULL; - - memset(dop, 0, sizeof(struct xfs_defer_ops)); - INIT_LIST_HEAD(&dop->dop_intake); - if (tp) { - ASSERT(tp->t_firstblock == NULLFSBLOCK); - tp->t_dfops = dop; - mp = tp->t_mountp; - } - trace_xfs_defer_init(mp, dop, _RET_IP_); -} - /* - * Move state from one xfs_defer_ops to another and reset the source to initial - * state. This is primarily used to carry state forward across transaction rolls - * with internal dfops. + * Move deferred ops from one transaction to another and reset the source to + * initial state. This is primarily used to carry state forward across + * transaction rolls with pending dfops. */ void xfs_defer_move( struct xfs_trans *dtp, struct xfs_trans *stp) { - struct xfs_defer_ops *dst = dtp->t_dfops; - struct xfs_defer_ops *src = stp->t_dfops; - ASSERT(dst != src); - - list_splice_init(&src->dop_intake, &dst->dop_intake); + list_splice_init(&stp->t_dfops, &dtp->t_dfops); /* * Low free space mode was historically controlled by a dfops field. diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index b2675f1ca909..2584a5b95b0d 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -7,7 +7,6 @@ #define __XFS_DEFER_H__ struct xfs_defer_op_type; -struct xfs_defer_ops; /* * Save a log intent item and a list of extents, so that we can replay @@ -40,7 +39,6 @@ void xfs_defer_add(struct xfs_trans *tp, enum xfs_defer_ops_type type, int xfs_defer_finish_noroll(struct xfs_trans **tp); int xfs_defer_finish(struct xfs_trans **tp); void xfs_defer_cancel(struct xfs_trans *); -void xfs_defer_init(struct xfs_trans *tp, struct xfs_defer_ops *dop); void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp); /* Description of a deferred type. */ diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c index 4ea1fddb126f..229152cd1a24 100644 --- a/fs/xfs/libxfs/xfs_dir2.c +++ b/fs/xfs/libxfs/xfs_dir2.c @@ -424,7 +424,6 @@ xfs_dir_removename( int v; /* type-checking value */ ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); - ASSERT(tp->t_dfops); XFS_STATS_INC(dp->i_mount, xs_dir_remove); args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); @@ -483,7 +482,6 @@ xfs_dir_replace( int v; /* type-checking value */ ASSERT(S_ISDIR(VFS_I(dp)->i_mode)); - ASSERT(tp->t_dfops); rval = xfs_dir_ino_validate(tp->t_mountp, inum); if (rval) diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h index ba5acd03de94..c3e3f6b813d8 100644 --- a/fs/xfs/libxfs/xfs_dir2.h +++ b/fs/xfs/libxfs/xfs_dir2.h @@ -9,7 +9,6 @@ #include "xfs_da_format.h" #include "xfs_da_btree.h" -struct xfs_defer_ops; struct xfs_da_args; struct xfs_inode; struct xfs_mount; diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 79a3e61a6991..be2014520155 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -15,7 +15,6 @@ struct xfs_dinode; struct xfs_inode; struct xfs_buf; -struct xfs_defer_ops; struct xfs_bmbt_irec; struct xfs_inode_log_item; struct xfs_mount; diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index cbceb320a2e7..38f405415b88 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -502,7 +502,6 @@ xfs_reflink_cancel_cow_blocks( if (error) break; } else if (del.br_state == XFS_EXT_UNWRITTEN || cancel_real) { - ASSERT((*tpp)->t_dfops); ASSERT((*tpp)->t_firstblock == NULLFSBLOCK); /* Free the CoW orphan record. */ @@ -678,7 +677,7 @@ xfs_reflink_end_cow( goto prev_extent; /* Unmap the old blocks in the data fork. */ - ASSERT(tp->t_dfops && tp->t_firstblock == NULLFSBLOCK); + ASSERT(tp->t_firstblock == NULLFSBLOCK); rlen = del.br_blockcount; error = __xfs_bunmapi(tp, ip, del.br_startoff, &rlen, 0, 1); if (error) @@ -1021,7 +1020,7 @@ xfs_reflink_remap_extent( /* Unmap the old blocks in the data fork. */ rlen = unmap_len; while (rlen) { - ASSERT(tp->t_dfops && tp->t_firstblock == NULLFSBLOCK); + ASSERT(tp->t_firstblock == NULLFSBLOCK); error = __xfs_bunmapi(tp, ip, destoff, &rlen, 0, 1); if (error) goto out_cancel; diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index fec9cfe3dfb4..ad315e83bc02 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2213,57 +2213,54 @@ DEFINE_BTREE_CUR_EVENT(xfs_btree_overlapped_query_range); /* deferred ops */ struct xfs_defer_pending; -struct xfs_defer_ops; DECLARE_EVENT_CLASS(xfs_defer_class, - TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, - unsigned long caller_ip), - TP_ARGS(mp, dop, caller_ip), + TP_PROTO(struct xfs_trans *tp, unsigned long caller_ip), + TP_ARGS(tp, caller_ip), TP_STRUCT__entry( __field(dev_t, dev) - __field(void *, dop) + __field(struct xfs_trans *, tp) __field(char, committed) __field(unsigned long, caller_ip) ), TP_fast_assign( - __entry->dev = mp ? mp->m_super->s_dev : 0; - __entry->dop = dop; + __entry->dev = tp->t_mountp->m_super->s_dev; + __entry->tp = tp; __entry->caller_ip = caller_ip; ), - TP_printk("dev %d:%d ops %p caller %pS", + TP_printk("dev %d:%d tp %p caller %pS", MAJOR(__entry->dev), MINOR(__entry->dev), - __entry->dop, + __entry->tp, (char *)__entry->caller_ip) ) #define DEFINE_DEFER_EVENT(name) \ DEFINE_EVENT(xfs_defer_class, name, \ - TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, \ - unsigned long caller_ip), \ - TP_ARGS(mp, dop, caller_ip)) + TP_PROTO(struct xfs_trans *tp, unsigned long caller_ip), \ + TP_ARGS(tp, caller_ip)) DECLARE_EVENT_CLASS(xfs_defer_error_class, - TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, int error), - TP_ARGS(mp, dop, error), + TP_PROTO(struct xfs_trans *tp, int error), + TP_ARGS(tp, error), TP_STRUCT__entry( __field(dev_t, dev) - __field(void *, dop) + __field(struct xfs_trans *, tp) __field(char, committed) __field(int, error) ), TP_fast_assign( - __entry->dev = mp ? mp->m_super->s_dev : 0; - __entry->dop = dop; + __entry->dev = tp->t_mountp->m_super->s_dev; + __entry->tp = tp; __entry->error = error; ), - TP_printk("dev %d:%d ops %p err %d", + TP_printk("dev %d:%d tp %p err %d", MAJOR(__entry->dev), MINOR(__entry->dev), - __entry->dop, + __entry->tp, __entry->error) ) #define DEFINE_DEFER_ERROR_EVENT(name) \ DEFINE_EVENT(xfs_defer_error_class, name, \ - TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, int error), \ - TP_ARGS(mp, dop, error)) + TP_PROTO(struct xfs_trans *tp, int error), \ + TP_ARGS(tp, error)) DECLARE_EVENT_CLASS(xfs_defer_pending_class, TP_PROTO(struct xfs_mount *mp, struct xfs_defer_pending *dfp), @@ -2382,7 +2379,6 @@ DEFINE_EVENT(xfs_map_extent_deferred_class, name, \ xfs_exntst_t state), \ TP_ARGS(mp, agno, op, agbno, ino, whichfork, offset, len, state)) -DEFINE_DEFER_EVENT(xfs_defer_init); DEFINE_DEFER_EVENT(xfs_defer_cancel); DEFINE_DEFER_EVENT(xfs_defer_trans_roll); DEFINE_DEFER_EVENT(xfs_defer_trans_abort); diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 413e4138357f..bedc5a5133a5 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -100,6 +100,7 @@ xfs_trans_dup( ntp->t_mountp = tp->t_mountp; INIT_LIST_HEAD(&ntp->t_items); INIT_LIST_HEAD(&ntp->t_busy); + INIT_LIST_HEAD(&ntp->t_dfops); ntp->t_firstblock = NULLFSBLOCK; ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); @@ -120,12 +121,8 @@ xfs_trans_dup( tp->t_rtx_res = tp->t_rtx_res_used; ntp->t_pflags = tp->t_pflags; - /* copy the dfops pointer if it's external, otherwise move it */ - xfs_defer_init(ntp, &ntp->t_dfops_internal); - if (tp->t_dfops != &tp->t_dfops_internal) - ntp->t_dfops = tp->t_dfops; - else - xfs_defer_move(ntp, tp); + /* move deferred ops over to the new tp */ + xfs_defer_move(ntp, tp); xfs_trans_dup_dqinfo(tp, ntp); @@ -280,8 +277,8 @@ xfs_trans_alloc( tp->t_mountp = mp; INIT_LIST_HEAD(&tp->t_items); INIT_LIST_HEAD(&tp->t_busy); + INIT_LIST_HEAD(&tp->t_dfops); tp->t_firstblock = NULLFSBLOCK; - xfs_defer_init(tp, &tp->t_dfops_internal); error = xfs_trans_reserve(tp, resp, blocks, rtextents); if (error) { @@ -929,7 +926,7 @@ __xfs_trans_commit( * Finish deferred items on final commit. Only permanent transactions * should ever have deferred ops. */ - WARN_ON_ONCE(!list_empty(&tp->t_dfops->dop_intake) && + WARN_ON_ONCE(!list_empty(&tp->t_dfops) && !(tp->t_flags & XFS_TRANS_PERM_LOG_RES)); if (!regrant && (tp->t_flags & XFS_TRANS_PERM_LOG_RES)) { error = xfs_defer_finish_noroll(&tp); diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 1cdc7c0ebeac..c3d278e96ad1 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -90,13 +90,10 @@ void xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *item, #define XFS_ITEM_FLUSHING 3 /* - * Deferred operations tracking structure. + * Deferred operation item relogging limits. */ #define XFS_DEFER_OPS_NR_INODES 2 /* join up to two inodes */ #define XFS_DEFER_OPS_NR_BUFS 2 /* join up to two buffers */ -struct xfs_defer_ops { - struct list_head dop_intake; /* unlogged pending work */ -}; /* * This is the structure maintained for every active transaction. @@ -114,7 +111,6 @@ typedef struct xfs_trans { struct xlog_ticket *t_ticket; /* log mgr ticket */ struct xfs_mount *t_mountp; /* ptr to fs mount struct */ struct xfs_dquot_acct *t_dqinfo; /* acctg info for dquots */ - struct xfs_defer_ops *t_dfops; /* dfops reference */ int64_t t_icount_delta; /* superblock icount change */ int64_t t_ifree_delta; /* superblock ifree change */ int64_t t_fdblocks_delta; /* superblock fdblocks chg */ @@ -136,8 +132,8 @@ typedef struct xfs_trans { int64_t t_rextslog_delta;/* superblocks rextslog chg */ struct list_head t_items; /* log item descriptors */ struct list_head t_busy; /* list of busy extents */ + struct list_head t_dfops; /* deferred operations */ unsigned long t_pflags; /* saved process flags state */ - struct xfs_defer_ops t_dfops_internal; } xfs_trans_t; /* -- cgit v1.2.3