fat_sync_bhs() does many individual write_dirty_buffer() calls without plugging, making batching in the block layer more difficult. It also does not pass the REQ_SYNC hint for these synchronous writes. Use a plug around the writes so the block layer can more easily batch them. Pass the REQ_SYNC hint to write_dirty_buffer(). Benchmarking was done under QEMU/KVM with a virtio-blk device using cache=directsync. Each result is the arithmetic mean of 10 samples. start = now_ns(); for (unsigned i = 0; i < count; i++) { fallocate(fds[i], FALLOC_FL_KEEP_SIZE, 0, bytes); } elapsed = now_ns() - start; Sync-mounted FAT32 using count=16 files: File size Cluster size Before After Improvement 256MiB 512B 13.11s 11.87s 1.10x 256MiB 4096B 1.657s 1.469s 1.13x Signed-off-by: Matheus Alves de Almeida --- fs/fat/misc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/fat/misc.c b/fs/fat/misc.c index b6a9e2e122cd..e8e2f13254d5 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -9,6 +9,7 @@ #include "fat.h" #include +#include /* * fat_fs_error reports a file system problem that might indicate fa data @@ -354,9 +355,14 @@ EXPORT_SYMBOL_GPL(fat_update_time); int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs) { int i, err = 0; + struct blk_plug plug; + + blk_start_plug(&plug); for (i = 0; i < nr_bhs; i++) - write_dirty_buffer(bhs[i], 0); + write_dirty_buffer(bhs[i], REQ_SYNC); + + blk_finish_plug(&plug); for (i = 0; i < nr_bhs; i++) { wait_on_buffer(bhs[i]); -- 2.43.0