aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-10-23 14:53:23 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-10-23 15:27:38 -0400
commit4a201d6e3f4253f918555cc7c27c418f8ac1bb65 (patch)
tree9424a999b43f8c4d397f513a32258a64f3bed61a
parent82f2e5472e2304e531c2fa85e457f4a71070044e (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.c61
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 */
227static 227static
228void nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int len) 228int 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
235static 238static
236int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page) 239int 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++;
261out:
253 nfs_readdir_release_array(page); 262 nfs_readdir_release_array(page);
254 return 0; 263 return ret;
255} 264}
256 265
257static 266static
@@ -388,21 +397,24 @@ different:
388static 397static
389void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) 398void 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
431out: 446out:
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;
514out_freepages: 527out_freepages: