]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - fs/nfs/nfs4proc.c
NFS: Use raw NFS access mask in nfs4_opendata_access()
[karo-tx-linux.git] / fs / nfs / nfs4proc.c
index 201ca3f2c4bac14986220fcdf6a6c37b734ffa96..583c2b38c908c82abf029a5cf9cec951f32cb247 100644 (file)
@@ -275,6 +275,7 @@ const u32 nfs4_fs_locations_bitmap[3] = {
 static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
                struct nfs4_readdir_arg *readdir)
 {
+       unsigned int attrs = FATTR4_WORD0_FILEID | FATTR4_WORD0_TYPE;
        __be32 *start, *p;
 
        if (cookie > 2) {
@@ -305,8 +306,9 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
                memcpy(p, ".\0\0\0", 4);                        /* entry */
                p++;
                *p++ = xdr_one;                         /* bitmap length */
-               *p++ = htonl(FATTR4_WORD0_FILEID);             /* bitmap */
-               *p++ = htonl(8);              /* attribute buffer length */
+               *p++ = htonl(attrs);                           /* bitmap */
+               *p++ = htonl(12);             /* attribute buffer length */
+               *p++ = htonl(NF4DIR);
                p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry)));
        }
        
@@ -317,8 +319,9 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
        memcpy(p, "..\0\0", 4);                         /* entry */
        p++;
        *p++ = xdr_one;                         /* bitmap length */
-       *p++ = htonl(FATTR4_WORD0_FILEID);             /* bitmap */
-       *p++ = htonl(8);              /* attribute buffer length */
+       *p++ = htonl(attrs);                           /* bitmap */
+       *p++ = htonl(12);             /* attribute buffer length */
+       *p++ = htonl(NF4DIR);
        p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry->d_parent)));
 
        readdir->pgbase = (char *)p - (char *)start;
@@ -698,7 +701,8 @@ static int nfs41_sequence_process(struct rpc_task *task,
        session = slot->table->session;
 
        if (slot->interrupted) {
-               slot->interrupted = 0;
+               if (res->sr_status != -NFS4ERR_DELAY)
+                       slot->interrupted = 0;
                interrupted = true;
        }
 
@@ -1033,11 +1037,11 @@ struct nfs4_opendata {
        struct nfs4_state *state;
        struct iattr attrs;
        unsigned long timestamp;
-       unsigned int rpc_done : 1;
-       unsigned int file_created : 1;
-       unsigned int is_recover : 1;
+       bool rpc_done;
+       bool file_created;
+       bool is_recover;
+       bool cancelled;
        int rpc_status;
-       int cancelled;
 };
 
 static bool nfs4_clear_cap_atomic_open_v1(struct nfs_server *server,
@@ -1961,7 +1965,7 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
                nfs4_stateid_copy(&data->o_res.stateid, &data->c_res.stateid);
                nfs_confirm_seqid(&data->owner->so_seqid, 0);
                renew_lease(data->o_res.server, data->timestamp);
-               data->rpc_done = 1;
+               data->rpc_done = true;
        }
 }
 
@@ -1971,7 +1975,7 @@ static void nfs4_open_confirm_release(void *calldata)
        struct nfs4_state *state = NULL;
 
        /* If this request hasn't been cancelled, do nothing */
-       if (data->cancelled == 0)
+       if (!data->cancelled)
                goto out_free;
        /* In case of error, no cleanup! */
        if (!data->rpc_done)
@@ -2014,7 +2018,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
 
        nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1);
        kref_get(&data->kref);
-       data->rpc_done = 0;
+       data->rpc_done = false;
        data->rpc_status = 0;
        data->timestamp = jiffies;
        if (data->is_recover)
@@ -2024,7 +2028,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
                return PTR_ERR(task);
        status = rpc_wait_for_completion_task(task);
        if (status != 0) {
-               data->cancelled = 1;
+               data->cancelled = true;
                smp_wmb();
        } else
                status = data->rpc_status;
@@ -2123,7 +2127,7 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
                if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM))
                        nfs_confirm_seqid(&data->owner->so_seqid, 0);
        }
-       data->rpc_done = 1;
+       data->rpc_done = true;
 }
 
 static void nfs4_open_release(void *calldata)
