aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/dir.c
diff options
context:
space:
mode:
authorBryan Schumaker <bjschuma@netapp.com>2011-03-23 14:48:29 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-03-23 15:13:11 -0400
commit480c2006ebb44ae03165695db7b3e38c04e0d102 (patch)
tree20bb22ea6db986e91017734f6c0390e1211b1765 /fs/nfs/dir.c
parente47c085afb3d16cbc6a4bfb10a3b074bb7c58998 (diff)
NFS: Create nfs_open_dir_context
nfs_opendir() created a context that held much more information than we need for a readdir. This patch introduces a slimmed-down nfs_open_dir_context that contains only the cookie and the cred used for RPC operations. The new context will eventually be used to help detect readdir loops. Signed-off-by: Bryan Schumaker <bjschuma@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r--fs/nfs/dir.c54
1 files changed, 47 insertions, 7 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index c5c71cb62fbd..cda73814f666 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -44,6 +44,7 @@
44/* #define NFS_DEBUG_VERBOSE 1 */ 44/* #define NFS_DEBUG_VERBOSE 1 */
45 45
46static int nfs_opendir(struct inode *, struct file *); 46static int nfs_opendir(struct inode *, struct file *);
47static int nfs_closedir(struct inode *, struct file *);
47static int nfs_readdir(struct file *, void *, filldir_t); 48static int nfs_readdir(struct file *, void *, filldir_t);
48static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *); 49static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
49static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *); 50static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *);
@@ -64,7 +65,7 @@ const struct file_operations nfs_dir_operations = {
64 .read = generic_read_dir, 65 .read = generic_read_dir,
65 .readdir = nfs_readdir, 66 .readdir = nfs_readdir,
66 .open = nfs_opendir, 67 .open = nfs_opendir,
67 .release = nfs_release, 68 .release = nfs_closedir,
68 .fsync = nfs_fsync_dir, 69 .fsync = nfs_fsync_dir,
69}; 70};
70 71
@@ -133,13 +134,33 @@ const struct inode_operations nfs4_dir_inode_operations = {
133 134
134#endif /* CONFIG_NFS_V4 */ 135#endif /* CONFIG_NFS_V4 */
135 136
137static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct rpc_cred *cred)
138{
139 struct nfs_open_dir_context *ctx;
140 ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
141 if (ctx != NULL) {
142 ctx->dir_cookie = 0;
143 ctx->cred = get_rpccred(cred);
144 } else
145 ctx = ERR_PTR(-ENOMEM);
146 return ctx;
147}
148
149static void put_nfs_open_dir_context(struct nfs_open_dir_context *ctx)
150{
151 put_rpccred(ctx->cred);
152 kfree(ctx);
153}
154
136/* 155/*
137 * Open file 156 * Open file
138 */ 157 */
139static int 158static int
140nfs_opendir(struct inode *inode, struct file *filp) 159nfs_opendir(struct inode *inode, struct file *filp)
141{ 160{
142 int res; 161 int res = 0;
162 struct nfs_open_dir_context *ctx;
163 struct rpc_cred *cred;
143 164
144 dfprintk(FILE, "NFS: open dir(%s/%s)\n", 165 dfprintk(FILE, "NFS: open dir(%s/%s)\n",
145 filp->f_path.dentry->d_parent->d_name.name, 166 filp->f_path.dentry->d_parent->d_name.name,
@@ -147,8 +168,15 @@ nfs_opendir(struct inode *inode, struct file *filp)
147 168
148 nfs_inc_stats(inode, NFSIOS_VFSOPEN); 169 nfs_inc_stats(inode, NFSIOS_VFSOPEN);
149 170
150 /* Call generic open code in order to cache credentials */ 171 cred = rpc_lookup_cred();
151 res = nfs_open(inode, filp); 172 if (IS_ERR(cred))
173 return PTR_ERR(cred);
174 ctx = alloc_nfs_open_dir_context(cred);
175 if (IS_ERR(ctx)) {
176 res = PTR_ERR(ctx);
177 goto out;
178 }
179 filp->private_data = ctx;
152 if (filp->f_path.dentry == filp->f_path.mnt->mnt_root) { 180 if (filp->f_path.dentry == filp->f_path.mnt->mnt_root) {
153 /* This is a mountpoint, so d_revalidate will never 181 /* This is a mountpoint, so d_revalidate will never
154 * have been called, so we need to refresh the 182 * have been called, so we need to refresh the
@@ -156,9 +184,18 @@ nfs_opendir(struct inode *inode, struct file *filp)
156 */ 184 */
157 __nfs_revalidate_inode(NFS_SERVER(inode), inode); 185 __nfs_revalidate_inode(NFS_SERVER(inode), inode);
158 } 186 }
187out:
188 put_rpccred(cred);
159 return res; 189 return res;
160} 190}
161 191
192static int
193nfs_closedir(struct inode *inode, struct file *filp)
194{
195 put_nfs_open_dir_context(filp->private_data);
196 return 0;
197}
198
162struct nfs_cache_array_entry { 199struct nfs_cache_array_entry {
163 u64 cookie; 200 u64 cookie;
164 u64 ino; 201 u64 ino;
@@ -355,7 +392,8 @@ static
355int nfs_readdir_xdr_filler(struct page **pages, nfs_readdir_descriptor_t *desc, 392int nfs_readdir_xdr_filler(struct page **pages, nfs_readdir_descriptor_t *desc,
356 struct nfs_entry *entry, struct file *file, struct inode *inode) 393 struct nfs_entry *entry, struct file *file, struct inode *inode)
357{ 394{
358 struct rpc_cred *cred = nfs_file_cred(file); 395 struct nfs_open_dir_context *ctx = file->private_data;
396 struct rpc_cred *cred = ctx->cred;
359 unsigned long timestamp, gencount; 397 unsigned long timestamp, gencount;
360 int error; 398 int error;
361 399
@@ -786,6 +824,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
786 struct inode *inode = dentry->d_inode; 824 struct inode *inode = dentry->d_inode;
787 nfs_readdir_descriptor_t my_desc, 825 nfs_readdir_descriptor_t my_desc,
788 *desc = &my_desc; 826 *desc = &my_desc;
827 struct nfs_open_dir_context *dir_ctx = filp->private_data;
789 int res; 828 int res;
790 829
791 dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", 830 dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
@@ -802,7 +841,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
802 memset(desc, 0, sizeof(*desc)); 841 memset(desc, 0, sizeof(*desc));
803 842
804 desc->file = filp; 843 desc->file = filp;
805 desc->dir_cookie = &nfs_file_open_context(filp)->dir_cookie; 844 desc->dir_cookie = &dir_ctx->dir_cookie;
806 desc->decode = NFS_PROTO(inode)->decode_dirent; 845 desc->decode = NFS_PROTO(inode)->decode_dirent;
807 desc->plus = NFS_USE_READDIRPLUS(inode); 846 desc->plus = NFS_USE_READDIRPLUS(inode);
808 847
@@ -854,6 +893,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin)
854{ 893{
855 struct dentry *dentry = filp->f_path.dentry; 894 struct dentry *dentry = filp->f_path.dentry;
856 struct inode *inode = dentry->d_inode; 895 struct inode *inode = dentry->d_inode;
896 struct nfs_open_dir_context *dir_ctx = filp->private_data;
857 897
858 dfprintk(FILE, "NFS: llseek dir(%s/%s, %lld, %d)\n", 898 dfprintk(FILE, "NFS: llseek dir(%s/%s, %lld, %d)\n",
859 dentry->d_parent->d_name.name, 899 dentry->d_parent->d_name.name,
@@ -873,7 +913,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin)
873 } 913 }
874 if (offset != filp->f_pos) { 914 if (offset != filp->f_pos) {
875 filp->f_pos = offset; 915 filp->f_pos = offset;
876 nfs_file_open_context(filp)->dir_cookie = 0; 916 dir_ctx->dir_cookie = 0;
877 } 917 }
878out: 918out:
879 mutex_unlock(&inode->i_mutex); 919 mutex_unlock(&inode->i_mutex);