diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-14 18:56:02 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-14 18:56:02 +0300 |
commit | 781fca5b104693bc9242199cc47c690dcaf6a4cb (patch) | |
tree | d216d4299ae5715331a535c84bab390a907bebd6 /fs/xfs/xfs_inode.c | |
parent | 10f3e23f07cb0c20f9bcb77a5b5a7eb2a1b2a2fe (diff) | |
parent | 01239d77b9dd978863d1a75f0d095ab942a1fe66 (diff) | |
download | linux-781fca5b104693bc9242199cc47c690dcaf6a4cb.tar.xz |
Merge tag 'xfs-4.19-merge-6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs updates from Darrick Wong:
"This is the second part of the XFS changes for 4.19.
The biggest changes are the removal of buffer heads frm XFS, a massive
reworking of the deferred transaction operations handling code, the
removal of the long defunct barrier/nobarrier mount options, and the
addition of a few more online repair functions.
Summary:
- Use extent maps to track pagecache page status instead of
bufferhead state.
- Refactor pagecache read and write paths to use the new iomap
library functions, which enable us to drop the old bufferhead code
for pagesize == blocksize filesystems.
- Set up parallel per-block-per-page metadata to track subpage
information that was tracked by buffer heads, which enables us to
drop the old bufferhead code for pagesize > blocksize filesystems.
- Tie a deferred ops control structure to a transaction so that we
can take advantage of an upper-level dfops without having to plumb
pointer passing through the code.
- Refactor the deferred ops code to track deferred ops as part of the
transaction structure (instead of as a separate data structure) so
that we can simplify the scoping rules around defer_ops.
- Refactor twisty delwri buffer submission code to avoid deadlocks.
- Shorten and fix indenting problems in the scrub code.
- Detect obviously bad summary counts at mount and fix them.
- Directly associate deferred ops control structure with a
transaction so that callers no longer have to manage it themselves.
- Remove a couple of IRIX-era inode macros.
- Remove the long-deprecated 'barrier' and 'nobarrier' mount options.
- Clean up the inode fork structure a bit.
- Check for bad fs summary counter values in the superblock.
- Reduce COW fork lookups during writeback.
- Refactor the deferred ops control structures into the transaction
structure, thereby eliminating the need for transaction users to
handle the deferred ops as a separate data structure.
- Add the ability to repair AG headers online.
- Fix a crash due to insufficient return value checking.
- Various fixes and cleanups"
* tag 'xfs-4.19-merge-6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: (155 commits)
xfs: fix a null pointer dereference in xfs_bmap_extents_to_btree
xfs: remove b_last_holder & associated macros
iomap: Switch to offset_in_page for clarity
xfs: Close race between direct IO and xfs_break_layouts()
xfs: repair the AGI
xfs: repair the AGFL
xfs: repair the AGF
xfs: remove dead error handling code in xfs_dquot_disk_alloc()
xfs: use WRITE_ONCE to update if_seq
xfs: fix a comment in xfs_log_reserve
xfs: only validate summary counts on primary superblock
xfs: substitute spaces with tabs
xfs: fold dfops into the transaction
xfs: always defer agfl block frees
xfs: pass transaction to xfs_defer_add()
xfs: replace xfs_defer_ops ->dop_pending with on-stack list
xfs: cancel dfops on xfs_defer_finish() error
xfs: clean out superfluous dfops dop params/vars
xfs: drop dop param from xfs_defer_op_type ->finish_item() callback
xfs: automatic dfops inode relogging
...
Diffstat (limited to 'fs/xfs/xfs_inode.c')
-rw-r--r-- | fs/xfs/xfs_inode.c | 177 |
1 files changed, 53 insertions, 124 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 5df4de666cc1..d957a46dc1cb 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -927,7 +927,7 @@ xfs_ialloc( case S_IFLNK: ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS; ip->i_df.if_flags = XFS_IFEXTENTS; - ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0; + ip->i_df.if_bytes = 0; ip->i_df.if_u1.if_root = NULL; break; default: @@ -1142,8 +1142,6 @@ xfs_create( struct xfs_inode *ip = NULL; struct xfs_trans *tp = NULL; int error; - struct xfs_defer_ops dfops; - xfs_fsblock_t first_block; bool unlock_dp_on_error = false; prid_t prid; struct xfs_dquot *udqp = NULL; @@ -1195,9 +1193,6 @@ xfs_create( xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); unlock_dp_on_error = true; - xfs_defer_init(&dfops, &first_block); - tp->t_agfl_dfops = &dfops; - /* * Reserve disk quota and the inode. */ @@ -1226,7 +1221,7 @@ xfs_create( unlock_dp_on_error = false; error = xfs_dir_createname(tp, dp, name, ip->i_ino, - &first_block, &dfops, resblks ? + resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0); if (error) { ASSERT(error != -ENOSPC); @@ -1238,11 +1233,11 @@ xfs_create( if (is_dir) { error = xfs_dir_init(tp, ip, dp); if (error) - goto out_bmap_cancel; + goto out_trans_cancel; error = xfs_bumplink(tp, dp); if (error) - goto out_bmap_cancel; + goto out_trans_cancel; } /* @@ -1260,10 +1255,6 @@ xfs_create( */ xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); - error = xfs_defer_finish(&tp, &dfops); - if (error) - goto out_bmap_cancel; - error = xfs_trans_commit(tp); if (error) goto out_release_inode; @@ -1275,8 +1266,6 @@ xfs_create( *ipp = ip; return 0; - out_bmap_cancel: - xfs_defer_cancel(&dfops); out_trans_cancel: xfs_trans_cancel(tp); out_release_inode: @@ -1287,7 +1276,7 @@ xfs_create( */ if (ip) { xfs_finish_inode_setup(ip); - IRELE(ip); + xfs_irele(ip); } xfs_qm_dqrele(udqp); @@ -1382,7 +1371,7 @@ xfs_create_tmpfile( */ if (ip) { xfs_finish_inode_setup(ip); - IRELE(ip); + xfs_irele(ip); } xfs_qm_dqrele(udqp); @@ -1401,8 +1390,6 @@ xfs_link( xfs_mount_t *mp = tdp->i_mount; xfs_trans_t *tp; int error; - struct xfs_defer_ops dfops; - xfs_fsblock_t first_block; int resblks; trace_xfs_link(tdp, target_name); @@ -1451,9 +1438,6 @@ xfs_link( goto error_return; } - xfs_defer_init(&dfops, &first_block); - tp->t_agfl_dfops = &dfops; - /* * Handle initial link state of O_TMPFILE inode */ @@ -1464,7 +1448,7 @@ xfs_link( } error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino, - &first_block, &dfops, resblks); + resblks); if (error) goto error_return; xfs_trans_ichgtime(tp, tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); @@ -1482,12 +1466,6 @@ xfs_link( if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) xfs_trans_set_sync(tp); - error = xfs_defer_finish(&tp, &dfops); - if (error) { - xfs_defer_cancel(&dfops); - goto error_return; - } - return xfs_trans_commit(tp); error_return: @@ -1545,8 +1523,6 @@ xfs_itruncate_extents_flags( { struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp = *tpp; - struct xfs_defer_ops dfops; - xfs_fsblock_t first_block; xfs_fileoff_t first_unmap_block; xfs_fileoff_t last_block; xfs_filblks_t unmap_len; @@ -1583,10 +1559,9 @@ 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); + ASSERT(tp->t_firstblock == NULLFSBLOCK); error = xfs_bunmapi(tp, ip, first_unmap_block, unmap_len, flags, - XFS_ITRUNC_MAX_EXTENTS, &first_block, - &dfops, &done); + XFS_ITRUNC_MAX_EXTENTS, &done); if (error) goto out_bmap_cancel; @@ -1594,10 +1569,9 @@ xfs_itruncate_extents_flags( * Duplicate the transaction that has the permanent * reservation and commit the old transaction. */ - xfs_defer_ijoin(&dfops, ip); - error = xfs_defer_finish(&tp, &dfops); + error = xfs_defer_finish(&tp); if (error) - goto out_bmap_cancel; + goto out; error = xfs_trans_roll_inode(&tp, ip); if (error) @@ -1631,7 +1605,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(&dfops); + xfs_defer_cancel(tp); goto out; } @@ -1733,7 +1707,6 @@ xfs_inactive_truncate( ASSERT(XFS_FORCED_SHUTDOWN(mp)); return error; } - xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); @@ -1774,8 +1747,6 @@ STATIC int xfs_inactive_ifree( struct xfs_inode *ip) { - struct xfs_defer_ops dfops; - xfs_fsblock_t first_block; struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; int error; @@ -1812,9 +1783,7 @@ xfs_inactive_ifree( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(&dfops, &first_block); - tp->t_agfl_dfops = &dfops; - error = xfs_ifree(tp, ip, &dfops); + error = xfs_ifree(tp, ip); if (error) { /* * If we fail to free the inode, shut down. The cancel @@ -1840,12 +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. */ - error = xfs_defer_finish(&tp, &dfops); - if (error) { - xfs_notice(mp, "%s: xfs_defer_finish returned error %d", - __func__, error); - xfs_defer_cancel(&dfops); - } error = xfs_trans_commit(tp); if (error) xfs_notice(mp, "%s: xfs_trans_commit returned error %d", @@ -1868,7 +1831,6 @@ xfs_inactive( xfs_inode_t *ip) { struct xfs_mount *mp; - struct xfs_ifork *cow_ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); int error; int truncate = 0; @@ -1877,7 +1839,6 @@ xfs_inactive( * to clean up here. */ if (VFS_I(ip)->i_mode == 0) { - ASSERT(ip->i_df.if_real_bytes == 0); ASSERT(ip->i_df.if_broot_bytes == 0); return; } @@ -1890,7 +1851,7 @@ xfs_inactive( return; /* Try to clean out the cow blocks if there are any. */ - if (xfs_is_reflink_inode(ip) && cow_ifp->if_bytes > 0) + if (xfs_inode_has_cow_data(ip)) xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, true); if (VFS_I(ip)->i_nlink != 0) { @@ -2445,9 +2406,8 @@ xfs_ifree_local_data( */ int xfs_ifree( - xfs_trans_t *tp, - xfs_inode_t *ip, - struct xfs_defer_ops *dfops) + struct xfs_trans *tp, + struct xfs_inode *ip) { int error; struct xfs_icluster xic = { 0 }; @@ -2466,7 +2426,7 @@ xfs_ifree( if (error) return error; - error = xfs_difree(tp, ip->i_ino, dfops, &xic); + error = xfs_difree(tp, ip->i_ino, &xic); if (error) return error; @@ -2577,8 +2537,6 @@ xfs_remove( xfs_trans_t *tp = NULL; int is_dir = S_ISDIR(VFS_I(ip)->i_mode); int error = 0; - struct xfs_defer_ops dfops; - xfs_fsblock_t first_block; uint resblks; trace_xfs_remove(dp, name); @@ -2658,13 +2616,10 @@ xfs_remove( if (error) goto out_trans_cancel; - xfs_defer_init(&dfops, &first_block); - tp->t_agfl_dfops = &dfops; - error = xfs_dir_removename(tp, dp, name, ip->i_ino, - &first_block, &dfops, resblks); + error = xfs_dir_removename(tp, dp, name, ip->i_ino, resblks); if (error) { ASSERT(error != -ENOENT); - goto out_bmap_cancel; + goto out_trans_cancel; } /* @@ -2675,10 +2630,6 @@ xfs_remove( if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) xfs_trans_set_sync(tp); - error = xfs_defer_finish(&tp, &dfops); - if (error) - goto out_bmap_cancel; - error = xfs_trans_commit(tp); if (error) goto std_return; @@ -2688,8 +2639,6 @@ xfs_remove( return 0; - out_bmap_cancel: - xfs_defer_cancel(&dfops); out_trans_cancel: xfs_trans_cancel(tp); std_return: @@ -2749,11 +2698,8 @@ xfs_sort_for_rename( static int xfs_finish_rename( - struct xfs_trans *tp, - struct xfs_defer_ops *dfops) + struct xfs_trans *tp) { - int error; - /* * If this is a synchronous mount, make sure that the rename transaction * goes to disk before returning to the user. @@ -2761,13 +2707,6 @@ xfs_finish_rename( if (tp->t_mountp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) xfs_trans_set_sync(tp); - error = xfs_defer_finish(&tp, dfops); - if (error) { - xfs_defer_cancel(dfops); - xfs_trans_cancel(tp); - return error; - } - return xfs_trans_commit(tp); } @@ -2785,8 +2724,6 @@ xfs_cross_rename( struct xfs_inode *dp2, struct xfs_name *name2, struct xfs_inode *ip2, - struct xfs_defer_ops *dfops, - xfs_fsblock_t *first_block, int spaceres) { int error = 0; @@ -2795,16 +2732,12 @@ xfs_cross_rename( int dp2_flags = 0; /* Swap inode number for dirent in first parent */ - error = xfs_dir_replace(tp, dp1, name1, - ip2->i_ino, - first_block, dfops, spaceres); + error = xfs_dir_replace(tp, dp1, name1, ip2->i_ino, spaceres); if (error) goto out_trans_abort; /* Swap inode number for dirent in second parent */ - error = xfs_dir_replace(tp, dp2, name2, - ip1->i_ino, - first_block, dfops, spaceres); + error = xfs_dir_replace(tp, dp2, name2, ip1->i_ino, spaceres); if (error) goto out_trans_abort; @@ -2818,8 +2751,7 @@ xfs_cross_rename( if (S_ISDIR(VFS_I(ip2)->i_mode)) { error = xfs_dir_replace(tp, ip2, &xfs_name_dotdot, - dp1->i_ino, first_block, - dfops, spaceres); + dp1->i_ino, spaceres); if (error) goto out_trans_abort; @@ -2845,8 +2777,7 @@ xfs_cross_rename( if (S_ISDIR(VFS_I(ip1)->i_mode)) { error = xfs_dir_replace(tp, ip1, &xfs_name_dotdot, - dp2->i_ino, first_block, - dfops, spaceres); + dp2->i_ino, spaceres); if (error) goto out_trans_abort; @@ -2885,10 +2816,9 @@ xfs_cross_rename( } xfs_trans_ichgtime(tp, dp1, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); xfs_trans_log_inode(tp, dp1, XFS_ILOG_CORE); - return xfs_finish_rename(tp, dfops); + return xfs_finish_rename(tp); out_trans_abort: - xfs_defer_cancel(dfops); xfs_trans_cancel(tp); return error; } @@ -2943,8 +2873,6 @@ xfs_rename( { struct xfs_mount *mp = src_dp->i_mount; struct xfs_trans *tp; - struct xfs_defer_ops dfops; - xfs_fsblock_t first_block; struct xfs_inode *wip = NULL; /* whiteout inode */ struct xfs_inode *inodes[__XFS_SORT_INODES]; int num_inodes = __XFS_SORT_INODES; @@ -3026,14 +2954,11 @@ xfs_rename( goto out_trans_cancel; } - xfs_defer_init(&dfops, &first_block); - tp->t_agfl_dfops = &dfops; - /* RENAME_EXCHANGE is unique from here on. */ if (flags & RENAME_EXCHANGE) return xfs_cross_rename(tp, src_dp, src_name, src_ip, target_dp, target_name, target_ip, - &dfops, &first_block, spaceres); + spaceres); /* * Set up the target. @@ -3054,10 +2979,9 @@ xfs_rename( * to account for the ".." reference from the new entry. */ error = xfs_dir_createname(tp, target_dp, target_name, - src_ip->i_ino, &first_block, - &dfops, spaceres); + src_ip->i_ino, spaceres); if (error) - goto out_bmap_cancel; + goto out_trans_cancel; xfs_trans_ichgtime(tp, target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); @@ -3065,7 +2989,7 @@ xfs_rename( if (new_parent && src_is_directory) { error = xfs_bumplink(tp, target_dp); if (error) - goto out_bmap_cancel; + goto out_trans_cancel; } } else { /* target_ip != NULL */ /* @@ -3094,10 +3018,9 @@ xfs_rename( * name at the destination directory, remove it first. */ error = xfs_dir_replace(tp, target_dp, target_name, - src_ip->i_ino, - &first_block, &dfops, spaceres); + src_ip->i_ino, spaceres); if (error) - goto out_bmap_cancel; + goto out_trans_cancel; xfs_trans_ichgtime(tp, target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); @@ -3108,7 +3031,7 @@ xfs_rename( */ error = xfs_droplink(tp, target_ip); if (error) - goto out_bmap_cancel; + goto out_trans_cancel; if (src_is_directory) { /* @@ -3116,7 +3039,7 @@ xfs_rename( */ error = xfs_droplink(tp, target_ip); if (error) - goto out_bmap_cancel; + goto out_trans_cancel; } } /* target_ip != NULL */ @@ -3129,11 +3052,10 @@ xfs_rename( * directory. */ error = xfs_dir_replace(tp, src_ip, &xfs_name_dotdot, - target_dp->i_ino, - &first_block, &dfops, spaceres); + target_dp->i_ino, spaceres); ASSERT(error != -EEXIST); if (error) - goto out_bmap_cancel; + goto out_trans_cancel; } /* @@ -3159,7 +3081,7 @@ xfs_rename( */ error = xfs_droplink(tp, src_dp); if (error) - goto out_bmap_cancel; + goto out_trans_cancel; } /* @@ -3169,12 +3091,12 @@ xfs_rename( */ if (wip) { error = xfs_dir_replace(tp, src_dp, src_name, wip->i_ino, - &first_block, &dfops, spaceres); + spaceres); } else error = xfs_dir_removename(tp, src_dp, src_name, src_ip->i_ino, - &first_block, &dfops, spaceres); + spaceres); if (error) - goto out_bmap_cancel; + goto out_trans_cancel; /* * For whiteouts, we need to bump the link count on the whiteout inode. @@ -3188,10 +3110,10 @@ xfs_rename( ASSERT(VFS_I(wip)->i_nlink == 0); error = xfs_bumplink(tp, wip); if (error) - goto out_bmap_cancel; + goto out_trans_cancel; error = xfs_iunlink_remove(tp, wip); if (error) - goto out_bmap_cancel; + goto out_trans_cancel; xfs_trans_log_inode(tp, wip, XFS_ILOG_CORE); /* @@ -3207,18 +3129,16 @@ xfs_rename( if (new_parent) xfs_trans_log_inode(tp, target_dp, XFS_ILOG_CORE); - error = xfs_finish_rename(tp, &dfops); + error = xfs_finish_rename(tp); if (wip) - IRELE(wip); + xfs_irele(wip); return error; -out_bmap_cancel: - xfs_defer_cancel(&dfops); out_trans_cancel: xfs_trans_cancel(tp); out_release_wip: if (wip) - IRELE(wip); + xfs_irele(wip); return error; } @@ -3674,3 +3594,12 @@ xfs_iflush_int( corrupt_out: return -EFSCORRUPTED; } + +/* Release an inode. */ +void +xfs_irele( + struct xfs_inode *ip) +{ + trace_xfs_irele(ip, _RET_IP_); + iput(VFS_I(ip)); +} |