]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - fs/nfs/dir.c
Merge tag 'nfs-for-3.11-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[karo-tx-linux.git] / fs / nfs / dir.c
index c3f21888654ff595cb0449055c2d2694bfc2d429..0fac2cb1ea18648d8befee687f3086f771b8b74a 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/pagevec.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
+#include <linux/swap.h>
 #include <linux/sched.h>
 #include <linux/kmemleak.h>
 #include <linux/xattr.h>
@@ -46,7 +47,7 @@
 
 static int nfs_opendir(struct inode *, struct file *);
 static int nfs_closedir(struct inode *, struct file *);
-static int nfs_readdir(struct file *, void *, filldir_t);
+static int nfs_readdir(struct file *, struct dir_context *);
 static int nfs_fsync_dir(struct file *, loff_t, loff_t, int);
 static loff_t nfs_llseek_dir(struct file *, loff_t, int);
 static void nfs_readdir_clear_array(struct page*);
@@ -54,7 +55,7 @@ static void nfs_readdir_clear_array(struct page*);
 const struct file_operations nfs_dir_operations = {
        .llseek         = nfs_llseek_dir,
        .read           = generic_read_dir,
-       .readdir        = nfs_readdir,
+       .iterate        = nfs_readdir,
        .open           = nfs_opendir,
        .release        = nfs_closedir,
        .fsync          = nfs_fsync_dir,
@@ -147,6 +148,7 @@ typedef int (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, int);
 typedef struct {
        struct file     *file;
        struct page     *page;
+       struct dir_context *ctx;
        unsigned long   page_index;
        u64             *dir_cookie;
        u64             last_cookie;
@@ -252,7 +254,7 @@ out:
 static
 int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc)
 {
-       loff_t diff = desc->file->f_pos - desc->current_index;
+       loff_t diff = desc->ctx->pos - desc->current_index;
        unsigned int index;
 
        if (diff < 0)
@@ -289,7 +291,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
                            || (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))) {
                                ctx->duped = 0;
                                ctx->attr_gencount = nfsi->attr_gencount;
-                       } else if (new_pos < desc->file->f_pos) {
+                       } else if (new_pos < desc->ctx->pos) {
                                if (ctx->duped > 0
                                    && ctx->dup_cookie == *desc->dir_cookie) {
                                        if (printk_ratelimit()) {
@@ -307,7 +309,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
                                ctx->dup_cookie = *desc->dir_cookie;
                                ctx->duped = -1;
                        }
-                       desc->file->f_pos = new_pos;
+                       desc->ctx->pos = new_pos;
                        desc->cache_entry_index = i;
                        return 0;
                }
@@ -405,13 +407,13 @@ different:
 }
 
 static
-bool nfs_use_readdirplus(struct inode *dir, struct file *filp)
+bool nfs_use_readdirplus(struct inode *dir, struct dir_context *ctx)
 {
        if (!nfs_server_capable(dir, NFS_CAP_READDIRPLUS))
                return false;
        if (test_and_clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags))
                return true;
-       if (filp->f_pos == 0)
+       if (ctx->pos == 0)
                return true;
        return false;
 }
@@ -713,8 +715,7 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
  * Once we've found the start of the dirent within a page: fill 'er up...
  */
 static 
-int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
-                  filldir_t filldir)
+int nfs_do_filldir(nfs_readdir_descriptor_t *desc)
 {
        struct file     *file = desc->file;
        int i = 0;
@@ -732,13 +733,12 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
                struct nfs_cache_array_entry *ent;
 
                ent = &array->array[i];
-               if (filldir(dirent, ent->string.name, ent->string.len,
-                   file->f_pos, nfs_compat_user_ino64(ent->ino),
-                   ent->d_type) < 0) {
+               if (!dir_emit(desc->ctx, ent->string.name, ent->string.len,
+                   nfs_compat_user_ino64(ent->ino), ent->d_type)) {
                        desc->eof = 1;
                        break;
                }
-               file->f_pos++;
+               desc->ctx->pos++;
                if (i < (array->size-1))
                        *desc->dir_cookie = array->array[i+1].cookie;
                else
@@ -770,8 +770,7 @@ out:
  *      directory in the page cache by the time we get here.
  */
 static inline
-int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
-                    filldir_t filldir)
+int uncached_readdir(nfs_readdir_descriptor_t *desc)
 {
        struct page     *page = NULL;
        int             status;
@@ -796,7 +795,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
        if (status < 0)
                goto out_release;
 
-       status = nfs_do_filldir(desc, dirent, filldir);
+       status = nfs_do_filldir(desc);
 
  out:
        dfprintk(DIRCACHE, "NFS: %s: returns %d\n",
@@ -811,35 +810,36 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
    last cookie cache takes care of the common case of reading the
    whole directory.
  */
-static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+static int nfs_readdir(struct file *file, struct dir_context *ctx)
 {
-       struct dentry   *dentry = filp->f_path.dentry;
+       struct dentry   *dentry = file->f_path.dentry;
        struct inode    *inode = dentry->d_inode;
        nfs_readdir_descriptor_t my_desc,
                        *desc = &my_desc;
-       struct nfs_open_dir_context *dir_ctx = filp->private_data;
+       struct nfs_open_dir_context *dir_ctx = file->private_data;
        int res;
 
        dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
                        dentry->d_parent->d_name.name, dentry->d_name.name,
-                       (long long)filp->f_pos);
+                       (long long)ctx->pos);
        nfs_inc_stats(inode, NFSIOS_VFSGETDENTS);
 
        /*
-        * filp->f_pos points to the dirent entry number.
+        * ctx->pos points to the dirent entry number.
         * *desc->dir_cookie has the cookie for the next entry. We have
         * to either find the entry with the appropriate number or
         * revalidate the cookie.
         */
        memset(desc, 0, sizeof(*desc));
 
-       desc->file = filp;
+       desc->file = file;
+       desc->ctx = ctx;
        desc->dir_cookie = &dir_ctx->dir_cookie;
        desc->decode = NFS_PROTO(inode)->decode_dirent;
-       desc->plus = nfs_use_readdirplus(inode, filp) ? 1 : 0;
+       desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0;
 
        nfs_block_sillyrename(dentry);
-       res = nfs_revalidate_mapping(inode, filp->f_mapping);
+       res = nfs_revalidate_mapping(inode, file->f_mapping);
        if (res < 0)
                goto out;
 
@@ -851,7 +851,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                        /* This means either end of directory */
                        if (*desc->dir_cookie && desc->eof == 0) {
                                /* Or that the server has 'lost' a cookie */
-                               res = uncached_readdir(desc, dirent, filldir);
+                               res = uncached_readdir(desc);
                                if (res == 0)
                                        continue;
                        }
@@ -868,7 +868,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                if (res < 0)
                        break;
 
-               res = nfs_do_filldir(desc, dirent, filldir);
+               res = nfs_do_filldir(desc);
                if (res < 0)
                        break;
        } while (!desc->eof);
@@ -1730,7 +1730,7 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)
                dir->i_ino, dentry->d_name.name);
 
        spin_lock(&dentry->d_lock);
-       if (dentry->d_count > 1) {
+       if (d_count(dentry) > 1) {
                spin_unlock(&dentry->d_lock);
                /* Start asynchronous writeout of the inode */
                write_inode_now(dentry->d_inode, 0);
@@ -1768,7 +1768,6 @@ EXPORT_SYMBOL_GPL(nfs_unlink);
  */
 int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 {
-       struct pagevec lru_pvec;
        struct page *page;
        char *kaddr;
        struct iattr attr;
@@ -1808,11 +1807,8 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
         * No big deal if we can't add this page to the page cache here.
         * READLINK will get the missing page from the server if needed.
         */
-       pagevec_init(&lru_pvec, 0);
-       if (!add_to_page_cache(page, dentry->d_inode->i_mapping, 0,
+       if (!add_to_page_cache_lru(page, dentry->d_inode->i_mapping, 0,
                                                        GFP_KERNEL)) {
-               pagevec_add(&lru_pvec, page);
-               pagevec_lru_add_file(&lru_pvec);
                SetPageUptodate(page);
                unlock_page(page);
        } else
@@ -1879,7 +1875,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n",
                 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
                 new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
-                new_dentry->d_count);
+                d_count(new_dentry));
 
        /*
         * For non-directories, check whether the target is busy and if so,
@@ -1897,7 +1893,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        rehash = new_dentry;
                }
 
-               if (new_dentry->d_count > 2) {
+               if (d_count(new_dentry) > 2) {
                        int err;
 
                        /* copy the target dentry's name */