diff options
author | Bryan Schumaker <bjschuma@netapp.com> | 2011-03-23 14:48:29 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-03-23 15:13:11 -0400 |
commit | 480c2006ebb44ae03165695db7b3e38c04e0d102 (patch) | |
tree | 20bb22ea6db986e91017734f6c0390e1211b1765 /fs/nfs/dir.c | |
parent | e47c085afb3d16cbc6a4bfb10a3b074bb7c58998 (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.c | 54 |
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 | ||
46 | static int nfs_opendir(struct inode *, struct file *); | 46 | static int nfs_opendir(struct inode *, struct file *); |
47 | static int nfs_closedir(struct inode *, struct file *); | ||
47 | static int nfs_readdir(struct file *, void *, filldir_t); | 48 | static int nfs_readdir(struct file *, void *, filldir_t); |
48 | static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *); | 49 | static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *); |
49 | static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *); | 50 | static 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 | ||
137 | static 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 | |||
149 | static 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 | */ |
139 | static int | 158 | static int |
140 | nfs_opendir(struct inode *inode, struct file *filp) | 159 | nfs_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 | } |
187 | out: | ||
188 | put_rpccred(cred); | ||
159 | return res; | 189 | return res; |
160 | } | 190 | } |
161 | 191 | ||
192 | static int | ||
193 | nfs_closedir(struct inode *inode, struct file *filp) | ||
194 | { | ||
195 | put_nfs_open_dir_context(filp->private_data); | ||
196 | return 0; | ||
197 | } | ||
198 | |||
162 | struct nfs_cache_array_entry { | 199 | struct nfs_cache_array_entry { |
163 | u64 cookie; | 200 | u64 cookie; |
164 | u64 ino; | 201 | u64 ino; |
@@ -355,7 +392,8 @@ static | |||
355 | int nfs_readdir_xdr_filler(struct page **pages, nfs_readdir_descriptor_t *desc, | 392 | int 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 | } |
878 | out: | 918 | out: |
879 | mutex_unlock(&inode->i_mutex); | 919 | mutex_unlock(&inode->i_mutex); |