nfs4callback.c 29.7 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
 *  Copyright (c) 2001 The Regents of the University of Michigan.
 *  All rights reserved.
 *
 *  Kendrick Smith <kmsmith@umich.edu>
 *  Andy Adamson <andros@umich.edu>
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the University nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <linux/sunrpc/clnt.h>
35
#include <linux/sunrpc/xprt.h>
36
#include <linux/sunrpc/svc_xprt.h>
37
#include <linux/slab.h>
38
39
#include "nfsd.h"
#include "state.h"
40
#include "netns.h"
41
#include "xdr4cb.h"
Linus Torvalds's avatar
Linus Torvalds committed
42
43
44

#define NFSDDBG_FACILITY                NFSDDBG_PROC

45
46
static void nfsd4_mark_cb_fault(struct nfs4_client *, int reason);

Linus Torvalds's avatar
Linus Torvalds committed
47
48
49
50
51
52
#define NFSPROC4_CB_NULL 0
#define NFSPROC4_CB_COMPOUND 1

/* Index of predefined Linux callback client operations */

struct nfs4_cb_compound_hdr {
53
54
	/* args */
	u32		ident;	/* minorversion 0 only */
Linus Torvalds's avatar
Linus Torvalds committed
55
	u32		nops;
56
	__be32		*nops_p;
57
	u32		minorversion;
58
59
	/* res */
	int		status;
Linus Torvalds's avatar
Linus Torvalds committed
60
61
};

62
63
64
65
/*
 * Handle decode buffer overflows out-of-line.
 */
static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
Linus Torvalds's avatar
Linus Torvalds committed
66
{
67
68
69
	dprintk("NFS: %s prematurely hit the end of our receive buffer. "
		"Remaining buffer length is %tu words.\n",
		func, xdr->end - xdr->p);
Linus Torvalds's avatar
Linus Torvalds committed
70
71
}

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
static __be32 *xdr_encode_empty_array(__be32 *p)
{
	*p++ = xdr_zero;
	return p;
}

/*
 * Encode/decode NFSv4 CB basic data types
 *
 * Basic NFSv4 callback data types are defined in section 15 of RFC
 * 3530: "Network File System (NFS) version 4 Protocol" and section
 * 20 of RFC 5661: "Network File System (NFS) Version 4 Minor Version
 * 1 Protocol"
 */

/*
 *	nfs_cb_opnum4
 *
 *	enum nfs_cb_opnum4 {
 *		OP_CB_GETATTR		= 3,
 *		  ...
 *	};
 */
enum nfs_cb_opnum4 {
	OP_CB_GETATTR			= 3,
	OP_CB_RECALL			= 4,
	OP_CB_LAYOUTRECALL		= 5,
	OP_CB_NOTIFY			= 6,
	OP_CB_PUSH_DELEG		= 7,
	OP_CB_RECALL_ANY		= 8,
	OP_CB_RECALLABLE_OBJ_AVAIL	= 9,
	OP_CB_RECALL_SLOT		= 10,
	OP_CB_SEQUENCE			= 11,
	OP_CB_WANTS_CANCELLED		= 12,
	OP_CB_NOTIFY_LOCK		= 13,
	OP_CB_NOTIFY_DEVICEID		= 14,
	OP_CB_ILLEGAL			= 10044
};

static void encode_nfs_cb_opnum4(struct xdr_stream *xdr, enum nfs_cb_opnum4 op)
{
	__be32 *p;

	p = xdr_reserve_space(xdr, 4);
	*p = cpu_to_be32(op);
}

/*
 * nfs_fh4
 *
 *	typedef opaque nfs_fh4<NFS4_FHSIZE>;
 */
static void encode_nfs_fh4(struct xdr_stream *xdr, const struct knfsd_fh *fh)
{
	u32 length = fh->fh_size;
	__be32 *p;

	BUG_ON(length > NFS4_FHSIZE);
	p = xdr_reserve_space(xdr, 4 + length);
	xdr_encode_opaque(p, &fh->fh_base, length);
}

Linus Torvalds's avatar
Linus Torvalds committed
134
/*
135
136
137
138
139
140
 * stateid4
 *
 *	struct stateid4 {
 *		uint32_t	seqid;
 *		opaque		other[12];
 *	};
Linus Torvalds's avatar
Linus Torvalds committed
141
 */
142
143
144
static void encode_stateid4(struct xdr_stream *xdr, const stateid_t *sid)
{
	__be32 *p;
Linus Torvalds's avatar
Linus Torvalds committed
145

146
147
148
149
150
151
152
153
154
155
156
157
	p = xdr_reserve_space(xdr, NFS4_STATEID_SIZE);
	*p++ = cpu_to_be32(sid->si_generation);
	xdr_encode_opaque_fixed(p, &sid->si_opaque, NFS4_STATEID_OTHER_SIZE);
}

/*
 * sessionid4
 *
 *	typedef opaque sessionid4[NFS4_SESSIONID_SIZE];
 */
static void encode_sessionid4(struct xdr_stream *xdr,
			      const struct nfsd4_session *session)
158
159
160
{
	__be32 *p;

161
162
163
	p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN);
	xdr_encode_opaque_fixed(p, session->se_sessionid.data,
					NFS4_MAX_SESSIONID_LEN);
164
165
}

166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/*
 * nfsstat4
 */
static const struct {
	int stat;
	int errno;
} nfs_cb_errtbl[] = {
	{ NFS4_OK,		0		},
	{ NFS4ERR_PERM,		-EPERM		},
	{ NFS4ERR_NOENT,	-ENOENT		},
	{ NFS4ERR_IO,		-EIO		},
	{ NFS4ERR_NXIO,		-ENXIO		},
	{ NFS4ERR_ACCESS,	-EACCES		},
	{ NFS4ERR_EXIST,	-EEXIST		},
	{ NFS4ERR_XDEV,		-EXDEV		},
	{ NFS4ERR_NOTDIR,	-ENOTDIR	},
	{ NFS4ERR_ISDIR,	-EISDIR		},
	{ NFS4ERR_INVAL,	-EINVAL		},
	{ NFS4ERR_FBIG,		-EFBIG		},
	{ NFS4ERR_NOSPC,	-ENOSPC		},
	{ NFS4ERR_ROFS,		-EROFS		},
	{ NFS4ERR_MLINK,	-EMLINK		},
	{ NFS4ERR_NAMETOOLONG,	-ENAMETOOLONG	},
	{ NFS4ERR_NOTEMPTY,	-ENOTEMPTY	},
	{ NFS4ERR_DQUOT,	-EDQUOT		},
	{ NFS4ERR_STALE,	-ESTALE		},
	{ NFS4ERR_BADHANDLE,	-EBADHANDLE	},
	{ NFS4ERR_BAD_COOKIE,	-EBADCOOKIE	},
	{ NFS4ERR_NOTSUPP,	-ENOTSUPP	},
	{ NFS4ERR_TOOSMALL,	-ETOOSMALL	},
	{ NFS4ERR_SERVERFAULT,	-ESERVERFAULT	},
	{ NFS4ERR_BADTYPE,	-EBADTYPE	},
	{ NFS4ERR_LOCKED,	-EAGAIN		},
	{ NFS4ERR_RESOURCE,	-EREMOTEIO	},
	{ NFS4ERR_SYMLINK,	-ELOOP		},
	{ NFS4ERR_OP_ILLEGAL,	-EOPNOTSUPP	},
	{ NFS4ERR_DEADLOCK,	-EDEADLK	},
	{ -1,			-EIO		}
};

/*
 * If we cannot translate the error, the recovery routines should
 * handle it.
 *
 * Note: remaining NFSv4 error codes have values > 10000, so should
 * not conflict with native Linux error codes.
 */
static int nfs_cb_stat_to_errno(int status)
{
	int i;

	for (i = 0; nfs_cb_errtbl[i].stat != -1; i++) {
		if (nfs_cb_errtbl[i].stat == status)
			return nfs_cb_errtbl[i].errno;
	}

	dprintk("NFSD: Unrecognized NFS CB status value: %u\n", status);
	return -status;
}

static int decode_cb_op_status(struct xdr_stream *xdr, enum nfs_opnum4 expected,
227
			       int *status)
228
229
230
231
232
233
234
235
236
237
{
	__be32 *p;
	u32 op;

	p = xdr_inline_decode(xdr, 4 + 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	op = be32_to_cpup(p++);
	if (unlikely(op != expected))
		goto out_unexpected;
238
	*status = nfs_cb_stat_to_errno(be32_to_cpup(p));
239
240
241
242
243
244
245
246
247
248
	return 0;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
out_unexpected:
	dprintk("NFSD: Callback server returned operation %d but "
		"we issued a request for %d\n", op, expected);
	return -EIO;
}

249
250
251
252
253
254
255
256
257
258
259
260
/*
 * CB_COMPOUND4args
 *
 *	struct CB_COMPOUND4args {
 *		utf8str_cs	tag;
 *		uint32_t	minorversion;
 *		uint32_t	callback_ident;
 *		nfs_cb_argop4	argarray<>;
 *	};
*/
static void encode_cb_compound4args(struct xdr_stream *xdr,
				    struct nfs4_cb_compound_hdr *hdr)
Linus Torvalds's avatar
Linus Torvalds committed
261
{
262
	__be32 * p;
Linus Torvalds's avatar
Linus Torvalds committed
263

264
265
266
267
268
	p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4);
	p = xdr_encode_empty_array(p);		/* empty tag */
	*p++ = cpu_to_be32(hdr->minorversion);
	*p++ = cpu_to_be32(hdr->ident);

269
	hdr->nops_p = p;
270
	*p = cpu_to_be32(hdr->nops);		/* argarray element count */
Linus Torvalds's avatar
Linus Torvalds committed
271
272
}

273
274
275
/*
 * Update argarray element count
 */
276
277
static void encode_cb_nops(struct nfs4_cb_compound_hdr *hdr)
{
278
279
	BUG_ON(hdr->nops > NFS4_MAX_BACK_CHANNEL_OPS);
	*hdr->nops_p = cpu_to_be32(hdr->nops);
280
281
}

282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
/*
 * CB_COMPOUND4res
 *
 *	struct CB_COMPOUND4res {
 *		nfsstat4	status;
 *		utf8str_cs	tag;
 *		nfs_cb_resop4	resarray<>;
 *	};
 */
static int decode_cb_compound4res(struct xdr_stream *xdr,
				  struct nfs4_cb_compound_hdr *hdr)
{
	u32 length;
	__be32 *p;

	p = xdr_inline_decode(xdr, 4 + 4);
	if (unlikely(p == NULL))
		goto out_overflow;
	hdr->status = be32_to_cpup(p++);
	/* Ignore the tag */
	length = be32_to_cpup(p++);
	p = xdr_inline_decode(xdr, length + 4);
	if (unlikely(p == NULL))
		goto out_overflow;
306
	p += XDR_QUADLEN(length);
307
308
309
310
311
312
313
	hdr->nops = be32_to_cpup(p);
	return 0;
out_overflow:
	print_overflow_msg(__func__, xdr);
	return -EIO;
}

314
315
316
317
318
319
320
321
322
323
324
325
/*
 * CB_RECALL4args
 *
 *	struct CB_RECALL4args {
 *		stateid4	stateid;
 *		bool		truncate;
 *		nfs_fh4		fh;
 *	};
 */
