Merge tag 'nfs-for-5.13-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[linux-2.6-microblaze.git] / fs / nfs / dir.c
index 3d8e369..1a6d286 100644 (file)
@@ -866,6 +866,8 @@ static int nfs_readdir_xdr_to_array(struct nfs_readdir_descriptor *desc,
                        break;
                }
 
+               verf_arg = verf_res;
+
                status = nfs_readdir_page_filler(desc, entry, pages, pglen,
                                                 arrays, narrays);
        } while (!status && nfs_readdir_page_needs_filling(page));
@@ -927,7 +929,12 @@ static int find_and_lock_cache_page(struct nfs_readdir_descriptor *desc)
                        }
                        return res;
                }
-               memcpy(nfsi->cookieverf, verf, sizeof(nfsi->cookieverf));
+               /*
+                * Set the cookie verifier if the page cache was empty
+                */
+               if (desc->page_index == 0)
+                       memcpy(nfsi->cookieverf, verf,
+                              sizeof(nfsi->cookieverf));
        }
        res = nfs_readdir_search_array(desc);
        if (res == 0) {
@@ -974,10 +981,10 @@ static int readdir_search_pagecache(struct nfs_readdir_descriptor *desc)
 /*
  * Once we've found the start of the dirent within a page: fill 'er up...
  */
-static void nfs_do_filldir(struct nfs_readdir_descriptor *desc)
+static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
+                          const __be32 *verf)
 {
        struct file     *file = desc->file;
-       struct nfs_inode *nfsi = NFS_I(file_inode(file));
        struct nfs_cache_array *array;
        unsigned int i = 0;
 
@@ -991,7 +998,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc)
                        desc->eof = true;
                        break;
                }
-               memcpy(desc->verf, nfsi->cookieverf, sizeof(desc->verf));
+               memcpy(desc->verf, verf, sizeof(desc->verf));
                if (i < (array->size-1))
                        desc->dir_cookie = array->array[i+1].cookie;
                else
@@ -1048,7 +1055,7 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc)
 
        for (i = 0; !desc->eof && i < sz && arrays[i]; i++) {
                desc->page = arrays[i];
-               nfs_do_filldir(desc);
+               nfs_do_filldir(desc, verf);
        }
        desc->page = NULL;
 
@@ -1069,6 +1076,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
 {
        struct dentry   *dentry = file_dentry(file);
        struct inode    *inode = d_inode(dentry);
+       struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_open_dir_context *dir_ctx = file->private_data;
        struct nfs_readdir_descriptor *desc;
        int res;
@@ -1122,7 +1130,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
                        break;
                }
                if (res == -ETOOSMALL && desc->plus) {
-                       clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
+                       clear_bit(NFS_INO_ADVISE_RDPLUS, &nfsi->flags);
                        nfs_zap_caches(inode);
                        desc->page_index = 0;
                        desc->plus = false;
@@ -1132,7 +1140,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
                if (res < 0)
                        break;
 
-               nfs_do_filldir(desc);
+               nfs_do_filldir(desc, nfsi->cookieverf);
                nfs_readdir_page_unlock_and_put_cached(desc);
        } while (!desc->eof);
 
@@ -1703,7 +1711,7 @@ static void nfs_drop_nlink(struct inode *inode)
        NFS_I(inode)->attr_gencount = nfs_inc_attr_generation_counter();
        nfs_set_cache_invalid(
                inode, NFS_INO_INVALID_CHANGE | NFS_INO_INVALID_CTIME |
-                              NFS_INO_INVALID_OTHER | NFS_INO_REVAL_FORCED);
+                              NFS_INO_INVALID_NLINK);
        spin_unlock(&inode->i_lock);
 }
 
@@ -2940,7 +2948,7 @@ static int nfs_execute_ok(struct inode *inode, int mask)
 
        if (S_ISDIR(inode->i_mode))
                return 0;
-       if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_OTHER)) {
+       if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_MODE)) {
                if (mask & MAY_NOT_BLOCK)
                        return -ECHILD;
                ret = __nfs_revalidate_inode(server, inode);
@@ -2998,7 +3006,8 @@ out_notsup:
        if (mask & MAY_NOT_BLOCK)
                return -ECHILD;
 
-       res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+       res = nfs_revalidate_inode(inode, NFS_INO_INVALID_MODE |
+                                                 NFS_INO_INVALID_OTHER);
        if (res == 0)
                res = generic_permission(&init_user_ns, inode, mask);
        goto out;