aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBryan Schumaker <bjschuma@netapp.com>2012-07-16 16:39:15 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-07-17 13:33:50 -0400
commitce4ef7c0a8a0594d7b9d088d73866a4389402a7e (patch)
tree2898effa24c9b74d27b17dd8219064524537af1e
parent466bfe7f4a5bee4cdd73d3f6bd290173a8c75a40 (diff)
NFS: Split out NFS v4 file operations
This patch moves the NFS v4 file functions into a new file that is only compiled when CONFIG_NFS_V4 is enabled. Signed-off-by: Bryan Schumaker <bjschuma@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/Makefile2
-rw-r--r--fs/nfs/file.c151
-rw-r--r--fs/nfs/internal.h17
-rw-r--r--fs/nfs/nfs4file.c126
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
13nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o 13nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
14nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o 14nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
15nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ 15nfs-$(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
19nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o 19nfs-$(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
49static int nfs_check_flags(int flags) 48int 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
78static int 77int
79nfs_file_release(struct inode *inode, struct file *filp) 78nfs_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
120static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) 119loff_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 */
145static int 144int
146nfs_file_flush(struct file *file, fl_owner_t id) 145nfs_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
170static ssize_t 169ssize_t
171nfs_file_read(struct kiocb *iocb, const struct iovec *iov, 170nfs_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
194static ssize_t 193ssize_t
195nfs_file_splice_read(struct file *filp, loff_t *ppos, 194nfs_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
216static int 215int
217nfs_file_mmap(struct file * file, struct vm_area_struct * vma) 216nfs_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 */
249static int 248int
250nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync) 249nfs_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
564static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, 563ssize_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
616static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, 615ssize_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 */
770static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) 769int 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 */
810static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) 809int 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 */
840static int nfs_setlease(struct file *file, long arg, struct file_lock **fl) 839int 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
868static int
869nfs4_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
936out_put_ctx:
937 put_nfs_open_context(ctx);
938out:
939 dput(parent);
940 return err;
941
942out_drop:
943 d_drop(dentry);
944 err = -EOPENSTALE;
945 goto out_put_ctx;
946}
947
948static int
949nfs4_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
965const 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 *);
257int nfs_mknod(struct inode *, struct dentry *, umode_t, dev_t); 257int nfs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
258int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); 258int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
259 259
260/* file.c */
261int nfs_file_fsync_commit(struct file *, loff_t, loff_t, int);
262loff_t nfs_file_llseek(struct file *, loff_t, int);
263int nfs_file_flush(struct file *, fl_owner_t);
264ssize_t nfs_file_read(struct kiocb *, const struct iovec *, unsigned long, loff_t);
265ssize_t nfs_file_splice_read(struct file *, loff_t *, struct pipe_inode_info *,
266 size_t, unsigned int);
267int nfs_file_mmap(struct file *, struct vm_area_struct *);
268ssize_t nfs_file_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
269int nfs_file_release(struct inode *, struct file *);
270int nfs_lock(struct file *, int, struct file_lock *);
271int nfs_flock(struct file *, int, struct file_lock *);
272ssize_t nfs_file_splice_write(struct pipe_inode_info *, struct file *, loff_t *,
273 size_t, unsigned int);
274int nfs_check_flags(int);
275int nfs_setlease(struct file *, long, struct file_lock **);
276
260/* inode.c */ 277/* inode.c */
261extern struct workqueue_struct *nfsiod_workqueue; 278extern struct workqueue_struct *nfsiod_workqueue;
262extern struct inode *nfs_alloc_inode(struct super_block *sb); 279extern 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
12static int
13nfs4_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
80out_put_ctx:
81 put_nfs_open_context(ctx);
82out:
83 dput(parent);
84 return err;
85
86out_drop:
87 d_drop(dentry);
88 err = -EOPENSTALE;
89 goto out_put_ctx;
90}
91
92static int
93nfs4_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
109const 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};