aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2011-07-08 08:34:39 -0400
committerChristoph Hellwig <hch@lst.de>2011-07-08 08:34:39 -0400
commit33b8f7c2479dfcbc5c27174e44b5f659d9f33c70 (patch)
tree4ea1c46d0e36185b1921d7ab4e586b1c6c306b03 /fs
parent8f04c47aa9712874af2c8816c2ca2a332cba80e4 (diff)
xfs: improve sync behaviour in the face of aggressive dirtying
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 livelock protection in the core writeback code, and another issue is the lock-less xfs_ioend_wait call, which doesn't prevent new ioend from being 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 it's work just like all other filesystems do. Note that the i_iocount wait which is rather suboptimal is simply removed here. We already do it in ->write_inode, which keeps the current supoptimal behaviour. We'll eventually need to remove that as well, but that's material for a separate commit. ------------------------------ snip ------------------------------ #!/bin/sh umount /dev/sda7 mkfs.xfs -f /dev/sda7 # mkfs.ext4 /dev/sda7 # mkfs.btrfs /dev/sda7 mount /dev/sda7 /fs echo $((50<<20)) > /proc/sys/vm/dirty_bytes pid= for i in `seq 10` do dd if=/dev/zero of=/fs/zero-$i bs=1M count=1000 & pid="$pid $!" done sleep 1 tic=$(date +'%s') sync tac=$(date +'%s') echo echo sync time: $((tac-tic)) egrep '(Dirty|Writeback|NFS_Unstable)' /proc/meminfo pidof dd > /dev/null && { kill -9 $pid; echo sync NOT livelocked; } ------------------------------ snip ------------------------------ Signed-off-by: Christoph Hellwig <hch@lst.de> Reported-by: Wu Fengguang <fengguang.wu@intel.com> Reviewed-by: Alex Elder <aelder@sgi.com> Reviewed-by: Dave Chinner <dchinner@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c8
1 files changed, 3 insertions, 5 deletions
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index 8ecad5ff9f9b..f54e8ee1ed62 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -359,14 +359,12 @@ xfs_quiesce_data(
359{ 359{
360 int error, error2 = 0; 360 int error, error2 = 0;
361 361
362 /* push non-blocking */
363 xfs_sync_data(mp, 0);
364 xfs_qm_sync(mp, SYNC_TRYLOCK); 362 xfs_qm_sync(mp, SYNC_TRYLOCK);
365
366 /* push and block till complete */
367 xfs_sync_data(mp, SYNC_WAIT);
368 xfs_qm_sync(mp, SYNC_WAIT); 363 xfs_qm_sync(mp, SYNC_WAIT);
369 364
365 /* force out the newly dirtied log buffers */
366 xfs_log_force(mp, XFS_LOG_SYNC);
367
370 /* write superblock and hoover up shutdown errors */ 368 /* write superblock and hoover up shutdown errors */
371 error = xfs_sync_fsdata(mp); 369 error = xfs_sync_fsdata(mp);
372 370