Skip to content

Commit

Permalink
Merge tag 'xfs-5.7-fixes-3' of git://git.kernel.org/pub/scm/fs/xfs/xf…
Browse files Browse the repository at this point in the history
…s-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
  • Loading branch information
Linus Torvalds committed Apr 18, 2020
2 parents 774acb2 + f0f7a67 commit c0d73a8
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 20 deletions.
10 changes: 10 additions & 0 deletions fs/xfs/xfs_icache.c
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,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);
}

Expand All @@ -938,7 +943,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);
}

Expand Down
5 changes: 4 additions & 1 deletion fs/xfs/xfs_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2363,7 +2363,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:
Expand Down
6 changes: 5 additions & 1 deletion fs/xfs/xfs_mount.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,12 @@ typedef struct xfs_mount {
struct xfs_kobj m_error_meta_kobj;
struct xfs_error_cfg m_error_cfg[XFS_ERR_CLASS_MAX][XFS_ERR_ERRNO_MAX];
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_unwritten_workqueue;
struct workqueue_struct *m_cil_workqueue;
Expand Down
1 change: 1 addition & 0 deletions fs/xfs/xfs_reflink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,7 @@ xfs_reflink_remap_extent(
uirec.br_startblock = irec->br_startblock + rlen;
uirec.br_startoff = irec->br_startoff + rlen;
uirec.br_blockcount = unmap_len - rlen;
uirec.br_state = irec->br_state;
unmap_len = rlen;

/* If this isn't a real mapping, we're done. */
Expand Down
40 changes: 22 additions & 18 deletions fs/xfs/xfs_super.c
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,20 @@ xfs_destroy_mount_workqueues(
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
* or a page lock. We use sync_inodes_sb() here to ensure we block while waiting
Expand All @@ -526,15 +540,15 @@ void
xfs_flush_inodes(
struct xfs_mount *mp)
{
struct super_block *sb = mp->m_super;

if (!__ratelimit(&mp->m_flush_inodes_ratelimit))
/*
* If flush_work() returns true then that means we waited for a flush
* which was already in progress. Don't bother running another scan.
*/
if (flush_work(&mp->m_flush_inodes_work))
return;

if (down_read_trylock(&sb->s_umount)) {
sync_inodes_sb(sb);
up_read(&sb->s_umount);
}
queue_work(mp->m_sync_workqueue, &mp->m_flush_inodes_work);
flush_work(&mp->m_flush_inodes_work);
}

/* Catch misguided souls that try to use this interface on XFS */
Expand Down Expand Up @@ -1369,17 +1383,6 @@ xfs_fc_fill_super(
if (error)
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);
if (error)
goto out_close_devices;
Expand Down Expand Up @@ -1752,6 +1755,7 @@ static int xfs_init_fs_context(
spin_lock_init(&mp->m_perag_lock);
mutex_init(&mp->m_growlock);
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_eofblocks_work, xfs_eofblocks_worker);
INIT_DELAYED_WORK(&mp->m_cowblocks_work, xfs_cowblocks_worker);
Expand Down

0 comments on commit c0d73a8

Please sign in to comment.