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