static void encode_cb_recall4args(struct xdr_stream *xdr,
				  const struct nfs4_delegation *dp,
				  struct nfs4_cb_compound_hdr *hdr)
Linus Torvalds's avatar
Linus Torvalds committed
326
{
327
	__be32 *p;
328
329

	encode_nfs_cb_opnum4(xdr, OP_CB_RECALL);
330
	encode_stateid4(xdr, &dp->dl_stid.sc_stateid);
331
332
333
334

	p = xdr_reserve_space(xdr, 4);
	*p++ = xdr_zero;			/* truncate */

335
	encode_nfs_fh4(xdr, &dp->dl_stid.sc_file->fi_fhandle);
336

337
	hdr->nops++;
Linus Torvalds's avatar
Linus Torvalds committed
338
339
}

340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
/*
 * CB_SEQUENCE4args
 *
 *	struct CB_SEQUENCE4args {
 *		sessionid4		csa_sessionid;
 *		sequenceid4		csa_sequenceid;
 *		slotid4			csa_slotid;
 *		slotid4			csa_highest_slotid;
 *		bool			csa_cachethis;
 *		referring_call_list4	csa_referring_call_lists<>;
 *	};
 */
static void encode_cb_sequence4args(struct xdr_stream *xdr,
				    const struct nfsd4_callback *cb,
				    struct nfs4_cb_compound_hdr *hdr)
355
{
356
	struct nfsd4_session *session = cb->cb_clp->cl_cb_session;
357
358
359
360
361
	__be32 *p;

	if (hdr->minorversion == 0)
		return;

362
363
364
365
366
367
368
369
370
	encode_nfs_cb_opnum4(xdr, OP_CB_SEQUENCE);
	encode_sessionid4(xdr, session);

	p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4 + 4);
	*p++ = cpu_to_be32(session->se_cb_seq_nr);	/* csa_sequenceid */
	*p++ = xdr_zero;			/* csa_slotid */
	*p++ = xdr_zero;			/* csa_highest_slotid */
	*p++ = xdr_zero;			/* csa_cachethis */
	xdr_encode_empty_array(p);		/* csa_referring_call_lists */
371
372
373
374

	hdr->nops++;
}

375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
/*
 * CB_SEQUENCE4resok
 *
 *	struct CB_SEQUENCE4resok {
 *		sessionid4	csr_sessionid;
 *		sequenceid4	csr_sequenceid;
 *		slotid4		csr_slotid;
 *		slotid4		csr_highest_slotid;
 *		slotid4		csr_target_highest_slotid;
 *	};
 *
 *	union CB_SEQUENCE4res switch (nfsstat4 csr_status) {
 *	case NFS4_OK:
 *		CB_SEQUENCE4resok	csr_resok4;
 *	default:
 *		void;
 *	};
 *
 * Our current back channel implmentation supports a single backchannel
 * with a single slot.
 */
static int decode_cb_sequence4resok(struct xdr_stream *xdr,
				    struct nfsd4_callback *cb)
{
	struct nfsd4_session *session = cb->cb_clp->cl_cb_session;
400
	int status = -ESERVERFAULT;
401
402
403
404
405
406
407
	__be32 *p;
	u32 dummy;

	/*
	 * If the server returns different values for sessionID, slotID or
	 * sequence number, the server is looney tunes.
	 */
408
	p = xdr_inline_decode(xdr, NFS4_MAX_SESSIONID_LEN + 4 + 4 + 4 + 4);
409
410
	if (unlikely(p == NULL))
		goto out_overflow;
411
412

	if (memcmp(p, session->se_sessionid.data, NFS4_MAX_SESSIONID_LEN)) {
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
		dprintk("NFS: %s Invalid session id\n", __func__);
		goto out;
	}
	p += XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN);

	dummy = be32_to_cpup(p++);
	if (dummy != session->se_cb_seq_nr) {
		dprintk("NFS: %s Invalid sequence number\n", __func__);
		goto out;
	}

	dummy = be32_to_cpup(p++);
	if (dummy != 0) {
		dprintk("NFS: %s Invalid slotid\n", __func__);
		goto out;
	}

	/*
	 * FIXME: process highest slotid and target highest slotid
	 */
	status = 0;
out:
435
	cb->cb_seq_status = status;
436
437
438
	return status;
out_overflow:
	print_overflow_msg(__func__, xdr);
439
440
	status = -EIO;
	goto out;
441
442
443
444
445
446
447
}

static int decode_cb_sequence4res(struct xdr_stream *xdr,
				  struct nfsd4_callback *cb)
{
	int status;

448
	if (cb->cb_clp->cl_minorversion == 0)
449
450
		return 0;

451
452
	status = decode_cb_op_status(xdr, OP_CB_SEQUENCE, &cb->cb_seq_status);
	if (unlikely(status || cb->cb_seq_status))
453
454
455
		return status;

	return decode_cb_sequence4resok(xdr, cb);
456
457
}

458
459
460
461
462
463
464
465
466
467
468
469
/*
 * NFSv4.0 and NFSv4.1 XDR encode functions
 *
 * NFSv4.0 callback argument types are defined in section 15 of RFC
 * 3530: "Network File System (NFS) version 4 Protocol" and section 20
 * of RFC 5661:  "Network File System (NFS) Version 4 Minor Version 1
 * Protocol".
 */

/*
 * NB: Without this zero space reservation, callbacks over krb5p fail
 */
470
471
static void nfs4_xdr_enc_cb_null(struct rpc_rqst *req, struct xdr_stream *xdr,
				 void *__unused)
