diff options
author | Christoph Hellwig <hch@lst.de> | 2008-12-22 15:11:15 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-01-05 11:54:28 -0500 |
commit | 4c728ef583b3d82266584da5cb068294c09df31e (patch) | |
tree | 1252fa82b5a7cf60c0898c3da810228b4c34ebb3 /fs/nfsd | |
parent | 6110e3abbff8b785907d4db50240e63c1be726e3 (diff) |
add a vfs_fsync helper
Fsync currently has a fdatawrite/fdatawait pair around the method call,
and a mutex_lock/unlock of the inode mutex. All callers of fsync have
to duplicate this, but we have a few and most of them don't quite get
it right. This patch adds a new vfs_fsync that takes care of this.
It's a little more complicated as usual as ->fsync might get a NULL file
pointer and just a dentry from nfsd, but otherwise gets afile and we
want to take the mapping and file operations from it when it is there.
Notes on the fsync callers:
- ecryptfs wasn't calling filemap_fdatawrite / filemap_fdatawait on the
lower file
- coda wasn't calling filemap_fdatawrite / filemap_fdatawait on the host
file, and returning 0 when ->fsync was missing
- shm wasn't calling either filemap_fdatawrite / filemap_fdatawait nor
taking i_mutex. Now given that shared memory doesn't have disk
backing not doing anything in fsync seems fine and I left it out of
the vfs_fsync conversion for now, but in that case we might just
not pass it through to the lower file at all but just call the no-op
simple_sync_file directly.
[and now actually export vfs_fsync]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/vfs.c | 35 |
1 files changed, 3 insertions, 32 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 5245a3965004..44aa92aba891 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -744,45 +744,16 @@ nfsd_close(struct file *filp) | |||
744 | fput(filp); | 744 | fput(filp); |
745 | } | 745 | } |
746 | 746 | ||
747 | /* | ||
748 | * Sync a file | ||
749 | * As this calls fsync (not fdatasync) there is no need for a write_inode | ||
750 | * after it. | ||
751 | */ | ||
752 | static inline int nfsd_dosync(struct file *filp, struct dentry *dp, | ||
753 | const struct file_operations *fop) | ||
754 | { | ||
755 | struct inode *inode = dp->d_inode; | ||
756 | int (*fsync) (struct file *, struct dentry *, int); | ||
757 | int err; | ||
758 | |||
759 | err = filemap_fdatawrite(inode->i_mapping); | ||
760 | if (err == 0 && fop && (fsync = fop->fsync)) | ||
761 | err = fsync(filp, dp, 0); | ||
762 | if (err == 0) | ||
763 | err = filemap_fdatawait(inode->i_mapping); | ||
764 | |||
765 | return err; | ||
766 | } | ||
767 | |||
768 | |||
769 | static int | 747 | static int |
770 | nfsd_sync(struct file *filp) | 748 | nfsd_sync(struct file *filp) |
771 | { | 749 | { |
772 | int err; | 750 | return vfs_fsync(filp, filp->f_path.dentry, 0); |
773 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
774 | dprintk("nfsd: sync file %s\n", filp->f_path.dentry->d_name.name); | ||
775 | mutex_lock(&inode->i_mutex); | ||
776 | err=nfsd_dosync(filp, filp->f_path.dentry, filp->f_op); | ||
777 | mutex_unlock(&inode->i_mutex); | ||
778 | |||
779 | return err; | ||
780 | } | 751 | } |
781 | 752 | ||
782 | int | 753 | int |
783 | nfsd_sync_dir(struct dentry *dp) | 754 | nfsd_sync_dir(struct dentry *dentry) |
784 | { | 755 | { |
785 | return nfsd_dosync(NULL, dp, dp->d_inode->i_fop); | 756 | return vfs_fsync(NULL, dentry, 0); |
786 | } | 757 | } |
787 | 758 | ||
788 | /* | 759 | /* |