diff options
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 1217 |
1 files changed, 776 insertions, 441 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e257172d438c..ededdbd0db38 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -33,15 +33,18 @@ | |||
33 | #include <linux/namei.h> | 33 | #include <linux/namei.h> |
34 | #include <linux/mount.h> | 34 | #include <linux/mount.h> |
35 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
36 | #include <linux/kmemleak.h> | ||
37 | #include <linux/xattr.h> | ||
36 | 38 | ||
37 | #include "nfs4_fs.h" | ||
38 | #include "delegation.h" | 39 | #include "delegation.h" |
39 | #include "iostat.h" | 40 | #include "iostat.h" |
40 | #include "internal.h" | 41 | #include "internal.h" |
42 | #include "fscache.h" | ||
41 | 43 | ||
42 | /* #define NFS_DEBUG_VERBOSE 1 */ | 44 | /* #define NFS_DEBUG_VERBOSE 1 */ |
43 | 45 | ||
44 | 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 *); | ||
45 | static int nfs_readdir(struct file *, void *, filldir_t); | 48 | static int nfs_readdir(struct file *, void *, filldir_t); |
46 | static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *); | 49 | static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *); |
47 | static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *); | 50 | static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *); |
@@ -55,13 +58,14 @@ static int nfs_rename(struct inode *, struct dentry *, | |||
55 | struct inode *, struct dentry *); | 58 | struct inode *, struct dentry *); |
56 | static int nfs_fsync_dir(struct file *, int); | 59 | static int nfs_fsync_dir(struct file *, int); |
57 | static loff_t nfs_llseek_dir(struct file *, loff_t, int); | 60 | static loff_t nfs_llseek_dir(struct file *, loff_t, int); |
61 | static void nfs_readdir_clear_array(struct page*); | ||
58 | 62 | ||
59 | const struct file_operations nfs_dir_operations = { | 63 | const struct file_operations nfs_dir_operations = { |
60 | .llseek = nfs_llseek_dir, | 64 | .llseek = nfs_llseek_dir, |
61 | .read = generic_read_dir, | 65 | .read = generic_read_dir, |
62 | .readdir = nfs_readdir, | 66 | .readdir = nfs_readdir, |
63 | .open = nfs_opendir, | 67 | .open = nfs_opendir, |
64 | .release = nfs_release, | 68 | .release = nfs_closedir, |
65 | .fsync = nfs_fsync_dir, | 69 | .fsync = nfs_fsync_dir, |
66 | }; | 70 | }; |
67 | 71 | ||
@@ -80,6 +84,10 @@ const struct inode_operations nfs_dir_inode_operations = { | |||
80 | .setattr = nfs_setattr, | 84 | .setattr = nfs_setattr, |
81 | }; | 85 | }; |
82 | 86 | ||
87 | const struct address_space_operations nfs_dir_aops = { | ||
88 | .freepage = nfs_readdir_clear_array, | ||
89 | }; | ||
90 | |||
83 | #ifdef CONFIG_NFS_V3 | 91 | #ifdef CONFIG_NFS_V3 |
84 | const struct inode_operations nfs3_dir_inode_operations = { | 92 | const struct inode_operations nfs3_dir_inode_operations = { |
85 | .create = nfs_create, | 93 | .create = nfs_create, |
@@ -104,8 +112,9 @@ const struct inode_operations nfs3_dir_inode_operations = { | |||
104 | #ifdef CONFIG_NFS_V4 | 112 | #ifdef CONFIG_NFS_V4 |
105 | 113 | ||
106 | static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *); | 114 | static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *); |
115 | static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd); | ||
107 | const struct inode_operations nfs4_dir_inode_operations = { | 116 | const struct inode_operations nfs4_dir_inode_operations = { |
108 | .create = nfs_create, | 117 | .create = nfs_open_create, |
109 | .lookup = nfs_atomic_lookup, | 118 | .lookup = nfs_atomic_lookup, |
110 | .link = nfs_link, | 119 | .link = nfs_link, |
111 | .unlink = nfs_unlink, | 120 | .unlink = nfs_unlink, |
@@ -117,20 +126,43 @@ const struct inode_operations nfs4_dir_inode_operations = { | |||
117 | .permission = nfs_permission, | 126 | .permission = nfs_permission, |
118 | .getattr = nfs_getattr, | 127 | .getattr = nfs_getattr, |
119 | .setattr = nfs_setattr, | 128 | .setattr = nfs_setattr, |
120 | .getxattr = nfs4_getxattr, | 129 | .getxattr = generic_getxattr, |
121 | .setxattr = nfs4_setxattr, | 130 | .setxattr = generic_setxattr, |
122 | .listxattr = nfs4_listxattr, | 131 | .listxattr = generic_listxattr, |
132 | .removexattr = generic_removexattr, | ||
123 | }; | 133 | }; |
124 | 134 | ||
125 | #endif /* CONFIG_NFS_V4 */ | 135 | #endif /* CONFIG_NFS_V4 */ |
126 | 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->duped = 0; | ||
143 | ctx->dir_cookie = 0; | ||
144 | ctx->dup_cookie = 0; | ||
145 | ctx->cred = get_rpccred(cred); | ||
146 | } else | ||
147 | ctx = ERR_PTR(-ENOMEM); | ||
148 | return ctx; | ||
149 | } | ||
150 | |||
151 | static void put_nfs_open_dir_context(struct nfs_open_dir_context *ctx) | ||
152 | { | ||
153 | put_rpccred(ctx->cred); | ||
154 | kfree(ctx); | ||
155 | } | ||
156 | |||
127 | /* | 157 | /* |
128 | * Open file | 158 | * Open file |
129 | */ | 159 | */ |
130 | static int | 160 | static int |
131 | nfs_opendir(struct inode *inode, struct file *filp) | 161 | nfs_opendir(struct inode *inode, struct file *filp) |
132 | { | 162 | { |
133 | int res; | 163 | int res = 0; |
164 | struct nfs_open_dir_context *ctx; | ||
165 | struct rpc_cred *cred; | ||
134 | 166 | ||
135 | dfprintk(FILE, "NFS: open dir(%s/%s)\n", | 167 | dfprintk(FILE, "NFS: open dir(%s/%s)\n", |
136 | filp->f_path.dentry->d_parent->d_name.name, | 168 | filp->f_path.dentry->d_parent->d_name.name, |
@@ -138,8 +170,15 @@ nfs_opendir(struct inode *inode, struct file *filp) | |||
138 | 170 | ||
139 | nfs_inc_stats(inode, NFSIOS_VFSOPEN); | 171 | nfs_inc_stats(inode, NFSIOS_VFSOPEN); |
140 | 172 | ||
141 | /* Call generic open code in order to cache credentials */ | 173 | cred = rpc_lookup_cred(); |
142 | res = nfs_open(inode, filp); | 174 | if (IS_ERR(cred)) |
175 | return PTR_ERR(cred); | ||
176 | ctx = alloc_nfs_open_dir_context(cred); | ||
177 | if (IS_ERR(ctx)) { | ||
178 | res = PTR_ERR(ctx); | ||
179 | goto out; | ||
180 | } | ||
181 | filp->private_data = ctx; | ||
143 | if (filp->f_path.dentry == filp->f_path.mnt->mnt_root) { | 182 | if (filp->f_path.dentry == filp->f_path.mnt->mnt_root) { |
144 | /* This is a mountpoint, so d_revalidate will never | 183 | /* This is a mountpoint, so d_revalidate will never |
145 | * have been called, so we need to refresh the | 184 | * have been called, so we need to refresh the |
@@ -147,54 +186,232 @@ nfs_opendir(struct inode *inode, struct file *filp) | |||
147 | */ | 186 | */ |
148 | __nfs_revalidate_inode(NFS_SERVER(inode), inode); | 187 | __nfs_revalidate_inode(NFS_SERVER(inode), inode); |
149 | } | 188 | } |
189 | out: | ||
190 | put_rpccred(cred); | ||
150 | return res; | 191 | return res; |
151 | } | 192 | } |
152 | 193 | ||
153 | typedef __be32 * (*decode_dirent_t)(__be32 *, struct nfs_entry *, int); | 194 | static int |
195 | nfs_closedir(struct inode *inode, struct file *filp) | ||
196 | { | ||
197 | put_nfs_open_dir_context(filp->private_data); | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | struct nfs_cache_array_entry { | ||
202 | u64 cookie; | ||
203 | u64 ino; | ||
204 | struct qstr string; | ||
205 | unsigned char d_type; | ||
206 | }; | ||
207 | |||
208 | struct nfs_cache_array { | ||
209 | unsigned int size; | ||
210 | int eof_index; | ||
211 | u64 last_cookie; | ||
212 | struct nfs_cache_array_entry array[0]; | ||
213 | }; | ||
214 | |||
215 | typedef int (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, int); | ||
154 | typedef struct { | 216 | typedef struct { |
155 | struct file *file; | 217 | struct file *file; |
156 | struct page *page; | 218 | struct page *page; |
157 | unsigned long page_index; | 219 | unsigned long page_index; |
158 | __be32 *ptr; | ||
159 | u64 *dir_cookie; | 220 | u64 *dir_cookie; |
221 | u64 last_cookie; | ||
160 | loff_t current_index; | 222 | loff_t current_index; |
161 | struct nfs_entry *entry; | ||
162 | decode_dirent_t decode; | 223 | decode_dirent_t decode; |
163 | int plus; | 224 | |
164 | unsigned long timestamp; | 225 | unsigned long timestamp; |
165 | unsigned long gencount; | 226 | unsigned long gencount; |
166 | int timestamp_valid; | 227 | unsigned int cache_entry_index; |
228 | unsigned int plus:1; | ||
229 | unsigned int eof:1; | ||
167 | } nfs_readdir_descriptor_t; | 230 | } nfs_readdir_descriptor_t; |
168 | 231 | ||
169 | /* Now we cache directories properly, by stuffing the dirent | 232 | /* |
170 | * data directly in the page cache. | 233 | * The caller is responsible for calling nfs_readdir_release_array(page) |
171 | * | ||
172 | * Inode invalidation due to refresh etc. takes care of | ||
173 | * _everything_, no sloppy entry flushing logic, no extraneous | ||
174 | * copying, network direct to page cache, the way it was meant | ||
175 | * to be. | ||
176 | * | ||
177 | * NOTE: Dirent information verification is done always by the | ||
178 | * page-in of the RPC reply, nowhere else, this simplies | ||
179 | * things substantially. | ||
180 | */ | 234 | */ |
181 | static | 235 | static |
182 | int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) | 236 | struct nfs_cache_array *nfs_readdir_get_array(struct page *page) |
183 | { | 237 | { |
184 | struct file *file = desc->file; | 238 | void *ptr; |
185 | struct inode *inode = file->f_path.dentry->d_inode; | 239 | if (page == NULL) |
186 | struct rpc_cred *cred = nfs_file_cred(file); | 240 | return ERR_PTR(-EIO); |
241 | ptr = kmap(page); | ||
242 | if (ptr == NULL) | ||
243 | return ERR_PTR(-ENOMEM); | ||
244 | return ptr; | ||
245 | } | ||
246 | |||
247 | static | ||
248 | void nfs_readdir_release_array(struct page *page) | ||
249 | { | ||
250 | kunmap(page); | ||
251 | } | ||
252 | |||
253 | /* | ||
254 | * we are freeing strings created by nfs_add_to_readdir_array() | ||
255 | */ | ||
256 | static | ||
257 | void nfs_readdir_clear_array(struct page *page) | ||
258 | { | ||
259 | struct nfs_cache_array *array; | ||
260 | int i; | ||
261 | |||
262 | array = kmap_atomic(page, KM_USER0); | ||
263 | for (i = 0; i < array->size; i++) | ||
264 | kfree(array->array[i].string.name); | ||
265 | kunmap_atomic(array, KM_USER0); | ||
266 | } | ||
267 | |||
268 | /* | ||
269 | * the caller is responsible for freeing qstr.name | ||
270 | * when called by nfs_readdir_add_to_array, the strings will be freed in | ||
271 | * nfs_clear_readdir_array() | ||
272 | */ | ||
273 | static | ||
274 | int nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int len) | ||
275 | { | ||
276 | string->len = len; | ||
277 | string->name = kmemdup(name, len, GFP_KERNEL); | ||
278 | if (string->name == NULL) | ||
279 | return -ENOMEM; | ||
280 | /* | ||
281 | * Avoid a kmemleak false positive. The pointer to the name is stored | ||
282 | * in a page cache page which kmemleak does not scan. | ||
283 | */ | ||
284 | kmemleak_not_leak(string->name); | ||
285 | string->hash = full_name_hash(name, len); | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static | ||
290 | int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page) | ||
291 | { | ||
292 | struct nfs_cache_array *array = nfs_readdir_get_array(page); | ||
293 | struct nfs_cache_array_entry *cache_entry; | ||
294 | int ret; | ||
295 | |||
296 | if (IS_ERR(array)) | ||
297 | return PTR_ERR(array); | ||
298 | |||
299 | cache_entry = &array->array[array->size]; | ||
300 | |||
301 | /* Check that this entry lies within the page bounds */ | ||
302 | ret = -ENOSPC; | ||
303 | if ((char *)&cache_entry[1] - (char *)page_address(page) > PAGE_SIZE) | ||
304 | goto out; | ||
305 | |||
306 | cache_entry->cookie = entry->prev_cookie; | ||
307 | cache_entry->ino = entry->ino; | ||
308 | cache_entry->d_type = entry->d_type; | ||
309 | ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len); | ||
310 | if (ret) | ||
311 | goto out; | ||
312 | array->last_cookie = entry->cookie; | ||
313 | array->size++; | ||
314 | if (entry->eof != 0) | ||
315 | array->eof_index = array->size; | ||
316 | out: | ||
317 | nfs_readdir_release_array(page); | ||
318 | return ret; | ||
319 | } | ||
320 | |||
321 | static | ||
322 | int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) | ||
323 | { | ||
324 | loff_t diff = desc->file->f_pos - desc->current_index; | ||
325 | unsigned int index; | ||
326 | struct nfs_open_dir_context *ctx = desc->file->private_data; | ||
327 | |||
328 | if (diff < 0) | ||
329 | goto out_eof; | ||
330 | if (diff >= array->size) { | ||
331 | if (array->eof_index >= 0) | ||
332 | goto out_eof; | ||
333 | return -EAGAIN; | ||
334 | } | ||
335 | |||
336 | index = (unsigned int)diff; | ||
337 | *desc->dir_cookie = array->array[index].cookie; | ||
338 | desc->cache_entry_index = index; | ||
339 | ctx->duped = 0; | ||
340 | return 0; | ||
341 | out_eof: | ||
342 | desc->eof = 1; | ||
343 | return -EBADCOOKIE; | ||
344 | } | ||
345 | |||
346 | static | ||
347 | int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) | ||
348 | { | ||
349 | int i; | ||
350 | loff_t new_pos; | ||
351 | int status = -EAGAIN; | ||
352 | struct nfs_open_dir_context *ctx = desc->file->private_data; | ||
353 | |||
354 | for (i = 0; i < array->size; i++) { | ||
355 | if (array->array[i].cookie == *desc->dir_cookie) { | ||
356 | new_pos = desc->current_index + i; | ||
357 | if (new_pos < desc->file->f_pos) { | ||
358 | ctx->dup_cookie = *desc->dir_cookie; | ||
359 | ctx->duped = 1; | ||
360 | } | ||
361 | desc->file->f_pos = new_pos; | ||
362 | desc->cache_entry_index = i; | ||
363 | return 0; | ||
364 | } | ||
365 | } | ||
366 | if (array->eof_index >= 0) { | ||
367 | status = -EBADCOOKIE; | ||
368 | if (*desc->dir_cookie == array->last_cookie) | ||
369 | desc->eof = 1; | ||
370 | } | ||
371 | return status; | ||
372 | } | ||
373 | |||
374 | static | ||
375 | int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc) | ||
376 | { | ||
377 | struct nfs_cache_array *array; | ||
378 | int status; | ||
379 | |||
380 | array = nfs_readdir_get_array(desc->page); | ||
381 | if (IS_ERR(array)) { | ||
382 | status = PTR_ERR(array); | ||
383 | goto out; | ||
384 | } | ||
385 | |||
386 | if (*desc->dir_cookie == 0) | ||
387 | status = nfs_readdir_search_for_pos(array, desc); | ||
388 | else | ||
389 | status = nfs_readdir_search_for_cookie(array, desc); | ||
390 | |||
391 | if (status == -EAGAIN) { | ||
392 | desc->last_cookie = array->last_cookie; | ||
393 | desc->current_index += array->size; | ||
394 | desc->page_index++; | ||
395 | } | ||
396 | nfs_readdir_release_array(desc->page); | ||
397 | out: | ||
398 | return status; | ||
399 | } | ||
400 | |||
401 | /* Fill a page with xdr information before transferring to the cache page */ | ||
402 | static | ||
403 | int nfs_readdir_xdr_filler(struct page **pages, nfs_readdir_descriptor_t *desc, | ||
404 | struct nfs_entry *entry, struct file *file, struct inode *inode) | ||
405 | { | ||
406 | struct nfs_open_dir_context *ctx = file->private_data; | ||
407 | struct rpc_cred *cred = ctx->cred; | ||
187 | unsigned long timestamp, gencount; | 408 | unsigned long timestamp, gencount; |
188 | int error; | 409 | int error; |
189 | 410 | ||
190 | dfprintk(DIRCACHE, "NFS: %s: reading cookie %Lu into page %lu\n", | ||
191 | __func__, (long long)desc->entry->cookie, | ||
192 | page->index); | ||
193 | |||
194 | again: | 411 | again: |
195 | timestamp = jiffies; | 412 | timestamp = jiffies; |
196 | gencount = nfs_inc_attr_generation_counter(); | 413 | gencount = nfs_inc_attr_generation_counter(); |
197 | error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, desc->entry->cookie, page, | 414 | error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, entry->cookie, pages, |
198 | NFS_SERVER(inode)->dtsize, desc->plus); | 415 | NFS_SERVER(inode)->dtsize, desc->plus); |
199 | if (error < 0) { | 416 | if (error < 0) { |
200 | /* We requested READDIRPLUS, but the server doesn't grok it */ | 417 | /* We requested READDIRPLUS, but the server doesn't grok it */ |
@@ -208,199 +425,307 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) | |||
208 | } | 425 | } |
209 | desc->timestamp = timestamp; | 426 | desc->timestamp = timestamp; |
210 | desc->gencount = gencount; | 427 | desc->gencount = gencount; |
211 | desc->timestamp_valid = 1; | 428 | error: |
212 | SetPageUptodate(page); | 429 | return error; |
213 | /* Ensure consistent page alignment of the data. | ||
214 | * Note: assumes we have exclusive access to this mapping either | ||
215 | * through inode->i_mutex or some other mechanism. | ||
216 | */ | ||
217 | if (invalidate_inode_pages2_range(inode->i_mapping, page->index + 1, -1) < 0) { | ||
218 | /* Should never happen */ | ||
219 | nfs_zap_mapping(inode, inode->i_mapping); | ||
220 | } | ||
221 | unlock_page(page); | ||
222 | return 0; | ||
223 | error: | ||
224 | unlock_page(page); | ||
225 | return -EIO; | ||
226 | } | 430 | } |
227 | 431 | ||
228 | static inline | 432 | static int xdr_decode(nfs_readdir_descriptor_t *desc, |
229 | int dir_decode(nfs_readdir_descriptor_t *desc) | 433 | struct nfs_entry *entry, struct xdr_stream *xdr) |
230 | { | 434 | { |
231 | __be32 *p = desc->ptr; | 435 | int error; |
232 | p = desc->decode(p, desc->entry, desc->plus); | 436 | |
233 | if (IS_ERR(p)) | 437 | error = desc->decode(xdr, entry, desc->plus); |
234 | return PTR_ERR(p); | 438 | if (error) |
235 | desc->ptr = p; | 439 | return error; |
236 | if (desc->timestamp_valid) { | 440 | entry->fattr->time_start = desc->timestamp; |
237 | desc->entry->fattr->time_start = desc->timestamp; | 441 | entry->fattr->gencount = desc->gencount; |
238 | desc->entry->fattr->gencount = desc->gencount; | ||
239 | } else | ||
240 | desc->entry->fattr->valid &= ~NFS_ATTR_FATTR; | ||
241 | return 0; | 442 | return 0; |
242 | } | 443 | } |
243 | 444 | ||
244 | static inline | 445 | static |
245 | void dir_page_release(nfs_readdir_descriptor_t *desc) | 446 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) |
246 | { | 447 | { |
247 | kunmap(desc->page); | 448 | if (dentry->d_inode == NULL) |
248 | page_cache_release(desc->page); | 449 | goto different; |
249 | desc->page = NULL; | 450 | if (nfs_compare_fh(entry->fh, NFS_FH(dentry->d_inode)) != 0) |
250 | desc->ptr = NULL; | 451 | goto different; |
452 | return 1; | ||
453 | different: | ||
454 | return 0; | ||
251 | } | 455 | } |
252 | 456 | ||
253 | /* | 457 | static |
254 | * Given a pointer to a buffer that has already been filled by a call | 458 | void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) |
255 | * to readdir, find the next entry with cookie '*desc->dir_cookie'. | ||
256 | * | ||
257 | * If the end of the buffer has been reached, return -EAGAIN, if not, | ||
258 | * return the offset within the buffer of the next entry to be | ||
259 | * read. | ||
260 | */ | ||
261 | static inline | ||
262 | int find_dirent(nfs_readdir_descriptor_t *desc) | ||
263 | { | 459 | { |
264 | struct nfs_entry *entry = desc->entry; | 460 | struct qstr filename = { |
265 | int loop_count = 0, | 461 | .len = entry->len, |
266 | status; | 462 | .name = entry->name, |
463 | }; | ||
464 | struct dentry *dentry; | ||
465 | struct dentry *alias; | ||
466 | struct inode *dir = parent->d_inode; | ||
467 | struct inode *inode; | ||
267 | 468 | ||
268 | while((status = dir_decode(desc)) == 0) { | 469 | if (filename.name[0] == '.') { |
269 | dfprintk(DIRCACHE, "NFS: %s: examining cookie %Lu\n", | 470 | if (filename.len == 1) |
270 | __func__, (unsigned long long)entry->cookie); | 471 | return; |
271 | if (entry->prev_cookie == *desc->dir_cookie) | 472 | if (filename.len == 2 && filename.name[1] == '.') |
272 | break; | 473 | return; |
273 | if (loop_count++ > 200) { | 474 | } |
274 | loop_count = 0; | 475 | filename.hash = full_name_hash(filename.name, filename.len); |
275 | schedule(); | 476 | |
477 | dentry = d_lookup(parent, &filename); | ||
478 | if (dentry != NULL) { | ||
479 | if (nfs_same_file(dentry, entry)) { | ||
480 | nfs_refresh_inode(dentry->d_inode, entry->fattr); | ||
481 | goto out; | ||
482 | } else { | ||
483 | d_drop(dentry); | ||
484 | dput(dentry); | ||
276 | } | 485 | } |
277 | } | 486 | } |
278 | return status; | 487 | |
488 | dentry = d_alloc(parent, &filename); | ||
489 | if (dentry == NULL) | ||
490 | return; | ||
491 | |||
492 | inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr); | ||
493 | if (IS_ERR(inode)) | ||
494 | goto out; | ||
495 | |||
496 | alias = d_materialise_unique(dentry, inode); | ||
497 | if (IS_ERR(alias)) | ||
498 | goto out; | ||
499 | else if (alias) { | ||
500 | nfs_set_verifier(alias, nfs_save_change_attribute(dir)); | ||
501 | dput(alias); | ||
502 | } else | ||
503 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
504 | |||
505 | out: | ||
506 | dput(dentry); | ||
279 | } | 507 | } |
280 | 508 | ||
281 | /* | 509 | /* Perform conversion from xdr to cache array */ |
282 | * Given a pointer to a buffer that has already been filled by a call | 510 | static |
283 | * to readdir, find the entry at offset 'desc->file->f_pos'. | 511 | int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, |
284 | * | 512 | struct page **xdr_pages, struct page *page, unsigned int buflen) |
285 | * If the end of the buffer has been reached, return -EAGAIN, if not, | ||
286 | * return the offset within the buffer of the next entry to be | ||
287 | * read. | ||
288 | */ | ||
289 | static inline | ||
290 | int find_dirent_index(nfs_readdir_descriptor_t *desc) | ||
291 | { | 513 | { |
292 | struct nfs_entry *entry = desc->entry; | 514 | struct xdr_stream stream; |
293 | int loop_count = 0, | 515 | struct xdr_buf buf; |
294 | status; | 516 | struct page *scratch; |
517 | struct nfs_cache_array *array; | ||
518 | unsigned int count = 0; | ||
519 | int status; | ||
295 | 520 | ||
296 | for(;;) { | 521 | scratch = alloc_page(GFP_KERNEL); |
297 | status = dir_decode(desc); | 522 | if (scratch == NULL) |
298 | if (status) | 523 | return -ENOMEM; |
299 | break; | ||
300 | 524 | ||
301 | dfprintk(DIRCACHE, "NFS: found cookie %Lu at index %Ld\n", | 525 | xdr_init_decode_pages(&stream, &buf, xdr_pages, buflen); |
302 | (unsigned long long)entry->cookie, desc->current_index); | 526 | xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); |
303 | 527 | ||
304 | if (desc->file->f_pos == desc->current_index) { | 528 | do { |
305 | *desc->dir_cookie = entry->cookie; | 529 | status = xdr_decode(desc, entry, &stream); |
530 | if (status != 0) { | ||
531 | if (status == -EAGAIN) | ||
532 | status = 0; | ||
306 | break; | 533 | break; |
307 | } | 534 | } |
308 | desc->current_index++; | 535 | |
309 | if (loop_count++ > 200) { | 536 | count++; |
310 | loop_count = 0; | 537 | |
311 | schedule(); | 538 | if (desc->plus != 0) |
312 | } | 539 | nfs_prime_dcache(desc->file->f_path.dentry, entry); |
540 | |||
541 | status = nfs_readdir_add_to_array(entry, page); | ||
542 | if (status != 0) | ||
543 | break; | ||
544 | } while (!entry->eof); | ||
545 | |||
546 | if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) { | ||
547 | array = nfs_readdir_get_array(page); | ||
548 | if (!IS_ERR(array)) { | ||
549 | array->eof_index = array->size; | ||
550 | status = 0; | ||
551 | nfs_readdir_release_array(page); | ||
552 | } else | ||
553 | status = PTR_ERR(array); | ||
313 | } | 554 | } |
555 | |||
556 | put_page(scratch); | ||
314 | return status; | 557 | return status; |
315 | } | 558 | } |
316 | 559 | ||
560 | static | ||
561 | void nfs_readdir_free_pagearray(struct page **pages, unsigned int npages) | ||
562 | { | ||
563 | unsigned int i; | ||
564 | for (i = 0; i < npages; i++) | ||
565 | put_page(pages[i]); | ||
566 | } | ||
567 | |||
568 | static | ||
569 | void nfs_readdir_free_large_page(void *ptr, struct page **pages, | ||
570 | unsigned int npages) | ||
571 | { | ||
572 | nfs_readdir_free_pagearray(pages, npages); | ||
573 | } | ||
574 | |||
317 | /* | 575 | /* |
318 | * Find the given page, and call find_dirent() or find_dirent_index in | 576 | * nfs_readdir_large_page will allocate pages that must be freed with a call |
319 | * order to try to return the next entry. | 577 | * to nfs_readdir_free_large_page |
320 | */ | 578 | */ |
321 | static inline | 579 | static |
322 | int find_dirent_page(nfs_readdir_descriptor_t *desc) | 580 | int nfs_readdir_large_page(struct page **pages, unsigned int npages) |
323 | { | 581 | { |
324 | struct inode *inode = desc->file->f_path.dentry->d_inode; | 582 | unsigned int i; |
325 | struct page *page; | ||
326 | int status; | ||
327 | 583 | ||
328 | dfprintk(DIRCACHE, "NFS: %s: searching page %ld for target %Lu\n", | 584 | for (i = 0; i < npages; i++) { |
329 | __func__, desc->page_index, | 585 | struct page *page = alloc_page(GFP_KERNEL); |
330 | (long long) *desc->dir_cookie); | 586 | if (page == NULL) |
587 | goto out_freepages; | ||
588 | pages[i] = page; | ||
589 | } | ||
590 | return 0; | ||
331 | 591 | ||
332 | /* If we find the page in the page_cache, we cannot be sure | 592 | out_freepages: |
333 | * how fresh the data is, so we will ignore readdir_plus attributes. | 593 | nfs_readdir_free_pagearray(pages, i); |
334 | */ | 594 | return -ENOMEM; |
335 | desc->timestamp_valid = 0; | 595 | } |
336 | page = read_cache_page(inode->i_mapping, desc->page_index, | 596 | |
337 | (filler_t *)nfs_readdir_filler, desc); | 597 | static |
338 | if (IS_ERR(page)) { | 598 | int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, struct inode *inode) |
339 | status = PTR_ERR(page); | 599 | { |
600 | struct page *pages[NFS_MAX_READDIR_PAGES]; | ||
601 | void *pages_ptr = NULL; | ||
602 | struct nfs_entry entry; | ||
603 | struct file *file = desc->file; | ||
604 | struct nfs_cache_array *array; | ||
605 | int status = -ENOMEM; | ||
606 | unsigned int array_size = ARRAY_SIZE(pages); | ||
607 | |||
608 | entry.prev_cookie = 0; | ||
609 | entry.cookie = desc->last_cookie; | ||
610 | entry.eof = 0; | ||
611 | entry.fh = nfs_alloc_fhandle(); | ||
612 | entry.fattr = nfs_alloc_fattr(); | ||
613 | entry.server = NFS_SERVER(inode); | ||
614 | if (entry.fh == NULL || entry.fattr == NULL) | ||
615 | goto out; | ||
616 | |||
617 | array = nfs_readdir_get_array(page); | ||
618 | if (IS_ERR(array)) { | ||
619 | status = PTR_ERR(array); | ||
340 | goto out; | 620 | goto out; |
341 | } | 621 | } |
622 | memset(array, 0, sizeof(struct nfs_cache_array)); | ||
623 | array->eof_index = -1; | ||
342 | 624 | ||
343 | /* NOTE: Someone else may have changed the READDIRPLUS flag */ | 625 | status = nfs_readdir_large_page(pages, array_size); |
344 | desc->page = page; | ||
345 | desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ | ||
346 | if (*desc->dir_cookie != 0) | ||
347 | status = find_dirent(desc); | ||
348 | else | ||
349 | status = find_dirent_index(desc); | ||
350 | if (status < 0) | 626 | if (status < 0) |
351 | dir_page_release(desc); | 627 | goto out_release_array; |
352 | out: | 628 | do { |
353 | dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __func__, status); | 629 | unsigned int pglen; |
630 | status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode); | ||
631 | |||
632 | if (status < 0) | ||
633 | break; | ||
634 | pglen = status; | ||
635 | status = nfs_readdir_page_filler(desc, &entry, pages, page, pglen); | ||
636 | if (status < 0) { | ||
637 | if (status == -ENOSPC) | ||
638 | status = 0; | ||
639 | break; | ||
640 | } | ||
641 | } while (array->eof_index < 0); | ||
642 | |||
643 | nfs_readdir_free_large_page(pages_ptr, pages, array_size); | ||
644 | out_release_array: | ||
645 | nfs_readdir_release_array(page); | ||
646 | out: | ||
647 | nfs_free_fattr(entry.fattr); | ||
648 | nfs_free_fhandle(entry.fh); | ||
354 | return status; | 649 | return status; |
355 | } | 650 | } |
356 | 651 | ||
357 | /* | 652 | /* |
358 | * Recurse through the page cache pages, and return a | 653 | * Now we cache directories properly, by converting xdr information |
359 | * filled nfs_entry structure of the next directory entry if possible. | 654 | * to an array that can be used for lookups later. This results in |
360 | * | 655 | * fewer cache pages, since we can store more information on each page. |
361 | * The target for the search is '*desc->dir_cookie' if non-0, | 656 | * We only need to convert from xdr once so future lookups are much simpler |
362 | * 'desc->file->f_pos' otherwise | ||
363 | */ | 657 | */ |
364 | static inline | 658 | static |
365 | int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) | 659 | int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page) |
366 | { | 660 | { |
367 | int loop_count = 0; | 661 | struct inode *inode = desc->file->f_path.dentry->d_inode; |
368 | int res; | 662 | int ret; |
369 | 663 | ||
370 | /* Always search-by-index from the beginning of the cache */ | 664 | ret = nfs_readdir_xdr_to_array(desc, page, inode); |
371 | if (*desc->dir_cookie == 0) { | 665 | if (ret < 0) |
372 | dfprintk(DIRCACHE, "NFS: readdir_search_pagecache() searching for offset %Ld\n", | 666 | goto error; |
373 | (long long)desc->file->f_pos); | 667 | SetPageUptodate(page); |
374 | desc->page_index = 0; | ||
375 | desc->entry->cookie = desc->entry->prev_cookie = 0; | ||
376 | desc->entry->eof = 0; | ||
377 | desc->current_index = 0; | ||
378 | } else | ||
379 | dfprintk(DIRCACHE, "NFS: readdir_search_pagecache() searching for cookie %Lu\n", | ||
380 | (unsigned long long)*desc->dir_cookie); | ||
381 | 668 | ||
382 | for (;;) { | 669 | if (invalidate_inode_pages2_range(inode->i_mapping, page->index + 1, -1) < 0) { |
383 | res = find_dirent_page(desc); | 670 | /* Should never happen */ |
384 | if (res != -EAGAIN) | 671 | nfs_zap_mapping(inode, inode->i_mapping); |
385 | break; | ||
386 | /* Align to beginning of next page */ | ||
387 | desc->page_index ++; | ||
388 | if (loop_count++ > 200) { | ||
389 | loop_count = 0; | ||
390 | schedule(); | ||
391 | } | ||
392 | } | 672 | } |
673 | unlock_page(page); | ||
674 | return 0; | ||
675 | error: | ||
676 | unlock_page(page); | ||
677 | return ret; | ||
678 | } | ||
393 | 679 | ||
394 | dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __func__, res); | 680 | static |
395 | return res; | 681 | void cache_page_release(nfs_readdir_descriptor_t *desc) |
682 | { | ||
683 | if (!desc->page->mapping) | ||
684 | nfs_readdir_clear_array(desc->page); | ||
685 | page_cache_release(desc->page); | ||
686 | desc->page = NULL; | ||
396 | } | 687 | } |
397 | 688 | ||
398 | static inline unsigned int dt_type(struct inode *inode) | 689 | static |
690 | struct page *get_cache_page(nfs_readdir_descriptor_t *desc) | ||
399 | { | 691 | { |
400 | return (inode->i_mode >> 12) & 15; | 692 | return read_cache_page(desc->file->f_path.dentry->d_inode->i_mapping, |
693 | desc->page_index, (filler_t *)nfs_readdir_filler, desc); | ||
401 | } | 694 | } |
402 | 695 | ||
403 | static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc); | 696 | /* |
697 | * Returns 0 if desc->dir_cookie was found on page desc->page_index | ||
698 | */ | ||
699 | static | ||
700 | int find_cache_page(nfs_readdir_descriptor_t *desc) | ||
701 | { | ||
702 | int res; | ||
703 | |||
704 | desc->page = get_cache_page(desc); | ||
705 | if (IS_ERR(desc->page)) | ||
706 | return PTR_ERR(desc->page); | ||
707 | |||
708 | res = nfs_readdir_search_array(desc); | ||
709 | if (res != 0) | ||
710 | cache_page_release(desc); | ||
711 | return res; | ||
712 | } | ||
713 | |||
714 | /* Search for desc->dir_cookie from the beginning of the page cache */ | ||
715 | static inline | ||
716 | int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) | ||
717 | { | ||
718 | int res; | ||
719 | |||
720 | if (desc->page_index == 0) { | ||
721 | desc->current_index = 0; | ||
722 | desc->last_cookie = 0; | ||
723 | } | ||
724 | do { | ||
725 | res = find_cache_page(desc); | ||
726 | } while (res == -EAGAIN); | ||
727 | return res; | ||
728 | } | ||
404 | 729 | ||
405 | /* | 730 | /* |
406 | * Once we've found the start of the dirent within a page: fill 'er up... | 731 | * Once we've found the start of the dirent within a page: fill 'er up... |
@@ -410,51 +735,52 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
410 | filldir_t filldir) | 735 | filldir_t filldir) |
411 | { | 736 | { |
412 | struct file *file = desc->file; | 737 | struct file *file = desc->file; |
413 | struct nfs_entry *entry = desc->entry; | 738 | int i = 0; |
414 | struct dentry *dentry = NULL; | 739 | int res = 0; |
415 | u64 fileid; | 740 | struct nfs_cache_array *array = NULL; |
416 | int loop_count = 0, | 741 | struct nfs_open_dir_context *ctx = file->private_data; |
417 | res; | 742 | |
418 | 743 | if (ctx->duped != 0 && ctx->dup_cookie == *desc->dir_cookie) { | |
419 | dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", | 744 | if (printk_ratelimit()) { |
420 | (unsigned long long)entry->cookie); | 745 | pr_notice("NFS: directory %s/%s contains a readdir loop. " |
421 | 746 | "Please contact your server vendor. " | |
422 | for(;;) { | 747 | "Offending cookie: %llu\n", |
423 | unsigned d_type = DT_UNKNOWN; | 748 | file->f_dentry->d_parent->d_name.name, |
424 | /* Note: entry->prev_cookie contains the cookie for | 749 | file->f_dentry->d_name.name, |
425 | * retrieving the current dirent on the server */ | 750 | *desc->dir_cookie); |
426 | fileid = entry->ino; | ||
427 | |||
428 | /* Get a dentry if we have one */ | ||
429 | if (dentry != NULL) | ||
430 | dput(dentry); | ||
431 | dentry = nfs_readdir_lookup(desc); | ||
432 | |||
433 | /* Use readdirplus info */ | ||
434 | if (dentry != NULL && dentry->d_inode != NULL) { | ||
435 | d_type = dt_type(dentry->d_inode); | ||
436 | fileid = NFS_FILEID(dentry->d_inode); | ||
437 | } | 751 | } |
752 | res = -ELOOP; | ||
753 | goto out; | ||
754 | } | ||
438 | 755 | ||
439 | res = filldir(dirent, entry->name, entry->len, | 756 | array = nfs_readdir_get_array(desc->page); |
440 | file->f_pos, nfs_compat_user_ino64(fileid), | 757 | if (IS_ERR(array)) { |
441 | d_type); | 758 | res = PTR_ERR(array); |
442 | if (res < 0) | 759 | goto out; |
443 | break; | 760 | } |
444 | file->f_pos++; | 761 | |
445 | *desc->dir_cookie = entry->cookie; | 762 | for (i = desc->cache_entry_index; i < array->size; i++) { |
446 | if (dir_decode(desc) != 0) { | 763 | struct nfs_cache_array_entry *ent; |
447 | desc->page_index ++; | 764 | |
765 | ent = &array->array[i]; | ||
766 | if (filldir(dirent, ent->string.name, ent->string.len, | ||
767 | file->f_pos, nfs_compat_user_ino64(ent->ino), | ||
768 | ent->d_type) < 0) { | ||
769 | desc->eof = 1; | ||
448 | break; | 770 | break; |
449 | } | 771 | } |
450 | if (loop_count++ > 200) { | 772 | file->f_pos++; |
451 | loop_count = 0; | 773 | if (i < (array->size-1)) |
452 | schedule(); | 774 | *desc->dir_cookie = array->array[i+1].cookie; |
453 | } | 775 | else |
776 | *desc->dir_cookie = array->last_cookie; | ||
454 | } | 777 | } |
455 | dir_page_release(desc); | 778 | if (array->eof_index >= 0) |
456 | if (dentry != NULL) | 779 | desc->eof = 1; |
457 | dput(dentry); | 780 | |
781 | nfs_readdir_release_array(desc->page); | ||
782 | out: | ||
783 | cache_page_release(desc); | ||
458 | dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", | 784 | dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", |
459 | (unsigned long long)*desc->dir_cookie, res); | 785 | (unsigned long long)*desc->dir_cookie, res); |
460 | return res; | 786 | return res; |
@@ -476,12 +802,9 @@ static inline | |||
476 | int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | 802 | int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, |
477 | filldir_t filldir) | 803 | filldir_t filldir) |
478 | { | 804 | { |
479 | struct file *file = desc->file; | ||
480 | struct inode *inode = file->f_path.dentry->d_inode; | ||
481 | struct rpc_cred *cred = nfs_file_cred(file); | ||
482 | struct page *page = NULL; | 805 | struct page *page = NULL; |
483 | int status; | 806 | int status; |
484 | unsigned long timestamp, gencount; | 807 | struct inode *inode = desc->file->f_path.dentry->d_inode; |
485 | 808 | ||
486 | dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n", | 809 | dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n", |
487 | (unsigned long long)*desc->dir_cookie); | 810 | (unsigned long long)*desc->dir_cookie); |
@@ -491,38 +814,23 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
491 | status = -ENOMEM; | 814 | status = -ENOMEM; |
492 | goto out; | 815 | goto out; |
493 | } | 816 | } |
494 | timestamp = jiffies; | 817 | |
495 | gencount = nfs_inc_attr_generation_counter(); | 818 | desc->page_index = 0; |
496 | status = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, | 819 | desc->last_cookie = *desc->dir_cookie; |
497 | *desc->dir_cookie, page, | ||
498 | NFS_SERVER(inode)->dtsize, | ||
499 | desc->plus); | ||
500 | desc->page = page; | 820 | desc->page = page; |
501 | desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ | 821 | |
502 | if (status >= 0) { | 822 | status = nfs_readdir_xdr_to_array(desc, page, inode); |
503 | desc->timestamp = timestamp; | ||
504 | desc->gencount = gencount; | ||
505 | desc->timestamp_valid = 1; | ||
506 | if ((status = dir_decode(desc)) == 0) | ||
507 | desc->entry->prev_cookie = *desc->dir_cookie; | ||
508 | } else | ||
509 | status = -EIO; | ||
510 | if (status < 0) | 823 | if (status < 0) |
511 | goto out_release; | 824 | goto out_release; |
512 | 825 | ||
513 | status = nfs_do_filldir(desc, dirent, filldir); | 826 | status = nfs_do_filldir(desc, dirent, filldir); |
514 | 827 | ||
515 | /* Reset read descriptor so it searches the page cache from | ||
516 | * the start upon the next call to readdir_search_pagecache() */ | ||
517 | desc->page_index = 0; | ||
518 | desc->entry->cookie = desc->entry->prev_cookie = 0; | ||
519 | desc->entry->eof = 0; | ||
520 | out: | 828 | out: |
521 | dfprintk(DIRCACHE, "NFS: %s: returns %d\n", | 829 | dfprintk(DIRCACHE, "NFS: %s: returns %d\n", |
522 | __func__, status); | 830 | __func__, status); |
523 | return status; | 831 | return status; |
524 | out_release: | 832 | out_release: |
525 | dir_page_release(desc); | 833 | cache_page_release(desc); |
526 | goto out; | 834 | goto out; |
527 | } | 835 | } |
528 | 836 | ||
@@ -536,8 +844,8 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
536 | struct inode *inode = dentry->d_inode; | 844 | struct inode *inode = dentry->d_inode; |
537 | nfs_readdir_descriptor_t my_desc, | 845 | nfs_readdir_descriptor_t my_desc, |
538 | *desc = &my_desc; | 846 | *desc = &my_desc; |
539 | struct nfs_entry my_entry; | 847 | struct nfs_open_dir_context *dir_ctx = filp->private_data; |
540 | int res = -ENOMEM; | 848 | int res; |
541 | 849 | ||
542 | dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", | 850 | dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", |
543 | dentry->d_parent->d_name.name, dentry->d_name.name, | 851 | dentry->d_parent->d_name.name, dentry->d_name.name, |
@@ -553,61 +861,48 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
553 | memset(desc, 0, sizeof(*desc)); | 861 | memset(desc, 0, sizeof(*desc)); |
554 | 862 | ||
555 | desc->file = filp; | 863 | desc->file = filp; |
556 | desc->dir_cookie = &nfs_file_open_context(filp)->dir_cookie; | 864 | desc->dir_cookie = &dir_ctx->dir_cookie; |
557 | desc->decode = NFS_PROTO(inode)->decode_dirent; | 865 | desc->decode = NFS_PROTO(inode)->decode_dirent; |
558 | desc->plus = NFS_USE_READDIRPLUS(inode); | 866 | desc->plus = NFS_USE_READDIRPLUS(inode); |
559 | 867 | ||
560 | my_entry.cookie = my_entry.prev_cookie = 0; | ||
561 | my_entry.eof = 0; | ||
562 | my_entry.fh = nfs_alloc_fhandle(); | ||
563 | my_entry.fattr = nfs_alloc_fattr(); | ||
564 | if (my_entry.fh == NULL || my_entry.fattr == NULL) | ||
565 | goto out_alloc_failed; | ||
566 | |||
567 | desc->entry = &my_entry; | ||
568 | |||
569 | nfs_block_sillyrename(dentry); | 868 | nfs_block_sillyrename(dentry); |
570 | res = nfs_revalidate_mapping(inode, filp->f_mapping); | 869 | res = nfs_revalidate_mapping(inode, filp->f_mapping); |
571 | if (res < 0) | 870 | if (res < 0) |
572 | goto out; | 871 | goto out; |
573 | 872 | ||
574 | while(!desc->entry->eof) { | 873 | do { |
575 | res = readdir_search_pagecache(desc); | 874 | res = readdir_search_pagecache(desc); |
576 | 875 | ||
577 | if (res == -EBADCOOKIE) { | 876 | if (res == -EBADCOOKIE) { |
877 | res = 0; | ||
578 | /* This means either end of directory */ | 878 | /* This means either end of directory */ |
579 | if (*desc->dir_cookie && desc->entry->cookie != *desc->dir_cookie) { | 879 | if (*desc->dir_cookie && desc->eof == 0) { |
580 | /* Or that the server has 'lost' a cookie */ | 880 | /* Or that the server has 'lost' a cookie */ |
581 | res = uncached_readdir(desc, dirent, filldir); | 881 | res = uncached_readdir(desc, dirent, filldir); |
582 | if (res >= 0) | 882 | if (res == 0) |
583 | continue; | 883 | continue; |
584 | } | 884 | } |
585 | res = 0; | ||
586 | break; | 885 | break; |
587 | } | 886 | } |
588 | if (res == -ETOOSMALL && desc->plus) { | 887 | if (res == -ETOOSMALL && desc->plus) { |
589 | clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); | 888 | clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); |
590 | nfs_zap_caches(inode); | 889 | nfs_zap_caches(inode); |
890 | desc->page_index = 0; | ||
591 | desc->plus = 0; | 891 | desc->plus = 0; |
592 | desc->entry->eof = 0; | 892 | desc->eof = 0; |
593 | continue; | 893 | continue; |
594 | } | 894 | } |
595 | if (res < 0) | 895 | if (res < 0) |
596 | break; | 896 | break; |
597 | 897 | ||
598 | res = nfs_do_filldir(desc, dirent, filldir); | 898 | res = nfs_do_filldir(desc, dirent, filldir); |
599 | if (res < 0) { | 899 | if (res < 0) |
600 | res = 0; | ||
601 | break; | 900 | break; |
602 | } | 901 | } while (!desc->eof); |
603 | } | ||
604 | out: | 902 | out: |
605 | nfs_unblock_sillyrename(dentry); | 903 | nfs_unblock_sillyrename(dentry); |
606 | if (res > 0) | 904 | if (res > 0) |
607 | res = 0; | 905 | res = 0; |
608 | out_alloc_failed: | ||
609 | nfs_free_fattr(my_entry.fattr); | ||
610 | nfs_free_fhandle(my_entry.fh); | ||
611 | dfprintk(FILE, "NFS: readdir(%s/%s) returns %d\n", | 906 | dfprintk(FILE, "NFS: readdir(%s/%s) returns %d\n", |
612 | dentry->d_parent->d_name.name, dentry->d_name.name, | 907 | dentry->d_parent->d_name.name, dentry->d_name.name, |
613 | res); | 908 | res); |
@@ -618,6 +913,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) | |||
618 | { | 913 | { |
619 | struct dentry *dentry = filp->f_path.dentry; | 914 | struct dentry *dentry = filp->f_path.dentry; |
620 | struct inode *inode = dentry->d_inode; | 915 | struct inode *inode = dentry->d_inode; |
916 | struct nfs_open_dir_context *dir_ctx = filp->private_data; | ||
621 | 917 | ||
622 | dfprintk(FILE, "NFS: llseek dir(%s/%s, %lld, %d)\n", | 918 | dfprintk(FILE, "NFS: llseek dir(%s/%s, %lld, %d)\n", |
623 | dentry->d_parent->d_name.name, | 919 | dentry->d_parent->d_name.name, |
@@ -637,7 +933,8 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) | |||
637 | } | 933 | } |
638 | if (offset != filp->f_pos) { | 934 | if (offset != filp->f_pos) { |
639 | filp->f_pos = offset; | 935 | filp->f_pos = offset; |
640 | nfs_file_open_context(filp)->dir_cookie = 0; | 936 | dir_ctx->dir_cookie = 0; |
937 | dir_ctx->duped = 0; | ||
641 | } | 938 | } |
642 | out: | 939 | out: |
643 | mutex_unlock(&inode->i_mutex); | 940 | mutex_unlock(&inode->i_mutex); |
@@ -703,7 +1000,8 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry) | |||
703 | * component of the path. | 1000 | * component of the path. |
704 | * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT. | 1001 | * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT. |
705 | */ | 1002 | */ |
706 | static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigned int mask) | 1003 | static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, |
1004 | unsigned int mask) | ||
707 | { | 1005 | { |
708 | if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT)) | 1006 | if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT)) |
709 | return 0; | 1007 | return 0; |
@@ -734,7 +1032,7 @@ int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) | |||
734 | { | 1032 | { |
735 | struct nfs_server *server = NFS_SERVER(inode); | 1033 | struct nfs_server *server = NFS_SERVER(inode); |
736 | 1034 | ||
737 | if (test_bit(NFS_INO_MOUNTPOINT, &NFS_I(inode)->flags)) | 1035 | if (IS_AUTOMOUNT(inode)) |
738 | return 0; | 1036 | return 0; |
739 | if (nd != NULL) { | 1037 | if (nd != NULL) { |
740 | /* VFS wants an on-the-wire revalidation */ | 1038 | /* VFS wants an on-the-wire revalidation */ |
@@ -783,7 +1081,7 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, | |||
783 | * If the parent directory is seen to have changed, we throw out the | 1081 | * If the parent directory is seen to have changed, we throw out the |
784 | * cached dentry and do a new lookup. | 1082 | * cached dentry and do a new lookup. |
785 | */ | 1083 | */ |
786 | static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | 1084 | static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) |
787 | { | 1085 | { |
788 | struct inode *dir; | 1086 | struct inode *dir; |
789 | struct inode *inode; | 1087 | struct inode *inode; |
@@ -792,6 +1090,9 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
792 | struct nfs_fattr *fattr = NULL; | 1090 | struct nfs_fattr *fattr = NULL; |
793 | int error; | 1091 | int error; |
794 | 1092 | ||
1093 | if (nd->flags & LOOKUP_RCU) | ||
1094 | return -ECHILD; | ||
1095 | |||
795 | parent = dget_parent(dentry); | 1096 | parent = dget_parent(dentry); |
796 | dir = parent->d_inode; | 1097 | dir = parent->d_inode; |
797 | nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE); | 1098 | nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE); |
@@ -829,7 +1130,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
829 | if (fhandle == NULL || fattr == NULL) | 1130 | if (fhandle == NULL || fattr == NULL) |
830 | goto out_error; | 1131 | goto out_error; |
831 | 1132 | ||
832 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1133 | error = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, &dentry->d_name, fhandle, fattr); |
833 | if (error) | 1134 | if (error) |
834 | goto out_bad; | 1135 | goto out_bad; |
835 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) | 1136 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) |
@@ -882,7 +1183,7 @@ out_error: | |||
882 | /* | 1183 | /* |
883 | * This is called from dput() when d_count is going to 0. | 1184 | * This is called from dput() when d_count is going to 0. |
884 | */ | 1185 | */ |
885 | static int nfs_dentry_delete(struct dentry *dentry) | 1186 | static int nfs_dentry_delete(const struct dentry *dentry) |
886 | { | 1187 | { |
887 | dfprintk(VFS, "NFS: dentry_delete(%s/%s, %x)\n", | 1188 | dfprintk(VFS, "NFS: dentry_delete(%s/%s, %x)\n", |
888 | dentry->d_parent->d_name.name, dentry->d_name.name, | 1189 | dentry->d_parent->d_name.name, dentry->d_name.name, |
@@ -930,10 +1231,23 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) | |||
930 | iput(inode); | 1231 | iput(inode); |
931 | } | 1232 | } |
932 | 1233 | ||
1234 | static void nfs_d_release(struct dentry *dentry) | ||
1235 | { | ||
1236 | /* free cached devname value, if it survived that far */ | ||
1237 | if (unlikely(dentry->d_fsdata)) { | ||
1238 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) | ||
1239 | WARN_ON(1); | ||
1240 | else | ||
1241 | kfree(dentry->d_fsdata); | ||
1242 | } | ||
1243 | } | ||
1244 | |||
933 | const struct dentry_operations nfs_dentry_operations = { | 1245 | const struct dentry_operations nfs_dentry_operations = { |
934 | .d_revalidate = nfs_lookup_revalidate, | 1246 | .d_revalidate = nfs_lookup_revalidate, |
935 | .d_delete = nfs_dentry_delete, | 1247 | .d_delete = nfs_dentry_delete, |
936 | .d_iput = nfs_dentry_iput, | 1248 | .d_iput = nfs_dentry_iput, |
1249 | .d_automount = nfs_d_automount, | ||
1250 | .d_release = nfs_d_release, | ||
937 | }; | 1251 | }; |
938 | 1252 | ||
939 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) | 1253 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) |
@@ -953,8 +1267,6 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
953 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) | 1267 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) |
954 | goto out; | 1268 | goto out; |
955 | 1269 | ||
956 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | ||
957 | |||
958 | /* | 1270 | /* |
959 | * If we're doing an exclusive create, optimize away the lookup | 1271 | * If we're doing an exclusive create, optimize away the lookup |
960 | * but don't hash the dentry. | 1272 | * but don't hash the dentry. |
@@ -974,7 +1286,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
974 | parent = dentry->d_parent; | 1286 | parent = dentry->d_parent; |
975 | /* Protect against concurrent sillydeletes */ | 1287 | /* Protect against concurrent sillydeletes */ |
976 | nfs_block_sillyrename(parent); | 1288 | nfs_block_sillyrename(parent); |
977 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1289 | error = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, &dentry->d_name, fhandle, fattr); |
978 | if (error == -ENOENT) | 1290 | if (error == -ENOENT) |
979 | goto no_entry; | 1291 | goto no_entry; |
980 | if (error < 0) { | 1292 | if (error < 0) { |
@@ -982,7 +1294,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
982 | goto out_unblock_sillyrename; | 1294 | goto out_unblock_sillyrename; |
983 | } | 1295 | } |
984 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); | 1296 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); |
985 | res = (struct dentry *)inode; | 1297 | res = ERR_CAST(inode); |
986 | if (IS_ERR(res)) | 1298 | if (IS_ERR(res)) |
987 | goto out_unblock_sillyrename; | 1299 | goto out_unblock_sillyrename; |
988 | 1300 | ||
@@ -1009,6 +1321,8 @@ const struct dentry_operations nfs4_dentry_operations = { | |||
1009 | .d_revalidate = nfs_open_revalidate, | 1321 | .d_revalidate = nfs_open_revalidate, |
1010 | .d_delete = nfs_dentry_delete, | 1322 | .d_delete = nfs_dentry_delete, |
1011 | .d_iput = nfs_dentry_iput, | 1323 | .d_iput = nfs_dentry_iput, |
1324 | .d_automount = nfs_d_automount, | ||
1325 | .d_release = nfs_d_release, | ||
1012 | }; | 1326 | }; |
1013 | 1327 | ||
1014 | /* | 1328 | /* |
@@ -1029,10 +1343,63 @@ static int is_atomic_open(struct nameidata *nd) | |||
1029 | return 1; | 1343 | return 1; |
1030 | } | 1344 | } |
1031 | 1345 | ||
1346 | static struct nfs_open_context *nameidata_to_nfs_open_context(struct dentry *dentry, struct nameidata *nd) | ||
1347 | { | ||
1348 | struct path path = { | ||
1349 | .mnt = nd->path.mnt, | ||
1350 | .dentry = dentry, | ||
1351 | }; | ||
1352 | struct nfs_open_context *ctx; | ||
1353 | struct rpc_cred *cred; | ||
1354 | fmode_t fmode = nd->intent.open.flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC); | ||
1355 | |||
1356 | cred = rpc_lookup_cred(); | ||
1357 | if (IS_ERR(cred)) | ||
1358 | return ERR_CAST(cred); | ||
1359 | ctx = alloc_nfs_open_context(&path, cred, fmode); | ||
1360 | put_rpccred(cred); | ||
1361 | if (ctx == NULL) | ||
1362 | return ERR_PTR(-ENOMEM); | ||
1363 | return ctx; | ||
1364 | } | ||
1365 | |||
1366 | static int do_open(struct inode *inode, struct file *filp) | ||
1367 | { | ||
1368 | nfs_fscache_set_inode_cookie(inode, filp); | ||
1369 | return 0; | ||
1370 | } | ||
1371 | |||
1372 | static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ctx) | ||
1373 | { | ||
1374 | struct file *filp; | ||
1375 | int ret = 0; | ||
1376 | |||
1377 | /* If the open_intent is for execute, we have an extra check to make */ | ||
1378 | if (ctx->mode & FMODE_EXEC) { | ||
1379 | ret = nfs_may_open(ctx->path.dentry->d_inode, | ||
1380 | ctx->cred, | ||
1381 | nd->intent.open.flags); | ||
1382 | if (ret < 0) | ||
1383 | goto out; | ||
1384 | } | ||
1385 | filp = lookup_instantiate_filp(nd, ctx->path.dentry, do_open); | ||
1386 | if (IS_ERR(filp)) | ||
1387 | ret = PTR_ERR(filp); | ||
1388 | else | ||
1389 | nfs_file_set_open_context(filp, ctx); | ||
1390 | out: | ||
1391 | put_nfs_open_context(ctx); | ||
1392 | return ret; | ||
1393 | } | ||
1394 | |||
1032 | static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 1395 | static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
1033 | { | 1396 | { |
1397 | struct nfs_open_context *ctx; | ||
1398 | struct iattr attr; | ||
1034 | struct dentry *res = NULL; | 1399 | struct dentry *res = NULL; |
1035 | int error; | 1400 | struct inode *inode; |
1401 | int open_flags; | ||
1402 | int err; | ||
1036 | 1403 | ||
1037 | dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n", | 1404 | dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n", |
1038 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); | 1405 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); |
@@ -1045,7 +1412,6 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
1045 | res = ERR_PTR(-ENAMETOOLONG); | 1412 | res = ERR_PTR(-ENAMETOOLONG); |
1046 | goto out; | 1413 | goto out; |
1047 | } | 1414 | } |
1048 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | ||
1049 | 1415 | ||
1050 | /* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash | 1416 | /* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash |
1051 | * the dentry. */ | 1417 | * the dentry. */ |
@@ -1054,29 +1420,61 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
1054 | goto out; | 1420 | goto out; |
1055 | } | 1421 | } |
1056 | 1422 | ||
1423 | ctx = nameidata_to_nfs_open_context(dentry, nd); | ||
1424 | res = ERR_CAST(ctx); | ||
1425 | if (IS_ERR(ctx)) | ||
1426 | goto out; | ||
1427 | |||
1428 | open_flags = nd->intent.open.flags; | ||
1429 | if (nd->flags & LOOKUP_CREATE) { | ||
1430 | attr.ia_mode = nd->intent.open.create_mode; | ||
1431 | attr.ia_valid = ATTR_MODE; | ||
1432 | attr.ia_mode &= ~current_umask(); | ||
1433 | } else { | ||
1434 | open_flags &= ~(O_EXCL | O_CREAT); | ||
1435 | attr.ia_valid = 0; | ||
1436 | } | ||
1437 | |||
1057 | /* Open the file on the server */ | 1438 | /* Open the file on the server */ |
1058 | res = nfs4_atomic_open(dir, dentry, nd); | 1439 | nfs_block_sillyrename(dentry->d_parent); |
1059 | if (IS_ERR(res)) { | 1440 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); |
1060 | error = PTR_ERR(res); | 1441 | if (IS_ERR(inode)) { |
1061 | switch (error) { | 1442 | nfs_unblock_sillyrename(dentry->d_parent); |
1443 | put_nfs_open_context(ctx); | ||
1444 | switch (PTR_ERR(inode)) { | ||
1062 | /* Make a negative dentry */ | 1445 | /* Make a negative dentry */ |
1063 | case -ENOENT: | 1446 | case -ENOENT: |
1447 | d_add(dentry, NULL); | ||
1064 | res = NULL; | 1448 | res = NULL; |
1065 | goto out; | 1449 | goto out; |
1066 | /* This turned out not to be a regular file */ | 1450 | /* This turned out not to be a regular file */ |
1067 | case -EISDIR: | ||
1068 | case -ENOTDIR: | 1451 | case -ENOTDIR: |
1069 | goto no_open; | 1452 | goto no_open; |
1070 | case -ELOOP: | 1453 | case -ELOOP: |
1071 | if (!(nd->intent.open.flags & O_NOFOLLOW)) | 1454 | if (!(nd->intent.open.flags & O_NOFOLLOW)) |
1072 | goto no_open; | 1455 | goto no_open; |
1456 | /* case -EISDIR: */ | ||
1073 | /* case -EINVAL: */ | 1457 | /* case -EINVAL: */ |
1074 | default: | 1458 | default: |
1459 | res = ERR_CAST(inode); | ||
1075 | goto out; | 1460 | goto out; |
1076 | } | 1461 | } |
1077 | } else if (res != NULL) | 1462 | } |
1463 | res = d_add_unique(dentry, inode); | ||
1464 | nfs_unblock_sillyrename(dentry->d_parent); | ||
1465 | if (res != NULL) { | ||
1466 | dput(ctx->path.dentry); | ||
1467 | ctx->path.dentry = dget(res); | ||
1078 | dentry = res; | 1468 | dentry = res; |
1469 | } | ||
1470 | err = nfs_intent_set_file(nd, ctx); | ||
1471 | if (err < 0) { | ||
1472 | if (res != NULL) | ||
1473 | dput(res); | ||
1474 | return ERR_PTR(err); | ||
1475 | } | ||
1079 | out: | 1476 | out: |
1477 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1080 | return res; | 1478 | return res; |
1081 | no_open: | 1479 | no_open: |
1082 | return nfs_lookup(dir, dentry, nd); | 1480 | return nfs_lookup(dir, dentry, nd); |
@@ -1085,14 +1483,21 @@ no_open: | |||
1085 | static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | 1483 | static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) |
1086 | { | 1484 | { |
1087 | struct dentry *parent = NULL; | 1485 | struct dentry *parent = NULL; |
1088 | struct inode *inode = dentry->d_inode; | 1486 | struct inode *inode; |
1089 | struct inode *dir; | 1487 | struct inode *dir; |
1488 | struct nfs_open_context *ctx; | ||
1090 | int openflags, ret = 0; | 1489 | int openflags, ret = 0; |
1091 | 1490 | ||
1491 | if (nd->flags & LOOKUP_RCU) | ||
1492 | return -ECHILD; | ||
1493 | |||
1494 | inode = dentry->d_inode; | ||
1092 | if (!is_atomic_open(nd) || d_mountpoint(dentry)) | 1495 | if (!is_atomic_open(nd) || d_mountpoint(dentry)) |
1093 | goto no_open; | 1496 | goto no_open; |
1497 | |||
1094 | parent = dget_parent(dentry); | 1498 | parent = dget_parent(dentry); |
1095 | dir = parent->d_inode; | 1499 | dir = parent->d_inode; |
1500 | |||
1096 | /* We can't create new files in nfs_open_revalidate(), so we | 1501 | /* We can't create new files in nfs_open_revalidate(), so we |
1097 | * optimize away revalidation of negative dentries. | 1502 | * optimize away revalidation of negative dentries. |
1098 | */ | 1503 | */ |
@@ -1112,99 +1517,96 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1112 | /* We can't create new files, or truncate existing ones here */ | 1517 | /* We can't create new files, or truncate existing ones here */ |
1113 | openflags &= ~(O_CREAT|O_EXCL|O_TRUNC); | 1518 | openflags &= ~(O_CREAT|O_EXCL|O_TRUNC); |
1114 | 1519 | ||
1520 | ctx = nameidata_to_nfs_open_context(dentry, nd); | ||
1521 | ret = PTR_ERR(ctx); | ||
1522 | if (IS_ERR(ctx)) | ||
1523 | goto out; | ||
1115 | /* | 1524 | /* |
1116 | * Note: we're not holding inode->i_mutex and so may be racing with | 1525 | * Note: we're not holding inode->i_mutex and so may be racing with |
1117 | * operations that change the directory. We therefore save the | 1526 | * operations that change the directory. We therefore save the |
1118 | * change attribute *before* we do the RPC call. | 1527 | * change attribute *before* we do the RPC call. |
1119 | */ | 1528 | */ |
1120 | ret = nfs4_open_revalidate(dir, dentry, openflags, nd); | 1529 | inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, NULL); |
1530 | if (IS_ERR(inode)) { | ||
1531 | ret = PTR_ERR(inode); | ||
1532 | switch (ret) { | ||
1533 | case -EPERM: | ||
1534 | case -EACCES: | ||
1535 | case -EDQUOT: | ||
1536 | case -ENOSPC: | ||
1537 | case -EROFS: | ||
1538 | goto out_put_ctx; | ||
1539 | default: | ||
1540 | goto out_drop; | ||
1541 | } | ||
1542 | } | ||
1543 | iput(inode); | ||
1544 | if (inode != dentry->d_inode) | ||
1545 | goto out_drop; | ||
1546 | |||
1547 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1548 | ret = nfs_intent_set_file(nd, ctx); | ||
1549 | if (ret >= 0) | ||
1550 | ret = 1; | ||
1121 | out: | 1551 | out: |
1122 | dput(parent); | 1552 | dput(parent); |
1123 | if (!ret) | ||
1124 | d_drop(dentry); | ||
1125 | return ret; | 1553 | return ret; |
1554 | out_drop: | ||
1555 | d_drop(dentry); | ||
1556 | ret = 0; | ||
1557 | out_put_ctx: | ||
1558 | put_nfs_open_context(ctx); | ||
1559 | goto out; | ||
1560 | |||
1126 | no_open_dput: | 1561 | no_open_dput: |
1127 | dput(parent); | 1562 | dput(parent); |
1128 | no_open: | 1563 | no_open: |
1129 | return nfs_lookup_revalidate(dentry, nd); | 1564 | return nfs_lookup_revalidate(dentry, nd); |
1130 | } | 1565 | } |
1131 | #endif /* CONFIG_NFSV4 */ | ||
1132 | 1566 | ||
1133 | static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) | 1567 | static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode, |
1568 | struct nameidata *nd) | ||
1134 | { | 1569 | { |
1135 | struct dentry *parent = desc->file->f_path.dentry; | 1570 | struct nfs_open_context *ctx = NULL; |
1136 | struct inode *dir = parent->d_inode; | 1571 | struct iattr attr; |
1137 | struct nfs_entry *entry = desc->entry; | 1572 | int error; |
1138 | struct dentry *dentry, *alias; | 1573 | int open_flags = 0; |
1139 | struct qstr name = { | ||
1140 | .name = entry->name, | ||
1141 | .len = entry->len, | ||
1142 | }; | ||
1143 | struct inode *inode; | ||
1144 | unsigned long verf = nfs_save_change_attribute(dir); | ||
1145 | 1574 | ||
1146 | switch (name.len) { | 1575 | dfprintk(VFS, "NFS: create(%s/%ld), %s\n", |
1147 | case 2: | 1576 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); |
1148 | if (name.name[0] == '.' && name.name[1] == '.') | ||
1149 | return dget_parent(parent); | ||
1150 | break; | ||
1151 | case 1: | ||
1152 | if (name.name[0] == '.') | ||
1153 | return dget(parent); | ||
1154 | } | ||
1155 | 1577 | ||
1156 | spin_lock(&dir->i_lock); | 1578 | attr.ia_mode = mode; |
1157 | if (NFS_I(dir)->cache_validity & NFS_INO_INVALID_DATA) { | 1579 | attr.ia_valid = ATTR_MODE; |
1158 | spin_unlock(&dir->i_lock); | ||
1159 | return NULL; | ||
1160 | } | ||
1161 | spin_unlock(&dir->i_lock); | ||
1162 | 1580 | ||
1163 | name.hash = full_name_hash(name.name, name.len); | 1581 | if ((nd->flags & LOOKUP_CREATE) != 0) { |
1164 | dentry = d_lookup(parent, &name); | 1582 | open_flags = nd->intent.open.flags; |
1165 | if (dentry != NULL) { | ||
1166 | /* Is this a positive dentry that matches the readdir info? */ | ||
1167 | if (dentry->d_inode != NULL && | ||
1168 | (NFS_FILEID(dentry->d_inode) == entry->ino || | ||
1169 | d_mountpoint(dentry))) { | ||
1170 | if (!desc->plus || entry->fh->size == 0) | ||
1171 | return dentry; | ||
1172 | if (nfs_compare_fh(NFS_FH(dentry->d_inode), | ||
1173 | entry->fh) == 0) | ||
1174 | goto out_renew; | ||
1175 | } | ||
1176 | /* No, so d_drop to allow one to be created */ | ||
1177 | d_drop(dentry); | ||
1178 | dput(dentry); | ||
1179 | } | ||
1180 | if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR)) | ||
1181 | return NULL; | ||
1182 | if (name.len > NFS_SERVER(dir)->namelen) | ||
1183 | return NULL; | ||
1184 | /* Note: caller is already holding the dir->i_mutex! */ | ||
1185 | dentry = d_alloc(parent, &name); | ||
1186 | if (dentry == NULL) | ||
1187 | return NULL; | ||
1188 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | ||
1189 | inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr); | ||
1190 | if (IS_ERR(inode)) { | ||
1191 | dput(dentry); | ||
1192 | return NULL; | ||
1193 | } | ||
1194 | 1583 | ||
1195 | alias = d_materialise_unique(dentry, inode); | 1584 | ctx = nameidata_to_nfs_open_context(dentry, nd); |
1196 | if (alias != NULL) { | 1585 | error = PTR_ERR(ctx); |
1197 | dput(dentry); | 1586 | if (IS_ERR(ctx)) |
1198 | if (IS_ERR(alias)) | 1587 | goto out_err_drop; |
1199 | return NULL; | ||
1200 | dentry = alias; | ||
1201 | } | 1588 | } |
1202 | 1589 | ||
1203 | out_renew: | 1590 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx); |
1204 | nfs_set_verifier(dentry, verf); | 1591 | if (error != 0) |
1205 | return dentry; | 1592 | goto out_put_ctx; |
1593 | if (ctx != NULL) { | ||
1594 | error = nfs_intent_set_file(nd, ctx); | ||
1595 | if (error < 0) | ||
1596 | goto out_err; | ||
1597 | } | ||
1598 | return 0; | ||
1599 | out_put_ctx: | ||
1600 | if (ctx != NULL) | ||
1601 | put_nfs_open_context(ctx); | ||
1602 | out_err_drop: | ||
1603 | d_drop(dentry); | ||
1604 | out_err: | ||
1605 | return error; | ||
1206 | } | 1606 | } |
1207 | 1607 | ||
1608 | #endif /* CONFIG_NFSV4 */ | ||
1609 | |||
1208 | /* | 1610 | /* |
1209 | * Code common to create, mkdir, and mknod. | 1611 | * Code common to create, mkdir, and mknod. |
1210 | */ | 1612 | */ |
@@ -1222,7 +1624,7 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, | |||
1222 | if (dentry->d_inode) | 1624 | if (dentry->d_inode) |
1223 | goto out; | 1625 | goto out; |
1224 | if (fhandle->size == 0) { | 1626 | if (fhandle->size == 0) { |
1225 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1627 | error = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, &dentry->d_name, fhandle, fattr); |
1226 | if (error) | 1628 | if (error) |
1227 | goto out_error; | 1629 | goto out_error; |
1228 | } | 1630 | } |
@@ -1269,7 +1671,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
1269 | if ((nd->flags & LOOKUP_CREATE) != 0) | 1671 | if ((nd->flags & LOOKUP_CREATE) != 0) |
1270 | open_flags = nd->intent.open.flags; | 1672 | open_flags = nd->intent.open.flags; |
1271 | 1673 | ||
1272 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd); | 1674 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, NULL); |
1273 | if (error != 0) | 1675 | if (error != 0) |
1274 | goto out_err; | 1676 | goto out_err; |
1275 | return 0; | 1677 | return 0; |
@@ -1351,76 +1753,6 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1351 | return error; | 1753 | return error; |
1352 | } | 1754 | } |
1353 | 1755 | ||
1354 | static int nfs_sillyrename(struct inode *dir, struct dentry *dentry) | ||
1355 | { | ||
1356 | static unsigned int sillycounter; | ||
1357 | const int fileidsize = sizeof(NFS_FILEID(dentry->d_inode))*2; | ||
1358 | const int countersize = sizeof(sillycounter)*2; | ||
1359 | const int slen = sizeof(".nfs")+fileidsize+countersize-1; | ||
1360 | char silly[slen+1]; | ||
1361 | struct qstr qsilly; | ||
1362 | struct dentry *sdentry; | ||
1363 | int error = -EIO; | ||
1364 | |||
1365 | dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n", | ||
1366 | dentry->d_parent->d_name.name, dentry->d_name.name, | ||
1367 | atomic_read(&dentry->d_count)); | ||
1368 | nfs_inc_stats(dir, NFSIOS_SILLYRENAME); | ||
1369 | |||
1370 | /* | ||
1371 | * We don't allow a dentry to be silly-renamed twice. | ||
1372 | */ | ||
1373 | error = -EBUSY; | ||
1374 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) | ||
1375 | goto out; | ||
1376 | |||
1377 | sprintf(silly, ".nfs%*.*Lx", | ||
1378 | fileidsize, fileidsize, | ||
1379 | (unsigned long long)NFS_FILEID(dentry->d_inode)); | ||
1380 | |||
1381 | /* Return delegation in anticipation of the rename */ | ||
1382 | nfs_inode_return_delegation(dentry->d_inode); | ||
1383 | |||
1384 | sdentry = NULL; | ||
1385 | do { | ||
1386 | char *suffix = silly + slen - countersize; | ||
1387 | |||
1388 | dput(sdentry); | ||
1389 | sillycounter++; | ||
1390 | sprintf(suffix, "%*.*x", countersize, countersize, sillycounter); | ||
1391 | |||
1392 | dfprintk(VFS, "NFS: trying to rename %s to %s\n", | ||
1393 | dentry->d_name.name, silly); | ||
1394 | |||
1395 | sdentry = lookup_one_len(silly, dentry->d_parent, slen); | ||
1396 | /* | ||
1397 | * N.B. Better to return EBUSY here ... it could be | ||
1398 | * dangerous to delete the file while it's in use. | ||
1399 | */ | ||
1400 | if (IS_ERR(sdentry)) | ||
1401 | goto out; | ||
1402 | } while(sdentry->d_inode != NULL); /* need negative lookup */ | ||
1403 | |||
1404 | qsilly.name = silly; | ||
1405 | qsilly.len = strlen(silly); | ||
1406 | if (dentry->d_inode) { | ||
1407 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, | ||
1408 | dir, &qsilly); | ||
1409 | nfs_mark_for_revalidate(dentry->d_inode); | ||
1410 | } else | ||
1411 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, | ||
1412 | dir, &qsilly); | ||
1413 | if (!error) { | ||
1414 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1415 | d_move(dentry, sdentry); | ||
1416 | error = nfs_async_unlink(dir, dentry); | ||
1417 | /* If we return 0 we don't unlink */ | ||
1418 | } | ||
1419 | dput(sdentry); | ||
1420 | out: | ||
1421 | return error; | ||
1422 | } | ||
1423 | |||
1424 | /* | 1756 | /* |
1425 | * Remove a file after making sure there are no pending writes, | 1757 | * Remove a file after making sure there are no pending writes, |
1426 | * and after checking that the file has only one user. | 1758 | * and after checking that the file has only one user. |
@@ -1471,11 +1803,9 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1471 | dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id, | 1803 | dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id, |
1472 | dir->i_ino, dentry->d_name.name); | 1804 | dir->i_ino, dentry->d_name.name); |
1473 | 1805 | ||
1474 | spin_lock(&dcache_lock); | ||
1475 | spin_lock(&dentry->d_lock); | 1806 | spin_lock(&dentry->d_lock); |
1476 | if (atomic_read(&dentry->d_count) > 1) { | 1807 | if (dentry->d_count > 1) { |
1477 | spin_unlock(&dentry->d_lock); | 1808 | spin_unlock(&dentry->d_lock); |
1478 | spin_unlock(&dcache_lock); | ||
1479 | /* Start asynchronous writeout of the inode */ | 1809 | /* Start asynchronous writeout of the inode */ |
1480 | write_inode_now(dentry->d_inode, 0); | 1810 | write_inode_now(dentry->d_inode, 0); |
1481 | error = nfs_sillyrename(dir, dentry); | 1811 | error = nfs_sillyrename(dir, dentry); |
@@ -1486,7 +1816,6 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1486 | need_rehash = 1; | 1816 | need_rehash = 1; |
1487 | } | 1817 | } |
1488 | spin_unlock(&dentry->d_lock); | 1818 | spin_unlock(&dentry->d_lock); |
1489 | spin_unlock(&dcache_lock); | ||
1490 | error = nfs_safe_remove(dentry); | 1819 | error = nfs_safe_remove(dentry); |
1491 | if (!error || error == -ENOENT) { | 1820 | if (!error || error == -ENOENT) { |
1492 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1821 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
@@ -1580,7 +1909,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | |||
1580 | d_drop(dentry); | 1909 | d_drop(dentry); |
1581 | error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); | 1910 | error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); |
1582 | if (error == 0) { | 1911 | if (error == 0) { |
1583 | atomic_inc(&inode->i_count); | 1912 | ihold(inode); |
1584 | d_add(dentry, inode); | 1913 | d_add(dentry, inode); |
1585 | } | 1914 | } |
1586 | return error; | 1915 | return error; |
@@ -1621,7 +1950,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1621 | dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n", | 1950 | dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n", |
1622 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, | 1951 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, |
1623 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name, | 1952 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name, |
1624 | atomic_read(&new_dentry->d_count)); | 1953 | new_dentry->d_count); |
1625 | 1954 | ||
1626 | /* | 1955 | /* |
1627 | * For non-directories, check whether the target is busy and if so, | 1956 | * For non-directories, check whether the target is busy and if so, |
@@ -1639,7 +1968,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1639 | rehash = new_dentry; | 1968 | rehash = new_dentry; |
1640 | } | 1969 | } |
1641 | 1970 | ||
1642 | if (atomic_read(&new_dentry->d_count) > 2) { | 1971 | if (new_dentry->d_count > 2) { |
1643 | int err; | 1972 | int err; |
1644 | 1973 | ||
1645 | /* copy the target dentry's name */ | 1974 | /* copy the target dentry's name */ |
@@ -1708,17 +2037,20 @@ static void nfs_access_free_list(struct list_head *head) | |||
1708 | } | 2037 | } |
1709 | } | 2038 | } |
1710 | 2039 | ||
1711 | int nfs_access_cache_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) | 2040 | int nfs_access_cache_shrinker(struct shrinker *shrink, |
2041 | struct shrink_control *sc) | ||
1712 | { | 2042 | { |
1713 | LIST_HEAD(head); | 2043 | LIST_HEAD(head); |
1714 | struct nfs_inode *nfsi; | 2044 | struct nfs_inode *nfsi, *next; |
1715 | struct nfs_access_entry *cache; | 2045 | struct nfs_access_entry *cache; |
2046 | int nr_to_scan = sc->nr_to_scan; | ||
2047 | gfp_t gfp_mask = sc->gfp_mask; | ||
1716 | 2048 | ||
1717 | if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL) | 2049 | if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL) |
1718 | return (nr_to_scan == 0) ? 0 : -1; | 2050 | return (nr_to_scan == 0) ? 0 : -1; |
1719 | 2051 | ||
1720 | spin_lock(&nfs_access_lru_lock); | 2052 | spin_lock(&nfs_access_lru_lock); |
1721 | list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) { | 2053 | list_for_each_entry_safe(nfsi, next, &nfs_access_lru_list, access_cache_inode_lru) { |
1722 | struct inode *inode; | 2054 | struct inode *inode; |
1723 | 2055 | ||
1724 | if (nr_to_scan-- == 0) | 2056 | if (nr_to_scan-- == 0) |
@@ -1941,11 +2273,14 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags) | |||
1941 | return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags)); | 2273 | return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags)); |
1942 | } | 2274 | } |
1943 | 2275 | ||
1944 | int nfs_permission(struct inode *inode, int mask) | 2276 | int nfs_permission(struct inode *inode, int mask, unsigned int flags) |
1945 | { | 2277 | { |
1946 | struct rpc_cred *cred; | 2278 | struct rpc_cred *cred; |
1947 | int res = 0; | 2279 | int res = 0; |
1948 | 2280 | ||
2281 | if (flags & IPERM_FLAG_RCU) | ||
2282 | return -ECHILD; | ||
2283 | |||
1949 | nfs_inc_stats(inode, NFSIOS_VFSACCESS); | 2284 | nfs_inc_stats(inode, NFSIOS_VFSACCESS); |
1950 | 2285 | ||
1951 | if ((mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) | 2286 | if ((mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) |
@@ -1993,7 +2328,7 @@ out: | |||
1993 | out_notsup: | 2328 | out_notsup: |
1994 | res = nfs_revalidate_inode(NFS_SERVER(inode), inode); | 2329 | res = nfs_revalidate_inode(NFS_SERVER(inode), inode); |
1995 | if (res == 0) | 2330 | if (res == 0) |
1996 | res = generic_permission(inode, mask, NULL); | 2331 | res = generic_permission(inode, mask, flags, NULL); |
1997 | goto out; | 2332 | goto out; |
1998 | } | 2333 | } |
1999 | 2334 | ||