Linus Torvalds's avatar
Linus Torvalds committed
472
{
473
	xdr_reserve_space(xdr, 0);
Linus Torvalds's avatar
Linus Torvalds committed
474
475
}

476
477
478
/*
 * 20.2. Operation 4: CB_RECALL - Recall a Delegation
 */
479
480
static void nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, struct xdr_stream *xdr,
				   const struct nfsd4_callback *cb)
Linus Torvalds's avatar
Linus Torvalds committed
481
{
482
	const struct nfs4_delegation *dp = cb_to_delegation(cb);
Linus Torvalds's avatar
Linus Torvalds committed
483
	struct nfs4_cb_compound_hdr hdr = {
484
		.ident = cb->cb_clp->cl_cb_ident,
485
		.minorversion = cb->cb_clp->cl_minorversion,
Linus Torvalds's avatar
Linus Torvalds committed
486
487
	};

488
489
	encode_cb_compound4args(xdr, &hdr);
	encode_cb_sequence4args(xdr, cb, &hdr);
490
	encode_cb_recall4args(xdr, dp, &hdr);
491
	encode_cb_nops(&hdr);
Linus Torvalds's avatar
Linus Torvalds committed
492
493
494
}


495
/*
496
497
498
499
500
501
 * NFSv4.0 and NFSv4.1 XDR decode functions
 *
 * NFSv4.0 callback result types are defined in section 15 of RFC
 * 3530: "Network File System (NFS) version 4 Protocol" and section 20
 * of RFC 5661:  "Network File System (NFS) Version 4 Minor Version 1
 * Protocol".
502
503
 */

504
505
static int nfs4_xdr_dec_cb_null(struct rpc_rqst *req, struct xdr_stream *xdr,
				void *__unused)
Linus Torvalds's avatar
Linus Torvalds committed
506
507
508
509
{
	return 0;
}

510
511
512
/*
 * 20.2. Operation 4: CB_RECALL - Recall a Delegation
 */
513
514
static int nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp,
				  struct xdr_stream *xdr,
515
				  struct nfsd4_callback *cb)
Linus Torvalds's avatar
Linus Torvalds committed
516
517
518
519
{
	struct nfs4_cb_compound_hdr hdr;
	int status;

520
	status = decode_cb_compound4res(xdr, &hdr);
521
	if (unlikely(status))
522
		return status;
523
524

	if (cb != NULL) {
525
		status = decode_cb_sequence4res(xdr, cb);
526
		if (unlikely(status || cb->cb_seq_status))
527
			return status;
528
	}
529

530
	return decode_cb_op_status(xdr, OP_CB_RECALL, &cb->cb_status);
Linus Torvalds's avatar
Linus Torvalds committed
531
532
}

533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
#ifdef CONFIG_NFSD_PNFS
/*
 * CB_LAYOUTRECALL4args
 *
 *	struct layoutrecall_file4 {
 *		nfs_fh4         lor_fh;
 *		offset4         lor_offset;
 *		length4         lor_length;
 *		stateid4        lor_stateid;
 *	};
 *
 *	union layoutrecall4 switch(layoutrecall_type4 lor_recalltype) {
 *	case LAYOUTRECALL4_FILE:
 *		layoutrecall_file4 lor_layout;
 *	case LAYOUTRECALL4_FSID:
 *		fsid4              lor_fsid;
 *	case LAYOUTRECALL4_ALL:
 *		void;
 *	};
 *
 *	struct CB_LAYOUTRECALL4args {
 *		layouttype4             clora_type;
 *		layoutiomode4           clora_iomode;
 *		bool                    clora_changed;
 *		layoutrecall4           clora_recall;
 *	};
 */
static void encode_cb_layout4args(struct xdr_stream *xdr,
				  const struct nfs4_layout_stateid *ls,
				  struct nfs4_cb_compound_hdr *hdr)
{
	__be32 *p;

	BUG_ON(hdr->minorversion == 0);

	p = xdr_reserve_space(xdr, 5 * 4);
	*p++ = cpu_to_be32(OP_CB_LAYOUTRECALL);
	*p++ = cpu_to_be32(ls->ls_layout_type);
	*p++ = cpu_to_be32(IOMODE_ANY);
	*p++ = cpu_to_be32(1);
	*p = cpu_to_be32(RETURN_FILE);

	encode_nfs_fh4(xdr, &ls->ls_stid.sc_file->fi_fhandle);

	p = xdr_reserve_space(xdr, 2 * 8);
	p = xdr_encode_hyper(p, 0);
	xdr_encode_hyper(p, NFS4_MAX_UINT64);

	encode_stateid4(xdr, &ls->ls_recall_sid);

	hdr->nops++;
}

static void nfs4_xdr_enc_cb_layout(struct rpc_rqst *req,
				   struct xdr_stream *xdr,
				   const struct nfsd4_callback *cb)
{
	const struct nfs4_layout_stateid *ls =
		container_of(cb, struct nfs4_layout_stateid, ls_recall);
	struct nfs4_cb_compound_hdr hdr = {
		.ident = 0,
594
		.minorversion = cb->cb_clp->cl_minorversion,
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
	};

	encode_cb_compound4args(xdr, &hdr);
	encode_cb_sequence4args(xdr, cb, &hdr);
	encode_cb_layout4args(xdr, ls, &hdr);
	encode_cb_nops(&hdr);
}

static int nfs4_xdr_dec_cb_layout(struct rpc_rqst *rqstp,
				  struct xdr_stream *xdr,
				  struct nfsd4_callback *cb)
{
	struct nfs4_cb_compound_hdr hdr;
	int status;

	status = decode_cb_compound4res(xdr, &hdr);
	if (unlikely(status))
612
613
		return status;

614
615
	if (cb) {
		status = decode_cb_sequence4res(xdr, cb);
616
		if (unlikely(status || cb->cb_seq_status))
617
			return status;
618
	}
619
	return decode_cb_op_status(xdr, OP_CB_LAYOUTRECALL, &cb->cb_status);
620
621
622
}
#endif /* CONFIG_NFSD_PNFS */

623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
static void encode_stateowner(struct xdr_stream *xdr, struct nfs4_stateowner *so)
{
	__be32	*p;

	p = xdr_reserve_space(xdr, 8 + 4 + so->so_owner.len);
	p = xdr_encode_opaque_fixed(p, &so->so_client->cl_clientid, 8);
	xdr_encode_opaque(p, so->so_owner.data, so->so_owner.len);
}

static void nfs4_xdr_enc_cb_notify_lock(struct rpc_rqst *req,
					struct xdr_stream *xdr,
					const struct nfsd4_callback *cb)
{
	const struct nfsd4_blocked_lock *nbl =
		container_of(cb, struct nfsd4_blocked_lock, nbl_cb);
	struct nfs4_lockowner *lo = (struct nfs4_lockowner *)nbl->nbl_lock.fl_owner;
	struct nfs4_cb_compound_hdr hdr = {
		.ident = 0,
		.minorversion = cb->cb_clp->cl_minorversion,
	};

	__be32 *p;

	BUG_ON(hdr.minorversion == 0);

	encode_cb_compound4args(xdr, &hdr);
	encode_cb_sequence4args(xdr, cb, &hdr);

	p = xdr_reserve_space(xdr, 4);
	*p = cpu_to_be32(OP_CB_NOTIFY_LOCK);
	encode_nfs_fh4(xdr, &nbl->nbl_fh);
	encode_stateowner(xdr, &lo->lo_owner);
	hdr.nops++;

	encode_cb_nops(&hdr);
}

static int nfs4_xdr_dec_cb_notify_lock(struct rpc_rqst *rqstp,
					struct xdr_stream *xdr,
					struct nfsd4_callback *cb)
{
	struct nfs4_cb_compound_hdr hdr;
	int status;

	status = decode_cb_compound4res(xdr, &hdr);
	if (unlikely(status))
		return status;

	if (cb) {
		status = decode_cb_sequence4res(xdr, cb);
		if (unlikely(status || cb->cb_seq_status))
			return status;
	}
	return decode_cb_op_status(xdr, OP_CB_NOTIFY_LOCK, &cb->cb_status);
}

Linus Torvalds's avatar
Linus Torvalds committed
679
680
681
/*
 * RPC procedure tables
 */
682
683
684
#define PROC(proc, call, argtype, restype)				\
[NFSPROC4_CLNT_##proc] = {						\
	.p_proc    = NFSPROC4_CB_##call,				\
685
	.p_encode  = (kxdreproc_t)nfs4_xdr_enc_##argtype,		\
686
	.p_decode  = (kxdrdproc_t)nfs4_xdr_dec_##restype,		\
687
688
689
690
	.p_arglen  = NFS4_enc_##argtype##_sz,				\
	.p_replen  = NFS4_dec_##restype##_sz,				\
	.p_statidx = NFSPROC4_CB_##call,				\
	.p_name    = #proc,						\
Linus Torvalds's avatar
Linus Torvalds committed
691
692
}

693
694
695
static struct rpc_procinfo nfs4_cb_procedures[] = {
	PROC(CB_NULL,	NULL,		cb_null,	cb_null),
	PROC(CB_RECALL,	COMPOUND,	cb_recall,	cb_recall),
696
697
698
#ifdef CONFIG_NFSD_PNFS
	PROC(CB_LAYOUT,	COMPOUND,	cb_layout,	cb_layout),
#endif
699
	PROC(CB_NOTIFY_LOCK,	COMPOUND,	cb_notify_lock,	cb_notify_lock),
Linus Torvalds's avatar
Linus Torvalds committed
700
701
};

702
static struct rpc_version nfs_cb_version4 = {
703
704
705
706
707
708
709
/*
 * Note on the callback rpc program version number: despite language in rfc
 * 5661 section 18.36.3 requiring servers to use 4 in this field, the
 * official xdr descriptions for both 4.0 and 4.1 specify version 1, and
 * in practice that appears to be what implementations use.  The section
 * 18.36.3 language is expected to be fixed in an erratum.
 */
710
711
712
	.number			= 1,
	.nrprocs		= ARRAY_SIZE(nfs4_cb_procedures),
	.procs			= nfs4_cb_procedures
Linus Torvalds's avatar
Linus Torvalds committed
713
714
};

715
static const struct rpc_version *nfs_cb_version[] = {
Linus Torvalds's avatar
Linus Torvalds committed
716
717
718
	&nfs_cb_version4,
};

719
static const struct rpc_program cb_program;
720
721

static struct rpc_stat cb_stats = {
722
	.program		= &cb_program
723
724
725
};

#define NFS4_CALLBACK 0x40000000
726
static const struct rpc_program cb_program = {
727
728
729
730
731
	.name			= "nfs4_cb",
	.number			= NFS4_CALLBACK,
	.nrvers			= ARRAY_SIZE(nfs_cb_version),
	.version		= nfs_cb_version,
	.stats			= &cb_stats,
732
	.pipe_dir_name		= "nfsd4_cb",
733
734
};

735
static int max_cb_time(struct net *net)
J. Bruce Fields's avatar
J. Bruce Fields committed
736
{
737
738
	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
	return max(nn->nfsd4_lease/10, (time_t)1) * HZ;
J. Bruce Fields's avatar
J. Bruce Fields committed
739
740
}

741
742
743
744
745
746
747
748
749
750
751
752
static struct rpc_cred *callback_cred;

int set_callback_cred(void)
{
	if (callback_cred)
		return 0;
	callback_cred = rpc_lookup_machine_cred("nfs");
	if (!callback_cred)
		return -ENOMEM;
	return 0;
}

753
754
755
756
757
758
759
760
void cleanup_callback_cred(void)
{
	if (callback_cred) {
		put_rpccred(callback_cred);
		callback_cred = NULL;
	}
}

761
static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses)
762
763
764
765
766
767
768
769
770
771
772
773
{
	if (clp->cl_minorversion == 0) {
		return get_rpccred(callback_cred);
	} else {
		struct rpc_auth *auth = client->cl_auth;
		struct auth_cred acred = {};

		acred.uid = ses->se_cb_sec.uid;
		acred.gid = ses->se_cb_sec.gid;
		return auth->au_ops->lookup_cred(client->cl_auth, &acred, 0);
	}
}
774

775
static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
776
{
777
	int maxtime = max_cb_time(clp->net);
778
	struct rpc_timeout	timeparms = {
779
		.to_initval	= maxtime,
J. Bruce Fields's avatar
J. Bruce Fields committed
780
		.to_retries	= 0,
781
		.to_maxval	= maxtime,
782
783
	};
	struct rpc_create_args args = {
784
		.net		= clp->net,
785
786
		.address	= (struct sockaddr *) &conn->cb_addr,
		.addrsize	= conn->cb_addrlen,
787
		.saddress	= (struct sockaddr *) &conn->cb_saddr,
788
		.timeout	= &timeparms,
789
		.program	= &cb_program,
790
		.version	= 0,
Olga Kornievskaia's avatar
Olga Kornievskaia committed
791
		.flags		= (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
792
	};
793
	struct rpc_clnt *client;
794
	struct rpc_cred *cred;
Linus Torvalds's avatar
Linus Torvalds committed
795

796
	if (clp->cl_minorversion == 0) {
797
		if (!clp->cl_cred.cr_principal &&
798
				(clp->cl_cred.cr_flavor >= RPC_AUTH_GSS_KRB5))
799
			return -EINVAL;
800
		args.client_name = clp->cl_cred.cr_principal;
801
		args.prognumber	= conn->cb_prog;
802
		args.protocol = XPRT_TRANSPORT_TCP;
803
		args.authflavor = clp->cl_cred.cr_flavor;
804
805
		clp->cl_cb_ident = conn->cb_ident;
	} else {
806
807
808
809
		if (!conn->cb_xprt)
			return -EINVAL;
		clp->cl_cb_conn.cb_xprt = conn->cb_xprt;
		clp->cl_cb_session = ses;
810
		args.bc_xprt = conn->cb_xprt;
811
		args.prognumber = clp->cl_cb_session->se_cb_prog;
812
813
		args.protocol = conn->cb_xprt->xpt_class->xcl_ident |
				XPRT_TRANSPORT_BC;
814
		args.authflavor = ses->se_cb_sec.flavor;
815
	}
816
	/* Create RPC client */
817
	client = rpc_create(&args);
818
	if (IS_ERR(client)) {
819
820
		dprintk("NFSD: couldn't create callback client: %ld\n",
			PTR_ERR(client));
821
822
		return PTR_ERR(client);
	}
823
824
825
826
827
	cred = get_backchannel_cred(clp, client, ses);
	if (IS_ERR(cred)) {
		rpc_shutdown_client(client);
		return PTR_ERR(cred);
	}
828
	clp->cl_cb_client = client;
829
	clp->cl_cb_cred = cred;
830
	return 0;
831
832
}

833
834
835
836
837
838
static void warn_no_callback_path(struct nfs4_client *clp, int reason)
{
	dprintk("NFSD: warning: no callback path to client %.*s: error %d\n",
		(int)clp->cl_name.len, clp->cl_name.data, reason);
}

839
840
static void nfsd4_mark_cb_down(struct nfs4_client *clp, int reason)
{
841
842
	if (test_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags))
		return;
843
844
845
846
	clp->cl_cb_state = NFSD4_CB_DOWN;
	warn_no_callback_path(clp, reason);
}

847
848
static void nfsd4_mark_cb_fault(struct nfs4_client *clp, int reason)
{
849
850
	if (test_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags))
		return;
851
852
853
854
	clp->cl_cb_state = NFSD4_CB_FAULT;
	warn_no_callback_path(clp, reason);
}

855
856
static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
{
857
	struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null);
858
859

	if (task->tk_status)
860
		nfsd4_mark_cb_down(clp, task->tk_status);
861
	else
862
		clp->cl_cb_state = NFSD4_CB_UP;
863
864
865
}

static const struct rpc_call_ops nfsd4_cb_probe_ops = {
866
867
	/* XXX: release method to ensure we set the cb channel down if
	 * necessary on early failure? */
868
869
870
	.rpc_call_done = nfsd4_cb_probe_done,
};

871
static struct workqueue_struct *callback_wq;
872

873
/*
874
875
 * Poke the callback thread to process any updates to the callback
 * parameters, and send a null probe.
876
 */
877
878
void nfsd4_probe_callback(struct nfs4_client *clp)
{
879
	clp->cl_cb_state = NFSD4_CB_UNKNOWN;
880
	set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags);
881
	nfsd4_run_cb(&clp->cl_cb_null);
882
883
}

884
void nfsd4_probe_callback_sync(struct nfs4_client *clp)
885
{
886
887
888
	nfsd4_probe_callback(clp);
	flush_workqueue(callback_wq);
}
889

890
void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
891
{
892
	clp->cl_cb_state = NFSD4_CB_UNKNOWN;
893
894
895
	spin_lock(&clp->cl_lock);
	memcpy(&clp->cl_cb_conn, conn, sizeof(struct nfs4_cb_conn));
	spin_unlock(&clp->cl_lock);
Linus Torvalds's avatar
Linus Torvalds committed
896
897
}

898
899
900
901
902
/*
 * There's currently a single callback channel slot.
 * If the slot is available, then mark it busy.  Otherwise, set the
 * thread for sleeping on the callback RPC wait queue.
 */
903
static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task)
904
905
906
{
	if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
		rpc_sleep_on(&clp->cl_cb_waitq, task, NULL);
907
908
909
910
911
912
		/* Race breaker */
		if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
			dprintk("%s slot is busy\n", __func__);
			return false;
		}
		rpc_wake_up_queued_task(&clp->cl_cb_waitq, task);
913
	}
914
	return true;
915
916
917
918
919
920
921
922
}

/*
 * TODO: cb_sequence should support referring call lists, cachethis, multiple
 * slots, and mark callback channel down on communication errors.
 */
static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
{
J. Bruce Fields's avatar
J. Bruce Fields committed
923
	struct nfsd4_callback *cb = calldata;
924
	struct nfs4_client *clp = cb->cb_clp;
925
	u32 minorversion = clp->cl_minorversion;
926

927
928
929
930
931
	/*
	 * cb_seq_status is only set in decode_cb_sequence4res,
	 * and so will remain 1 if an rpc level failure occurs.
	 */
	cb->cb_seq_status = 1;
932
	cb->cb_status = 0;
933
	if (minorversion) {
934
		if (!nfsd41_cb_get_slot(clp, task))
935
936
937
938
939
			return;
	}
	rpc_call_start(task);
}

940
static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback *cb)
941
{
942
	struct nfs4_client *clp = cb->cb_clp;
943
944
	struct nfsd4_session *session = clp->cl_cb_session;
	bool ret = true;
945

946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
	if (!clp->cl_minorversion) {
		/*
		 * If the backchannel connection was shut down while this
		 * task was queued, we need to resubmit it after setting up
		 * a new backchannel connection.
		 *
		 * Note that if we lost our callback connection permanently
		 * the submission code will error out, so we don't need to
		 * handle that case here.
		 */
		if (task->tk_flags & RPC_TASK_KILLED)
			goto need_restart;

		return true;
	}
961

962
963
	switch (cb->cb_seq_status) {
	case 0:
964
965
966
967
968
969
970
		/*
		 * No need for lock, access serialized in nfsd4_cb_prepare
		 *
		 * RFC5661 20.9.3
		 * If CB_SEQUENCE returns an error, then the state of the slot
		 * (sequence ID, cached reply) MUST NOT change.
		 */
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
		++session->se_cb_seq_nr;
		break;
	case -ESERVERFAULT:
		++session->se_cb_seq_nr;
	case 1:
	case -NFS4ERR_BADSESSION:
		nfsd4_mark_cb_fault(cb->cb_clp, cb->cb_seq_status);
		ret = false;
		break;
	case -NFS4ERR_DELAY:
		if (!rpc_restart_call(task))
			goto out;

		rpc_delay(task, 2 * HZ);
		return false;
	case -NFS4ERR_BADSLOT:
		goto retry_nowait;
	case -NFS4ERR_SEQ_MISORDERED:
		if (session->se_cb_seq_nr != 1) {
			session->se_cb_seq_nr = 1;
			goto retry_nowait;
		}
		break;
	default:
		dprintk("%s: unprocessed error %d\n", __func__,
			cb->cb_seq_status);
997
998
	}

999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
	clear_bit(0, &clp->cl_cb_slot_busy);
	rpc_wake_up_next(&clp->cl_cb_waitq);
	dprintk("%s: freed slot, new seqid=%d\n", __func__,
		clp->cl_cb_session->se_cb_seq_nr);

	if (task->tk_flags & RPC_TASK_KILLED)
		goto need_restart;
out:
	return ret;
retry_nowait:
	if (rpc_restart_call_prepare(task))
		ret = false;
	goto out;
need_restart:
	task->tk_status = 0;
	cb->cb_need_restart = true;
	return false;
}

static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
{
	struct nfsd4_callback *cb = calldata;
	struct nfs4_client *clp = cb->cb_clp;

	dprintk("%s: minorversion=%d\n", __func__,
		clp->cl_minorversion);

	if (!nfsd4_cb_sequence_done(task, cb))
1027
1028
		return;

1029
1030
1031
1032
1033
	if (cb->cb_status) {
		WARN_ON_ONCE(task->tk_status);
		task->tk_status = cb->cb_status;
	}

1034
	switch (cb->cb_ops->done(cb, task)) {
1035
	case 0:
1036
1037
1038
1039
		task->tk_status = 0;
		rpc_restart_call_prepare(task);
		return;
	case 1:
1040
		break;
1041
	case -1:
1042
		/* Network partition? */
1043
		nfsd4_mark_cb_down(clp, task->tk_status);
1044
1045
1046
		break;
	default:
		BUG();
1047
1048
1049
	}
}

1050
static void nfsd4_cb_release(void *calldata)
1051
{
J. Bruce Fields's avatar
J. Bruce Fields committed
1052
	struct nfsd4_callback *cb = calldata;
1053

1054
1055
1056
	if (cb->cb_need_restart)
		nfsd4_run_cb(cb);
	else
1057
		cb->cb_ops->release(cb);
1058

1059
1060
}

1061
static const struct rpc_call_ops nfsd4_cb_ops = {
1062
	.rpc_call_prepare = nfsd4_cb_prepare,
1063
1064
	.rpc_call_done = nfsd4_cb_done,
	.rpc_release = nfsd4_cb_release,
1065
1066
};

1067
1068
int nfsd4_create_callback_queue(void)
{
1069
	callback_wq = alloc_ordered_workqueue("nfsd4_callbacks", 0);
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
	if (!callback_wq)
		return -ENOMEM;
	return 0;
}

void nfsd4_destroy_callback_queue(void)
{
	destroy_workqueue(callback_wq);
}

1080
/* must be called under the state lock */
1081
void nfsd4_shutdown_callback(struct nfs4_client *clp)
1082
{
1083
	set_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags);
1084
	/*
1085
	 * Note this won't actually result in a null callback;
1086
	 * instead, nfsd4_run_cb_null() will detect the killed
1087
	 * client, destroy the rpc client, and stop:
1088
	 */
1089
	nfsd4_run_cb(&clp->cl_cb_null);
1090
1091
1092
	flush_workqueue(callback_wq);
}

1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
/* requires cl_lock: */
static struct nfsd4_conn * __nfsd4_find_backchannel(struct nfs4_client *clp)
{
	struct nfsd4_session *s;
	struct nfsd4_conn *c;

	list_for_each_entry(s, &clp->cl_sessions, se_perclnt) {
		list_for_each_entry(c, &s->se_conns, cn_persession) {
			if (c->cn_flags & NFS4_CDFC4_BACK)
				return c;
		}
	}
	return NULL;
}

1108
static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
1109
1110
1111
{
	struct nfs4_cb_conn conn;
	struct nfs4_client *clp = cb->cb_clp;
1112
1113
	struct nfsd4_session *ses = NULL;
	struct nfsd4_conn *c;
1114
1115
1116
1117
1118
1119
1120
1121
1122
	int err;

	/*
	 * This is either an update, or the client dying; in either case,
	 * kill the old client:
	 */
	if (clp->cl_cb_client) {
		rpc_shutdown_client(clp->cl_cb_client);
		clp->cl_cb_client = NULL;
1123
1124
		put_rpccred(clp->cl_cb_cred);
		clp->cl_cb_cred = NULL;
1125
	}
1126
1127
1128
1129
	if (clp->cl_cb_conn.cb_xprt) {
		svc_xprt_put(clp->cl_cb_conn.cb_xprt);
		clp->cl_cb_conn.cb_xprt = NULL;
	}
1130
	if (test_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags))
1131
1132
1133
1134
1135
1136
		return;
	spin_lock(&clp->cl_lock);
	/*
	 * Only serialized callback code is allowed to clear these
	 * flags; main nfsd code can only set them:
	 */
1137
1138
	BUG_ON(!(clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK));
	clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags);
1139
	memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn));
1140
1141
1142
1143
1144
1145
	c = __nfsd4_find_backchannel(clp);
	if (c) {
		svc_xprt_get(c->cn_xprt);
		conn.cb_xprt = c->cn_xprt;
		ses = c->cn_session;
	}
1146
1147
	spin_unlock(&clp->cl_lock);

1148
	err = setup_callback_client(clp, &conn, ses);
1149
	if (err) {
1150
		nfsd4_mark_cb_down(clp, err);
1151
1152
		return;
	}
1153
1154
}

1155
static void
1156
nfsd4_run_cb_work(struct work_struct *work)
J. Bruce Fields's avatar
J. Bruce Fields committed
1157
{
1158
1159
	struct nfsd4_callback *cb =
		container_of(work, struct nfsd4_callback, cb_work);
1160
	struct nfs4_client *clp = cb->cb_clp;
1161
	struct rpc_clnt *clnt;
Linus Torvalds's avatar
Linus Torvalds committed
1162

1163
1164
1165
1166
1167
1168
	if (cb->cb_need_restart) {
		cb->cb_need_restart = false;
	} else {
		if (cb->cb_ops && cb->cb_ops->prepare)
			cb->cb_ops->prepare(cb);
	}
1169

1170
	if (clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK)
1171
1172
1173
1174
1175
		nfsd4_process_cb_update(cb);

	clnt = clp->cl_cb_client;
	if (!clnt) {
		/* Callback channel broken, or client killed; give up: */
1176
1177
		if (cb->cb_ops && cb->cb_ops->release)
			cb->cb_ops->release(cb);
1178
		return;
1179
	}
1180
1181
1182
1183
1184
1185
1186
1187
1188

	/*
	 * Don't send probe messages for 4.1 or later.
	 */
	if (!cb->cb_ops && clp->cl_minorversion) {
		clp->cl_cb_state = NFSD4_CB_UP;
		return;
	}

1189
	cb->cb_msg.rpc_cred = clp->cl_cb_cred;
1190
	rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
1191
			cb->cb_ops ? &nfsd4_cb_ops : &nfsd4_cb_probe_ops, cb);
1192
1193
}

1194
void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp,
1195
		const struct nfsd4_callback_ops *ops, enum nfsd4_cb_op op)
1196
{
1197
	cb->cb_clp = clp;
1198
	cb->cb_msg.rpc_proc = &nfs4_cb_procedures[op];
1199
1200
	cb->cb_msg.rpc_argp = cb;
	cb->cb_msg.rpc_resp = cb;
1201
1202
	cb->cb_ops = ops;
	INIT_WORK(&cb->cb_work, nfsd4_run_cb_work);
1203
	cb->cb_seq_status = 1;
1204
	cb->cb_status = 0;
1205
	cb->cb_need_restart = false;
1206
}
1207

1208
1209
void nfsd4_run_cb(struct nfsd4_callback *cb)
{
1210
	queue_work(callback_wq, &cb->cb_work);
1211
}