Message ID | 1422989137-14153-1-git-send-email-loghyr@primarydata.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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 <thomas.haynes@primarydata.com> wrote: > > From: Peng Tao <tao.peng@primarydata.com> > > Signed-off-by: Peng Tao <tao.peng@primarydata.com> > Signed-off-by: Tom Haynes <Thomas.Haynes@primarydata.com> > --- > 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 > -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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);