2015-02-03 18:45:47

by Thomas Haynes

[permalink] [raw]
Subject: [PATCH v6a 10/53] nfs41: create NFSv3 DS connection if specified

From: Peng Tao <[email protected]>

Signed-off-by: Peng Tao <[email protected]>
Signed-off-by: Tom Haynes <[email protected]>
---
fs/nfs/nfs4super.c | 3 ++
fs/nfs/pnfs.h | 7 ++++-
fs/nfs/pnfs_nfs.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 93 insertions(+), 5 deletions(-)

diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index 6f340f0..48cea3c 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -346,6 +346,9 @@ out:

static void __exit exit_nfs_v4(void)
{
+ /* Not called in the _init(), conditionally loaded */
+ nfs4_pnfs_v3_ds_connect_unload();
+
unregister_nfs_version(&nfs_v4);
nfs4_unregister_sysctl();
nfs_idmap_quit();
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 70ffec1..c398821 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -323,9 +323,10 @@ 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_v3_ds_connect_unload(void);
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, u32 versoin, u32 minor_version,
+ unsigned int retrans, u32 version, u32 minor_version,
rpc_authflavor_t au_flavor);
struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net,
struct xdr_stream *xdr,
@@ -615,6 +616,10 @@ static inline struct nfs4_threshold *pnfs_mdsthreshold_alloc(void)
return NULL;
}

+static inline void nfs4_pnfs_v3_ds_connect_unload(void)
+{
+}
+
#endif /* CONFIG_NFS_V4_1 */

#endif /* FS_NFS_PNFS_H */
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c
index ad211a4..23c851d 100644
--- a/fs/nfs/pnfs_nfs.c
+++ b/fs/nfs/pnfs_nfs.c
@@ -10,6 +10,7 @@
#include <linux/nfs_fs.h>
#include <linux/nfs_page.h>
#include <linux/sunrpc/addr.h>
+#include <linux/module.h>

#include "nfs4session.h"
#include "internal.h"
@@ -550,7 +551,75 @@ static void nfs4_clear_ds_conn_bit(struct nfs4_pnfs_ds *ds)
wake_up_bit(&ds->ds_state, NFS4DS_CONNECTING);
}

-static int _nfs4_pnfs_ds_connect(struct nfs_server *mds_srv,
+static struct nfs_client *(*get_v3_ds_connect)(
+ struct nfs_client *mds_clp,
+ const struct sockaddr *ds_addr,
+ int ds_addrlen,
+ int ds_proto,
+ unsigned int ds_timeo,
+ unsigned int ds_retrans,
+ rpc_authflavor_t au_flavor);
+
+static bool load_v3_ds_connect(void)
+{
+ if (!get_v3_ds_connect) {
+ get_v3_ds_connect = symbol_request(nfs3_set_ds_client);
+ WARN_ON_ONCE(!get_v3_ds_connect);
+ }
+
+ return(get_v3_ds_connect != NULL);
+}
+
+void __exit nfs4_pnfs_v3_ds_connect_unload(void)
+{
+ if (get_v3_ds_connect) {
+ symbol_put(nfs3_set_ds_client);
+ get_v3_ds_connect = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(nfs4_pnfs_v3_ds_connect_unload);
+
+static int _nfs4_pnfs_v3_ds_connect(struct nfs_server *mds_srv,
+ struct nfs4_pnfs_ds *ds,
+ unsigned int timeo,
+ unsigned int retrans,
+ rpc_authflavor_t au_flavor)
+{
+ 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, au_flavor);
+
+ if (!load_v3_ds_connect())
+ goto out;
+
+ 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 = get_v3_ds_connect(mds_srv->nfs_client,
+ (struct sockaddr *)&da->da_addr,
+ da->da_addrlen, IPPROTO_TCP,
+ timeo, retrans, au_flavor);
+ if (!IS_ERR(clp))
+ break;
+ }
+
+ if (IS_ERR(clp)) {
+ status = PTR_ERR(clp);
+ goto out;
+ }
+
+ smp_wmb();
+ ds->ds_clp = clp;
+ dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr);
+out:
+ return status;
+}
+
+static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv,
struct nfs4_pnfs_ds *ds,
unsigned int timeo,
unsigned int retrans,
@@ -562,7 +631,7 @@ static int _nfs4_pnfs_ds_connect(struct nfs_server *mds_srv,
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);
+ au_flavor);

