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