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 ------------------------------ #!/bin/sh DEV=/dev/sda7 umount ${DEV} mkfs.xfs -f {DEV} mount ${DEV} /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 ------------------------------ 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 +0200 +++ 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); _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs