From: Suparna Bhattacharya The current implementation of O_SYNC support for AIO calls sync_page_range explicitly in the high level aio write handlers after invoking the fops aio_write method. This a duplication of logic across sync i/o and aio (not good from a maintenance perspective, and more error prone, e.g. forgets to check for O_DIRECT). More importantly, it doesn't take into account the possibility that different filesystems may have their own O_SYNC implementations in their corresponding aio methods. This is a problem for example in the case of ext3 which may commit the journal after data and meta-data are written out. This patch fixes the above problems by moving the call to sync_page_range out of the high level aio_pwrite handler, and back into generic_file_aio_write for both aio and sync i/o. It takes care to make sure that sync_page_range is called only after all the data is copied in the AIO case, rather than on every retry. include/linux/writeback.h | 0 mm/filemap.c | 16 ++++++++++++++++ mm/page-writeback.c | 0 3 files changed, 16 insertions(+) diff -puN include/linux/writeback.h~aio-O_SYNC-fix include/linux/writeback.h diff -puN mm/filemap.c~aio-O_SYNC-fix mm/filemap.c --- 25/mm/filemap.c~aio-O_SYNC-fix 2003-08-20 23:30:33.000000000 -0700 +++ 25-akpm/mm/filemap.c 2003-08-20 23:30:33.000000000 -0700 @@ -1928,17 +1928,33 @@ ssize_t generic_file_aio_write(struct ki BUG_ON(iocb->ki_pos != pos); + if (!buf && !is_sync_kiocb(iocb)) { + /* nothing to transfer, may just need to sync data */ + ret = count; + goto osync; + } + down(&inode->i_sem); ret = generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos); up(&inode->i_sem); + /* + * Avoid doing a sync in parts for aio - its more efficient to + * call in again after all the data has been copied + */ + if (!is_sync_kiocb(iocb)) + return ret; + +osync: if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) { ssize_t err; err = sync_page_range(inode, mapping, pos, ret); if (err < 0) ret = err; + else + iocb->ki_pos = pos + err; } return ret; } diff -puN mm/page-writeback.c~aio-O_SYNC-fix mm/page-writeback.c _