@@ -413,7 +413,7 @@ static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
* Test if two socket addresses represent the same actual socket,
* by comparing (only) relevant fields, including the port number.
*/
-int nfs_sockaddr_cmp(const struct sockaddr *sa1,
+static int nfs_sockaddr_cmp(const struct sockaddr *sa1,
const struct sockaddr *sa2)
{
if (sa1->sa_family != sa2->sa_family)
@@ -427,7 +427,6 @@ int nfs_sockaddr_cmp(const struct sockaddr *sa1,
}
return 0;
}
-EXPORT_SYMBOL(nfs_sockaddr_cmp);
/* Common match routine for v4.0 and v4.1 callback services */
bool
@@ -592,7 +591,6 @@ int nfs4_check_client_ready(struct nfs_client *clp)
return -EPROTONOSUPPORT;
return 0;
}
-EXPORT_SYMBOL(nfs4_check_client_ready);
/*
* Initialise the timeout values for a connection
@@ -1379,7 +1377,7 @@ error:
/*
* Set up an NFS4 client
*/
-int nfs4_set_client(struct nfs_server *server,
+static int nfs4_set_client(struct nfs_server *server,
const char *hostname,
const struct sockaddr *addr,
const size_t addrlen,
@@ -1416,8 +1414,48 @@ error:
dprintk("<-- nfs4_set_client() = xerror %d\n", error);
return error;
}
-EXPORT_SYMBOL(nfs4_set_client);
+/*
+ * Set up a pNFS Data Server client.
+ *
+ * Return any existing nfs_client that matches server address,port,version
+ * and minorversion.
+ *
+ * For a new nfs_client, use a soft mount (default), a low retrans and a
+ * low timeout interval so that if a connection is lost, we retry through
+ * the MDS.
+ */
+struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
+ const struct sockaddr *ds_addr,
+ int ds_addrlen, int ds_proto)
+{
+ struct nfs_client_initdata cl_init = {
+ .addr = ds_addr,
+ .addrlen = ds_addrlen,
+ .rpc_ops = &nfs_v4_clientops,
+ .proto = ds_proto,
+ .minorversion = mds_clp->cl_minorversion,
+ };
+ struct rpc_timeout ds_timeout = {
+ .to_initval = 15 * HZ,
+ .to_maxval = 15 * HZ,
+ .to_retries = 1,
+ .to_exponential = 1,
+ };
+ struct nfs_client *clp;
+
+ /*
+ * Set an authflavor equual to the MDS value. Use the MDS nfs_client
+ * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
+ * (section 13.1 RFC 5661).
+ */
+ clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr,
+ mds_clp->cl_rpcclient->cl_auth->au_flavor, 0);
+
+ dprintk("<-- %s %p\n", __func__, clp);
+ return clp;
+}
+EXPORT_SYMBOL(nfs4_set_ds_client);
/*
* Session has been established, and the client marked ready.
@@ -148,16 +148,9 @@ extern struct nfs_server *nfs_clone_server(struct nfs_server *,
struct nfs_fattr *);
extern void nfs_mark_client_ready(struct nfs_client *clp, int state);
extern int nfs4_check_client_ready(struct nfs_client *clp);
-extern int nfs_sockaddr_cmp(const struct sockaddr *sa1,
- const struct sockaddr *sa2);
-extern int nfs4_set_client(struct nfs_server *server,
- const char *hostname,
- const struct sockaddr *addr,
- const size_t addrlen,
- const char *ip_addr,
- rpc_authflavor_t authflavour,
- int proto, const struct rpc_timeout *timeparms,
- u32 minorversion);
+extern struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
+ const struct sockaddr *ds_addr,
+ int ds_addrlen, int ds_proto);
#ifdef CONFIG_PROC_FS
extern int __init nfs_fs_proc_init(void);
extern void nfs_fs_proc_exit(void);
@@ -104,68 +104,43 @@ _data_server_lookup_locked(u32 ip_addr, u32 port)
return NULL;
}
-/* Create an rpc to the data server defined in 'dev_list' */
+/*
+ * Create an rpc to the nfs4_pnfs_ds data server
+ * Currently only support IPv4
+ */
static int
nfs4_pnfs_ds_create(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds)
{
- struct nfs_server *tmp;
- struct sockaddr_in sin;
- struct rpc_clnt *mds_clnt = mds_srv->client;
- struct nfs_client *clp = mds_srv->nfs_client;
- struct sockaddr *mds_addr;
+ struct nfs_client *clp;
+ struct sockaddr_in sin;
int err = 0;
dprintk("--> %s ip:port %x:%hu au_flavor %d\n", __func__,
ntohl(ds->ds_ip_addr), ntohs(ds->ds_port),
- mds_clnt->cl_auth->au_flavor);
+ mds_srv->nfs_client->cl_rpcclient->cl_auth->au_flavor);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ds->ds_ip_addr;
sin.sin_port = ds->ds_port;
- /*
- * If this DS is also the MDS, use the MDS session only if the
- * MDS exchangeid flags show the EXCHGID4_FLAG_USE_PNFS_DS pNFS role.
- */
- mds_addr = (struct sockaddr *)&clp->cl_addr;
- if (nfs_sockaddr_cmp((struct sockaddr *)&sin, mds_addr)) {
+ clp = nfs4_set_ds_client(mds_srv->nfs_client, (struct sockaddr *)&sin,
+ sizeof(sin), IPPROTO_TCP);
+ if (IS_ERR(clp)) {
+ err = PTR_ERR(clp);
+ goto out;
+ }
+
+ if ((clp->cl_exchange_flags & EXCHGID4_FLAG_MASK_PNFS) != 0) {
+ dprintk("%s [existing] ip=%x, port=%hu\n", __func__,
+ ntohl(ds->ds_ip_addr), ntohs(ds->ds_port));
+
if (!(clp->cl_exchange_flags & EXCHGID4_FLAG_USE_PNFS_DS)) {
- printk(KERN_INFO
- "ip:port %x:%hu is not a pNFS Data Server\n",
- ntohl(ds->ds_ip_addr), ntohs(ds->ds_port));
err = -ENODEV;
- } else {
- atomic_inc(&clp->cl_count);
- ds->ds_clp = clp;
- dprintk("%s Using MDS Session for DS\n", __func__);
+ goto out_put;
}
goto out;
}
- /* Temporay server for nfs4_set_client */
- tmp = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
- if (!tmp)
- goto out;
-
- /*
- * Set a retrans, timeout interval, and authflavor equual to the MDS
- * values. Use the MDS nfs_client cl_ipaddr field so as to use the
- * same co_ownerid as the MDS.
- */
- err = nfs4_set_client(tmp,
- mds_srv->nfs_client->cl_hostname,
- (struct sockaddr *)&sin,
- sizeof(struct sockaddr),
- mds_srv->nfs_client->cl_ipaddr,
- mds_clnt->cl_auth->au_flavor,
- IPPROTO_TCP,
- mds_clnt->cl_xprt->timeout,
- 1 /* minorversion */);
- if (err < 0)
- goto out_free;
-
- clp = tmp->nfs_client;
-
/* Ask for only the EXCHGID4_FLAG_USE_PNFS_DS pNFS role */
dprintk("%s EXCHANGE_ID for clp %p\n", __func__, clp);
clp->cl_exchange_flags = EXCHGID4_FLAG_USE_PNFS_DS;
@@ -177,8 +152,6 @@ nfs4_pnfs_ds_create(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds)
goto out_put;
if (!(clp->cl_exchange_flags & EXCHGID4_FLAG_USE_PNFS_DS)) {
- printk(KERN_INFO "ip:port %x:%hu is not a pNFS Data Server\n",
- ntohl(ds->ds_ip_addr), ntohs(ds->ds_port));
err = -ENODEV;
goto out_put;
}
@@ -191,20 +164,15 @@ nfs4_pnfs_ds_create(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds)
spin_unlock(&mds_srv->nfs_client->cl_lock);
clp->cl_last_renewal = jiffies;
- clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
ds->ds_clp = clp;
- dprintk("%s: ip=%x, port=%hu, rpcclient %p\n", __func__,
- ntohl(ds->ds_ip_addr), ntohs(ds->ds_port),
- clp->cl_rpcclient);
-out_free:
- kfree(tmp);
+ dprintk("%s [new] ip=%x, port=%hu\n", __func__, ntohl(ds->ds_ip_addr),
+ ntohs(ds->ds_port));
out:
- dprintk("%s Returns %d\n", __func__, err);
return err;
out_put:
nfs_put_client(clp);
- goto out_free;
+ goto out;
}
static void