Commit c0d73a86 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'xfs-5.7-fixes-3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs fixes from Darrick Wong:
 "The three commits here fix some livelocks and other clashes with
  fsfreeze, a potential corruption problem, and a minor race between
  processes freeing and allocating space when the filesystem is near
  ENOSPC.

  Summary:

   - Fix a partially uninitialized variable.

   - Teach the background gc threads to apply for fsfreeze protection.

   - Fix some scaling problems when multiple threads try to flush the
     filesystem when we're about to hit ENOSPC"

* tag 'xfs-5.7-fixes-3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
  xfs: move inode flush to the sync workqueue
  xfs: fix partially uninitialized structure in xfs_reflink_remap_extent
  xfs: acquire superblock freeze protection on eofblocks scans
parents 774acb2a f0f7a674
...@@ -911,7 +911,12 @@ xfs_eofblocks_worker( ...@@ -911,7 +911,12 @@ xfs_eofblocks_worker(
{ {
struct xfs_mount *mp = container_of(to_delayed_work(work), struct xfs_mount *mp = container_of(to_delayed_work(work),
struct xfs_mount, m_eofblocks_work); struct xfs_mount, m_eofblocks_work);
if (!sb_start_write_trylock(mp->m_super))
return;
xfs_icache_free_eofblocks(mp, NULL); xfs_icache_free_eofblocks(mp, NULL);
sb_end_write(mp->m_super);
xfs_queue_eofblocks(mp); xfs_queue_eofblocks(mp);
} }
...@@ -938,7 +943,12 @@ xfs_cowblocks_worker( ...@@ -938,7 +943,12 @@ xfs_cowblocks_worker(
{ {
struct xfs_mount *mp = container_of(to_delayed_work(work), struct xfs_mount *mp = container_of(to_delayed_work(work),
struct xfs_mount, m_cowblocks_work); struct xfs_mount, m_cowblocks_work);
if (!sb_start_write_trylock(mp->m_super))
return;
xfs_icache_free_cowblocks(mp, NULL); xfs_icache_free_cowblocks(mp, NULL);
sb_end_write(mp->m_super);
xfs_queue_cowblocks(mp); xfs_queue_cowblocks(mp);
} }
......
...@@ -2363,7 +2363,10 @@ xfs_file_ioctl( ...@@ -2363,7 +2363,10 @@ xfs_file_ioctl(
if (error) if (error)
return 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: default:
......
...@@ -167,8 +167,12 @@ typedef struct xfs_mount { ...@@ -167,8 +167,12 @@ typedef struct xfs_mount {
struct xfs_kobj m_error_meta_kobj; struct xfs_kobj m_error_meta_kobj;
struct xfs_error_cfg m_error_cfg[XFS_ERR_CLASS_MAX][XFS_ERR_ERRNO_MAX]; struct xfs_error_cfg m_error_cfg[XFS_ERR_CLASS_MAX][XFS_ERR_ERRNO_MAX];
struct xstats m_stats; /* per-fs stats */ struct xstats m_stats; /* per-fs stats */
struct ratelimit_state m_flush_inodes_ratelimit;
/*
* Workqueue item so that we can coalesce multiple inode flush attempts
* into a single flush.
*/
struct work_struct m_flush_inodes_work;
struct workqueue_struct *m_buf_workqueue; struct workqueue_struct *m_buf_workqueue;
struct workqueue_struct *m_unwritten_workqueue; struct workqueue_struct *m_unwritten_workqueue;
struct workqueue_struct *m_cil_workqueue; struct workqueue_struct *m_cil_workqueue;
......
...@@ -1051,6 +1051,7 @@ xfs_reflink_remap_extent( ...@@ -1051,6 +1051,7 @@ xfs_reflink_remap_extent(
uirec.br_startblock = irec->br_startblock + rlen; uirec.br_startblock = irec->br_startblock + rlen;
uirec.br_startoff = irec->br_startoff + rlen; uirec.br_startoff = irec->br_startoff + rlen;
uirec.br_blockcount = unmap_len - rlen; uirec.br_blockcount = unmap_len - rlen;
uirec.br_state = irec->br_state;
unmap_len = rlen; unmap_len = rlen;
/* If this isn't a real mapping, we're done. */ /* If this isn't a real mapping, we're done. */
......
...@@ -516,6 +516,20 @@ xfs_destroy_mount_workqueues( ...@@ -516,6 +516,20 @@ xfs_destroy_mount_workqueues(
destroy_workqueue(mp->m_buf_workqueue); destroy_workqueue(mp->m_buf_workqueue);
} }
static void
xfs_flush_inodes_worker(
struct work_struct *work)
{
struct xfs_mount *mp = container_of(work, struct xfs_mount,
m_flush_inodes_work);
struct super_block *sb = mp->m_super;
if (down_read_trylock(&sb->s_umount)) {
sync_inodes_sb(sb);
up_read(&sb->s_umount);
}
}
/* /*
* Flush all dirty data to disk. Must not be called while holding an XFS_ILOCK * Flush all dirty data to disk. Must not be called while holding an XFS_ILOCK
* or a page lock. We use sync_inodes_sb() here to ensure we block while waiting * or a page lock. We use sync_inodes_sb() here to ensure we block while waiting
...@@ -526,15 +540,15 @@ void ...@@ -526,15 +540,15 @@ void
xfs_flush_inodes( xfs_flush_inodes(
struct xfs_mount *mp) struct xfs_mount *mp)
{ {
struct super_block *sb = mp->m_super; /*
* If flush_work() returns true then that means we waited for a flush
if (!__ratelimit(&mp->m_flush_inodes_ratelimit)) * which was already in progress. Don't bother running another scan.
*/
if (flush_work(&mp->m_flush_inodes_work))
return; return;
if (down_read_trylock(&sb->s_umount)) { queue_work(mp->m_sync_workqueue, &mp->m_flush_inodes_work);
sync_inodes_sb(sb); flush_work(&mp->m_flush_inodes_work);
up_read(&sb->s_umount);
}
} }
/* Catch misguided souls that try to use this interface on XFS */ /* Catch misguided souls that try to use this interface on XFS */
...@@ -1369,17 +1383,6 @@ xfs_fc_fill_super( ...@@ -1369,17 +1383,6 @@ xfs_fc_fill_super(
if (error) if (error)
goto out_free_names; goto out_free_names;
/*
* Cap the number of invocations of xfs_flush_inodes to 16 for every
* quarter of a second. The magic numbers here were determined by
* observation neither to cause stalls in writeback when there are a
* lot of IO threads and the fs is near ENOSPC, nor cause any fstest
* regressions. YMMV.
*/
ratelimit_state_init(&mp->m_flush_inodes_ratelimit, HZ / 4, 16);
ratelimit_set_flags(&mp->m_flush_inodes_ratelimit,
RATELIMIT_MSG_ON_RELEASE);
error = xfs_init_mount_workqueues(mp); error = xfs_init_mount_workqueues(mp);
if (error) if (error)
goto out_close_devices; goto out_close_devices;
...@@ -1752,6 +1755,7 @@ static int xfs_init_fs_context( ...@@ -1752,6 +1755,7 @@ static int xfs_init_fs_context(
spin_lock_init(&mp->m_perag_lock); spin_lock_init(&mp->m_perag_lock);
mutex_init(&mp->m_growlock); mutex_init(&mp->m_growlock);
atomic_set(&mp->m_active_trans, 0); atomic_set(&mp->m_active_trans, 0);
INIT_WORK(&mp->m_flush_inodes_work, xfs_flush_inodes_worker);
INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker); INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);
INIT_DELAYED_WORK(&mp->m_eofblocks_work, xfs_eofblocks_worker); INIT_DELAYED_WORK(&mp->m_eofblocks_work, xfs_eofblocks_worker);
INIT_DELAYED_WORK(&mp->m_cowblocks_work, xfs_cowblocks_worker); INIT_DELAYED_WORK(&mp->m_cowblocks_work, xfs_cowblocks_worker);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment