diff options
author | Andy Adamson <andros@netapp.com> | 2013-09-06 14:14:00 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-09-06 14:49:16 -0400 |
commit | 0e20162ed1e9a639fc61d62c71327169fb1a1970 (patch) | |
tree | 299ac444cffc3087c5221c30bce9fbbf4ba9d133 /fs/nfs/nfs4client.c | |
parent | 4109bb7496640aa97a12904527ba8e3a19b7ce7a (diff) |
NFSv4.1 Use MDS auth flavor for data server connection
Commit 4edaa308 "NFS: Use "krb5i" to establish NFSv4 state whenever possible"
uses the nfs_client cl_rpcclient for all state management operations, and
will use krb5i or auth_sys with no regard to the mount command authflavor
choice.
The MDS, as any NFSv4.1 mount point, uses the nfs_server rpc client for all
non-state management operations with a different nfs_server for each fsid
encountered traversing the mount point, each with a potentially different
auth flavor.
pNFS data servers are not mounted in the normal sense as there is no associated
nfs_server structure. Data servers can also export multiple fsids, each with
a potentially different auth flavor.
Data servers need to use the same authflavor as the MDS server rpc client for
non-state management operations. Populate a list of rpc clients with the MDS
server rpc client auth flavor for the DS to use.
Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4client.c')
-rw-r--r-- | fs/nfs/nfs4client.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 98c0104bb0c4..f798925d8291 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -41,9 +41,124 @@ static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion) | |||
41 | } | 41 | } |
42 | 42 | ||
43 | #ifdef CONFIG_NFS_V4_1 | 43 | #ifdef CONFIG_NFS_V4_1 |
44 | /** | ||
45 | * Per auth flavor data server rpc clients | ||
46 | */ | ||
47 | struct nfs4_ds_server { | ||
48 | struct list_head list; /* ds_clp->cl_ds_clients */ | ||
49 | struct rpc_clnt *rpc_clnt; | ||
50 | }; | ||
51 | |||
52 | /** | ||
53 | * Common lookup case for DS I/O | ||
54 | */ | ||
55 | static struct nfs4_ds_server * | ||
56 | nfs4_find_ds_client(struct nfs_client *ds_clp, rpc_authflavor_t flavor) | ||
57 | { | ||
58 | struct nfs4_ds_server *dss; | ||
59 | |||
60 | rcu_read_lock(); | ||
61 | list_for_each_entry_rcu(dss, &ds_clp->cl_ds_clients, list) { | ||
62 | if (dss->rpc_clnt->cl_auth->au_flavor != flavor) | ||
63 | continue; | ||
64 | goto out; | ||
65 | } | ||
66 | dss = NULL; | ||
67 | out: | ||
68 | rcu_read_unlock(); | ||
69 | return dss; | ||
70 | } | ||
71 | |||
72 | static struct nfs4_ds_server * | ||
73 | nfs4_add_ds_client(struct nfs_client *ds_clp, rpc_authflavor_t flavor, | ||
74 | struct nfs4_ds_server *new) | ||
75 | { | ||
76 | struct nfs4_ds_server *dss; | ||
77 | |||
78 | spin_lock(&ds_clp->cl_lock); | ||
79 | list_for_each_entry(dss, &ds_clp->cl_ds_clients, list) { | ||
80 | if (dss->rpc_clnt->cl_auth->au_flavor != flavor) | ||
81 | continue; | ||
82 | goto out; | ||
83 | } | ||
84 | if (new) | ||
85 | list_add_rcu(&new->list, &ds_clp->cl_ds_clients); | ||
86 | dss = new; | ||
87 | out: | ||
88 | spin_unlock(&ds_clp->cl_lock); /* need some lock to protect list */ | ||
89 | return dss; | ||
90 | } | ||
91 | |||
92 | static struct nfs4_ds_server * | ||
93 | nfs4_alloc_ds_server(struct nfs_client *ds_clp, rpc_authflavor_t flavor) | ||
94 | { | ||
95 | struct nfs4_ds_server *dss; | ||
96 | |||
97 | dss = kmalloc(sizeof(*dss), GFP_NOFS); | ||
98 | if (dss == NULL) | ||
99 | return ERR_PTR(-ENOMEM); | ||
100 | |||
101 | dss->rpc_clnt = rpc_clone_client_set_auth(ds_clp->cl_rpcclient, flavor); | ||
102 | if (IS_ERR(dss->rpc_clnt)) { | ||
103 | int err = PTR_ERR(dss->rpc_clnt); | ||
104 | kfree (dss); | ||
105 | return ERR_PTR(err); | ||
106 | } | ||
107 | INIT_LIST_HEAD(&dss->list); | ||
108 | |||
109 | return dss; | ||
110 | } | ||
111 | |||
112 | static void | ||
113 | nfs4_free_ds_server(struct nfs4_ds_server *dss) | ||
114 | { | ||
115 | rpc_release_client(dss->rpc_clnt); | ||
116 | kfree(dss); | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * Find or create a DS rpc client with th MDS server rpc client auth flavor | ||
121 | * in the nfs_client cl_ds_clients list. | ||
122 | */ | ||
123 | struct rpc_clnt * | ||
124 | nfs4_find_or_create_ds_client(struct nfs_client *ds_clp, struct inode *inode) | ||
125 | { | ||
126 | struct nfs4_ds_server *dss, *new; | ||
127 | rpc_authflavor_t flavor = NFS_SERVER(inode)->client->cl_auth->au_flavor; | ||
128 | |||
129 | dss = nfs4_find_ds_client(ds_clp, flavor); | ||
130 | if (dss != NULL) | ||
131 | goto out; | ||
132 | new = nfs4_alloc_ds_server(ds_clp, flavor); | ||
133 | if (IS_ERR(new)) | ||
134 | return ERR_CAST(new); | ||
135 | dss = nfs4_add_ds_client(ds_clp, flavor, new); | ||
136 | if (dss != new) | ||
137 | nfs4_free_ds_server(new); | ||
138 | out: | ||
139 | return dss->rpc_clnt; | ||
140 | } | ||
141 | EXPORT_SYMBOL_GPL(nfs4_find_or_create_ds_client); | ||
142 | |||
143 | static void | ||
144 | nfs4_shutdown_ds_clients(struct nfs_client *clp) | ||
145 | { | ||
146 | struct nfs4_ds_server *dss; | ||
147 | LIST_HEAD(shutdown_list); | ||
148 | |||
149 | while (!list_empty(&clp->cl_ds_clients)) { | ||
150 | dss = list_entry(clp->cl_ds_clients.next, | ||
151 | struct nfs4_ds_server, list); | ||
152 | list_del(&dss->list); | ||
153 | rpc_shutdown_client(dss->rpc_clnt); | ||
154 | kfree (dss); | ||
155 | } | ||
156 | } | ||
157 | |||
44 | void nfs41_shutdown_client(struct nfs_client *clp) | 158 | void nfs41_shutdown_client(struct nfs_client *clp) |
45 | { | 159 | { |
46 | if (nfs4_has_session(clp)) { | 160 | if (nfs4_has_session(clp)) { |
161 | nfs4_shutdown_ds_clients(clp); | ||
47 | nfs4_destroy_session(clp->cl_session); | 162 | nfs4_destroy_session(clp->cl_session); |
48 | nfs4_destroy_clientid(clp); | 163 | nfs4_destroy_clientid(clp); |
49 | } | 164 | } |
@@ -77,6 +192,7 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) | |||
77 | 192 | ||
78 | spin_lock_init(&clp->cl_lock); | 193 | spin_lock_init(&clp->cl_lock); |
79 | INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); | 194 | INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); |
195 | INIT_LIST_HEAD(&clp->cl_ds_clients); | ||
80 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); | 196 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); |
81 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; | 197 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; |
82 | clp->cl_minorversion = cl_init->minorversion; | 198 | clp->cl_minorversion = cl_init->minorversion; |