]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - fs/nfs/flexfilelayout/flexfilelayoutdev.c
flexfiles: add kerneldoc header to nfs4_ff_layout_prepare_ds
[mirror_ubuntu-artful-kernel.git] / fs / nfs / flexfilelayout / flexfilelayoutdev.c
index add0e5a70bd60f70479452ddc8a0ccf853c2c87f..35d84d0c0f21a8232a22741d6185b8b3c1730aa7 100644 (file)
@@ -228,7 +228,8 @@ ff_ds_error_match(const struct nfs4_ff_layout_ds_err *e1,
                return e1->opnum < e2->opnum ? -1 : 1;
        if (e1->status != e2->status)
                return e1->status < e2->status ? -1 : 1;
-       ret = memcmp(&e1->stateid, &e2->stateid, sizeof(e1->stateid));
+       ret = memcmp(e1->stateid.data, e2->stateid.data,
+                       sizeof(e1->stateid.data));
        if (ret != 0)
                return ret;
        ret = memcmp(&e1->deviceid, &e2->deviceid, sizeof(e1->deviceid));
@@ -302,40 +303,26 @@ int ff_layout_track_ds_error(struct nfs4_flexfile_layout *flo,
        return 0;
 }
 
-/* currently we only support AUTH_NONE and AUTH_SYS */
-static rpc_authflavor_t
-nfs4_ff_layout_choose_authflavor(struct nfs4_ff_layout_mirror *mirror)
+static struct rpc_cred *
+ff_layout_get_mirror_cred(struct nfs4_ff_layout_mirror *mirror, u32 iomode)
 {
-       if (mirror->uid == (u32)-1)
-               return RPC_AUTH_NULL;
-       return RPC_AUTH_UNIX;
-}
+       struct rpc_cred *cred, __rcu **pcred;
 
-/* fetch cred for NFSv3 DS */
-static int ff_layout_update_mirror_cred(struct nfs4_ff_layout_mirror *mirror,
-                                     struct nfs4_pnfs_ds *ds)
-{
-       if (ds->ds_clp && !mirror->cred &&
-           mirror->mirror_ds->ds_versions[0].version == 3) {
-               struct rpc_auth *auth = ds->ds_clp->cl_rpcclient->cl_auth;
-               struct rpc_cred *cred;
-               struct auth_cred acred = {
-                       .uid = make_kuid(&init_user_ns, mirror->uid),
-                       .gid = make_kgid(&init_user_ns, mirror->gid),
-               };
-
-               /* AUTH_NULL ignores acred */
-               cred = auth->au_ops->lookup_cred(auth, &acred, 0);
-               if (IS_ERR(cred)) {
-                       dprintk("%s: lookup_cred failed with %ld\n",
-                               __func__, PTR_ERR(cred));
-                       return PTR_ERR(cred);
-               } else {
-                       if (cmpxchg(&mirror->cred, NULL, cred))
-                               put_rpccred(cred);
-               }
-       }
-       return 0;
+       if (iomode == IOMODE_READ)
+               pcred = &mirror->ro_cred;
+       else
+               pcred = &mirror->rw_cred;
+
+       rcu_read_lock();
+       do {
+               cred = rcu_dereference(*pcred);
+               if (!cred)
+                       break;
+
+               cred = get_rpccred_rcu(cred);
+       } while(!cred);
+       rcu_read_unlock();
+       return cred;
 }
 
 struct nfs_fh *
@@ -356,7 +343,23 @@ out:
        return fh;
 }
 
-/* Upon return, either ds is connected, or ds is NULL */
+/**
+ * nfs4_ff_layout_prepare_ds - prepare a DS connection for an RPC call
+ * @lseg: the layout segment we're operating on
+ * @ds_idx: index of the DS to use
+ * @fail_return: return layout on connect failure?
+ *
+ * Try to prepare a DS connection to accept an RPC call. This involves
+ * selecting a mirror to use and connecting the client to it if it's not
+ * already connected.
+ *
+ * Since we only need a single functioning mirror to satisfy a read, we don't
+ * want to return the layout if there is one. For writes though, any down
+ * mirror should result in a LAYOUTRETURN. @fail_return is how we distinguish
+ * between the two cases.
+ *
+ * Returns a pointer to a connected DS object on success or NULL on failure.
+ */
 struct nfs4_pnfs_ds *
 nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
                          bool fail_return)
