From a300bad22f3ae5811c0f1a5c5c8a95825b3d262d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 8 Apr 2003 21:31:36 -0700 Subject: [PATCH] [PATCH] Make msync(MS_ASYNC) no longer start the I/O MS_ASYNC will currently wait on previously-submitted I/O, then start new I/O and not wait on it. This can cause undesirable blocking if msync is called rapidly against the same memory. So instead, change msync(MS_ASYNC) to not start any IO at all. Just flush the pte dirty bits into the pageframe and leave it at that. The IO _will_ happen within a kupdate period. And the application can use fsync() or fadvise(FADV_DONTNEED) if it actually wants to schedule the IO immediately. (This has triggered an ext3 bug - the page's buffers get dirtied so fast that kjournald keeps writing the buffers over and over for 10-20 seconds before deciding to give up for some reason) --- mm/msync.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/mm/msync.c b/mm/msync.c index 31b84cfd9207f..5e4d464c7efe1 100644 --- a/mm/msync.c +++ b/mm/msync.c @@ -125,11 +125,13 @@ static int filemap_sync(struct vm_area_struct * vma, unsigned long address, /* * MS_SYNC syncs the entire file - including mappings. * - * MS_ASYNC initiates writeout of just the dirty mapped data. - * This provides no guarantee of file integrity - things like indirect - * blocks may not have started writeout. MS_ASYNC is primarily useful - * where the application knows that it has finished with the data and - * wishes to intelligently schedule its own I/O traffic. + * MS_ASYNC does not start I/O (it used to, up to 2.5.67). Instead, it just + * marks the relevant pages dirty. The application may now run fsync() to + * write out the dirty pages and wait on the writeout and check the result. + * Or the application may run fadvise(FADV_DONTNEED) against the fd to start + * async writeout immediately. + * So my _not_ starting I/O in MS_ASYNC we provide complete flexibility to + * applications. */ static int msync_interval(struct vm_area_struct * vma, unsigned long start, unsigned long end, int flags) @@ -143,22 +145,20 @@ static int msync_interval(struct vm_area_struct * vma, if (file && (vma->vm_flags & VM_SHARED)) { ret = filemap_sync(vma, start, end-start, flags); - if (!ret && (flags & (MS_SYNC|MS_ASYNC))) { - struct inode * inode = file->f_dentry->d_inode; + if (!ret && (flags & MS_SYNC)) { + struct inode *inode = file->f_dentry->d_inode; int err; down(&inode->i_sem); ret = filemap_fdatawrite(inode->i_mapping); - if (flags & MS_SYNC) { - if (file->f_op && file->f_op->fsync) { - err = file->f_op->fsync(file, file->f_dentry, 1); - if (err && !ret) - ret = err; - } - err = filemap_fdatawait(inode->i_mapping); - if (!ret) + if (file->f_op && file->f_op->fsync) { + err = file->f_op->fsync(file,file->f_dentry,1); + if (err && !ret) ret = err; } + err = filemap_fdatawait(inode->i_mapping); + if (!ret) + ret = err; up(&inode->i_sem); } } -- 2.53.0