nfs41: pull nfs4_ds_connect from file layout to generic pnfs
authorPeng Tao <tao.peng@primarydata.com>
Thu, 29 May 2014 13:06:58 +0000 (21:06 +0800)
committerTom Haynes <loghyr@primarydata.com>
Tue, 3 Feb 2015 19:06:32 +0000 (11:06 -0800)
It can be reused by flexfiles layout client.

Reviewed-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: Peng Tao <tao.peng@primarydata.com>
Signed-off-by: Tom Haynes <Thomas.Haynes@primarydata.com>
fs/nfs/filelayout/filelayoutdev.c
fs/nfs/pnfs.h
fs/nfs/pnfs_nfs.c

index c7f6041a287fd79de055f1dbd6e7796e967b9a0a..27bdd8ce177e7136bdc874cda45245dd1a937ff7 100644 (file)
 static unsigned int dataserver_timeo = NFS4_DEF_DS_TIMEO;
 static unsigned int dataserver_retrans = NFS4_DEF_DS_RETRANS;
 
-/*
- * Create an rpc connection to the nfs4_pnfs_ds data server
- * Currently only supports IPv4 and IPv6 addresses
- */
-static int
-nfs4_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds)
-{
-       struct nfs_client *clp = ERR_PTR(-EIO);
-       struct nfs4_pnfs_ds_addr *da;
-       int status = 0;
-
-       dprintk("--> %s DS %s au_flavor %d\n", __func__, ds->ds_remotestr,
-               mds_srv->nfs_client->cl_rpcclient->cl_auth->au_flavor);
-
-       list_for_each_entry(da, &ds->ds_addrs, da_node) {
-               dprintk("%s: DS %s: trying address %s\n",
-                       __func__, ds->ds_remotestr, da->da_remotestr);
-
-               clp = nfs4_set_ds_client(mds_srv->nfs_client,
-                                       (struct sockaddr *)&da->da_addr,
-                                       da->da_addrlen, IPPROTO_TCP,
-                                       dataserver_timeo, dataserver_retrans);
-               if (!IS_ERR(clp))
-                       break;
-       }
-
-       if (IS_ERR(clp)) {
-               status = PTR_ERR(clp);
-               goto out;
-       }
-
-       status = nfs4_init_ds_session(clp, mds_srv->nfs_client->cl_lease_time);
-       if (status)
-               goto out_put;
-
-       smp_wmb();
-       ds->ds_clp = clp;
-       dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr);
-out:
-       return status;
-out_put:
-       nfs_put_client(clp);
-       goto out;
-}
-
 void
 nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
 {
@@ -302,22 +257,7 @@ nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j)
        return flseg->fh_array[i];
 }
 
-static void nfs4_wait_ds_connect(struct nfs4_pnfs_ds *ds)
-{
-       might_sleep();
-       wait_on_bit_action(&ds->ds_state, NFS4DS_CONNECTING,
-                          nfs_wait_bit_killable, TASK_KILLABLE);
-}
-
-static void nfs4_clear_ds_conn_bit(struct nfs4_pnfs_ds *ds)
-{
-       smp_mb__before_atomic();
-       clear_bit(NFS4DS_CONNECTING, &ds->ds_state);
-       smp_mb__after_atomic();
-       wake_up_bit(&ds->ds_state, NFS4DS_CONNECTING);
-}
-
-
+/* Upon return, either ds is connected, or ds is NULL */
 struct nfs4_pnfs_ds *
 nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
 {
@@ -325,6 +265,7 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
        struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx];
        struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
        struct nfs4_pnfs_ds *ret = ds;
+       struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode);
 
        if (ds == NULL) {
                printk(KERN_ERR "NFS: %s: No data server for offset index %d\n",
@@ -336,18 +277,9 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
        if (ds->ds_clp)
                goto out_test_devid;
 
-       if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) {
-               struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode);
-               int err;
-
-               err = nfs4_ds_connect(s, ds);
-               if (err)
-                       nfs4_mark_deviceid_unavailable(devid);
-               nfs4_clear_ds_conn_bit(ds);
-       } else {
-               /* Either ds is connected, or ds is NULL */
-               nfs4_wait_ds_connect(ds);
-       }
+       nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo,
+                            dataserver_retrans);
+
 out_test_devid:
        if (filelayout_test_devid_unavailable(devid))
                ret = NULL;