@@ -2132,7 +2136,7 @@ static void nfs4_open_release(void *calldata)
        struct nfs4_state *state = NULL;
 
        /* If this request hasn't been cancelled, do nothing */
-       if (data->cancelled == 0)
+       if (!data->cancelled)
                goto out_free;
        /* In case of error, no cleanup! */
        if (data->rpc_status != 0 || !data->rpc_done)
@@ -2178,20 +2182,20 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
 
        nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1);
        kref_get(&data->kref);
-       data->rpc_done = 0;
+       data->rpc_done = false;
        data->rpc_status = 0;
-       data->cancelled = 0;
-       data->is_recover = 0;
+       data->cancelled = false;
+       data->is_recover = false;
        if (isrecover) {
                nfs4_set_sequence_privileged(&o_arg->seq_args);
-               data->is_recover = 1;
+               data->is_recover = true;
        }
        task = rpc_run_task(&task_setup_data);
        if (IS_ERR(task))
                return PTR_ERR(task);
        status = rpc_wait_for_completion_task(task);
        if (status != 0) {
-               data->cancelled = 1;
+               data->cancelled = true;
                smp_wmb();
        } else
                status = data->rpc_status;
@@ -2232,7 +2236,7 @@ static int nfs4_opendata_access(struct rpc_cred *cred,
                                int openflags)
 {
        struct nfs_access_entry cache;
-       u32 mask;
+       u32 mask, flags;
 
        /* access call failed or for some reason the server doesn't
         * support any access modes -- defer access call until later */
@@ -2246,16 +2250,20 @@ static int nfs4_opendata_access(struct rpc_cred *cred,
         */
        if (openflags & __FMODE_EXEC) {
                /* ONLY check for exec rights */
-               mask = MAY_EXEC;
+               if (S_ISDIR(state->inode->i_mode))
+                       mask = NFS4_ACCESS_LOOKUP;
+               else
+                       mask = NFS4_ACCESS_EXECUTE;
        } else if ((fmode & FMODE_READ) && !opendata->file_created)
-               mask = MAY_READ;
+               mask = NFS4_ACCESS_READ;
 
        cache.cred = cred;
        cache.jiffies = jiffies;
        nfs_access_set_mask(&cache, opendata->o_res.access_result);
        nfs_access_add_cache(state->inode, &cache);
 
-       if ((mask & ~cache.mask & (MAY_READ | MAY_EXEC)) == 0)
+       flags = NFS4_ACCESS_READ | NFS4_ACCESS_EXECUTE | NFS4_ACCESS_LOOKUP;
+       if ((mask & ~cache.mask & flags) == 0)
                return 0;
 
        return -EACCES;
@@ -2286,9 +2294,9 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
 
        if (o_arg->open_flags & O_CREAT) {
                if (o_arg->open_flags & O_EXCL)
-                       data->file_created = 1;
+                       data->file_created = true;
                else if (o_res->cinfo.before != o_res->cinfo.after)
-                       data->file_created = 1;
+                       data->file_created = true;
                if (data->file_created || dir->i_version != o_res->cinfo.after)
                        update_changeattr(dir, &o_res->cinfo,
                                        o_res->f_attr->time_start);
@@ -2300,8 +2308,10 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
                if (status != 0)
                        return status;
        }
-       if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
+       if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) {
+               nfs4_sequence_free_slot(&o_res->seq_res);
                nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr, o_res->f_label);
+       }
        return 0;
 }
 
@@ -3265,6 +3275,7 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
                .rpc_resp = &res,
        };
        int status;
+       int i;
 
        bitmask[0] = FATTR4_WORD0_SUPPORTED_ATTRS |
                     FATTR4_WORD0_FH_EXPIRE_TYPE |
@@ -3330,8 +3341,13 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
                server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE;
                server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
                server->cache_consistency_bitmask[2] = 0;
+
+               /* Avoid a regression due to buggy server */
+               for (i = 0; i < ARRAY_SIZE(res.exclcreat_bitmask); i++)
+                       res.exclcreat_bitmask[i] &= res.attr_bitmask[i];
                memcpy(server->exclcreat_bitmask, res.exclcreat_bitmask,
                        sizeof(server->exclcreat_bitmask));
+
                server->acl_bitmask = res.acl_bitmask;
                server->fh_expire_type = res.fh_expire_type;
        }
