]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
xfs: acquire superblock freeze protection on eofblocks scans
authorBrian Foster <bfoster@redhat.com>
Sun, 12 Apr 2020 20:11:10 +0000 (13:11 -0700)
committerStefan Bader <stefan.bader@canonical.com>
Thu, 14 May 2020 08:54:28 +0000 (10:54 +0200)
BugLink: https://bugs.launchpad.net/bugs/1878256
commit 4b674b9ac852937af1f8c62f730c325fb6eadcdb upstream.

The filesystem freeze sequence in XFS waits on any background
eofblocks or cowblocks scans to complete before the filesystem is
quiesced. At this point, the freezer has already stopped the
transaction subsystem, however, which means a truncate or cowblock
cancellation in progress is likely blocked in transaction
allocation. This results in a deadlock between freeze and the
associated scanner.

Fix this problem by holding superblock write protection across calls
into the block reapers. Since protection for background scans is
acquired from the workqueue task context, trylock to avoid a similar
deadlock between freeze and blocking on the write lock.

Fixes: d6b636ebb1c9f ("xfs: halt auto-reclamation activities while rebuilding rmap")
Reported-by: Paul Furtado <paulfurtado91@gmail.com>
Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Chandan Rajendra <chandanrlinux@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
fs/xfs/xfs_icache.c
fs/xfs/xfs_ioctl.c

index dadafd1dca3690ab7826181bc61ff60c2ee0144b..d4de7ec4e5d24c9f7b2f44f43c94faf55342fdf3 100644 (file)
@@ -907,7 +907,12 @@ xfs_eofblocks_worker(
 {
        struct xfs_mount *mp = container_of(to_delayed_work(work),
                                struct xfs_mount, m_eofblocks_work);
+
+       if (!sb_start_write_trylock(mp->m_super))
+               return;
        xfs_icache_free_eofblocks(mp, NULL);
+       sb_end_write(mp->m_super);
+
        xfs_queue_eofblocks(mp);
 }
 
@@ -934,7 +939,12 @@ xfs_cowblocks_worker(
 {
        struct xfs_mount *mp = container_of(to_delayed_work(work),
                                struct xfs_mount, m_cowblocks_work);
+
+       if (!sb_start_write_trylock(mp->m_super))
+               return;
        xfs_icache_free_cowblocks(mp, NULL);
+       sb_end_write(mp->m_super);
+
        xfs_queue_cowblocks(mp);
 }
 
index f5ecd50aa2eff9e4666d0b221acf4d8f530c3379..4e09fd6a7cd20b14e4edff012893db33430c456e 100644 (file)
@@ -2106,7 +2106,10 @@ xfs_file_ioctl(
                if (error)
                        return error;
 
-               return xfs_icache_free_eofblocks(mp, &keofb);
+               sb_start_write(mp->m_super);
+               error = xfs_icache_free_eofblocks(mp, &keofb);
+               sb_end_write(mp->m_super);
+               return error;
        }
 
        default: