Commit 7405f9e1 authored by Peng Tao's avatar Peng Tao Committed by Tom Haynes

nfs41: pull nfs4_ds_connect from file layout to generic pnfs

It can be reused by flexfiles layout client.
Reviewed-by: default avatarJeff Layton <jlayton@primarydata.com>
Signed-off-by: default avatarPeng Tao <tao.peng@primarydata.com>
Signed-off-by: default avatarTom Haynes <Thomas.Haynes@primarydata.com>
parent 6b7f3cf9
...@@ -41,51 +41,6 @@ ...@@ -41,51 +41,6 @@
static unsigned int dataserver_timeo = NFS4_DEF_DS_TIMEO; static unsigned int dataserver_timeo = NFS4_DEF_DS_TIMEO;
static unsigned int dataserver_retrans = NFS4_DEF_DS_RETRANS; 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 void
nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) 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) ...@@ -302,22 +257,7 @@ nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j)
return flseg->fh_array[i]; return flseg->fh_array[i];
} }
static void nfs4_wait_ds_connect(struct nfs4_pnfs_ds *ds) /* Upon return, either ds is connected, or ds is NULL */
{
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);
}
struct nfs4_pnfs_ds * struct nfs4_pnfs_ds *
nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx) 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) ...@@ -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_pnfs_ds *ds = dsaddr->ds_list[ds_idx];
struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
struct nfs4_pnfs_ds *ret = ds; struct nfs4_pnfs_ds *ret = ds;
struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode);
if (ds == NULL) { if (ds == NULL) {
printk(KERN_ERR "NFS: %s: No data server for offset index %d\n", 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) ...@@ -336,18 +277,9 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
if (ds->ds_clp) if (ds->ds_clp)
goto out_test_devid; goto out_test_devid;
if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) { nfs4_pnfs_ds_connect(s, ds, devid, dataserver_timeo,
struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode); dataserver_retrans);
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);
}
out_test_devid: out_test_devid:
if (filelayout_test_devid_unavailable(devid)) if (filelayout_test_devid_unavailable(devid))
ret = NULL; ret = NULL;
......
...@@ -312,6 +312,9 @@ void pnfs_generic_write_commit_done(struct rpc_task *task, void *data); ...@@ -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); void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds);
struct nfs4_pnfs_ds *nfs4_pnfs_ds_add(struct list_head *dsaddrs, struct nfs4_pnfs_ds *nfs4_pnfs_ds_add(struct list_head *dsaddrs,
gfp_t gfp_flags); 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 nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net,
struct xdr_stream *xdr, struct xdr_stream *xdr,
gfp_t gfp_flags); gfp_t gfp_flags);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/nfs_page.h> #include <linux/nfs_page.h>
#include <linux/sunrpc/addr.h> #include <linux/sunrpc/addr.h>
#include "nfs4session.h"
#include "internal.h" #include "internal.h"
#include "pnfs.h" #include "pnfs.h"
...@@ -534,6 +535,86 @@ nfs4_pnfs_ds_add(struct list_head *dsaddrs, gfp_t gfp_flags) ...@@ -534,6 +535,86 @@ nfs4_pnfs_ds_add(struct list_head *dsaddrs, gfp_t gfp_flags)
} }
EXPORT_SYMBOL_GPL(nfs4_pnfs_ds_add); 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. * Currently only supports ipv4, ipv6 and one multi-path address.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment