diff options
| -rw-r--r-- | fs/nfs/Makefile | 2 | ||||
| -rw-r--r-- | fs/nfs/file.c | 151 | ||||
| -rw-r--r-- | fs/nfs/internal.h | 17 | ||||
| -rw-r--r-- | fs/nfs/nfs4file.c | 126 |
4 files changed, 160 insertions, 136 deletions
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index 4a78e76440f8..e882a389b2ed 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile | |||
| @@ -13,7 +13,7 @@ nfs-$(CONFIG_NFS_V2) += proc.o nfs2xdr.o | |||
| 13 | nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o | 13 | nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o |
| 14 | nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o | 14 | nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o |
| 15 | nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ | 15 | nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ |
| 16 | nfs4super.o delegation.o idmap.o \ | 16 | nfs4super.o nfs4file.o delegation.o idmap.o \ |
| 17 | callback.o callback_xdr.o callback_proc.o \ | 17 | callback.o callback_xdr.o callback_proc.o \ |
| 18 | nfs4namespace.o | 18 | nfs4namespace.o |
| 19 | nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o | 19 | nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 76239178e959..70d124a61b98 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
| @@ -35,7 +35,6 @@ | |||
| 35 | #include "internal.h" | 35 | #include "internal.h" |
| 36 | #include "iostat.h" | 36 | #include "iostat.h" |
| 37 | #include "fscache.h" | 37 | #include "fscache.h" |
| 38 | #include "pnfs.h" | ||
| 39 | 38 | ||
| 40 | #define NFSDBG_FACILITY NFSDBG_FILE | 39 | #define NFSDBG_FACILITY NFSDBG_FILE |
| 41 | 40 | ||
| @@ -46,7 +45,7 @@ static const struct vm_operations_struct nfs_file_vm_ops; | |||
| 46 | # define IS_SWAPFILE(inode) (0) | 45 | # define IS_SWAPFILE(inode) (0) |
| 47 | #endif | 46 | #endif |
| 48 | 47 | ||
| 49 | static int nfs_check_flags(int flags) | 48 | int nfs_check_flags(int flags) |
| 50 | { | 49 | { |
| 51 | if ((flags & (O_APPEND | O_DIRECT)) == (O_APPEND | O_DIRECT)) | 50 | if ((flags & (O_APPEND | O_DIRECT)) == (O_APPEND | O_DIRECT)) |
| 52 | return -EINVAL; | 51 | return -EINVAL; |
| @@ -75,7 +74,7 @@ nfs_file_open(struct inode *inode, struct file *filp) | |||
| 75 | return res; | 74 | return res; |
| 76 | } | 75 | } |
| 77 | 76 | ||
| 78 | static int | 77 | int |
| 79 | nfs_file_release(struct inode *inode, struct file *filp) | 78 | nfs_file_release(struct inode *inode, struct file *filp) |
| 80 | { | 79 | { |
| 81 | dprintk("NFS: release(%s/%s)\n", | 80 | dprintk("NFS: release(%s/%s)\n", |
| @@ -117,7 +116,7 @@ force_reval: | |||
| 117 | return __nfs_revalidate_inode(server, inode); | 116 | return __nfs_revalidate_inode(server, inode); |
| 118 | } | 117 | } |
| 119 | 118 | ||
| 120 | static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) | 119 | loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) |
| 121 | { | 120 | { |
| 122 | dprintk("NFS: llseek file(%s/%s, %lld, %d)\n", | 121 | dprintk("NFS: llseek file(%s/%s, %lld, %d)\n", |
| 123 | filp->f_path.dentry->d_parent->d_name.name, | 122 | filp->f_path.dentry->d_parent->d_name.name, |
| @@ -142,7 +141,7 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) | |||
| 142 | /* | 141 | /* |
| 143 | * Flush all dirty pages, and check for write errors. | 142 | * Flush all dirty pages, and check for write errors. |
| 144 | */ | 143 | */ |
| 145 | static int | 144 | int |
| 146 | nfs_file_flush(struct file *file, fl_owner_t id) | 145 | nfs_file_flush(struct file *file, fl_owner_t id) |
| 147 | { | 146 | { |
| 148 | struct dentry *dentry = file->f_path.dentry; | 147 | struct dentry *dentry = file->f_path.dentry; |
| @@ -167,7 +166,7 @@ nfs_file_flush(struct file *file, fl_owner_t id) | |||
| 167 | return vfs_fsync(file, 0); | 166 | return vfs_fsync(file, 0); |
| 168 | } | 167 | } |
| 169 | 168 | ||
| 170 | static ssize_t | 169 | ssize_t |
| 171 | nfs_file_read(struct kiocb *iocb, const struct iovec *iov, | 170 | nfs_file_read(struct kiocb *iocb, const struct iovec *iov, |
| 172 | unsigned long nr_segs, loff_t pos) | 171 | unsigned long nr_segs, loff_t pos) |
| 173 | { | 172 | { |
| @@ -191,7 +190,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov, | |||
| 191 | return result; | 190 | return result; |
| 192 | } | 191 | } |
| 193 | 192 | ||
| 194 | static ssize_t | 193 | ssize_t |
| 195 | nfs_file_splice_read(struct file *filp, loff_t *ppos, | 194 | nfs_file_splice_read(struct file *filp, loff_t *ppos, |
| 196 | struct pipe_inode_info *pipe, size_t count, | 195 | struct pipe_inode_info *pipe, size_t count, |
| 197 | unsigned int flags) | 196 | unsigned int flags) |
| @@ -213,7 +212,7 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos, | |||
| 213 | return res; | 212 | return res; |
| 214 | } | 213 | } |
| 215 | 214 | ||
| 216 | static int | 215 | int |
| 217 | nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | 216 | nfs_file_mmap(struct file * file, struct vm_area_struct * vma) |
| 218 | { | 217 | { |
| 219 | struct dentry *dentry = file->f_path.dentry; | 218 | struct dentry *dentry = file->f_path.dentry; |
| @@ -246,7 +245,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
| 246 | * nfs_file_write() that a write error occurred, and hence cause it to | 245 | * nfs_file_write() that a write error occurred, and hence cause it to |
| 247 | * fall back to doing a synchronous write. | 246 | * fall back to doing a synchronous write. |
| 248 | */ | 247 | */ |
| 249 | static int | 248 | int |
| 250 | nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync) | 249 | nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync) |
| 251 | { | 250 | { |
| 252 | struct dentry *dentry = file->f_path.dentry; | 251 | struct dentry *dentry = file->f_path.dentry; |
| @@ -561,8 +560,8 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode) | |||
| 561 | return 0; | 560 | return 0; |
| 562 | } | 561 | } |
| 563 | 562 | ||
| 564 | static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, | 563 | ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, |
| 565 | unsigned long nr_segs, loff_t pos) | 564 | unsigned long nr_segs, loff_t pos) |
| 566 | { | 565 | { |
| 567 | struct dentry * dentry = iocb->ki_filp->f_path.dentry; | 566 | struct dentry * dentry = iocb->ki_filp->f_path.dentry; |
| 568 | struct inode * inode = dentry->d_inode; | 567 | struct inode * inode = dentry->d_inode; |
| @@ -613,9 +612,9 @@ out_swapfile: | |||
| 613 | goto out; | 612 | goto out; |
| 614 | } | 613 | } |
| 615 | 614 | ||
| 616 | static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | 615 | ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, |
| 617 | struct file *filp, loff_t *ppos, | 616 | struct file *filp, loff_t *ppos, |
| 618 | size_t count, unsigned int flags) | 617 | size_t count, unsigned int flags) |
| 619 | { | 618 | { |
| 620 | struct dentry *dentry = filp->f_path.dentry; | 619 | struct dentry *dentry = filp->f_path.dentry; |
| 621 | struct inode *inode = dentry->d_inode; | 620 | struct inode *inode = dentry->d_inode; |
| @@ -767,7 +766,7 @@ out: | |||
| 767 | /* | 766 | /* |
| 768 | * Lock a (portion of) a file | 767 | * Lock a (portion of) a file |
| 769 | */ | 768 | */ |
| 770 | static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | 769 | int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) |
| 771 | { | 770 | { |
| 772 | struct inode *inode = filp->f_mapping->host; | 771 | struct inode *inode = filp->f_mapping->host; |
| 773 | int ret = -ENOLCK; | 772 | int ret = -ENOLCK; |
| @@ -807,7 +806,7 @@ out_err: | |||
| 807 | /* | 806 | /* |
| 808 | * Lock a (portion of) a file | 807 | * Lock a (portion of) a file |
| 809 | */ | 808 | */ |
| 810 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | 809 | int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) |
| 811 | { | 810 | { |
| 812 | struct inode *inode = filp->f_mapping->host; | 811 | struct inode *inode = filp->f_mapping->host; |
| 813 | int is_local = 0; | 812 | int is_local = 0; |
| @@ -837,7 +836,7 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | |||
| 837 | * There is no protocol support for leases, so we have no way to implement | 836 | * There is no protocol support for leases, so we have no way to implement |
| 838 | * them correctly in the face of opens by other clients. | 837 | * them correctly in the face of opens by other clients. |
| 839 | */ | 838 | */ |
| 840 | static int nfs_setlease(struct file *file, long arg, struct file_lock **fl) | 839 | int nfs_setlease(struct file *file, long arg, struct file_lock **fl) |
| 841 | { | 840 | { |
| 842 | dprintk("NFS: setlease(%s/%s, arg=%ld)\n", | 841 | dprintk("NFS: setlease(%s/%s, arg=%ld)\n", |
| 843 | file->f_path.dentry->d_parent->d_name.name, | 842 | file->f_path.dentry->d_parent->d_name.name, |
| @@ -863,121 +862,3 @@ const struct file_operations nfs_file_operations = { | |||
| 863 | .check_flags = nfs_check_flags, | 862 | .check_flags = nfs_check_flags, |
| 864 | .setlease = nfs_setlease, | 863 | .setlease = nfs_setlease, |
| 865 | }; | 864 | }; |
| 866 | |||
| 867 | #ifdef CONFIG_NFS_V4 | ||
| 868 | static int | ||
| 869 | nfs4_file_open(struct inode *inode, struct file *filp) | ||
| 870 | { | ||
| 871 | struct nfs_open_context *ctx; | ||
| 872 | struct dentry *dentry = filp->f_path.dentry; | ||
| 873 | struct dentry *parent = NULL; | ||
| 874 | struct inode *dir; | ||
| 875 | unsigned openflags = filp->f_flags; | ||
| 876 | struct iattr attr; | ||
| 877 | int err; | ||
| 878 | |||
| 879 | BUG_ON(inode != dentry->d_inode); | ||
| 880 | /* | ||
| 881 | * If no cached dentry exists or if it's negative, NFSv4 handled the | ||
| 882 | * opens in ->lookup() or ->create(). | ||
| 883 | * | ||
| 884 | * We only get this far for a cached positive dentry. We skipped | ||
| 885 | * revalidation, so handle it here by dropping the dentry and returning | ||
| 886 | * -EOPENSTALE. The VFS will retry the lookup/create/open. | ||
| 887 | */ | ||
| 888 | |||
| 889 | dprintk("NFS: open file(%s/%s)\n", | ||
| 890 | dentry->d_parent->d_name.name, | ||
| 891 | dentry->d_name.name); | ||
| 892 | |||
| 893 | if ((openflags & O_ACCMODE) == 3) | ||
| 894 | openflags--; | ||
| 895 | |||
| 896 | /* We can't create new files here */ | ||
| 897 | openflags &= ~(O_CREAT|O_EXCL); | ||
| 898 | |||
| 899 | parent = dget_parent(dentry); | ||
| 900 | dir = parent->d_inode; | ||
| 901 | |||
| 902 | ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode); | ||
| 903 | err = PTR_ERR(ctx); | ||
| 904 | if (IS_ERR(ctx)) | ||
| 905 | goto out; | ||
| 906 | |||
| 907 | attr.ia_valid = ATTR_OPEN; | ||
| 908 | if (openflags & O_TRUNC) { | ||
| 909 | attr.ia_valid |= ATTR_SIZE; | ||
| 910 | attr.ia_size = 0; | ||
| 911 | nfs_wb_all(inode); | ||
| 912 | } | ||
| 913 | |||
| 914 | inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr); | ||
| 915 | if (IS_ERR(inode)) { | ||
| 916 | err = PTR_ERR(inode); | ||
| 917 | switch (err) { | ||
| 918 | case -EPERM: | ||
| 919 | case -EACCES: | ||
| 920 | case -EDQUOT: | ||
| 921 | case -ENOSPC: | ||
| 922 | case -EROFS: | ||
| 923 | goto out_put_ctx; | ||
| 924 | default: | ||
| 925 | goto out_drop; | ||
| 926 | } | ||
| 927 | } | ||
| 928 | iput(inode); | ||
| 929 | if (inode != dentry->d_inode) | ||
| 930 | goto out_drop; | ||
| 931 | |||
| 932 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 933 | nfs_file_set_open_context(filp, ctx); | ||
| 934 | err = 0; | ||
| 935 | |||
| 936 | out_put_ctx: | ||
| 937 | put_nfs_open_context(ctx); | ||
| 938 | out: | ||
| 939 | dput(parent); | ||
| 940 | return err; | ||
| 941 | |||
| 942 | out_drop: | ||
| 943 | d_drop(dentry); | ||
| 944 | err = -EOPENSTALE; | ||
| 945 | goto out_put_ctx; | ||
| 946 | } | ||
| 947 | |||
| 948 | static int | ||
| 949 | nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | ||
| 950 | { | ||
| 951 | int ret; | ||
| 952 | struct inode *inode = file->f_path.dentry->d_inode; | ||
| 953 | |||
| 954 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | ||
| 955 | mutex_lock(&inode->i_mutex); | ||
| 956 | ret = nfs_file_fsync_commit(file, start, end, datasync); | ||
| 957 | if (!ret && !datasync) | ||
| 958 | /* application has asked for meta-data sync */ | ||
| 959 | ret = pnfs_layoutcommit_inode(inode, true); | ||
| 960 | mutex_unlock(&inode->i_mutex); | ||
| 961 | |||
| 962 | return ret; | ||
| 963 | } | ||
| 964 | |||
| 965 | const struct file_operations nfs4_file_operations = { | ||
| 966 | .llseek = nfs_file_llseek, | ||
| 967 | .read = do_sync_read, | ||
| 968 | .write = do_sync_write, | ||
| 969 | .aio_read = nfs_file_read, | ||
| 970 | .aio_write = nfs_file_write, | ||
| 971 | .mmap = nfs_file_mmap, | ||
| 972 | .open = nfs4_file_open, | ||
| 973 | .flush = nfs_file_flush, | ||
| 974 | .release = nfs_file_release, | ||
| 975 | .fsync = nfs4_file_fsync, | ||
| 976 | .lock = nfs_lock, | ||
| 977 | .flock = nfs_flock, | ||
| 978 | .splice_read = nfs_file_splice_read, | ||
| 979 | .splice_write = nfs_file_splice_write, | ||
| 980 | .check_flags = nfs_check_flags, | ||
| 981 | .setlease = nfs_setlease, | ||
| 982 | }; | ||
| 983 | #endif /* CONFIG_NFS_V4 */ | ||
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 35a8ffec69f6..ca7200a53caf 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -257,6 +257,23 @@ int nfs_link(struct dentry *, struct inode *, struct dentry *); | |||
| 257 | int nfs_mknod(struct inode *, struct dentry *, umode_t, dev_t); | 257 | int nfs_mknod(struct inode *, struct dentry *, umode_t, dev_t); |
| 258 | int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); | 258 | int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); |
| 259 | 259 | ||
| 260 | /* file.c */ | ||
| 261 | int nfs_file_fsync_commit(struct file *, loff_t, loff_t, int); | ||
| 262 | loff_t nfs_file_llseek(struct file *, loff_t, int); | ||
| 263 | int nfs_file_flush(struct file *, fl_owner_t); | ||
| 264 | ssize_t nfs_file_read(struct kiocb *, const struct iovec *, unsigned long, loff_t); | ||
| 265 | ssize_t nfs_file_splice_read(struct file *, loff_t *, struct pipe_inode_info *, | ||
| 266 | size_t, unsigned int); | ||
| 267 | int nfs_file_mmap(struct file *, struct vm_area_struct *); | ||
| 268 | ssize_t nfs_file_write(struct kiocb *, const struct iovec *, unsigned long, loff_t); | ||
| 269 | int nfs_file_release(struct inode *, struct file *); | ||
| 270 | int nfs_lock(struct file *, int, struct file_lock *); | ||
| 271 | int nfs_flock(struct file *, int, struct file_lock *); | ||
| 272 | ssize_t nfs_file_splice_write(struct pipe_inode_info *, struct file *, loff_t *, | ||
| 273 | size_t, unsigned int); | ||
| 274 | int nfs_check_flags(int); | ||
| 275 | int nfs_setlease(struct file *, long, struct file_lock **); | ||
| 276 | |||
| 260 | /* inode.c */ | 277 | /* inode.c */ |
| 261 | extern struct workqueue_struct *nfsiod_workqueue; | 278 | extern struct workqueue_struct *nfsiod_workqueue; |
| 262 | extern struct inode *nfs_alloc_inode(struct super_block *sb); | 279 | extern struct inode *nfs_alloc_inode(struct super_block *sb); |
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c new file mode 100644 index 000000000000..acb65e7887f8 --- /dev/null +++ b/fs/nfs/nfs4file.c | |||
| @@ -0,0 +1,126 @@ | |||
| 1 | /* | ||
| 2 | * linux/fs/nfs/file.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 1992 Rick Sladkey | ||
| 5 | */ | ||
| 6 | #include <linux/nfs_fs.h> | ||
| 7 | #include "internal.h" | ||
| 8 | #include "pnfs.h" | ||
| 9 | |||
| 10 | #define NFSDBG_FACILITY NFSDBG_FILE | ||
| 11 | |||
| 12 | static int | ||
| 13 | nfs4_file_open(struct inode *inode, struct file *filp) | ||
| 14 | { | ||
| 15 | struct nfs_open_context *ctx; | ||
| 16 | struct dentry *dentry = filp->f_path.dentry; | ||
| 17 | struct dentry *parent = NULL; | ||
| 18 | struct inode *dir; | ||
| 19 | unsigned openflags = filp->f_flags; | ||
| 20 | struct iattr attr; | ||
| 21 | int err; | ||
| 22 | |||
| 23 | BUG_ON(inode != dentry->d_inode); | ||
| 24 | /* | ||
| 25 | * If no cached dentry exists or if it's negative, NFSv4 handled the | ||
| 26 | * opens in ->lookup() or ->create(). | ||
| 27 | * | ||
| 28 | * We only get this far for a cached positive dentry. We skipped | ||
| 29 | * revalidation, so handle it here by dropping the dentry and returning | ||
| 30 | * -EOPENSTALE. The VFS will retry the lookup/create/open. | ||
| 31 | */ | ||
| 32 | |||
| 33 | dprintk("NFS: open file(%s/%s)\n", | ||
| 34 | dentry->d_parent->d_name.name, | ||
| 35 | dentry->d_name.name); | ||
| 36 | |||
| 37 | if ((openflags & O_ACCMODE) == 3) | ||
| 38 | openflags--; | ||
| 39 | |||
| 40 | /* We can't create new files here */ | ||
| 41 | openflags &= ~(O_CREAT|O_EXCL); | ||
| 42 | |||
| 43 | parent = dget_parent(dentry); | ||
| 44 | dir = parent->d_inode; | ||
| 45 | |||
| 46 | ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode); | ||
| 47 | err = PTR_ERR(ctx); | ||
| 48 | if (IS_ERR(ctx)) | ||
| 49 | goto out; | ||
| 50 | |||
| 51 | attr.ia_valid = ATTR_OPEN; | ||
| 52 | if (openflags & O_TRUNC) { | ||
| 53 | attr.ia_valid |= ATTR_SIZE; | ||
| 54 | attr.ia_size = 0; | ||
| 55 | nfs_wb_all(inode); | ||
| 56 | } | ||
| 57 | |||
| 58 | inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr); | ||
| 59 | if (IS_ERR(inode)) { | ||
| 60 | err = PTR_ERR(inode); | ||
| 61 | switch (err) { | ||
| 62 | case -EPERM: | ||
| 63 | case -EACCES: | ||
| 64 | case -EDQUOT: | ||
| 65 | case -ENOSPC: | ||
| 66 | case -EROFS: | ||
| 67 | goto out_put_ctx; | ||
| 68 | default: | ||
| 69 | goto out_drop; | ||
| 70 | } | ||
| 71 | } | ||
| 72 | iput(inode); | ||
| 73 | if (inode != dentry->d_inode) | ||
| 74 | goto out_drop; | ||
| 75 | |||
| 76 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 77 | nfs_file_set_open_context(filp, ctx); | ||
| 78 | err = 0; | ||
| 79 | |||
| 80 | out_put_ctx: | ||
| 81 | put_nfs_open_context(ctx); | ||
| 82 | out: | ||
| 83 | dput(parent); | ||
| 84 | return err; | ||
| 85 | |||
| 86 | out_drop: | ||
| 87 | d_drop(dentry); | ||
| 88 | err = -EOPENSTALE; | ||
| 89 | goto out_put_ctx; | ||
| 90 | } | ||
| 91 | |||
| 92 | static int | ||
| 93 | nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | ||
| 94 | { | ||
| 95 | int ret; | ||
| 96 | struct inode *inode = file->f_path.dentry->d_inode; | ||
| 97 | |||
| 98 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | ||
| 99 | mutex_lock(&inode->i_mutex); | ||
| 100 | ret = nfs_file_fsync_commit(file, start, end, datasync); | ||
| 101 | if (!ret && !datasync) | ||
| 102 | /* application has asked for meta-data sync */ | ||
| 103 | ret = pnfs_layoutcommit_inode(inode, true); | ||
| 104 | mutex_unlock(&inode->i_mutex); | ||
| 105 | |||
| 106 | return ret; | ||
| 107 | } | ||
| 108 | |||
| 109 | const struct file_operations nfs4_file_operations = { | ||
| 110 | .llseek = nfs_file_llseek, | ||
| 111 | .read = do_sync_read, | ||
| 112 | .write = do_sync_write, | ||
| 113 | .aio_read = nfs_file_read, | ||
| 114 | .aio_write = nfs_file_write, | ||
| 115 | .mmap = nfs_file_mmap, | ||
| 116 | .open = nfs4_file_open, | ||
| 117 | .flush = nfs_file_flush, | ||
| 118 | .release = nfs_file_release, | ||
| 119 | .fsync = nfs4_file_fsync, | ||
| 120 | .lock = nfs_lock, | ||
| 121 | .flock = nfs_flock, | ||
| 122 | .splice_read = nfs_file_splice_read, | ||
| 123 | .splice_write = nfs_file_splice_write, | ||
| 124 | .check_flags = nfs_check_flags, | ||
| 125 | .setlease = nfs_setlease, | ||
| 126 | }; | ||
