|
@@ -745,15 +745,17 @@ 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.
|
|
|
+ * If connection fails, make devid unavailable and return a -errno.
|
|
|
*/
|
|
|
-void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
|
|
|
+int 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, u32 version, u32 minor_version)
|
|
|
{
|
|
|
- if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) {
|
|
|
- int err = 0;
|
|
|
+ int err;
|
|
|
|
|
|
+again:
|
|
|
+ err = 0;
|
|
|
+ if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) {
|
|
|
if (version == 3) {
|
|
|
err = _nfs4_pnfs_v3_ds_connect(mds_srv, ds, timeo,
|
|
|
retrans);
|
|
@@ -766,12 +768,29 @@ void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
|
|
|
err = -EPROTONOSUPPORT;
|
|
|
}
|
|
|
|
|
|
- if (err)
|
|
|
- nfs4_mark_deviceid_unavailable(devid);
|
|
|
nfs4_clear_ds_conn_bit(ds);
|
|
|
} else {
|
|
|
nfs4_wait_ds_connect(ds);
|
|
|
+
|
|
|
+ /* what was waited on didn't connect AND didn't mark unavail */
|
|
|
+ if (!ds->ds_clp && !nfs4_test_deviceid_unavailable(devid))
|
|
|
+ goto again;
|
|
|
}
|
|
|
+
|
|
|
+ /*
|
|
|
+ * At this point the ds->ds_clp should be ready, but it might have
|
|
|
+ * hit an error.
|
|
|
+ */
|
|
|
+ if (!err) {
|
|
|
+ if (!ds->ds_clp || !nfs_client_init_is_complete(ds->ds_clp)) {
|
|
|
+ WARN_ON_ONCE(ds->ds_clp ||
|
|
|
+ !nfs4_test_deviceid_unavailable(devid));
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ err = nfs_client_init_status(ds->ds_clp);
|
|
|
+ }
|
|
|
+
|
|
|
+ return err;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(nfs4_pnfs_ds_connect);
|
|
|
|