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