@@ -367,7 +370,6 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
        struct inode *ino = lseg->pls_layout->plh_inode;
        struct nfs_server *s = NFS_SERVER(ino);
        unsigned int max_payload;
-       rpc_authflavor_t flavor;
 
        if (!ff_layout_mirror_valid(lseg, mirror)) {
                pr_err_ratelimited("NFS: %s: No data server for offset index %d\n",
@@ -383,9 +385,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
        /* matching smp_wmb() in _nfs4_pnfs_v3/4_ds_connect */
        smp_rmb();
        if (ds->ds_clp)
-               goto out_update_creds;
-
-       flavor = nfs4_ff_layout_choose_authflavor(mirror);
+               goto out;
 
        /* FIXME: For now we assume the server sent only one version of NFS
         * to use for the DS.
@@ -394,7 +394,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
                             dataserver_retrans,
                             mirror->mirror_ds->ds_versions[0].version,
                             mirror->mirror_ds->ds_versions[0].minor_version,
-                            flavor);
+                            RPC_AUTH_UNIX);
 
        /* connect success, check rsize/wsize limit */
        if (ds->ds_clp) {
@@ -410,20 +410,10 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
                                         mirror, lseg->pls_range.offset,
                                         lseg->pls_range.length, NFS4ERR_NXIO,
                                         OP_ILLEGAL, GFP_NOIO);
-               if (!fail_return) {
-                       if (ff_layout_has_available_ds(lseg))
-                               set_bit(NFS_LAYOUT_RETURN_REQUESTED,
-                                       &lseg->pls_layout->plh_flags);
-                       else
-                               pnfs_error_mark_layout_for_return(ino, lseg);
-               } else
+               if (fail_return || !ff_layout_has_available_ds(lseg))
                        pnfs_error_mark_layout_for_return(ino, lseg);
                ds = NULL;
-               goto out;
        }
-out_update_creds:
-       if (ff_layout_update_mirror_cred(mirror, ds))
-               ds = NULL;
 out:
        return ds;
 }
@@ -433,16 +423,15 @@ ff_layout_get_ds_cred(struct pnfs_layout_segment *lseg, u32 ds_idx,
                      struct rpc_cred *mdscred)
 {
        struct nfs4_ff_layout_mirror *mirror = FF_LAYOUT_COMP(lseg, ds_idx);
-       struct rpc_cred *cred = ERR_PTR(-EINVAL);
-
-       if (!nfs4_ff_layout_prepare_ds(lseg, ds_idx, true))
-               goto out;
+       struct rpc_cred *cred;
 
-       if (mirror && mirror->cred)
-               cred = mirror->cred;
-       else
-               cred = mdscred;
-out:
+       if (mirror) {
+               cred = ff_layout_get_mirror_cred(mirror, lseg->pls_range.iomode);
+               if (!cred)
+                       cred = get_rpccred(mdscred);
+       } else {
+               cred = get_rpccred(mdscred);
+       }
        return cred;
 }
 
@@ -562,6 +551,12 @@ bool ff_layout_has_available_ds(struct pnfs_layout_segment *lseg)
        return ff_rw_layout_has_available_ds(lseg);
 }
 
+bool ff_layout_avoid_mds_available_ds(struct pnfs_layout_segment *lseg)
+{
+       return ff_layout_no_fallback_to_mds(lseg) ||
+              ff_layout_has_available_ds(lseg);
+}
+
 module_param(dataserver_retrans, uint, 0644);
 MODULE_PARM_DESC(dataserver_retrans, "The  number of times the NFSv4.1 client "
                        "retries a request before it attempts further "