Merge tag 'for-linus-5.11-rc1b-tag' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / fs / nfs / nfs3proc.c
index 2397cee..5c4e23a 100644 (file)
@@ -154,14 +154,14 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 }
 
 static int
-nfs3_proc_lookup(struct inode *dir, struct dentry *dentry,
-                struct nfs_fh *fhandle, struct nfs_fattr *fattr,
-                struct nfs4_label *label)
+__nfs3_proc_lookup(struct inode *dir, const char *name, size_t len,
+                  struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+                  unsigned short task_flags)
 {
        struct nfs3_diropargs   arg = {
                .fh             = NFS_FH(dir),
-               .name           = dentry->d_name.name,
-               .len            = dentry->d_name.len
+               .name           = name,
+               .len            = len
        };
        struct nfs3_diropres    res = {
                .fh             = fhandle,
@@ -173,17 +173,11 @@ nfs3_proc_lookup(struct inode *dir, struct dentry *dentry,
                .rpc_resp       = &res,
        };
        int                     status;
-       unsigned short task_flags = 0;
-
-       /* Is this is an attribute revalidation, subject to softreval? */
-       if (nfs_lookup_is_soft_revalidate(dentry))
-               task_flags |= RPC_TASK_TIMEOUT;
 
        res.dir_attr = nfs_alloc_fattr();
        if (res.dir_attr == NULL)
                return -ENOMEM;
 
-       dprintk("NFS call  lookup %pd2\n", dentry);
        nfs_fattr_init(fattr);
        status = rpc_call_sync(NFS_CLIENT(dir), &msg, task_flags);
        nfs_refresh_inode(dir, res.dir_attr);
@@ -198,6 +192,37 @@ nfs3_proc_lookup(struct inode *dir, struct dentry *dentry,
        return status;
 }
 
+static int
+nfs3_proc_lookup(struct inode *dir, struct dentry *dentry,
+                struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+                struct nfs4_label *label)
+{
+       unsigned short task_flags = 0;
+
+       /* Is this is an attribute revalidation, subject to softreval? */
+       if (nfs_lookup_is_soft_revalidate(dentry))
+               task_flags |= RPC_TASK_TIMEOUT;
+
+       dprintk("NFS call  lookup %pd2\n", dentry);
+       return __nfs3_proc_lookup(dir, dentry->d_name.name,
+                                 dentry->d_name.len, fhandle, fattr,
+                                 task_flags);
+}
+
+static int nfs3_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle,
+                            struct nfs_fattr *fattr, struct nfs4_label *label)
+{
+       const char dotdot[] = "..";
+       const size_t len = strlen(dotdot);
+       unsigned short task_flags = 0;
+
+       if (NFS_SERVER(inode)->flags & NFS_MOUNT_SOFTREVAL)
+               task_flags |= RPC_TASK_TIMEOUT;
+
+       return __nfs3_proc_lookup(inode, dotdot, len, fhandle, fattr,
+                                 task_flags);
+}
+
 static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
 {
        struct nfs3_accessargs  arg = {
@@ -637,37 +662,36 @@ out:
  * Also note that this implementation handles both plain readdir and
  * readdirplus.
  */
-static int
-nfs3_proc_readdir(struct dentry *dentry, const struct cred *cred,
-                 u64 cookie, struct page **pages, unsigned int count, bool plus)
+static int nfs3_proc_readdir(struct nfs_readdir_arg *nr_arg,
+                            struct nfs_readdir_res *nr_res)
 {
-       struct inode            *dir = d_inode(dentry);
-       __be32                  *verf = NFS_I(dir)->cookieverf;
+       struct inode            *dir = d_inode(nr_arg->dentry);
        struct nfs3_readdirargs arg = {
                .fh             = NFS_FH(dir),
-               .cookie         = cookie,
-               .verf           = {verf[0], verf[1]},
-               .plus           = plus,
-               .count          = count,
-               .pages          = pages
+               .cookie         = nr_arg->cookie,
+               .plus           = nr_arg->plus,
+               .count          = nr_arg->page_len,
+               .pages          = nr_arg->pages
        };
        struct nfs3_readdirres  res = {
-               .verf           = verf,
-               .plus           = plus
+               .verf           = nr_res->verf,
+               .plus           = nr_arg->plus,
        };
        struct rpc_message      msg = {
                .rpc_proc       = &nfs3_procedures[NFS3PROC_READDIR],
                .rpc_argp       = &arg,
                .rpc_resp       = &res,
-               .rpc_cred       = cred,
+               .rpc_cred       = nr_arg->cred,
        };
        int status = -ENOMEM;
 
-       if (plus)
+       if (nr_arg->plus)
                msg.rpc_proc = &nfs3_procedures[NFS3PROC_READDIRPLUS];
+       if (arg.cookie)
+               memcpy(arg.verf, nr_arg->verf, sizeof(arg.verf));
 
-       dprintk("NFS call  readdir%s %d\n",
-                       plus? "plus" : "", (unsigned int) cookie);
+       dprintk("NFS call  readdir%s %llu\n", nr_arg->plus ? "plus" : "",
+               (unsigned long long)nr_arg->cookie);
 
        res.dir_attr = nfs_alloc_fattr();
        if (res.dir_attr == NULL)
@@ -680,8 +704,8 @@ nfs3_proc_readdir(struct dentry *dentry, const struct cred *cred,
 
        nfs_free_fattr(res.dir_attr);
 out:
-       dprintk("NFS reply readdir%s: %d\n",
-                       plus? "plus" : "", status);
+       dprintk("NFS reply readdir%s: %d\n", nr_arg->plus ? "plus" : "",
+               status);
        return status;
 }
 
@@ -1004,6 +1028,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
        .getattr        = nfs3_proc_getattr,
        .setattr        = nfs3_proc_setattr,
        .lookup         = nfs3_proc_lookup,
+       .lookupp        = nfs3_proc_lookupp,
        .access         = nfs3_proc_access,
        .readlink       = nfs3_proc_readlink,
        .create         = nfs3_proc_create,