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