[Top] [All Lists]

[PATCH 4/4] xfs: improve sync behaviour in the fact of aggressive dirtyi

To: xfs@xxxxxxxxxxx
Subject: [PATCH 4/4] xfs: improve sync behaviour in the fact of aggressive dirtying
From: Christoph Hellwig <hch@xxxxxxxxxxxxx>
Date: Wed, 22 Jun 2011 16:01:33 -0400
References: <20110622200129.218994186@xxxxxxxxxxxxxxxxxxxxxx>
User-agent: quilt/0.48-1
The following script from Wu Fengguang shows very bad behaviour in XFS
when aggressively dirtying data during a sync on XFS, with sync times
up to almost 10 times as long as ext4.

A large part of the issue is that XFS writes data out itself two times
in the ->sync_fs method, overriding the lifelock protection in the core
writeback code, and another issue is the lock less xfs_ioend_wait call,
which doesn't prevent new ioend from beeing queue up while waiting for
the count to reach zero.

This patch removes the XFS-internal sync calls and relies on the VFS
to do its work just like all other filesystems do, and instead of waiting
for pending ioends just flushes the workqueues used to process them.

With these fixes sync times with concurrent dirtiers are up to part
with other filesystems.

------------------------------ snip ------------------------------

umount ${DEV}
mkfs.xfs -f {DEV}
mount ${DEV} /fs

echo $((50<<20)) > /proc/sys/vm/dirty_bytes

for i in `seq 10`
        dd if=/dev/zero of=/fs/zero-$i bs=1M count=1000 &
        pid="$pid $!"

sleep 1

tic=$(date +'%s')
tac=$(date +'%s')

echo sync time: $((tac-tic))
egrep '(Dirty|Writeback|NFS_Unstable)' /proc/meminfo

pidof dd > /dev/null && { kill -9 $pid; echo sync NOT livelocked; }
------------------------------ snip ------------------------------

Reported-by: Wu Fengguang <fengguang.wu@xxxxxxxxx>
Signed-off-by: Christoph Hellwig <hch@xxxxxx>

Index: xfs/fs/xfs/linux-2.6/xfs_sync.c
--- xfs.orig/fs/xfs/linux-2.6/xfs_sync.c        2011-06-22 08:50:38.454850057 
+++ xfs/fs/xfs/linux-2.6/xfs_sync.c     2011-06-22 20:47:39.246005258 +0200
@@ -359,14 +359,16 @@ xfs_quiesce_data(
        int                     error, error2 = 0;
-       /* push non-blocking */
-       xfs_sync_data(mp, 0);
        xfs_qm_sync(mp, SYNC_TRYLOCK);
-       /* push and block till complete */
-       xfs_sync_data(mp, SYNC_WAIT);
        xfs_qm_sync(mp, SYNC_WAIT);
+       /* flush all pending size updates and unwritten extent conversions */
+       flush_workqueue(mp->m_data_iodone_queue);
+       flush_workqueue(mp->m_unwritten_iodone_queue);
+       /* force out the newly dirtied log buffers */
+       xfs_log_force(mp, XFS_LOG_SYNC);
        /* write superblock and hoover up shutdown errors */
        error = xfs_sync_fsdata(mp);

<Prev in Thread] Current Thread [Next in Thread>