aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/callback.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/callback.c')
-rw-r--r--fs/nfs/callback.c83
1 files changed, 70 insertions, 13 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 93a8b3bd69e3..199016528fcb 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -16,9 +16,7 @@
16#include <linux/freezer.h> 16#include <linux/freezer.h>
17#include <linux/kthread.h> 17#include <linux/kthread.h>
18#include <linux/sunrpc/svcauth_gss.h> 18#include <linux/sunrpc/svcauth_gss.h>
19#if defined(CONFIG_NFS_V4_1)
20#include <linux/sunrpc/bc_xprt.h> 19#include <linux/sunrpc/bc_xprt.h>
21#endif
22 20
23#include <net/inet_sock.h> 21#include <net/inet_sock.h>
24 22
@@ -137,6 +135,33 @@ out_err:
137 135
138#if defined(CONFIG_NFS_V4_1) 136#if defined(CONFIG_NFS_V4_1)
139/* 137/*
138 * * CB_SEQUENCE operations will fail until the callback sessionid is set.
139 * */
140int nfs4_set_callback_sessionid(struct nfs_client *clp)
141{
142 struct svc_serv *serv = clp->cl_rpcclient->cl_xprt->bc_serv;
143 struct nfs4_sessionid *bc_sid;
144
145 if (!serv->sv_bc_xprt)
146 return -EINVAL;
147
148 /* on success freed in xprt_free */
149 bc_sid = kmalloc(sizeof(struct nfs4_sessionid), GFP_KERNEL);
150 if (!bc_sid)
151 return -ENOMEM;
152 memcpy(bc_sid->data, &clp->cl_session->sess_id.data,
153 NFS4_MAX_SESSIONID_LEN);
154 spin_lock_bh(&serv->sv_cb_lock);
155 serv->sv_bc_xprt->xpt_bc_sid = bc_sid;
156 spin_unlock_bh(&serv->sv_cb_lock);
157 dprintk("%s set xpt_bc_sid=%u:%u:%u:%u for sv_bc_xprt %p\n", __func__,
158 ((u32 *)bc_sid->data)[0], ((u32 *)bc_sid->data)[1],
159 ((u32 *)bc_sid->data)[2], ((u32 *)bc_sid->data)[3],
160 serv->sv_bc_xprt);
161 return 0;
162}
163
164/*
140 * The callback service for NFSv4.1 callbacks 165 * The callback service for NFSv4.1 callbacks
141 */ 166 */
142static int 167static int
@@ -177,30 +202,38 @@ nfs41_callback_svc(void *vrqstp)
177struct svc_rqst * 202struct svc_rqst *
178nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) 203nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt)
179{ 204{
180 struct svc_xprt *bc_xprt; 205 struct svc_rqst *rqstp;
181 struct svc_rqst *rqstp = ERR_PTR(-ENOMEM); 206 int ret;
182 207
183 dprintk("--> %s\n", __func__); 208 /*
184 /* Create a svc_sock for the service */ 209 * Create an svc_sock for the back channel service that shares the
185 bc_xprt = svc_sock_create(serv, xprt->prot); 210 * fore channel connection.
186 if (!bc_xprt) 211 * Returns the input port (0) and sets the svc_serv bc_xprt on success
212 */
213 ret = svc_create_xprt(serv, "tcp-bc", &init_net, PF_INET, 0,
214 SVC_SOCK_ANONYMOUS);
215 if (ret < 0) {
216 rqstp = ERR_PTR(ret);
187 goto out; 217 goto out;
218 }
188 219
189 /* 220 /*
190 * Save the svc_serv in the transport so that it can 221 * Save the svc_serv in the transport so that it can
191 * be referenced when the session backchannel is initialized 222 * be referenced when the session backchannel is initialized
192 */ 223 */
193 serv->bc_xprt = bc_xprt;
194 xprt->bc_serv = serv; 224 xprt->bc_serv = serv;
195 225
196 INIT_LIST_HEAD(&serv->sv_cb_list); 226 INIT_LIST_HEAD(&serv->sv_cb_list);
197 spin_lock_init(&serv->sv_cb_lock); 227 spin_lock_init(&serv->sv_cb_lock);
198 init_waitqueue_head(&serv->sv_cb_waitq); 228 init_waitqueue_head(&serv->sv_cb_waitq);
199 rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]); 229 rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
200 if (IS_ERR(rqstp)) 230 if (IS_ERR(rqstp)) {
201 svc_sock_destroy(bc_xprt); 231 svc_xprt_put(serv->sv_bc_xprt);
232 serv->sv_bc_xprt = NULL;
233 }
202out: 234out:
203 dprintk("--> %s return %p\n", __func__, rqstp); 235 dprintk("--> %s return %ld\n", __func__,
236 IS_ERR(rqstp) ? PTR_ERR(rqstp) : 0);
204 return rqstp; 237 return rqstp;
205} 238}
206 239
@@ -233,6 +266,10 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
233 struct nfs_callback_data *cb_info) 266 struct nfs_callback_data *cb_info)
234{ 267{
235} 268}
269int nfs4_set_callback_sessionid(struct nfs_client *clp)
270{
271 return 0;
272}
236#endif /* CONFIG_NFS_V4_1 */ 273#endif /* CONFIG_NFS_V4_1 */
237 274
238/* 275/*
@@ -328,6 +365,9 @@ static int check_gss_callback_principal(struct nfs_client *clp,
328 struct rpc_clnt *r = clp->cl_rpcclient; 365 struct rpc_clnt *r = clp->cl_rpcclient;
329 char *p = svc_gss_principal(rqstp); 366 char *p = svc_gss_principal(rqstp);
330 367
368 /* No RPC_AUTH_GSS on NFSv4.1 back channel yet */
369 if (clp->cl_minorversion != 0)
370 return SVC_DROP;
331 /* 371 /*
332 * It might just be a normal user principal, in which case 372 * It might just be a normal user principal, in which case
333 * userspace won't bother to tell us the name at all. 373 * userspace won't bother to tell us the name at all.
@@ -345,6 +385,23 @@ static int check_gss_callback_principal(struct nfs_client *clp,
345 return SVC_OK; 385 return SVC_OK;
346} 386}
347 387
388/* pg_authenticate method helper */
389static struct nfs_client *nfs_cb_find_client(struct svc_rqst *rqstp)
390{
391 struct nfs4_sessionid *sessionid = bc_xprt_sid(rqstp);
392 int is_cb_compound = rqstp->rq_proc == CB_COMPOUND ? 1 : 0;
393
394 dprintk("--> %s rq_proc %d\n", __func__, rqstp->rq_proc);
395 if (svc_is_backchannel(rqstp))
396 /* Sessionid (usually) set after CB_NULL ping */
397 return nfs4_find_client_sessionid(svc_addr(rqstp), sessionid,
398 is_cb_compound);
399 else
400 /* No callback identifier in pg_authenticate */
401 return nfs4_find_client_no_ident(svc_addr(rqstp));
402}
403
404/* pg_authenticate method for nfsv4 callback threads. */
348static int nfs_callback_authenticate(struct svc_rqst *rqstp) 405static int nfs_callback_authenticate(struct svc_rqst *rqstp)
349{ 406{
350 struct nfs_client *clp; 407 struct nfs_client *clp;
@@ -352,7 +409,7 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp)
352 int ret = SVC_OK; 409 int ret = SVC_OK;
353 410
354 /* Don't talk to strangers */ 411 /* Don't talk to strangers */
355 clp = nfs_find_client(svc_addr(rqstp), 4); 412 clp = nfs_cb_find_client(rqstp);
356 if (clp == NULL) 413 if (clp == NULL)
357 return SVC_DROP; 414 return SVC_DROP;
358 415