]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/nfs/nfs4namespace.c
Merge /home/v4l/v4l/for_upstream
[karo-tx-linux.git] / fs / nfs / nfs4namespace.c
index a7f3dedc4ec7bade9df84ed6f0fc7524507b9c21..79fbb61ce202bcb90df2c8ad0f7f3ecf3bba7aac 100644 (file)
@@ -132,6 +132,35 @@ static size_t nfs_parse_server_name(char *string, size_t len,
        return ret;
 }
 
+rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
+{
+       struct gss_api_mech *mech;
+       struct xdr_netobj oid;
+       int i;
+       rpc_authflavor_t pseudoflavor = RPC_AUTH_UNIX;
+
+       for (i = 0; i < flavors->num_flavors; i++) {
+               struct nfs4_secinfo_flavor *flavor;
+               flavor = &flavors->flavors[i];
+
+               if (flavor->flavor == RPC_AUTH_NULL || flavor->flavor == RPC_AUTH_UNIX) {
+                       pseudoflavor = flavor->flavor;
+                       break;
+               } else if (flavor->flavor == RPC_AUTH_GSS) {
+                       oid.len  = flavor->gss.sec_oid4.len;
+                       oid.data = flavor->gss.sec_oid4.data;
+                       mech = gss_mech_get_by_OID(&oid);
+                       if (!mech)
+                               continue;
+                       pseudoflavor = gss_svc_to_pseudoflavor(mech, flavor->gss.service);
+                       gss_mech_put(mech);
+                       break;
+               }
+       }
+
+       return pseudoflavor;
+}
+
 static rpc_authflavor_t nfs4_negotiate_security(struct inode *inode, struct qstr *name)
 {
        struct page *page;
@@ -163,25 +192,13 @@ out:
 struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *clnt, struct inode *inode,
                                        struct qstr *name)
 {
-       struct rpc_clnt *clone;
-       struct rpc_auth *auth;
        rpc_authflavor_t flavor;
 
        flavor = nfs4_negotiate_security(inode, name);
-       if (flavor < 0)
-               return ERR_PTR(flavor);
-
-       clone = rpc_clone_client(clnt);
-       if (IS_ERR(clone))
-               return clone;
+       if ((int)flavor < 0)
+               return ERR_PTR((int)flavor);
 
-       auth = rpcauth_create(flavor, clone);
-       if (!auth) {
-               rpc_shutdown_client(clone);
-               clone = ERR_PTR(-EIO);
-       }
-
-       return clone;
+       return rpc_clone_client_set_auth(clnt, flavor);
 }
 
 static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
@@ -300,7 +317,7 @@ out:
  * @dentry - dentry of referral
  *
  */
-struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry)
+static struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry)
 {
        struct vfsmount *mnt = ERR_PTR(-ENOMEM);
        struct dentry *parent;
@@ -341,3 +358,25 @@ out:
        dprintk("%s: done\n", __func__);
        return mnt;
 }
+
+struct vfsmount *nfs4_submount(struct nfs_server *server, struct dentry *dentry,
+                              struct nfs_fh *fh, struct nfs_fattr *fattr)
+{
+       struct dentry *parent = dget_parent(dentry);
+       struct rpc_clnt *client;
+       struct vfsmount *mnt;
+
+       /* Look it up again to get its attributes and sec flavor */
+       client = nfs4_proc_lookup_mountpoint(parent->d_inode, &dentry->d_name, fh, fattr);
+       dput(parent);
+       if (IS_ERR(client))
+               return ERR_CAST(client);
+
+       if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
+               mnt = nfs_do_refmount(client, dentry);
+       else
+               mnt = nfs_do_submount(dentry, fh, fattr, client->cl_auth->au_flavor);
+
+       rpc_shutdown_client(client);
+       return mnt;
+}