diff options
author | Peng Tao <tao.peng@primarydata.com> | 2014-05-30 06:15:59 -0400 |
---|---|---|
committer | Tom Haynes <loghyr@primarydata.com> | 2015-02-03 14:06:35 -0500 |
commit | 5f01d9539496577b9ee62e213f4122a2a209550c (patch) | |
tree | b6313926f5567e019c1800f9c15f2f7475ac21f3 /fs | |
parent | 30626f9c32f0ad5e2c4173f10fb4b1358bbba6ec (diff) |
nfs41: create NFSv3 DS connection if specified
Signed-off-by: Peng Tao <tao.peng@primarydata.com>
Signed-off-by: Tom Haynes <Thomas.Haynes@primarydata.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/nfs4super.c | 3 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 7 | ||||
-rw-r--r-- | 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 6f340f02f2ba..48cea3c30e5d 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c | |||
@@ -346,6 +346,9 @@ out: | |||
346 | 346 | ||
347 | static void __exit exit_nfs_v4(void) | 347 | static void __exit exit_nfs_v4(void) |
348 | { | 348 | { |
349 | /* Not called in the _init(), conditionally loaded */ | ||
350 | nfs4_pnfs_v3_ds_connect_unload(); | ||
351 | |||
349 | unregister_nfs_version(&nfs_v4); | 352 | unregister_nfs_version(&nfs_v4); |
350 | nfs4_unregister_sysctl(); | 353 | nfs4_unregister_sysctl(); |
351 | nfs_idmap_quit(); | 354 | nfs_idmap_quit(); |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 70ffec135696..c39882191651 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); | |||
323 | void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds); | 323 | void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds); |
324 | struct nfs4_pnfs_ds *nfs4_pnfs_ds_add(struct list_head *dsaddrs, | 324 | struct nfs4_pnfs_ds *nfs4_pnfs_ds_add(struct list_head *dsaddrs, |
325 | gfp_t gfp_flags); | 325 | gfp_t gfp_flags); |
326 | void nfs4_pnfs_v3_ds_connect_unload(void); | ||
326 | void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds, | 327 | void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds, |
327 | struct nfs4_deviceid_node *devid, unsigned int timeo, | 328 | struct nfs4_deviceid_node *devid, unsigned int timeo, |
328 | unsigned int retrans, u32 versoin, u32 minor_version, | 329 | unsigned int retrans, u32 version, u32 minor_version, |
329 | rpc_authflavor_t au_flavor); | 330 | rpc_authflavor_t au_flavor); |
330 | struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net, | 331 | struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net, |
331 | struct xdr_stream *xdr, | 332 | struct xdr_stream *xdr, |
@@ -615,6 +616,10 @@ static inline struct nfs4_threshold *pnfs_mdsthreshold_alloc(void) | |||
615 | return NULL; | 616 | return NULL; |
616 | } | 617 | } |
617 | 618 | ||
619 | static inline void nfs4_pnfs_v3_ds_connect_unload(void) | ||
620 | { | ||
621 | } | ||
622 | |||
618 | #endif /* CONFIG_NFS_V4_1 */ | 623 | #endif /* CONFIG_NFS_V4_1 */ |
619 | 624 | ||
620 | #endif /* FS_NFS_PNFS_H */ | 625 | #endif /* FS_NFS_PNFS_H */ |
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c index ad211a4e1874..23c851d4c9a9 100644 --- a/fs/nfs/pnfs_nfs.c +++ b/fs/nfs/pnfs_nfs.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/nfs_fs.h> | 10 | #include <linux/nfs_fs.h> |
11 | #include <linux/nfs_page.h> | 11 | #include <linux/nfs_page.h> |
12 | #include <linux/sunrpc/addr.h> | 12 | #include <linux/sunrpc/addr.h> |
13 | #include <linux/module.h> | ||
13 | 14 | ||
14 | #include "nfs4session.h" | 15 | #include "nfs4session.h" |
15 | #include "internal.h" | 16 | #include "internal.h" |
@@ -550,7 +551,75 @@ static void nfs4_clear_ds_conn_bit(struct nfs4_pnfs_ds *ds) | |||
550 | wake_up_bit(&ds->ds_state, NFS4DS_CONNECTING); | 551 | wake_up_bit(&ds->ds_state, NFS4DS_CONNECTING); |
551 | } | 552 | } |
552 | 553 | ||
553 | static int _nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, | 554 | static struct nfs_client *(*get_v3_ds_connect)( |
555 | struct nfs_client *mds_clp, | ||
556 | const struct sockaddr *ds_addr, | ||
557 | int ds_addrlen, | ||
558 | int ds_proto, | ||
559 | unsigned int ds_timeo, | ||
560 | unsigned int ds_retrans, | ||
561 | rpc_authflavor_t au_flavor); | ||
562 | |||
563 | static bool load_v3_ds_connect(void) | ||
564 | { | ||
565 | if (!get_v3_ds_connect) { | ||
566 | get_v3_ds_connect = symbol_request(nfs3_set_ds_client); | ||
567 | WARN_ON_ONCE(!get_v3_ds_connect); | ||
568 | } | ||
569 | |||
570 | return(get_v3_ds_connect != NULL); | ||
571 | } | ||
572 | |||
573 | void __exit nfs4_pnfs_v3_ds_connect_unload(void) | ||
574 | { | ||
575 | if (get_v3_ds_connect) { | ||
576 | symbol_put(nfs3_set_ds_client); | ||
577 | get_v3_ds_connect = NULL; | ||
578 | } | ||
579 | } | ||
580 | EXPORT_SYMBOL_GPL(nfs4_pnfs_v3_ds_connect_unload); | ||
581 | |||
582 | static int _nfs4_pnfs_v3_ds_connect(struct nfs_server *mds_srv, | ||
583 | struct nfs4_pnfs_ds *ds, | ||
584 | unsigned int timeo, | ||
585 | unsigned int retrans, | ||
586 | rpc_authflavor_t au_flavor) | ||
587 | { | ||
588 | struct nfs_client *clp = ERR_PTR(-EIO); | ||
589 | struct nfs4_pnfs_ds_addr *da; | ||
590 | int status = 0; | ||
591 | |||
592 | dprintk("--> %s DS %s au_flavor %d\n", __func__, | ||
593 | ds->ds_remotestr, au_flavor); | ||
594 | |||
595 | if (!load_v3_ds_connect()) | ||
596 | goto out; | ||
597 | |||
598 | list_for_each_entry(da, &ds->ds_addrs, da_node) { | ||
599 | dprintk("%s: DS %s: trying address %s\n", | ||
600 | __func__, ds->ds_remotestr, da->da_remotestr); | ||
601 | |||
602 | clp = get_v3_ds_connect(mds_srv->nfs_client, | ||
603 | (struct sockaddr *)&da->da_addr, | ||
604 | da->da_addrlen, IPPROTO_TCP, | ||
605 | timeo, retrans, au_flavor); | ||
606 | if (!IS_ERR(clp)) | ||
607 | break; | ||
608 | } | ||
609 | |||
610 | if (IS_ERR(clp)) { | ||
611 | status = PTR_ERR(clp); | ||
612 | goto out; | ||
613 | } | ||
614 | |||
615 | smp_wmb(); | ||
616 | ds->ds_clp = clp; | ||
617 | dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr); | ||
618 | out: | ||
619 | return status; | ||
620 | } | ||
621 | |||
622 | static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv, | ||
554 | struct nfs4_pnfs_ds *ds, | 623 | struct nfs4_pnfs_ds *ds, |
555 | unsigned int timeo, | 624 | unsigned int timeo, |
556 | unsigned int retrans, | 625 | unsigned int retrans, |
@@ -562,7 +631,7 @@ static int _nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, | |||
562 | int status = 0; | 631 | int status = 0; |
563 | 632 | ||
564 | dprintk("--> %s DS %s au_flavor %d\n", __func__, ds->ds_remotestr, | 633 | dprintk("--> %s DS %s au_flavor %d\n", __func__, ds->ds_remotestr, |
565 | mds_srv->nfs_client->cl_rpcclient->cl_auth->au_flavor); | 634 | au_flavor); |
566 | 635 | ||
567 | list_for_each_entry(da, &ds->ds_addrs, da_node) { | 636 | list_for_each_entry(da, &ds->ds_addrs, da_node) { |
568 | dprintk("%s: DS %s: trying address %s\n", | 637 | 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, | |||
609 | if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) { | 678 | if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) { |
610 | int err = 0; | 679 | int err = 0; |
611 | 680 | ||
612 | err = _nfs4_pnfs_ds_connect(mds_srv, ds, timeo, retrans, | 681 | if (version == 3) { |
613 | minor_version, au_flavor); | 682 | err = _nfs4_pnfs_v3_ds_connect(mds_srv, ds, timeo, |
683 | retrans, au_flavor); | ||
684 | } else if (version == 4) { | ||
685 | err = _nfs4_pnfs_v4_ds_connect(mds_srv, ds, timeo, | ||
686 | retrans, minor_version, | ||
687 | au_flavor); | ||
688 | } else { | ||
689 | dprintk("%s: unsupported DS version %d\n", __func__, | ||
690 | version); | ||
691 | err = -EPROTONOSUPPORT; | ||
692 | } | ||
693 | |||
614 | if (err) | 694 | if (err) |
615 | nfs4_mark_deviceid_unavailable(devid); | 695 | nfs4_mark_deviceid_unavailable(devid); |
616 | nfs4_clear_ds_conn_bit(ds); | 696 | nfs4_clear_ds_conn_bit(ds); |