@@ -3793,6 +3809,54 @@ nfs4_proc_lookup_mountpoint(struct inode *dir, const struct qstr *name,
        return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client;
 }
 
+static int _nfs4_proc_lookupp(struct inode *inode,
+               struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+               struct nfs4_label *label)
+{
+       struct rpc_clnt *clnt = NFS_CLIENT(inode);
+       struct nfs_server *server = NFS_SERVER(inode);
+       int                    status;
+       struct nfs4_lookupp_arg args = {
+               .bitmask = server->attr_bitmask,
+               .fh = NFS_FH(inode),
+       };
+       struct nfs4_lookupp_res res = {
+               .server = server,
+               .fattr = fattr,
+               .label = label,
+               .fh = fhandle,
+       };
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUPP],
+               .rpc_argp = &args,
+               .rpc_resp = &res,
+       };
+
+       args.bitmask = nfs4_bitmask(server, label);
+
+       nfs_fattr_init(fattr);
+
+       dprintk("NFS call  lookupp ino=0x%lx\n", inode->i_ino);
+       status = nfs4_call_sync(clnt, server, &msg, &args.seq_args,
+                               &res.seq_res, 0);
+       dprintk("NFS reply lookupp: %d\n", status);
+       return status;
+}
+
+static int nfs4_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle,
+                            struct nfs_fattr *fattr, struct nfs4_label *label)
+{
+       struct nfs4_exception exception = { };
+       int err;
+       do {
+               err = _nfs4_proc_lookupp(inode, fhandle, fattr, label);
+               trace_nfs4_lookupp(inode, err);
+               err = nfs4_handle_exception(NFS_SERVER(inode), err,
+                               &exception);
+       } while (exception.retry);
+       return err;
+}
+
 static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
 {
        struct nfs_server *server = NFS_SERVER(inode);
@@ -4263,7 +4327,7 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
 }
 
 static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-               u64 cookie, struct page **pages, unsigned int count, int plus)
+               u64 cookie, struct page **pages, unsigned int count, bool plus)
 {
        struct inode            *dir = d_inode(dentry);
        struct nfs4_readdir_arg args = {
@@ -4301,7 +4365,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 }
 
 static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-               u64 cookie, struct page **pages, unsigned int count, int plus)
+               u64 cookie, struct page **pages, unsigned int count, bool plus)
 {
        struct nfs4_exception exception = { };
        int err;
@@ -4610,7 +4674,7 @@ static int nfs4_proc_pgio_rpc_prepare(struct rpc_task *task,
                return 0;
        if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context,
                                hdr->args.lock_context,
-                               hdr->rw_ops->rw_mode) == -EIO)
+                               hdr->rw_mode) == -EIO)
                return -EIO;
        if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags)))
                return -EIO;
@@ -4804,8 +4868,10 @@ static int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred,
        if (!atomic_inc_not_zero(&clp->cl_count))
                return -EIO;
        data = kmalloc(sizeof(*data), GFP_NOFS);
-       if (data == NULL)
+       if (data == NULL) {
+               nfs_put_client(clp);
                return -ENOMEM;
+       }
        data->client = clp;
        data->timestamp = jiffies;
        return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT,
@@ -5782,6 +5848,7 @@ struct nfs4_unlockdata {
        struct nfs_locku_res res;
        struct nfs4_lock_state *lsp;
        struct nfs_open_context *ctx;
+       struct nfs_lock_context *l_ctx;
        struct file_lock fl;
        struct nfs_server *server;
        unsigned long timestamp;
@@ -5806,6 +5873,7 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
        atomic_inc(&lsp->ls_count);
        /* Ensure we don't close file until we're done freeing locks! */
        p->ctx = get_nfs_open_context(ctx);
+       p->l_ctx = nfs_get_lock_context(ctx);
        memcpy(&p->fl, fl, sizeof(p->fl));
        p->server = NFS_SERVER(inode);
        return p;
@@ -5816,6 +5884,7 @@ static void nfs4_locku_release_calldata(void *data)
        struct nfs4_unlockdata *calldata = data;
        nfs_free_seqid(calldata->arg.seqid);
        nfs4_put_lock_state(calldata->lsp);
+       nfs_put_lock_context(calldata->l_ctx);
        put_nfs_open_context(calldata->ctx);
        kfree(calldata);
 }
@@ -5857,6 +5926,10 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
 {
        struct nfs4_unlockdata *calldata = data;
 
+       if (test_bit(NFS_CONTEXT_UNLOCK, &calldata->l_ctx->open_context->flags) &&
+               nfs_async_iocounter_wait(task, calldata->l_ctx))
+               return;
+
        if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
                goto out_wait;
        nfs4_stateid_copy(&calldata->arg.stateid, &calldata->lsp->ls_stateid);
@@ -5908,6 +5981,8 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
         * canceled lock is passed in, and it won't be an unlock.
         */
        fl->fl_type = F_UNLCK;
+       if (fl->fl_flags & FL_CLOSE)
+               set_bit(NFS_CONTEXT_UNLOCK, &ctx->flags);
 
        data = nfs4_alloc_unlockdata(fl, ctx, lsp, seqid);
        if (data == NULL) {
@@ -6114,7 +6189,7 @@ static void nfs4_lock_release(void *calldata)
 
        dprintk("%s: begin!\n", __func__);
        nfs_free_seqid(data->arg.open_seqid);
-       if (data->cancelled != 0) {
+       if (data->cancelled) {
                struct rpc_task *task;
                task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,
                                data->arg.lock_seqid);
@@ -6197,7 +6272,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
                        nfs4_handle_setlk_error(data->server, data->lsp,
                                        data->arg.new_lock_owner, ret);
        } else
-               data->cancelled = 1;
+               data->cancelled = true;
        rpc_put_task(task);
        dprintk("%s: done, ret = %d!\n", __func__, ret);
        trace_nfs4_set_lock(fl, state, &data->res.stateid, cmd, ret);
@@ -6445,9 +6520,6 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
        ctx = nfs_file_open_context(filp);
        state = ctx->state;
 
-       if (request->fl_start < 0 || request->fl_end < 0)
-               return -EINVAL;
-
        if (IS_GETLK(cmd)) {
                if (state != NULL)
                        return nfs4_proc_getlk(state, F_GETLK, request);
@@ -6470,20 +6542,6 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
            !test_bit(NFS_STATE_POSIX_LOCKS, &state->flags))
                return -ENOLCK;
 
-       /*
-        * Don't rely on the VFS having checked the file open mode,
-        * since it won't do this for flock() locks.
-        */
-       switch (request->fl_type) {
-       case F_RDLCK:
-               if (!(filp->f_mode & FMODE_READ))
-                       return -EBADF;
-               break;
-       case F_WRLCK:
-               if (!(filp->f_mode & FMODE_WRITE))
-                       return -EBADF;
-       }
-
        status = nfs4_set_lock_state(state, request);
        if (status != 0)
                return status;
@@ -7155,8 +7213,6 @@ int nfs4_proc_bind_one_conn_to_session(struct rpc_clnt *clnt,
        };
        struct rpc_task *task;
 
-       dprintk("--> %s\n", __func__);
-
        nfs4_copy_sessionid(&args.sessionid, &clp->cl_session->sess_id);
        if (!(clp->cl_session->flags & SESSION4_BACK_CHAN))
                args.dir = NFS4_CDFC4_FORE;
@@ -7176,24 +7232,20 @@ int nfs4_proc_bind_one_conn_to_session(struct rpc_clnt *clnt,
                if (memcmp(res.sessionid.data,
                    clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) {
                        dprintk("NFS: %s: Session ID mismatch\n", __func__);
-                       status = -EIO;
-                       goto out;
+                       return -EIO;
                }
                if ((res.dir & args.dir) != res.dir || res.dir == 0) {
                        dprintk("NFS: %s: Unexpected direction from server\n",
                                __func__);
-                       status = -EIO;
-                       goto out;
+                       return -EIO;
                }
                if (res.use_conn_in_rdma_mode != args.use_conn_in_rdma_mode) {
                        dprintk("NFS: %s: Server returned RDMA mode = true\n",
                                __func__);
-                       status = -EIO;
-                       goto out;
+                       return -EIO;
                }
        }
-out:
-       dprintk("<-- %s status= %d\n", __func__, status);
+
        return status;
 }
 
@@ -7378,12 +7430,11 @@ static void nfs4_exchange_id_done(struct rpc_task *task, void *data)
        if (status == 0) {
                clp->cl_clientid = cdata->res.clientid;
                clp->cl_exchange_flags = cdata->res.flags;
+               clp->cl_seqid = cdata->res.seqid;
                /* Client ID is not confirmed */
-               if (!(cdata->res.flags & EXCHGID4_FLAG_CONFIRMED_R)) {
+               if (!(cdata->res.flags & EXCHGID4_FLAG_CONFIRMED_R))
                        clear_bit(NFS4_SESSION_ESTABLISHED,
-                       &clp->cl_session->session_state);
-                       clp->cl_seqid = cdata->res.seqid;
-               }
+                                 &clp->cl_session->session_state);
 
                kfree(clp->cl_serverowner);
                clp->cl_serverowner = cdata->res.server_owner;
@@ -7459,15 +7510,16 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
        };
        struct nfs41_exchange_id_data *calldata;
        struct rpc_task *task;
-       int status = -EIO;
+       int status;
 
        if (!atomic_inc_not_zero(&clp->cl_count))
-               goto out;
+               return -EIO;
 
-       status = -ENOMEM;
        calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
-       if (!calldata)
-               goto out;
+       if (!calldata) {
+               nfs_put_client(clp);
+               return -ENOMEM;
+       }
 
        if (!xprt)
                nfs4_init_boot_verifier(clp, &verifier);
@@ -7476,10 +7528,6 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
        if (status)
                goto out_calldata;
 
-       dprintk("NFS call  exchange_id auth=%s, '%s'\n",
-               clp->cl_rpcclient->cl_auth->au_ops->au_name,
-               clp->cl_owner_id);
-
        calldata->res.server_owner = kzalloc(sizeof(struct nfs41_server_owner),
                                                GFP_NOFS);
        status = -ENOMEM;
@@ -7545,13 +7593,6 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
 
        rpc_put_task(task);
 out:
-       if (clp->cl_implid != NULL)
-               dprintk("NFS reply exchange_id: Server Implementation ID: "
-                       "domain: %s, name: %s, date: %llu,%u\n",
-                       clp->cl_implid->domain, clp->cl_implid->name,
-                       clp->cl_implid->date.seconds,
-                       clp->cl_implid->date.nseconds);
-       dprintk("NFS reply exchange_id: %d\n", status);
        return status;
 
 out_impl_id:
@@ -7769,17 +7810,13 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
 
        nfs4_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0);
        nfs4_set_sequence_privileged(&args.la_seq_args);
-       dprintk("--> %s\n", __func__);
        task = rpc_run_task(&task_setup);
 
        if (IS_ERR(task))
-               status = PTR_ERR(task);
-       else {
-               status = task->tk_status;
-               rpc_put_task(task);
-       }
-       dprintk("<-- %s return %d\n", __func__, status);
+               return PTR_ERR(task);
 
+       status = task->tk_status;
+       rpc_put_task(task);
        return status;
 }
 
@@ -8180,6 +8217,12 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf
                /* fall through */
        case -NFS4ERR_RETRY_UNCACHED_REP:
                return -EAGAIN;
+       case -NFS4ERR_BADSESSION:
+       case -NFS4ERR_DEADSESSION:
+       case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+               nfs4_schedule_session_recovery(clp->cl_session,
+                               task->tk_status);
+               break;
        default:
                nfs4_schedule_lease_recovery(clp);
        }
@@ -8258,7 +8301,6 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp,
        if (status == 0)
                status = task->tk_status;
        rpc_put_task(task);
-       return 0;
 out:
        dprintk("<-- %s status=%d\n", __func__, status);
        return status;
@@ -8357,6 +8399,7 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
                 */
                pnfs_mark_layout_stateid_invalid(lo, &head);
                spin_unlock(&inode->i_lock);
+               nfs_commit_inode(inode, 0);
                pnfs_free_lseg_list(&head);
                status = -EAGAIN;
                goto out;
@@ -9323,6 +9366,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
        .getattr        = nfs4_proc_getattr,
        .setattr        = nfs4_proc_setattr,
        .lookup         = nfs4_proc_lookup,
+       .lookupp        = nfs4_proc_lookupp,
        .access         = nfs4_proc_access,
        .readlink       = nfs4_proc_readlink,
        .create         = nfs4_proc_create,