list_for_each_entry(da, &ds->ds_addrs, da_node) {
dprintk("%s: DS %s: trying address %s\n",
@@ -609,8 +678,19 @@ void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) {
int err = 0;

- err = _nfs4_pnfs_ds_connect(mds_srv, ds, timeo, retrans,
- minor_version, au_flavor);
+ if (version == 3) {
+ err = _nfs4_pnfs_v3_ds_connect(mds_srv, ds, timeo,
+ retrans, au_flavor);
+ } else if (version == 4) {
+ err = _nfs4_pnfs_v4_ds_connect(mds_srv, ds, timeo,
+ retrans, minor_version,
+ au_flavor);
+ } else {
+ dprintk("%s: unsupported DS version %d\n", __func__,
+ version);
+ err = -EPROTONOSUPPORT;
+ }
+
if (err)
nfs4_mark_deviceid_unavailable(devid);
nfs4_clear_ds_conn_bit(ds);
--
1.9.3



2015-02-03 18:47:16

by Thomas Haynes

[permalink] [raw]
Subject: Re: [PATCH v6a 10/53] nfs41: create NFSv3 DS connection if specified

Hi Trond,

I’ve squashed the fix for the issue Anna raised into this patch.

Please use it in place of the v6 version.

Thanks,
Tom

> On Feb 3, 2015, at 10:45 AM, Tom Haynes <[email protected]> wrote:
>
> From: Peng Tao <[email protected]>
>
> Signed-off-by: Peng Tao <[email protected]>
> Signed-off-by: Tom Haynes <[email protected]>
> ---
> fs/nfs/nfs4super.c | 3 ++
> fs/nfs/pnfs.h | 7 ++++-
> fs/nfs/pnfs_nfs.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++---
> 3 files changed, 93 insertions(+), 5 deletions(-)
>
> diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
> index 6f340f0..48cea3c 100644
> --- a/fs/nfs/nfs4super.c
> +++ b/fs/nfs/nfs4super.c
> @@ -346,6 +346,9 @@ out:
>
> static void __exit exit_nfs_v4(void)
> {
> + /* Not called in the _init(), conditionally loaded */
> + nfs4_pnfs_v3_ds_connect_unload();
> +
> unregister_nfs_version(&nfs_v4);
> nfs4_unregister_sysctl();
> nfs_idmap_quit();
> diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
> index 70ffec1..c398821 100644
> --- a/fs/nfs/pnfs.h
> +++ b/fs/nfs/pnfs.h
> @@ -323,9 +323,10 @@ 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_v3_ds_connect_unload(void);
> 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, u32 versoin, u32 minor_version,
> + unsigned int retrans, u32 version, u32 minor_version,
> rpc_authflavor_t au_flavor);
> struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net,
> struct xdr_stream *xdr,
> @@ -615,6 +616,10 @@ static inline struct nfs4_threshold *pnfs_mdsthreshold_alloc(void)
> return NULL;
> }
>
> +static inline void nfs4_pnfs_v3_ds_connect_unload(void)
> +{
> +}
> +
> #endif /* CONFIG_NFS_V4_1 */
>
> #endif /* FS_NFS_PNFS_H */
> diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c
> index ad211a4..23c851d 100644
> --- a/fs/nfs/pnfs_nfs.c
> +++ b/fs/nfs/pnfs_nfs.c
> @@ -10,6 +10,7 @@
> #include <linux/nfs_fs.h>
> #include <linux/nfs_page.h>
> #include <linux/sunrpc/addr.h>
> +#include <linux/module.h>
>
> #include "nfs4session.h"
> #include "internal.h"
> @@ -550,7 +551,75 @@ static void nfs4_clear_ds_conn_bit(struct nfs4_pnfs_ds *ds)
> wake_up_bit(&ds->ds_state, NFS4DS_CONNECTING);
> }
>
> -static int _nfs4_pnfs_ds_connect(struct nfs_server *mds_srv,
> +static struct nfs_client *(*get_v3_ds_connect)(
> + struct nfs_client *mds_clp,
> + const struct sockaddr *ds_addr,
> + int ds_addrlen,
> + int ds_proto,
> + unsigned int ds_timeo,
> + unsigned int ds_retrans,
> + rpc_authflavor_t au_flavor);
> +
> +static bool load_v3_ds_connect(void)
> +{
> + if (!get_v3_ds_connect) {
> + get_v3_ds_connect = symbol_request(nfs3_set_ds_client);
> + WARN_ON_ONCE(!get_v3_ds_connect);
> + }
> +
> + return(get_v3_ds_connect != NULL);
> +}
> +
> +void __exit nfs4_pnfs_v3_ds_connect_unload(void)
> +{
> + if (get_v3_ds_connect) {
> + symbol_put(nfs3_set_ds_client);
> + get_v3_ds_connect = NULL;
> + }
> +}
> +EXPORT_SYMBOL_GPL(nfs4_pnfs_v3_ds_connect_unload);
> +
> +static int _nfs4_pnfs_v3_ds_connect(struct nfs_server *mds_srv,
> + struct nfs4_pnfs_ds *ds,
> + unsigned int timeo,
> + unsigned int retrans,
> + rpc_authflavor_t au_flavor)
> +{
> + 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, au_flavor);
> +
> + if (!load_v3_ds_connect())
> + goto out;
> +
> + 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 = get_v3_ds_connect(mds_srv->nfs_client,
> + (struct sockaddr *)&da->da_addr,
> + da->da_addrlen, IPPROTO_TCP,
> + timeo, retrans, au_flavor);
> + if (!IS_ERR(clp))
> + break;
> + }
> +
> + if (IS_ERR(clp)) {
> + status = PTR_ERR(clp);
> + goto out;
> + }
> +
> + smp_wmb();
> + ds->ds_clp = clp;
> + dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr);
> +out:
> + return status;
> +}
> +
> +static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv,
> struct nfs4_pnfs_ds *ds,
> unsigned int timeo,
> unsigned int retrans,
> @@ -562,7 +631,7 @@ static int _nfs4_pnfs_ds_connect(struct nfs_server *mds_srv,
> 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);
> + au_flavor);
>
> list_for_each_entry(da, &ds->ds_addrs, da_node) {
> dprintk("%s: DS %s: trying address %s\n",
> @@ -609,8 +678,19 @@ void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
> if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) {
> int err = 0;
>
> - err = _nfs4_pnfs_ds_connect(mds_srv, ds, timeo, retrans,
> - minor_version, au_flavor);
> + if (version == 3) {
> + err = _nfs4_pnfs_v3_ds_connect(mds_srv, ds, timeo,
> + retrans, au_flavor);
> + } else if (version == 4) {
> + err = _nfs4_pnfs_v4_ds_connect(mds_srv, ds, timeo,
> + retrans, minor_version,
> + au_flavor);
> + } else {
> + dprintk("%s: unsupported DS version %d\n", __func__,
> + version);
> + err = -EPROTONOSUPPORT;
> + }
> +
> if (err)
> nfs4_mark_deviceid_unavailable(devid);
> nfs4_clear_ds_conn_bit(ds);
> --
> 1.9.3
>