NFS: Avoid PUTROOTFH when managing leases
[deliverable/linux.git] / fs / nfs / nfs4proc.c
index 81343944e09671897d32f3c244782cc9551371c4..510a7dd84c464d6248df3f05cb6f3a2db6a6fcbd 100644 (file)
@@ -2506,7 +2506,7 @@ static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandl
 
        auth = rpcauth_create(flavor, server->client);
        if (IS_ERR(auth)) {
-               ret = -EIO;
+               ret = -EACCES;
                goto out;
        }
        ret = nfs4_lookup_root(server, fhandle, info);
@@ -2547,24 +2547,36 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
        return status;
 }
 
-/*
- * get the file handle for the "/" directory on the server
+static int nfs4_do_find_root_sec(struct nfs_server *server,
+               struct nfs_fh *fhandle, struct nfs_fsinfo *info)
+{
+       int mv = server->nfs_client->cl_minorversion;
+       return nfs_v4_minor_ops[mv]->find_root_sec(server, fhandle, info);
+}
+
+/**
+ * nfs4_proc_get_rootfh - get file handle for server's pseudoroot
+ * @server: initialized nfs_server handle
+ * @fhandle: we fill in the pseudo-fs root file handle
+ * @info: we fill in an FSINFO struct
+ *
+ * Returns zero on success, or a negative errno.
  */
 int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle,
                         struct nfs_fsinfo *info)
 {
-       int minor_version = server->nfs_client->cl_minorversion;
-       int status = nfs4_lookup_root(server, fhandle, info);
-       if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR))
-               /*
-                * A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM
-                * by nfs4_map_errors() as this function exits.
-                */
-               status = nfs_v4_minor_ops[minor_version]->find_root_sec(server, fhandle, info);
+       int status;
+
+       status = nfs4_lookup_root(server, fhandle, info);
+       if ((status == -NFS4ERR_WRONGSEC) &&
+           !(server->flags & NFS_MOUNT_SECFLAVOUR))
+               status = nfs4_do_find_root_sec(server, fhandle, info);
+
        if (status == 0)
                status = nfs4_server_capabilities(server, fhandle);
        if (status == 0)
                status = nfs4_do_fsinfo(server, fhandle, info);
+
        return nfs4_map_errors(status);
 }
 
@@ -3443,12 +3455,21 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
 static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
 {
        struct nfs4_exception exception = { };
+       unsigned long now = jiffies;
        int err;
 
        do {
-               err = nfs4_handle_exception(server,
-                               _nfs4_do_fsinfo(server, fhandle, fsinfo),
-                               &exception);
+               err = _nfs4_do_fsinfo(server, fhandle, fsinfo);
+               if (err == 0) {
+                       struct nfs_client *clp = server->nfs_client;
+
+                       spin_lock(&clp->cl_lock);
+                       clp->cl_lease_time = fsinfo->lease_time * HZ;
+                       clp->cl_last_renewal = now;
+                       spin_unlock(&clp->cl_lock);
+                       break;
+               }
+               err = nfs4_handle_exception(server, err, &exception);
        } while (exception.retry);
        return err;
 }
@@ -4289,27 +4310,17 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
                struct nfs4_setclientid_res *arg,
                struct rpc_cred *cred)
 {
-       struct nfs_fsinfo fsinfo;
        struct rpc_message msg = {
                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID_CONFIRM],
                .rpc_argp = arg,
-               .rpc_resp = &fsinfo,
                .rpc_cred = cred,
        };
-       unsigned long now;
        int status;
 
        dprintk("NFS call  setclientid_confirm auth=%s, (client ID %llx)\n",
                clp->cl_rpcclient->cl_auth->au_ops->au_name,
                clp->cl_clientid);
-       now = jiffies;
        status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
-       if (status == 0) {
-               spin_lock(&clp->cl_lock);
-               clp->cl_lease_time = fsinfo.lease_time * HZ;
-               clp->cl_last_renewal = now;
-               spin_unlock(&clp->cl_lock);
-       }
        dprintk("NFS reply setclientid_confirm: %d\n", status);
        return status;
 }
This page took 0.057844 seconds and 5 git commands to generate.