Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
[pandora-kernel.git] / fs / nfs / nfs4proc.c
index dfd1e6d..69c0f3c 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
+#include <linux/nfs_mount.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/module.h>
@@ -443,8 +444,8 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
        if (res->sr_status == 1)
                res->sr_status = NFS_OK;
 
-       /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */
-       if (!res->sr_slot)
+       /* don't increment the sequence number if the task wasn't sent */
+       if (!RPC_WAS_SENT(task))
                goto out;
 
        /* Check the SEQUENCE operation status */
@@ -2185,9 +2186,14 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
        struct nfs4_exception exception = { };
        int err;
        do {
-               err = nfs4_handle_exception(server,
-                               _nfs4_lookup_root(server, fhandle, info),
-                               &exception);
+               err = _nfs4_lookup_root(server, fhandle, info);
+               switch (err) {
+               case 0:
+               case -NFS4ERR_WRONGSEC:
+                       break;
+               default:
+                       err = nfs4_handle_exception(server, err, &exception);
+               }
        } while (exception.retry);
        return err;
 }
@@ -2204,31 +2210,51 @@ static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandl
                goto out;
        }
        ret = nfs4_lookup_root(server, fhandle, info);
-       if (ret < 0)
-               ret = -EAGAIN;
 out:
        return ret;
 }
 
-/*
- * get the file handle for the "/" directory on the server
- */
-static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
+static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
                              struct nfs_fsinfo *info)
 {
        int i, len, status = 0;
-       rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS + 2];
+       rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS];
 
-       flav_array[0] = RPC_AUTH_UNIX;
-       len = gss_mech_list_pseudoflavors(&flav_array[1]);
-       flav_array[1+len] = RPC_AUTH_NULL;
-       len += 2;
+       len = gss_mech_list_pseudoflavors(&flav_array[0]);
+       flav_array[len] = RPC_AUTH_NULL;
+       len += 1;
 
        for (i = 0; i < len; i++) {
                status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]);
-               if (status == 0)
-                       break;
+               if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
+                       continue;
+               break;
        }
+       /*
+        * -EACCESS could mean that the user doesn't have correct permissions
+        * to access the mount.  It could also mean that we tried to mount
+        * with a gss auth flavor, but rpc.gssd isn't running.  Either way,
+        * existing mount programs don't handle -EACCES very well so it should
+        * be mapped to -EPERM instead.
+        */
+       if (status == -EACCES)
+               status = -EPERM;
+       return status;
+}
+
+/*
+ * get the file handle for the "/" directory on the server
+ */
+static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
+                             struct nfs_fsinfo *info)
+{
+       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 = nfs4_find_root_sec(server, fhandle, info);
        if (status == 0)
                status = nfs4_server_capabilities(server, fhandle);
        if (status == 0)
@@ -3725,21 +3751,20 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
                                sizeof(setclientid.sc_uaddr), "%s.%u.%u",
                                clp->cl_ipaddr, port >> 8, port & 255);
 
-               status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+               status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
                if (status != -NFS4ERR_CLID_INUSE)
                        break;
-               if (signalled())
+               if (loop != 0) {
+                       ++clp->cl_id_uniquifier;
                        break;
-               if (loop++ & 1)
-                       ssleep(clp->cl_lease_time / HZ + 1);
-               else
-                       if (++clp->cl_id_uniquifier == 0)
-                               break;
+               }
+               ++loop;
+               ssleep(clp->cl_lease_time / HZ + 1);
        }
        return status;
 }
 
-static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
+int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
                struct nfs4_setclientid_res *arg,
                struct rpc_cred *cred)
 {
@@ -3754,7 +3779,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
        int status;
 
        now = jiffies;
-       status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+       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;
@@ -3764,26 +3789,6 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
        return status;
 }
 
-int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
-               struct nfs4_setclientid_res *arg,
-               struct rpc_cred *cred)
-{
-       long timeout = 0;
-       int err;
-       do {
-               err = _nfs4_proc_setclientid_confirm(clp, arg, cred);
-               switch (err) {
-                       case 0:
-                               return err;
-                       case -NFS4ERR_RESOURCE:
-                               /* The IBM lawyers misread another document! */
-                       case -NFS4ERR_DELAY:
-                               err = nfs4_delay(clp->cl_rpcclient, &timeout);
-               }
-       } while (err == 0);
-       return err;
-}
-
 struct nfs4_delegreturndata {
        struct nfs4_delegreturnargs args;
        struct nfs4_delegreturnres res;
@@ -4788,7 +4793,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
                                init_utsname()->domainname,
                                clp->cl_rpcclient->cl_auth->au_flavor);
 
-       status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+       status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
        if (!status)
                status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags);
        dprintk("<-- %s status= %d\n", __func__, status);
@@ -4871,7 +4876,8 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
                .rpc_client = clp->cl_rpcclient,
                .rpc_message = &msg,
                .callback_ops = &nfs4_get_lease_time_ops,
-               .callback_data = &data
+               .callback_data = &data,
+               .flags = RPC_TASK_TIMEOUT,
        };
        int status;
 
@@ -5173,7 +5179,7 @@ static int _nfs4_proc_create_session(struct nfs_client *clp)
        nfs4_init_channel_attrs(&args);
        args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN);
 
-       status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0);
+       status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
 
        if (!status)
                /* Verify the session's negotiated channel_attrs values */
@@ -5196,20 +5202,10 @@ int nfs4_proc_create_session(struct nfs_client *clp)
        int status;
        unsigned *ptr;
        struct nfs4_session *session = clp->cl_session;
-       long timeout = 0;
-       int err;
 
        dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);
 
-       do {
-               status = _nfs4_proc_create_session(clp);
-               if (status == -NFS4ERR_DELAY) {
-                       err = nfs4_delay(clp->cl_rpcclient, &timeout);
-                       if (err)
-                               status = err;
-               }
-       } while (status == -NFS4ERR_DELAY);
-
+       status = _nfs4_proc_create_session(clp);
        if (status)
                goto out;
 
@@ -5250,7 +5246,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session)
        msg.rpc_argp = session;
        msg.rpc_resp = NULL;
        msg.rpc_cred = NULL;
-       status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0);
+       status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
 
        if (status)
                printk(KERN_WARNING