index 403d7bb67c4167722efeaa06c481714f9f8ca7c7..9a8937c31d973db44f3d468df8aaf8250753b283 100644 (file)
@@ -312,6 +312,9 @@ void pnfs_generic_write_commit_done(struct rpc_task *task, void *data);
 void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds);
 struct nfs4_pnfs_ds *nfs4_pnfs_ds_add(struct list_head *dsaddrs,
                                      gfp_t gfp_flags);
+void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
+                         struct nfs4_deviceid_node *devid, unsigned int timeo,
+                         unsigned int retrans);
 struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net,
                                                 struct xdr_stream *xdr,
                                                 gfp_t gfp_flags);
index 81ec449138a8a8d0e353ff6410798aca6b6ea3a2..5a92e76c6c53b1db99ea07e34441dc09a4465921 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/nfs_page.h>
 #include <linux/sunrpc/addr.h>
 
+#include "nfs4session.h"
 #include "internal.h"
 #include "pnfs.h"
 
@@ -534,6 +535,86 @@ out:
 }
 EXPORT_SYMBOL_GPL(nfs4_pnfs_ds_add);
 
+static void nfs4_wait_ds_connect(struct nfs4_pnfs_ds *ds)
+{
+       might_sleep();
+       wait_on_bit(&ds->ds_state, NFS4DS_CONNECTING,
+                       TASK_KILLABLE);
+}
+
+static void nfs4_clear_ds_conn_bit(struct nfs4_pnfs_ds *ds)
+{
+       smp_mb__before_atomic();
+       clear_bit(NFS4DS_CONNECTING, &ds->ds_state);
+       smp_mb__after_atomic();
+       wake_up_bit(&ds->ds_state, NFS4DS_CONNECTING);
+}
+
+static int _nfs4_pnfs_ds_connect(struct nfs_server *mds_srv,
+                                struct nfs4_pnfs_ds *ds,
+                                unsigned int timeo,
+                                unsigned int retrans)
+{
+       struct nfs_client *clp = ERR_PTR(-EIO);
+       struct nfs4_pnfs_ds_addr *da;
+       int status = 0;
+
+       dprintk("--> %s DS %s au_flavor %d\n", __func__, ds->ds_remotestr,
+               mds_srv->nfs_client->cl_rpcclient->cl_auth->au_flavor);
+
+       list_for_each_entry(da, &ds->ds_addrs, da_node) {
+               dprintk("%s: DS %s: trying address %s\n",
+                       __func__, ds->ds_remotestr, da->da_remotestr);
+
+               clp = nfs4_set_ds_client(mds_srv->nfs_client,
+                                       (struct sockaddr *)&da->da_addr,
+                                       da->da_addrlen, IPPROTO_TCP,
+                                       timeo, retrans);
+               if (!IS_ERR(clp))
+                       break;
+       }
+
+       if (IS_ERR(clp)) {
+               status = PTR_ERR(clp);
+               goto out;
+       }
+
+       status = nfs4_init_ds_session(clp, mds_srv->nfs_client->cl_lease_time);
+       if (status)
+               goto out_put;
+
+       smp_wmb();
+       ds->ds_clp = clp;
+       dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr);
+out:
+       return status;
+out_put:
+       nfs_put_client(clp);
+       goto out;
+}
+
+/*
+ * Create an rpc connection to the nfs4_pnfs_ds data server.
+ * Currently only supports IPv4 and IPv6 addresses.
+ * If connection fails, make devid unavailable.
+ */
+void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
+                         struct nfs4_deviceid_node *devid, unsigned int timeo,
+                         unsigned int retrans)
+{
+       if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) {
+               int err = 0;
+
+               err = _nfs4_pnfs_ds_connect(mds_srv, ds, timeo, retrans);
+               if (err)
+                       nfs4_mark_deviceid_unavailable(devid);
+               nfs4_clear_ds_conn_bit(ds);
+       } else {
+               nfs4_wait_ds_connect(ds);
+       }
+}
+EXPORT_SYMBOL_GPL(nfs4_pnfs_ds_connect);
+
 /*
  * Currently only supports ipv4, ipv6 and one multi-path address.
  */