Messages in this thread Patch in this message | | | Date | Wed, 9 May 2001 09:30:18 +0200 | Subject | Re: nfs MAP_SHARED corruption fix | From | Trond Myklebust <> |
| |
In addition to the two changes I proposed to Andrea's new patch, I also realized we might want to do a fdatasync() when locking files. If we don't, then locking won't be atomic on mmap()...
Here therefore is Andrea's patch with the changes I propose. Opinions?
Cheers, Trond
diff -u --recursive --new-file linux-2.4.4-fixes/fs/nfs/file.c linux-2.4.4-mmap/fs/nfs/file.c --- linux-2.4.4/fs/nfs/file.c Fri Feb 9 20:29:44 2001 +++ linux-2.4.4-mmap/fs/nfs/file.c Wed May 9 09:18:45 2001 @@ -39,6 +39,7 @@ static ssize_t nfs_file_write(struct file *, const char *, size_t, loff_t *); static int nfs_file_flush(struct file *); static int nfs_fsync(struct file *, struct dentry *dentry, int datasync); +static void nfs_file_close_vma(struct vm_area_struct *); struct file_operations nfs_file_operations = { read: nfs_file_read, @@ -57,6 +58,11 @@ setattr: nfs_notify_change, }; +static struct vm_operations_struct nfs_file_vm_ops = { + nopage: filemap_nopage, + close: nfs_file_close_vma, +}; + /* Hack for future NFS swap support */ #ifndef IS_SWAPFILE # define IS_SWAPFILE(inode) (0) @@ -104,6 +110,20 @@ return result; } +static void nfs_file_close_vma(struct vm_area_struct * vma) +{ + struct inode * inode; + + inode = vma->vm_file->f_dentry->d_inode; + + if (inode->i_state & I_DIRTY_PAGES) { + down(&inode->i_sem); + filemap_fdatasync(inode->i_mapping); + nfs_wb_all(inode); + up(&inode->i_sem); + } +} + static int nfs_file_mmap(struct file * file, struct vm_area_struct * vma) { @@ -115,8 +135,11 @@ dentry->d_parent->d_name.name, dentry->d_name.name); status = nfs_revalidate_inode(NFS_SERVER(inode), inode); - if (!status) + if (!status) { status = generic_file_mmap(file, vma); + if (!status) + vma->vm_ops = &nfs_file_vm_ops; + } return status; } @@ -283,9 +306,10 @@ * Flush all pending writes before doing anything * with locks.. */ - down(&filp->f_dentry->d_inode->i_sem); + down(&inode->i_sem); + filemap_fdatasync(inode->i_mapping); status = nfs_wb_all(inode); - up(&filp->f_dentry->d_inode->i_sem); + up(&inode->i_sem); if (status < 0) return status; @@ -300,10 +324,11 @@ */ out_ok: if ((cmd == F_SETLK || cmd == F_SETLKW) && fl->fl_type != F_UNLCK) { - down(&filp->f_dentry->d_inode->i_sem); + down(&inode->i_sem); + filemap_fdatasync(inode->i_mapping); nfs_wb_all(inode); /* we may have slept */ nfs_zap_caches(inode); - up(&filp->f_dentry->d_inode->i_sem); + up(&inode->i_sem); } return status; } - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |