]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/nfs/nfs4proc.c
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux.git] / fs / nfs / nfs4proc.c
index 22175b85b586554bb9d3a75baa87e24b88480f04..69b7ab7a58157f4d7b3e7787d4d2b1dc9750ff7d 100644 (file)
@@ -2974,10 +2974,13 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
        struct dentry *dentry;
        struct nfs4_state *state;
        fmode_t acc_mode = _nfs4_ctx_to_accessmode(ctx);
+       struct inode *dir = d_inode(opendata->dir);
+       unsigned long dir_verifier;
        unsigned int seq;
        int ret;
 
        seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
+       dir_verifier = nfs_save_change_attribute(dir);
 
        ret = _nfs4_proc_open(opendata, ctx);
        if (ret != 0)
@@ -3005,8 +3008,19 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
                        dput(ctx->dentry);
                        ctx->dentry = dentry = alias;
                }
-               nfs_set_verifier(dentry,
-                               nfs_save_change_attribute(d_inode(opendata->dir)));
+       }
+
+       switch(opendata->o_arg.claim) {
+       default:
+               break;
+       case NFS4_OPEN_CLAIM_NULL:
+       case NFS4_OPEN_CLAIM_DELEGATE_CUR:
+       case NFS4_OPEN_CLAIM_DELEGATE_PREV:
+               if (!opendata->rpc_done)
+                       break;
+               if (opendata->o_res.delegation_type != 0)
+                       dir_verifier = nfs_save_change_attribute(dir);
+               nfs_set_verifier(dentry, dir_verifier);
        }
 
        /* Parse layoutget results before we check for access */
@@ -3199,6 +3213,11 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir,
                        exception.retry = 1;
                        continue;
                }
+               if (status == -NFS4ERR_EXPIRED) {
+                       nfs4_schedule_lease_recovery(server->nfs_client);
+                       exception.retry = 1;
+                       continue;
+               }
                if (status == -EAGAIN) {
                        /* We must have found a delegation */
                        exception.retry = 1;
@@ -3251,6 +3270,8 @@ static int _nfs4_do_setattr(struct inode *inode,
                nfs_put_lock_context(l_ctx);
                if (status == -EIO)
                        return -EBADF;
+               else if (status == -EAGAIN)
+                       goto zero_stateid;
        } else {
 zero_stateid:
                nfs4_stateid_copy(&arg->stateid, &zero_stateid);
@@ -4175,7 +4196,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 }
 
 static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir,
-               const struct qstr *name, struct nfs_fh *fhandle,
+               struct dentry *dentry, struct nfs_fh *fhandle,
                struct nfs_fattr *fattr, struct nfs4_label *label)
 {
        struct nfs_server *server = NFS_SERVER(dir);
@@ -4183,7 +4204,7 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir,
        struct nfs4_lookup_arg args = {
                .bitmask = server->attr_bitmask,
                .dir_fh = NFS_FH(dir),
-               .name = name,
+               .name = &dentry->d_name,
        };
        struct nfs4_lookup_res res = {
                .server = server,
@@ -4196,13 +4217,20 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir,
                .rpc_argp = &args,
                .rpc_resp = &res,
        };
+       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;
 
        args.bitmask = nfs4_bitmask(server, label);
 
        nfs_fattr_init(fattr);
 
-       dprintk("NFS call  lookup %s\n", name->name);
-       status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, &res.seq_res, 0);
+       dprintk("NFS call  lookup %pd2\n", dentry);
+       nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 0);
+       status = nfs4_do_call_sync(clnt, server, &msg,
+                       &args.seq_args, &res.seq_res, task_flags);
        dprintk("NFS reply lookup: %d\n", status);
        return status;
 }
@@ -4216,16 +4244,17 @@ static void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr)
 }
 
 static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir,
-                                  const struct qstr *name, struct nfs_fh *fhandle,
+                                  struct dentry *dentry, struct nfs_fh *fhandle,
                                   struct nfs_fattr *fattr, struct nfs4_label *label)
 {
        struct nfs4_exception exception = {
                .interruptible = true,
        };
        struct rpc_clnt *client = *clnt;
+       const struct qstr *name = &dentry->d_name;
        int err;
        do {
-               err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr, label);
+               err = _nfs4_proc_lookup(client, dir, dentry, fhandle, fattr, label);
                trace_nfs4_lookup(dir, name, err);
                switch (err) {
                case -NFS4ERR_BADNAME:
@@ -4260,14 +4289,14 @@ static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir,
        return err;
 }
 
-static int nfs4_proc_lookup(struct inode *dir, const struct qstr *name,
+static int nfs4_proc_lookup(struct inode *dir, struct dentry *dentry,
                            struct nfs_fh *fhandle, struct nfs_fattr *fattr,
                            struct nfs4_label *label)
 {
        int status;
        struct rpc_clnt *client = NFS_CLIENT(dir);
 
-       status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, label);
+       status = nfs4_proc_lookup_common(&client, dir, dentry, fhandle, fattr, label);
        if (client != NFS_CLIENT(dir)) {
                rpc_shutdown_client(client);
                nfs_fixup_secinfo_attributes(fattr);
@@ -4276,13 +4305,13 @@ static int nfs4_proc_lookup(struct inode *dir, const struct qstr *name,
 }
 
 struct rpc_clnt *
-nfs4_proc_lookup_mountpoint(struct inode *dir, const struct qstr *name,
+nfs4_proc_lookup_mountpoint(struct inode *dir, struct dentry *dentry,
                            struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
        struct rpc_clnt *client = NFS_CLIENT(dir);
        int status;
 
-       status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr, NULL);
+       status = nfs4_proc_lookup_common(&client, dir, dentry, fhandle, fattr, NULL);
        if (status < 0)
                return ERR_PTR(status);
        return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client;
@@ -5038,16 +5067,13 @@ static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, str
        struct nfs4_exception exception = {
                .interruptible = true,
        };
-       unsigned long now = jiffies;
        int err;
 
        do {
                err = _nfs4_do_fsinfo(server, fhandle, fsinfo);
                trace_nfs4_fsinfo(server, fhandle, fsinfo->fattr, err);
                if (err == 0) {
-                       nfs4_set_lease_period(server->nfs_client,
-                                       fsinfo->lease_time * HZ,
-                                       now);
+                       nfs4_set_lease_period(server->nfs_client, fsinfo->lease_time * HZ);
                        break;
                }
                err = nfs4_handle_exception(server, err, &exception);
@@ -5310,7 +5336,7 @@ static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
        hdr->timestamp   = jiffies;
 
        msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE];
-       nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 1, 0);
+       nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 0, 0);
        nfs4_state_protect_write(server->nfs_client, clnt, msg, hdr);
 }
 
@@ -6111,6 +6137,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
                .callback_data = &setclientid,
                .flags = RPC_TASK_TIMEOUT | RPC_TASK_NO_ROUND_ROBIN,
        };
+       unsigned long now = jiffies;
        int status;
 
        /* nfs_client_id4 */
@@ -6143,6 +6170,9 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
                clp->cl_acceptor = rpcauth_stringify_acceptor(setclientid.sc_cred);
                put_rpccred(setclientid.sc_cred);
        }
+
+       if (status == 0)
+               do_renew_lease(clp, now);
 out:
        trace_nfs4_setclientid(clp, status);
        dprintk("NFS reply setclientid: %d\n", status);
@@ -8230,6 +8260,7 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, const struct cred *cre
        struct rpc_task *task;
        struct nfs41_exchange_id_args *argp;
        struct nfs41_exchange_id_res *resp;
+       unsigned long now = jiffies;
        int status;
 
        task = nfs4_run_exchange_id(clp, cred, sp4_how, NULL);
@@ -8250,6 +8281,8 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, const struct cred *cre
        if (status != 0)
                goto out;
 
+       do_renew_lease(clp, now);
+
        clp->cl_clientid = resp->clientid;
        clp->cl_exchange_flags = resp->flags;
        clp->cl_seqid = resp->seqid;