NFS: Fix a page leak in uncached_readdir()
[linux-block.git] / fs / nfs / dir.c
index 662df2a5fad5d06fac235314220e7270fe9eef02..353f47c31b1d8c7662a08f75082887c700d326f0 100644 (file)
@@ -466,8 +466,9 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
        struct xdr_stream stream;
        struct xdr_buf buf;
        __be32 *ptr = xdr_page;
-       int status;
        struct nfs_cache_array *array;
+       unsigned int count = 0;
+       int status;
 
        buf.head->iov_base = xdr_page;
        buf.head->iov_len = buflen;
@@ -488,6 +489,8 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
                        break;
                }
 
+               count++;
+
                if (desc->plus == 1)
                        nfs_prime_dcache(desc->file->f_path.dentry, entry);
 
@@ -496,13 +499,14 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
                        break;
        } while (!entry->eof);
 
-       if (status == -EBADCOOKIE && entry->eof) {
+       if (count == 0 || (status == -EBADCOOKIE && entry->eof == 1)) {
                array = nfs_readdir_get_array(page);
                if (!IS_ERR(array)) {
                        array->eof_index = array->size;
                        status = 0;
                        nfs_readdir_release_array(page);
-               }
+               } else
+                       status = PTR_ERR(array);
        }
        return status;
 }
@@ -697,11 +701,12 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
        int res = 0;
        struct nfs_cache_array *array = NULL;
        unsigned int d_type = DT_UNKNOWN;
-       struct dentry *dentry = NULL;
 
        array = nfs_readdir_get_array(desc->page);
-       if (IS_ERR(array))
-               return PTR_ERR(array);
+       if (IS_ERR(array)) {
+               res = PTR_ERR(array);
+               goto out;
+       }
 
        for (i = desc->cache_entry_index; i < array->size; i++) {
                d_type = DT_UNKNOWN;
@@ -722,9 +727,8 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
                desc->eof = 1;
 
        nfs_readdir_release_array(desc->page);
+out:
        cache_page_release(desc);
-       if (dentry != NULL)
-               dput(dentry);
        dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n",
                        (unsigned long long)*desc->dir_cookie, res);
        return res;
@@ -759,13 +763,14 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
                goto out;
        }
 
+       desc->page_index = 0;
+       desc->page = page;
+
        if (nfs_readdir_xdr_to_array(desc, page, inode) == -1) {
                status = -EIO;
                goto out_release;
        }
 
-       desc->page_index = 0;
-       desc->page = page;
        status = nfs_do_filldir(desc, dirent, filldir);
 
  out: