1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25/*
26 * This is the loadable module wrapper.
27 */
28#include <sys/systm.h>
29#include <sys/modctl.h>
30#include <sys/syscall.h>
31#include <sys/ddi.h>
32#include <sys/cmn_err.h>
33
34#include <nfs/nfs.h>
35#include <nfs/nfs_clnt.h>
36#include <nfs/nfs4.h>
37#include <nfs/rnode4.h>
38
39/*
40 * The global tag list.
41 */
42ctag_t nfs4_ctags[] = NFS4_TAG_INITIALIZER;
43
44/*
45 * The NFS Version 4 client VFS.
46 */
47static vfsdef_t vfw4 = {
48	VFSDEF_VERSION,
49	"nfs4",
50	nfs4init,
51	VSW_CANREMOUNT|VSW_NOTZONESAFE|VSW_STATS|VSW_ZMOUNT,
52	NULL
53};
54
55struct modlfs modlfs4 = {
56	&mod_fsops,
57	"network filesystem version 4",
58	&vfw4
59};
60
61static uint_t nfs4_max_transfer_size = 32 * 1024;
62static uint_t nfs4_max_transfer_size_cots = 1024 * 1024;
63static uint_t nfs4_max_transfer_size_rdma = 1024 * 1024;
64
65int
66nfs4tsize(void)
67{
68	/*
69	 * For the moment, just return nfs4_max_transfer_size until we
70	 * can query the appropriate transport.
71	 */
72	return (nfs4_max_transfer_size);
73}
74
75uint_t
76nfs4_tsize(struct knetconfig *knp)
77{
78
79	if (knp->knc_semantics == NC_TPI_COTS_ORD ||
80	    knp->knc_semantics == NC_TPI_COTS)
81		return (nfs4_max_transfer_size_cots);
82	if (knp->knc_semantics == NC_TPI_RDMA)
83		return (nfs4_max_transfer_size_rdma);
84	return (nfs4_max_transfer_size);
85}
86
87uint_t
88rfs4_tsize(struct svc_req *req)
89{
90
91	if (req->rq_xprt->xp_type == T_COTS_ORD ||
92	    req->rq_xprt->xp_type == T_COTS)
93		return (nfs4_max_transfer_size_cots);
94	if (req->rq_xprt->xp_type == T_RDMA)
95		return (nfs4_max_transfer_size_rdma);
96	return (nfs4_max_transfer_size);
97}
98
99int
100nfs4_setopts(vnode_t *vp, model_t model, struct nfs_args *buf)
101{
102	mntinfo4_t *mi;			/* mount info, pointed at by vfs */
103	STRUCT_HANDLE(nfs_args, args);
104	int flags;
105
106#ifdef lint
107	model = model;
108#endif
109
110	STRUCT_SET_HANDLE(args, model, buf);
111
112	flags = STRUCT_FGET(args, flags);
113
114	/*
115	 * Set option fields in mount info record
116	 */
117	mi = VTOMI4(vp);
118
119
120	if (flags & NFSMNT_NOAC) {
121		mutex_enter(&mi->mi_lock);
122		mi->mi_flags |= MI4_NOAC;
123		mutex_exit(&mi->mi_lock);
124		PURGE_ATTRCACHE4(vp);
125	}
126
127	mutex_enter(&mi->mi_lock);
128	if (flags & NFSMNT_NOCTO)
129		mi->mi_flags |= MI4_NOCTO;
130	if (flags & NFSMNT_LLOCK)
131		mi->mi_flags |= MI4_LLOCK;
132	if (flags & NFSMNT_GRPID)
133		mi->mi_flags |= MI4_GRPID;
134	mutex_exit(&mi->mi_lock);
135
136	if (flags & NFSMNT_RETRANS) {
137		if (STRUCT_FGET(args, retrans) < 0)
138			return (EINVAL);
139		mi->mi_retrans = STRUCT_FGET(args, retrans);
140	}
141	if (flags & NFSMNT_TIMEO) {
142		if (STRUCT_FGET(args, timeo) <= 0)
143			return (EINVAL);
144		mi->mi_timeo = STRUCT_FGET(args, timeo);
145	}
146	if (flags & NFSMNT_RSIZE) {
147		if (STRUCT_FGET(args, rsize) <= 0)
148			return (EINVAL);
149		mi->mi_tsize = MIN(mi->mi_tsize, STRUCT_FGET(args, rsize));
150		mi->mi_curread = MIN(mi->mi_curread, mi->mi_tsize);
151	}
152	if (flags & NFSMNT_WSIZE) {
153		if (STRUCT_FGET(args, wsize) <= 0)
154			return (EINVAL);
155		mi->mi_stsize = MIN(mi->mi_stsize, STRUCT_FGET(args, wsize));
156		mi->mi_curwrite = MIN(mi->mi_curwrite, mi->mi_stsize);
157	}
158	if (flags & NFSMNT_ACREGMIN) {
159		if (STRUCT_FGET(args, acregmin) < 0)
160			mi->mi_acregmin = SEC2HR(ACMINMAX);
161		else
162			mi->mi_acregmin = SEC2HR(MIN(STRUCT_FGET(args,
163			    acregmin), ACMINMAX));
164	}
165	if (flags & NFSMNT_ACREGMAX) {
166		if (STRUCT_FGET(args, acregmax) < 0)
167			mi->mi_acregmax = SEC2HR(ACMAXMAX);
168		else
169			mi->mi_acregmax = SEC2HR(MIN(STRUCT_FGET(args,
170			    acregmax), ACMAXMAX));
171	}
172	if (flags & NFSMNT_ACDIRMIN) {
173		if (STRUCT_FGET(args, acdirmin) < 0)
174			mi->mi_acdirmin = SEC2HR(ACMINMAX);
175		else
176			mi->mi_acdirmin = SEC2HR(MIN(STRUCT_FGET(args,
177			    acdirmin), ACMINMAX));
178	}
179	if (flags & NFSMNT_ACDIRMAX) {
180		if (STRUCT_FGET(args, acdirmax) < 0)
181			mi->mi_acdirmax = SEC2HR(ACMAXMAX);
182		else
183			mi->mi_acdirmax = SEC2HR(MIN(STRUCT_FGET(args,
184			    acdirmax), ACMAXMAX));
185	}
186
187	return (0);
188}
189
190/*
191 * This returns 1 if the seqid should be bumped upon receiving this
192 * 'res->status' for a seqid dependent operation; otherwise return 0.
193 */
194int
195nfs4_need_to_bump_seqid(COMPOUND4res_clnt *res)
196{
197	int i, seqid_dep_op = 0;
198	nfs_resop4 *resop;
199
200	resop = res->array;
201
202	for (i = 0; i < res->array_len; i++) {
203		switch (resop[i].resop) {
204		case OP_CLOSE:
205		case OP_OPEN:
206		case OP_OPEN_CONFIRM:
207		case OP_OPEN_DOWNGRADE:
208		case OP_LOCK:
209		case OP_LOCKU:
210			seqid_dep_op = 1;
211			break;
212		default:
213			continue;
214		}
215	}
216
217	if (!seqid_dep_op)
218		return (0);
219
220	switch (res->status) {
221	case NFS4ERR_STALE_CLIENTID:
222	case NFS4ERR_STALE_STATEID:
223	case NFS4ERR_BAD_STATEID:
224	case NFS4ERR_BAD_SEQID:
225	case NFS4ERR_BADXDR:
226	case NFS4ERR_OLD_STATEID:
227	case NFS4ERR_RESOURCE:
228	case NFS4ERR_NOFILEHANDLE:
229		return (0);
230	default:
231		return (1);
232	}
233}
234
235/*
236 * Returns 1 if the error is a RPC error that we should retry.
237 */
238int
239nfs4_rpc_retry_error(int error)
240{
241	switch (error) {
242	case ETIMEDOUT:
243	case ECONNREFUSED:
244	case ENETDOWN:
245	case ENETUNREACH:
246	case ENETRESET:
247	case ECONNABORTED:
248	case EHOSTUNREACH:
249	case ECONNRESET:
250		return (1);
251	default:
252		return (0);
253	}
254}
255
256char *
257nfs4_stat_to_str(nfsstat4 error)
258{
259	static char	buf[40];
260
261	switch (error) {
262	case NFS4_OK:
263		return ("NFS4_OK");
264	case NFS4ERR_PERM:
265		return ("NFS4ERR_PERM");
266	case NFS4ERR_NOENT:
267		return ("NFS4ERR_NOENT");
268	case NFS4ERR_IO:
269		return ("NFS4ERR_IO");
270	case NFS4ERR_NXIO:
271		return ("NFS4ERR_NXIO");
272	case NFS4ERR_ACCESS:
273		return ("NFS4ERR_ACCESS");
274	case NFS4ERR_EXIST:
275		return ("NFS4ERR_EXIST");
276	case NFS4ERR_XDEV:
277		return ("NFS4ERR_XDEV");
278	case NFS4ERR_NOTDIR:
279		return ("NFS4ERR_NOTDIR");
280	case NFS4ERR_ISDIR:
281		return ("NFS4ERR_ISDIR");
282	case NFS4ERR_INVAL:
283		return ("NFS4ERR_INVAL");
284	case NFS4ERR_FBIG:
285		return ("NFS4ERR_FBIG");
286	case NFS4ERR_NOSPC:
287		return ("NFS4ERR_NOSPC");
288	case NFS4ERR_ROFS:
289		return ("NFS4ERR_ROFS");
290	case NFS4ERR_MLINK:
291		return ("NFS4ERR_MLINK");
292	case NFS4ERR_NAMETOOLONG:
293		return ("NFS4ERR_NAMETOOLONG");
294	case NFS4ERR_NOTEMPTY:
295		return ("NFSS4ERR_NOTEMPTY");
296	case NFS4ERR_DQUOT:
297		return ("NFS4ERR_DQUOT");
298	case NFS4ERR_STALE:
299		return ("NFS4ERR_STALE");
300	case NFS4ERR_BADHANDLE:
301		return ("NFS4ERR_BADHANDLE");
302	case NFS4ERR_BAD_COOKIE:
303		return ("NFS4ERR_BAD_COOKIE");
304	case NFS4ERR_NOTSUPP:
305		return ("NFS4ERR_NOTSUPP");
306	case NFS4ERR_TOOSMALL:
307		return ("NFS4ERR_TOOSMALL");
308	case NFS4ERR_SERVERFAULT:
309		return ("NFS4ERR_SERVERFAULT");
310	case NFS4ERR_BADTYPE:
311		return ("NFS4ERR_BADTYPE");
312	case NFS4ERR_DELAY:
313		return ("NFS4ERR_DELAY");
314	case NFS4ERR_SAME:
315		return ("NFS4ERR_SAME");
316	case NFS4ERR_DENIED:
317		return ("NFS4ERR_DENIED");
318	case NFS4ERR_EXPIRED:
319		return ("NFS4ERR_EXPIRED");
320	case NFS4ERR_LOCKED:
321		return ("NFS4ERR_LOCKED");
322	case NFS4ERR_GRACE:
323		return ("NFS4ERR_GRACE");
324	case NFS4ERR_FHEXPIRED:
325		return ("NFS4ERR_FHEXPIRED");
326	case NFS4ERR_SHARE_DENIED:
327		return ("NFS4ERR_SHARE_DENIED");
328	case NFS4ERR_WRONGSEC:
329		return ("NFS4ERR_WRONGSEC");
330	case NFS4ERR_CLID_INUSE:
331		return ("NFS4ERR_CLID_INUSE");
332	case NFS4ERR_RESOURCE:
333		return ("NFS4ERR_RESOURCE");
334	case NFS4ERR_MOVED:
335		return ("NFS4ERR_MOVED");
336	case NFS4ERR_NOFILEHANDLE:
337		return ("NFS4ERR_NOFILEHANDLE");
338	case NFS4ERR_MINOR_VERS_MISMATCH:
339		return ("NFS4ERR_MINOR_VERS_MISMATCH");
340	case NFS4ERR_STALE_CLIENTID:
341		return ("NFS4ERR_STALE_CLIENTID");
342	case NFS4ERR_STALE_STATEID:
343		return ("NFS4ERR_STALE_STATEID");
344	case NFS4ERR_OLD_STATEID:
345		return ("NFS4ERR_OLD_STATEID");
346	case NFS4ERR_BAD_STATEID:
347		return ("NFS4ERR_BAD_STATEID");
348	case NFS4ERR_BAD_SEQID:
349		return ("NFS4ERR_BAD_SEQID");
350	case NFS4ERR_NOT_SAME:
351		return ("NFS4ERR_NOT_SAME");
352	case NFS4ERR_LOCK_RANGE:
353		return ("NFS4ERR_LOCK_RANGE");
354	case NFS4ERR_SYMLINK:
355		return ("NFS4ERR_SYMLINK");
356	case NFS4ERR_RESTOREFH:
357		return ("NFS4ERR_RESTOREFH");
358	case NFS4ERR_LEASE_MOVED:
359		return ("NFS4ERR_LEASE_MOVED");
360	case NFS4ERR_ATTRNOTSUPP:
361		return ("NFS4ERR_ATTRNOTSUPP");
362	case NFS4ERR_NO_GRACE:
363		return ("NFS4ERR_NO_GRACE");
364	case NFS4ERR_RECLAIM_BAD:
365		return ("NFS4ERR_RECLAIM_BAD");
366	case NFS4ERR_RECLAIM_CONFLICT:
367		return ("NFS4ERR_RECLAIM_CONFLICT");
368	case NFS4ERR_BADXDR:
369		return ("NFS4ERR_BADXDR");
370	case NFS4ERR_LOCKS_HELD:
371		return ("NFS4ERR_LOCKS_HELD");
372	case NFS4ERR_OPENMODE:
373		return ("NFS4ERR_OPENMODE");
374	case NFS4ERR_BADOWNER:
375		return ("NFS4ERR_BADOWNER");
376	case NFS4ERR_BADCHAR:
377		return ("NFS4ERR_BADCHAR");
378	case NFS4ERR_BADNAME:
379		return ("NFS4ERR_BADNAME");
380	case NFS4ERR_BAD_RANGE:
381		return ("NFS4ERR_BAD_RANGE");
382	case NFS4ERR_LOCK_NOTSUPP:
383		return ("NFS4ERR_LOCK_NOTSUPP");
384	case NFS4ERR_OP_ILLEGAL:
385		return ("NFS4ERR_OP_ILLEGAL");
386	case NFS4ERR_DEADLOCK:
387		return ("NFS4ERR_DEADLOCK");
388	case NFS4ERR_FILE_OPEN:
389		return ("NFS4ERR_FILE_OPEN");
390	case NFS4ERR_ADMIN_REVOKED:
391		return ("NFS4ERR_ADMIN_REVOKED");
392	case NFS4ERR_CB_PATH_DOWN:
393		return ("NFS4ERR_CB_PATH_DOWN");
394	default:
395		(void) snprintf(buf, 40, "Unknown error %d", (int)error);
396		return (buf);
397	}
398}
399
400char *
401nfs4_recov_action_to_str(nfs4_recov_t what)
402{
403	static char buf[40];
404
405	switch (what) {
406	case NR_STALE:
407		return ("NR_STALE");
408	case NR_FAILOVER:
409		return ("NR_FAILOVER");
410	case NR_CLIENTID:
411		return ("NR_CLIENTID");
412	case NR_OPENFILES:
413		return ("NR_OPENFILES");
414	case NR_WRONGSEC:
415		return ("NR_WRONGSEC");
416	case NR_EXPIRED:
417		return ("NR_EXPIRED");
418	case NR_BAD_STATEID:
419		return ("NR_BAD_STATEID");
420	case NR_FHEXPIRED:
421		return ("NR_FHEXPIRED");
422	case NR_BADHANDLE:
423		return ("NR_BADHANDLE");
424	case NR_BAD_SEQID:
425		return ("NR_BAD_SEQID");
426	case NR_OLDSTATEID:
427		return ("NR_OLDSTATEID");
428	case NR_GRACE:
429		return ("NR_GRACE");
430	case NR_DELAY:
431		return ("NR_DELAY");
432	case NR_LOST_LOCK:
433		return ("NR_LOST_LOCK");
434	case NR_LOST_STATE_RQST:
435		return ("NR_LOST_STATE_RQST");
436	case NR_MOVED:
437		return ("NR_MOVED");
438	default:
439		(void) snprintf(buf, 40, "Unknown, code %d", (int)what);
440		return (buf);
441	}
442}
443
444char *
445nfs4_op_to_str(nfs_opnum4 op)
446{
447	static char buf[40];
448
449	switch (REAL_OP4(op)) {
450	case OP_ACCESS:
451		return ("OP_ACCESS");
452	case OP_CLOSE:
453		return ("OP_CLOSE");
454	case OP_COMMIT:
455		return ("OP_COMMIT");
456	case OP_CREATE:
457		return ("OP_CREATE");
458	case OP_DELEGPURGE:
459		return ("OP_DELEGPURGE");
460	case OP_DELEGRETURN:
461		return ("OP_DELEGRETURN");
462	case OP_GETATTR:
463		return ("OP_GETATTR");
464	case OP_GETFH:
465		return ("OP_GETFH");
466	case OP_LINK:
467		return ("OP_LINK");
468	case OP_LOCK:
469		return ("OP_LOCK");
470	case OP_LOCKT:
471		return ("OP_LOCKT");
472	case OP_LOCKU:
473		return ("OP_LOCKU");
474	case OP_LOOKUP:
475		return ("OP_LOOKUP");
476	case OP_LOOKUPP:
477		return ("OP_LOOKUPP");
478	case OP_NVERIFY:
479		return ("OP_NVERIFY");
480	case OP_OPEN:
481		return ("OP_OPEN");
482	case OP_OPENATTR:
483		return ("OP_OPENATTR");
484	case OP_OPEN_CONFIRM:
485		return ("OP_OPEN_CONFIRM");
486	case OP_OPEN_DOWNGRADE:
487		return ("OP_OPEN_DOWNGRADE");
488	case OP_PUTFH:
489		return ("OP_PUTFH");
490	case OP_PUTPUBFH:
491		return ("OP_PUTPUBFH");
492	case OP_PUTROOTFH:
493		return ("OP_PUTROOTFH");
494	case OP_READ:
495		return ("OP_READ");
496	case OP_READDIR:
497		return ("OP_READDIR");
498	case OP_READLINK:
499		return ("OP_READLINK");
500	case OP_REMOVE:
501		return ("OP_REMOVE");
502	case OP_RENAME:
503		return ("OP_RENAME");
504	case OP_RENEW:
505		return ("OP_RENEW");
506	case OP_RESTOREFH:
507		return ("OP_RESTOREFH");
508	case OP_SAVEFH:
509		return ("OP_SAVEFH");
510	case OP_SECINFO:
511		return ("OP_SECINFO");
512	case OP_SETATTR:
513		return ("OP_SETATTR");
514	case OP_SETCLIENTID:
515		return ("OP_SETCLIENTID");
516	case OP_SETCLIENTID_CONFIRM:
517		return ("OP_SETCLIENTID_CONFIRM");
518	case OP_VERIFY:
519		return ("OP_VERIFY");
520	case OP_WRITE:
521		return ("OP_WRITE");
522	case OP_RELEASE_LOCKOWNER:
523		return ("OP_RELEASE_LOCKOWNER");
524	case OP_ILLEGAL:
525		return ("OP_ILLEGAL");
526	default:
527		(void) snprintf(buf, 40, "Unknown op %d", (int)op);
528		return (buf);
529	}
530}
531