diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-10-23 14:53:23 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-10-23 15:27:38 -0400 |
commit | 4a201d6e3f4253f918555cc7c27c418f8ac1bb65 (patch) | |
tree | 9424a999b43f8c4d397f513a32258a64f3bed61a | |
parent | 82f2e5472e2304e531c2fa85e457f4a71070044e (diff) |
NFS: Ensure we check all allocation return values in new readdir code
Also some clean ups.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/dir.c | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 2a768d05a534..257e4052492e 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -225,33 +225,42 @@ int nfs_readdir_clear_array(struct page *page, gfp_t mask) | |||
225 | * nfs_clear_readdir_array() | 225 | * nfs_clear_readdir_array() |
226 | */ | 226 | */ |
227 | static | 227 | static |
228 | void nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int len) | 228 | int nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int len) |
229 | { | 229 | { |
230 | string->len = len; | 230 | string->len = len; |
231 | string->name = kmemdup(name, len, GFP_KERNEL); | 231 | string->name = kmemdup(name, len, GFP_KERNEL); |
232 | string->hash = full_name_hash(string->name, string->len); | 232 | if (string->name == NULL) |
233 | return -ENOMEM; | ||
234 | string->hash = full_name_hash(name, len); | ||
235 | return 0; | ||
233 | } | 236 | } |
234 | 237 | ||
235 | static | 238 | static |
236 | int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page) | 239 | int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page) |
237 | { | 240 | { |
238 | struct nfs_cache_array *array = nfs_readdir_get_array(page); | 241 | struct nfs_cache_array *array = nfs_readdir_get_array(page); |
242 | struct nfs_cache_array_entry *cache_entry; | ||
243 | int ret; | ||
244 | |||
239 | if (IS_ERR(array)) | 245 | if (IS_ERR(array)) |
240 | return PTR_ERR(array); | 246 | return PTR_ERR(array); |
241 | if (array->size >= MAX_READDIR_ARRAY) { | 247 | ret = -EIO; |
242 | nfs_readdir_release_array(page); | 248 | if (array->size >= MAX_READDIR_ARRAY) |
243 | return -EIO; | 249 | goto out; |
244 | } | ||
245 | 250 | ||
246 | array->array[array->size].cookie = entry->prev_cookie; | 251 | cache_entry = &array->array[array->size]; |
252 | cache_entry->cookie = entry->prev_cookie; | ||
253 | cache_entry->ino = entry->ino; | ||
254 | ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len); | ||
255 | if (ret) | ||
256 | goto out; | ||
247 | array->last_cookie = entry->cookie; | 257 | array->last_cookie = entry->cookie; |
248 | array->array[array->size].ino = entry->ino; | ||
249 | nfs_readdir_make_qstr(&array->array[array->size].string, entry->name, entry->len); | ||
250 | if (entry->eof == 1) | 258 | if (entry->eof == 1) |
251 | array->eof_index = array->size; | 259 | array->eof_index = array->size; |
252 | array->size++; | 260 | array->size++; |
261 | out: | ||
253 | nfs_readdir_release_array(page); | 262 | nfs_readdir_release_array(page); |
254 | return 0; | 263 | return ret; |
255 | } | 264 | } |
256 | 265 | ||
257 | static | 266 | static |
@@ -388,21 +397,24 @@ different: | |||
388 | static | 397 | static |
389 | void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | 398 | void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) |
390 | { | 399 | { |
391 | struct qstr filename; | 400 | struct qstr filename = { |
392 | struct dentry *dentry = NULL; | 401 | .len = entry->len, |
393 | struct dentry *alias = NULL; | 402 | .name = entry->name, |
403 | }; | ||
404 | struct dentry *dentry; | ||
405 | struct dentry *alias; | ||
394 | struct inode *dir = parent->d_inode; | 406 | struct inode *dir = parent->d_inode; |
395 | struct inode *inode; | 407 | struct inode *inode; |
396 | 408 | ||
397 | nfs_readdir_make_qstr(&filename, entry->name, entry->len); | 409 | if (filename.name[0] == '.') { |
398 | if (filename.len == 1 && filename.name[0] == '.') | 410 | if (filename.len == 1) |
399 | dentry = dget(parent); | 411 | return; |
400 | else if (filename.len == 2 && filename.name[0] == '.' | 412 | if (filename.len == 2 && filename.name[1] == '.') |
401 | && filename.name[1] == '.') | 413 | return; |
402 | dentry = dget_parent(parent); | 414 | } |
403 | else | 415 | filename.hash = full_name_hash(filename.name, filename.len); |
404 | dentry = d_lookup(parent, &filename); | ||
405 | 416 | ||
417 | dentry = d_lookup(parent, &filename); | ||
406 | if (dentry != NULL) { | 418 | if (dentry != NULL) { |
407 | if (nfs_same_file(dentry, entry)) { | 419 | if (nfs_same_file(dentry, entry)) { |
408 | nfs_refresh_inode(dentry->d_inode, entry->fattr); | 420 | nfs_refresh_inode(dentry->d_inode, entry->fattr); |
@@ -414,6 +426,9 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
414 | } | 426 | } |
415 | 427 | ||
416 | dentry = d_alloc(parent, &filename); | 428 | dentry = d_alloc(parent, &filename); |
429 | if (dentry == NULL) | ||
430 | return; | ||
431 | |||
417 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | 432 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; |
418 | inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr); | 433 | inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr); |
419 | if (IS_ERR(inode)) | 434 | if (IS_ERR(inode)) |
@@ -430,8 +445,6 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
430 | 445 | ||
431 | out: | 446 | out: |
432 | dput(dentry); | 447 | dput(dentry); |
433 | kfree(filename.name); | ||
434 | return; | ||
435 | } | 448 | } |
436 | 449 | ||
437 | /* Perform conversion from xdr to cache array */ | 450 | /* Perform conversion from xdr to cache array */ |
@@ -508,7 +521,7 @@ void *nfs_readdir_large_page(struct page **pages, unsigned int npages) | |||
508 | pages[i] = page; | 521 | pages[i] = page; |
509 | } | 522 | } |
510 | 523 | ||
511 | ptr = vm_map_ram(pages, NFS_MAX_READDIR_PAGES, 0, PAGE_KERNEL); | 524 | ptr = vm_map_ram(pages, npages, 0, PAGE_KERNEL); |
512 | if (!IS_ERR_OR_NULL(ptr)) | 525 | if (!IS_ERR_OR_NULL(ptr)) |
513 | return ptr; | 526 | return ptr; |
514 | out_freepages: | 527 | out_freepages: |