Patch "xfs: pull up iolock from xfs_free_eofblocks()" has been added to the 4.10-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
xfs: pull up iolock from xfs_free_eofblocks()
to the 4.10-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
xfs-pull-up-iolock-from-xfs_free_eofblocks.patch
and it can be found in the queue-4.10 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
a36b926180cda375ac2ec89e1748b47137cfc51cMon Sep 17 00:00:00 2001
From: Brian Foster <[email protected]>
Date: Fri, 27 Jan 2017 23:22:55 -0800
Subject: xfs: pull up iolock from xfs_free_eofblocks()
From: Brian Foster <[email protected]>
commit a36b926180cda375ac2ec89e1748b47137cfc51c upstream.
xfs_free_eofblocks() requires the IOLOCK_EXCL lock, but is called from different contexts where the lock may or may not be held. The need_iolock parameter exists for this reason, to indicate whether xfs_free_eofblocks() must acquire the iolock itself before it can proceed.
This is ugly and confusing. Simplify the semantics of xfs_free_eofblocks() to require the caller to acquire the iolock appropriately and kill the need_iolock parameter. While here, the mp param can be removed as well as the xfs_mount is accessible from the xfs_inode structure. This patch does not change behavior.
--- fs/xfs/xfs_bmap_util.c | 41 +++++++++++++++------------------------ fs/xfs/xfs_bmap_util.h | 3 -- fs/xfs/xfs_icache.c | 24 ++++++++++++++--------- fs/xfs/xfs_inode.c | 51 ++++++++++++++++++++++++++----------------------- 4 files changed, 60 insertions(+), 59 deletions(-)
fs/xfs/xfs_bmap_util.c +16 -25
@@ -917,17 +917,18 @@ xfs_can_free_eofblocks(struct xfs_inode*/ int xfs_free_eofblocks ( -xfs_mount_t *mp, -xfs_inode_t *ip, -bool need_iolock) +struct xfs_inode *ip) { -xfs_trans_t *tp; -int error; -xfs_fileoff_t end_fsb; -xfs_fileoff_t last_fsb; -xfs_filblks_t map_len; -int nimaps; -xfs_bmbt_irec_t imap; +struct xfs_trans *tp; +int error; +xfs_fileoff_t end_fsb; +xfs_fileoff_t last_fsb; +xfs_filblks_t map_len; +int nimaps; +struct xfs_bmbt_irec imap; +struct xfs_mount *mp = ip->i_mount; + +ASSERT (xfs_isilocked (ip,XFS_IOLOCK_EXCL ));/* * Figure out if there are any blocks beyond the end
@@ -944,6 +945,10 @@ xfs_free_eofblocks( error =xfs_bmapi_read (ip, end_fsb, map_len, &imap, &nimaps,0 );xfs_iunlock (ip,XFS_ILOCK_SHARED ); +/* +* If there are blocks after the end of file, truncate the file to its +* current size to free them up. +*/ if (!error && (nimaps !=0 ) && (imap.br_startblock !=HOLESTARTBLOCK || ip->i_delayed_blks)) {
@@ -954,22 +959,10 @@ xfs_free_eofblocks(if (error)return error; -/* -* There are blocks after the end of file. -* Free them up now by truncating the file to -* its current size. -*/ -if (need_iolock) { -if (!xfs_ilock_nowait (ip,XFS_IOLOCK_EXCL )) -return -EAGAIN ; - } - error =xfs_trans_alloc (mp, &M_RES (mp)->tr_itruncate,0 ,0 ,0 , &tp);if (error) {ASSERT (XFS_FORCED_SHUTDOWN (mp)); -if (need_iolock) -xfs_iunlock (ip,XFS_IOLOCK_EXCL );return error; }
@@ -997,8 +990,6 @@ xfs_free_eofblocks( }xfs_iunlock (ip,XFS_ILOCK_EXCL ); -if (need_iolock) -xfs_iunlock (ip,XFS_IOLOCK_EXCL ); }return error; }
@@ -1415,7 +1406,7 @@ xfs_shift_file_space(* into the accessible region of the file. */ if (xfs_can_free_eofblocks (ip, true)) { - error =xfs_free_eofblocks (mp, ip, false); + error =xfs_free_eofblocks (ip);if (error)return error; }
fs/xfs/xfs_bmap_util.h +1 -2
@@ -63,8 +63,7 @@ int xfs_insert_file_space(struct xfs_ino/* EOF block manipulation functions */ bool xfs_can_free_eofblocks (struct xfs_inode *ip,bool force); -int xfs_free_eofblocks (struct xfs_mount *mp,struct xfs_inode *ip, -bool need_iolock); +int xfs_free_eofblocks (struct xfs_inode *ip);int xfs_swap_extents (struct xfs_inode *ip,struct xfs_inode *tip,struct xfs_swapext *sx);
fs/xfs/xfs_icache.c +15 -9
@@ -1322,7 +1322,7 @@ xfs_inode_free_eofblocks(int flags, void *args) { - int ret; + int ret = 0;struct xfs_eofblocks *eofb = args;bool need_iolock = true;int match;
@@ -1358,19 +1358,25 @@ xfs_inode_free_eofblocks(return 0 ;/* -* A scan owner implies we already hold the iolock. Skip it in -* xfs_free_eofblocks() to avoid deadlock. This also eliminates -* the possibility of EAGAIN being returned. +* A scan owner implies we already hold the iolock. Skip it here +* to avoid deadlock. */ if (eofb->eof_scan_owner == ip->i_ino) need_iolock = false; } - ret =xfs_free_eofblocks (ip->i_mount, ip, need_iolock); - -/* don't revisit the inode if we're not waiting */ -if (ret == -EAGAIN && !(flags &SYNC_WAIT )) - ret =0 ; +/* +* If the caller is waiting, return -EAGAIN to keep the background +* scanner moving and revisit the inode in a subsequent pass. +*/ +if (need_iolock && !xfs_ilock_nowait (ip,XFS_IOLOCK_EXCL )) { +if (flags &SYNC_WAIT ) + ret = -EAGAIN ; +return ret; + } + ret =xfs_free_eofblocks (ip); +if (need_iolock) +xfs_iunlock (ip,XFS_IOLOCK_EXCL );return ret; }
fs/xfs/xfs_inode.c +28 -23
68 lines not on this page · raw message
Patches currently in stable-queue which might be from [email protected] are
queue-4.10/xfs-sync-eofblocks-scans-under-iolock-are-livelock-prone.patch queue-4.10/xfs-pull-up-iolock-from-xfs_free_eofblocks.patch