xref: /titanic_44/usr/src/uts/common/fs/nfs/nfs4_srv.c (revision c8ded1b3f134553aedbe7b2519523571113972a0)
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 /*
23  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
24  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
25  * Copyright (c) 2012 by Delphix. All rights reserved.
26  */
27 
28 /*
29  *	Copyright (c) 1983,1984,1985,1986,1987,1988,1989  AT&T.
30  *	All Rights Reserved
31  */
32 
33 #include <sys/param.h>
34 #include <sys/types.h>
35 #include <sys/systm.h>
36 #include <sys/cred.h>
37 #include <sys/buf.h>
38 #include <sys/vfs.h>
39 #include <sys/vfs_opreg.h>
40 #include <sys/vnode.h>
41 #include <sys/uio.h>
42 #include <sys/errno.h>
43 #include <sys/sysmacros.h>
44 #include <sys/statvfs.h>
45 #include <sys/kmem.h>
46 #include <sys/dirent.h>
47 #include <sys/cmn_err.h>
48 #include <sys/debug.h>
49 #include <sys/systeminfo.h>
50 #include <sys/flock.h>
51 #include <sys/pathname.h>
52 #include <sys/nbmlock.h>
53 #include <sys/share.h>
54 #include <sys/atomic.h>
55 #include <sys/policy.h>
56 #include <sys/fem.h>
57 #include <sys/sdt.h>
58 #include <sys/ddi.h>
59 #include <sys/zone.h>
60 
61 #include <fs/fs_reparse.h>
62 
63 #include <rpc/types.h>
64 #include <rpc/auth.h>
65 #include <rpc/rpcsec_gss.h>
66 #include <rpc/svc.h>
67 
68 #include <nfs/nfs.h>
69 #include <nfs/export.h>
70 #include <nfs/nfs_cmd.h>
71 #include <nfs/lm.h>
72 #include <nfs/nfs4.h>
73 
74 #include <sys/strsubr.h>
75 #include <sys/strsun.h>
76 
77 #include <inet/common.h>
78 #include <inet/ip.h>
79 #include <inet/ip6.h>
80 
81 #include <sys/tsol/label.h>
82 #include <sys/tsol/tndb.h>
83 
84 #define	RFS4_MAXLOCK_TRIES 4	/* Try to get the lock this many times */
85 static int rfs4_maxlock_tries = RFS4_MAXLOCK_TRIES;
86 #define	RFS4_LOCK_DELAY 10	/* Milliseconds */
87 static clock_t  rfs4_lock_delay = RFS4_LOCK_DELAY;
88 extern struct svc_ops rdma_svc_ops;
89 extern int nfs_loaned_buffers;
90 /* End of Tunables */
91 
92 static int rdma_setup_read_data4(READ4args *, READ4res *);
93 
94 /*
95  * Used to bump the stateid4.seqid value and show changes in the stateid
96  */
97 #define	next_stateid(sp) (++(sp)->bits.chgseq)
98 
99 /*
100  * RFS4_MINLEN_ENTRY4: XDR-encoded size of smallest possible dirent.
101  *	This is used to return NFS4ERR_TOOSMALL when clients specify
102  *	maxcount that isn't large enough to hold the smallest possible
103  *	XDR encoded dirent.
104  *
105  *	    sizeof cookie (8 bytes) +
106  *	    sizeof name_len (4 bytes) +
107  *	    sizeof smallest (padded) name (4 bytes) +
108  *	    sizeof bitmap4_len (12 bytes) +   NOTE: we always encode len=2 bm4
109  *	    sizeof attrlist4_len (4 bytes) +
110  *	    sizeof next boolean (4 bytes)
111  *
112  * RFS4_MINLEN_RDDIR4: XDR-encoded size of READDIR op reply containing
113  * the smallest possible entry4 (assumes no attrs requested).
114  *	sizeof nfsstat4 (4 bytes) +
115  *	sizeof verifier4 (8 bytes) +
116  *	sizeof entry4list bool (4 bytes) +
117  *	sizeof entry4 	(36 bytes) +
118  *	sizeof eof bool  (4 bytes)
119  *
120  * RFS4_MINLEN_RDDIR_BUF: minimum length of buffer server will provide to
121  *	VOP_READDIR.  Its value is the size of the maximum possible dirent
122  *	for solaris.  The DIRENT64_RECLEN macro returns	the size of dirent
123  *	required for a given name length.  MAXNAMELEN is the maximum
124  *	filename length allowed in Solaris.  The first two DIRENT64_RECLEN()
125  *	macros are to allow for . and .. entries -- just a minor tweak to try
126  *	and guarantee that buffer we give to VOP_READDIR will be large enough
127  *	to hold ., .., and the largest possible solaris dirent64.
128  */
129 #define	RFS4_MINLEN_ENTRY4 36
130 #define	RFS4_MINLEN_RDDIR4 (4 + NFS4_VERIFIER_SIZE + 4 + RFS4_MINLEN_ENTRY4 + 4)
131 #define	RFS4_MINLEN_RDDIR_BUF \
132 	(DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2) + DIRENT64_RECLEN(MAXNAMELEN))
133 
134 /*
135  * It would be better to pad to 4 bytes since that's what XDR would do,
136  * but the dirents UFS gives us are already padded to 8, so just take
137  * what we're given.  Dircount is only a hint anyway.  Currently the
138  * solaris kernel is ASCII only, so there's no point in calling the
139  * UTF8 functions.
140  *
141  * dirent64: named padded to provide 8 byte struct alignment
142  *	d_ino(8) + d_off(8) + d_reclen(2) + d_name(namelen + null(1) + pad)
143  *
144  * cookie: uint64_t   +  utf8namelen: uint_t  +   utf8name padded to 8 bytes
145  *
146  */
147 #define	DIRENT64_TO_DIRCOUNT(dp) \
148 	(3 * BYTES_PER_XDR_UNIT + DIRENT64_NAMELEN((dp)->d_reclen))
149 
150 time_t rfs4_start_time;			/* Initialized in rfs4_srvrinit */
151 
152 static sysid_t lockt_sysid;		/* dummy sysid for all LOCKT calls */
153 
154 u_longlong_t	nfs4_srv_caller_id;
155 uint_t		nfs4_srv_vkey = 0;
156 
157 verifier4	Write4verf;
158 verifier4	Readdir4verf;
159 
160 void	rfs4_init_compound_state(struct compound_state *);
161 
162 static void	nullfree(caddr_t);
163 static void	rfs4_op_inval(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
164 			struct compound_state *);
165 static void	rfs4_op_access(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
166 			struct compound_state *);
167 static void	rfs4_op_close(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
168 			struct compound_state *);
169 static void	rfs4_op_commit(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
170 			struct compound_state *);
171 static void	rfs4_op_create(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
172 			struct compound_state *);
173 static void	rfs4_op_create_free(nfs_resop4 *resop);
174 static void	rfs4_op_delegreturn(nfs_argop4 *, nfs_resop4 *,
175 			struct svc_req *, struct compound_state *);
176 static void	rfs4_op_delegpurge(nfs_argop4 *, nfs_resop4 *,
177 			struct svc_req *, struct compound_state *);
178 static void	rfs4_op_getattr(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
179 			struct compound_state *);
180 static void	rfs4_op_getattr_free(nfs_resop4 *);
181 static void	rfs4_op_getfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
182 			struct compound_state *);
183 static void	rfs4_op_getfh_free(nfs_resop4 *);
184 static void	rfs4_op_illegal(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
185 			struct compound_state *);
186 static void	rfs4_op_link(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
187 			struct compound_state *);
188 static void	rfs4_op_lock(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
189 			struct compound_state *);
190 static void	lock_denied_free(nfs_resop4 *);
191 static void	rfs4_op_locku(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
192 			struct compound_state *);
193 static void	rfs4_op_lockt(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
194 			struct compound_state *);
195 static void	rfs4_op_lookup(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
196 			struct compound_state *);
197 static void	rfs4_op_lookupp(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
198 			struct compound_state *);
199 static void	rfs4_op_openattr(nfs_argop4 *argop, nfs_resop4 *resop,
200 				struct svc_req *req, struct compound_state *cs);
201 static void	rfs4_op_nverify(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
202 			struct compound_state *);
203 static void	rfs4_op_open(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
204 			struct compound_state *);
205 static void	rfs4_op_open_confirm(nfs_argop4 *, nfs_resop4 *,
206 			struct svc_req *, struct compound_state *);
207 static void	rfs4_op_open_downgrade(nfs_argop4 *, nfs_resop4 *,
208 			struct svc_req *, struct compound_state *);
209 static void	rfs4_op_putfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
210 			struct compound_state *);
211 static void	rfs4_op_putpubfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
212 			struct compound_state *);
213 static void	rfs4_op_putrootfh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
214 			struct compound_state *);
215 static void	rfs4_op_read(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
216 			struct compound_state *);
217 static void	rfs4_op_read_free(nfs_resop4 *);
218 static void	rfs4_op_readdir_free(nfs_resop4 *resop);
219 static void	rfs4_op_readlink(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
220 			struct compound_state *);
221 static void	rfs4_op_readlink_free(nfs_resop4 *);
222 static void	rfs4_op_release_lockowner(nfs_argop4 *, nfs_resop4 *,
223 			struct svc_req *, struct compound_state *);
224 static void	rfs4_op_remove(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
225 			struct compound_state *);
226 static void	rfs4_op_rename(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
227 			struct compound_state *);
228 static void	rfs4_op_renew(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
229 			struct compound_state *);
230 static void	rfs4_op_restorefh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
231 			struct compound_state *);
232 static void	rfs4_op_savefh(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
233 			struct compound_state *);
234 static void	rfs4_op_setattr(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
235 			struct compound_state *);
236 static void	rfs4_op_verify(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
237 			struct compound_state *);
238 static void	rfs4_op_write(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
239 			struct compound_state *);
240 static void	rfs4_op_setclientid(nfs_argop4 *, nfs_resop4 *,
241 			struct svc_req *, struct compound_state *);
242 static void	rfs4_op_setclientid_confirm(nfs_argop4 *, nfs_resop4 *,
243 			struct svc_req *req, struct compound_state *);
244 static void	rfs4_op_secinfo(nfs_argop4 *, nfs_resop4 *, struct svc_req *,
245 			struct compound_state *);
246 static void	rfs4_op_secinfo_free(nfs_resop4 *);
247 
248 static nfsstat4 check_open_access(uint32_t,
249 				struct compound_state *, struct svc_req *);
250 nfsstat4 rfs4_client_sysid(rfs4_client_t *, sysid_t *);
251 void rfs4_ss_clid(rfs4_client_t *);
252 
253 /*
254  * translation table for attrs
255  */
256 struct nfs4_ntov_table {
257 	union nfs4_attr_u *na;
258 	uint8_t amap[NFS4_MAXNUM_ATTRS];
259 	int attrcnt;
260 	bool_t vfsstat;
261 };
262 
263 static void	nfs4_ntov_table_init(struct nfs4_ntov_table *ntovp);
264 static void	nfs4_ntov_table_free(struct nfs4_ntov_table *ntovp,
265 				    struct nfs4_svgetit_arg *sargp);
266 
267 static nfsstat4	do_rfs4_set_attrs(bitmap4 *resp, fattr4 *fattrp,
268 		    struct compound_state *cs, struct nfs4_svgetit_arg *sargp,
269 		    struct nfs4_ntov_table *ntovp, nfs4_attr_cmd_t cmd);
270 
271 fem_t		*deleg_rdops;
272 fem_t		*deleg_wrops;
273 
274 rfs4_servinst_t *rfs4_cur_servinst = NULL;	/* current server instance */
275 kmutex_t	rfs4_servinst_lock;	/* protects linked list */
276 int		rfs4_seen_first_compound;	/* set first time we see one */
277 
278 /*
279  * NFS4 op dispatch table
280  */
281 
282 struct rfsv4disp {
283 	void	(*dis_proc)();		/* proc to call */
284 	void	(*dis_resfree)();	/* frees space allocated by proc */
285 	int	dis_flags;		/* RPC_IDEMPOTENT, etc... */
286 };
287 
288 static struct rfsv4disp rfsv4disptab[] = {
289 	/*
290 	 * NFS VERSION 4
291 	 */
292 
293 	/* RFS_NULL = 0 */
294 	{rfs4_op_illegal, nullfree, 0},
295 
296 	/* UNUSED = 1 */
297 	{rfs4_op_illegal, nullfree, 0},
298 
299 	/* UNUSED = 2 */
300 	{rfs4_op_illegal, nullfree, 0},
301 
302 	/* OP_ACCESS = 3 */
303 	{rfs4_op_access, nullfree, RPC_IDEMPOTENT},
304 
305 	/* OP_CLOSE = 4 */
306 	{rfs4_op_close, nullfree, 0},
307 
308 	/* OP_COMMIT = 5 */
309 	{rfs4_op_commit, nullfree, RPC_IDEMPOTENT},
310 
311 	/* OP_CREATE = 6 */
312 	{rfs4_op_create, nullfree, 0},
313 
314 	/* OP_DELEGPURGE = 7 */
315 	{rfs4_op_delegpurge, nullfree, 0},
316 
317 	/* OP_DELEGRETURN = 8 */
318 	{rfs4_op_delegreturn, nullfree, 0},
319 
320 	/* OP_GETATTR = 9 */
321 	{rfs4_op_getattr, rfs4_op_getattr_free, RPC_IDEMPOTENT},
322 
323 	/* OP_GETFH = 10 */
324 	{rfs4_op_getfh, rfs4_op_getfh_free, RPC_ALL},
325 
326 	/* OP_LINK = 11 */
327 	{rfs4_op_link, nullfree, 0},
328 
329 	/* OP_LOCK = 12 */
330 	{rfs4_op_lock, lock_denied_free, 0},
331 
332 	/* OP_LOCKT = 13 */
333 	{rfs4_op_lockt, lock_denied_free, 0},
334 
335 	/* OP_LOCKU = 14 */
336 	{rfs4_op_locku, nullfree, 0},
337 
338 	/* OP_LOOKUP = 15 */
339 	{rfs4_op_lookup, nullfree, (RPC_IDEMPOTENT | RPC_PUBLICFH_OK)},
340 
341 	/* OP_LOOKUPP = 16 */
342 	{rfs4_op_lookupp, nullfree, (RPC_IDEMPOTENT | RPC_PUBLICFH_OK)},
343 
344 	/* OP_NVERIFY = 17 */
345 	{rfs4_op_nverify, nullfree, RPC_IDEMPOTENT},
346 
347 	/* OP_OPEN = 18 */
348 	{rfs4_op_open, rfs4_free_reply, 0},
349 
350 	/* OP_OPENATTR = 19 */
351 	{rfs4_op_openattr, nullfree, 0},
352 
353 	/* OP_OPEN_CONFIRM = 20 */
354 	{rfs4_op_open_confirm, nullfree, 0},
355 
356 	/* OP_OPEN_DOWNGRADE = 21 */
357 	{rfs4_op_open_downgrade, nullfree, 0},
358 
359 	/* OP_OPEN_PUTFH = 22 */
360 	{rfs4_op_putfh, nullfree, RPC_ALL},
361 
362 	/* OP_PUTPUBFH = 23 */
363 	{rfs4_op_putpubfh, nullfree, RPC_ALL},
364 
365 	/* OP_PUTROOTFH = 24 */
366 	{rfs4_op_putrootfh, nullfree, RPC_ALL},
367 
368 	/* OP_READ = 25 */
369 	{rfs4_op_read, rfs4_op_read_free, RPC_IDEMPOTENT},
370 
371 	/* OP_READDIR = 26 */
372 	{rfs4_op_readdir, rfs4_op_readdir_free, RPC_IDEMPOTENT},
373 
374 	/* OP_READLINK = 27 */
375 	{rfs4_op_readlink, rfs4_op_readlink_free, RPC_IDEMPOTENT},
376 
377 	/* OP_REMOVE = 28 */
378 	{rfs4_op_remove, nullfree, 0},
379 
380 	/* OP_RENAME = 29 */
381 	{rfs4_op_rename, nullfree, 0},
382 
383 	/* OP_RENEW = 30 */
384 	{rfs4_op_renew, nullfree, 0},
385 
386 	/* OP_RESTOREFH = 31 */
387 	{rfs4_op_restorefh, nullfree, RPC_ALL},
388 
389 	/* OP_SAVEFH = 32 */
390 	{rfs4_op_savefh, nullfree, RPC_ALL},
391 
392 	/* OP_SECINFO = 33 */
393 	{rfs4_op_secinfo, rfs4_op_secinfo_free, 0},
394 
395 	/* OP_SETATTR = 34 */
396 	{rfs4_op_setattr, nullfree, 0},
397 
398 	/* OP_SETCLIENTID = 35 */
399 	{rfs4_op_setclientid, nullfree, 0},
400 
401 	/* OP_SETCLIENTID_CONFIRM = 36 */
402 	{rfs4_op_setclientid_confirm, nullfree, 0},
403 
404 	/* OP_VERIFY = 37 */
405 	{rfs4_op_verify, nullfree, RPC_IDEMPOTENT},
406 
407 	/* OP_WRITE = 38 */
408 	{rfs4_op_write, nullfree, 0},
409 
410 	/* OP_RELEASE_LOCKOWNER = 39 */
411 	{rfs4_op_release_lockowner, nullfree, 0},
412 };
413 
414 static uint_t rfsv4disp_cnt = sizeof (rfsv4disptab) / sizeof (rfsv4disptab[0]);
415 
416 #define	OP_ILLEGAL_IDX (rfsv4disp_cnt)
417 
418 #ifdef DEBUG
419 
420 int		rfs4_fillone_debug = 0;
421 int		rfs4_no_stub_access = 1;
422 int		rfs4_rddir_debug = 0;
423 
424 static char    *rfs4_op_string[] = {
425 	"rfs4_op_null",
426 	"rfs4_op_1 unused",
427 	"rfs4_op_2 unused",
428 	"rfs4_op_access",
429 	"rfs4_op_close",
430 	"rfs4_op_commit",
431 	"rfs4_op_create",
432 	"rfs4_op_delegpurge",
433 	"rfs4_op_delegreturn",
434 	"rfs4_op_getattr",
435 	"rfs4_op_getfh",
436 	"rfs4_op_link",
437 	"rfs4_op_lock",
438 	"rfs4_op_lockt",
439 	"rfs4_op_locku",
440 	"rfs4_op_lookup",
441 	"rfs4_op_lookupp",
442 	"rfs4_op_nverify",
443 	"rfs4_op_open",
444 	"rfs4_op_openattr",
445 	"rfs4_op_open_confirm",
446 	"rfs4_op_open_downgrade",
447 	"rfs4_op_putfh",
448 	"rfs4_op_putpubfh",
449 	"rfs4_op_putrootfh",
450 	"rfs4_op_read",
451 	"rfs4_op_readdir",
452 	"rfs4_op_readlink",
453 	"rfs4_op_remove",
454 	"rfs4_op_rename",
455 	"rfs4_op_renew",
456 	"rfs4_op_restorefh",
457 	"rfs4_op_savefh",
458 	"rfs4_op_secinfo",
459 	"rfs4_op_setattr",
460 	"rfs4_op_setclientid",
461 	"rfs4_op_setclient_confirm",
462 	"rfs4_op_verify",
463 	"rfs4_op_write",
464 	"rfs4_op_release_lockowner",
465 	"rfs4_op_illegal"
466 };
467 #endif
468 
469 void	rfs4_ss_chkclid(rfs4_client_t *);
470 
471 extern size_t   strlcpy(char *dst, const char *src, size_t dstsize);
472 
473 extern void	rfs4_free_fs_locations4(fs_locations4 *);
474 
475 #ifdef	nextdp
476 #undef nextdp
477 #endif
478 #define	nextdp(dp)	((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
479 
480 static const fs_operation_def_t nfs4_rd_deleg_tmpl[] = {
481 	VOPNAME_OPEN,		{ .femop_open = deleg_rd_open },
482 	VOPNAME_WRITE,		{ .femop_write = deleg_rd_write },
483 	VOPNAME_SETATTR,	{ .femop_setattr = deleg_rd_setattr },
484 	VOPNAME_RWLOCK,		{ .femop_rwlock = deleg_rd_rwlock },
485 	VOPNAME_SPACE,		{ .femop_space = deleg_rd_space },
486 	VOPNAME_SETSECATTR,	{ .femop_setsecattr = deleg_rd_setsecattr },
487 	VOPNAME_VNEVENT,	{ .femop_vnevent = deleg_rd_vnevent },
488 	NULL,			NULL
489 };
490 static const fs_operation_def_t nfs4_wr_deleg_tmpl[] = {
491 	VOPNAME_OPEN,		{ .femop_open = deleg_wr_open },
492 	VOPNAME_READ,		{ .femop_read = deleg_wr_read },
493 	VOPNAME_WRITE,		{ .femop_write = deleg_wr_write },
494 	VOPNAME_SETATTR,	{ .femop_setattr = deleg_wr_setattr },
495 	VOPNAME_RWLOCK,		{ .femop_rwlock = deleg_wr_rwlock },
496 	VOPNAME_SPACE,		{ .femop_space = deleg_wr_space },
497 	VOPNAME_SETSECATTR,	{ .femop_setsecattr = deleg_wr_setsecattr },
498 	VOPNAME_VNEVENT,	{ .femop_vnevent = deleg_wr_vnevent },
499 	NULL,			NULL
500 };
501 
502 int
503 rfs4_srvrinit(void)
504 {
505 	timespec32_t verf;
506 	int error;
507 	extern void rfs4_attr_init();
508 	extern krwlock_t rfs4_deleg_policy_lock;
509 
510 	/*
511 	 * The following algorithm attempts to find a unique verifier
512 	 * to be used as the write verifier returned from the server
513 	 * to the client.  It is important that this verifier change
514 	 * whenever the server reboots.  Of secondary importance, it
515 	 * is important for the verifier to be unique between two
516 	 * different servers.
517 	 *
518 	 * Thus, an attempt is made to use the system hostid and the
519 	 * current time in seconds when the nfssrv kernel module is
520 	 * loaded.  It is assumed that an NFS server will not be able
521 	 * to boot and then to reboot in less than a second.  If the
522 	 * hostid has not been set, then the current high resolution
523 	 * time is used.  This will ensure different verifiers each
524 	 * time the server reboots and minimize the chances that two
525 	 * different servers will have the same verifier.
526 	 * XXX - this is broken on LP64 kernels.
527 	 */
528 	verf.tv_sec = (time_t)zone_get_hostid(NULL);
529 	if (verf.tv_sec != 0) {
530 		verf.tv_nsec = gethrestime_sec();
531 	} else {
532 		timespec_t tverf;
533 
534 		gethrestime(&tverf);
535 		verf.tv_sec = (time_t)tverf.tv_sec;
536 		verf.tv_nsec = tverf.tv_nsec;
537 	}
538 
539 	Write4verf = *(uint64_t *)&verf;
540 
541 	rfs4_attr_init();
542 	mutex_init(&rfs4_deleg_lock, NULL, MUTEX_DEFAULT, NULL);
543 
544 	/* Used to manage create/destroy of server state */
545 	mutex_init(&rfs4_state_lock, NULL, MUTEX_DEFAULT, NULL);
546 
547 	/* Used to manage access to server instance linked list */
548 	mutex_init(&rfs4_servinst_lock, NULL, MUTEX_DEFAULT, NULL);
549 
550 	/* Used to manage access to rfs4_deleg_policy */
551 	rw_init(&rfs4_deleg_policy_lock, NULL, RW_DEFAULT, NULL);
552 
553 	error = fem_create("deleg_rdops", nfs4_rd_deleg_tmpl, &deleg_rdops);
554 	if (error != 0) {
555 		rfs4_disable_delegation();
556 	} else {
557 		error = fem_create("deleg_wrops", nfs4_wr_deleg_tmpl,
558 		    &deleg_wrops);
559 		if (error != 0) {
560 			rfs4_disable_delegation();
561 			fem_free(deleg_rdops);
562 		}
563 	}
564 
565 	nfs4_srv_caller_id = fs_new_caller_id();
566 
567 	lockt_sysid = lm_alloc_sysidt();
568 
569 	vsd_create(&nfs4_srv_vkey, NULL);
570 
571 	return (0);
572 }
573 
574 void
575 rfs4_srvrfini(void)
576 {
577 	extern krwlock_t rfs4_deleg_policy_lock;
578 
579 	if (lockt_sysid != LM_NOSYSID) {
580 		lm_free_sysidt(lockt_sysid);
581 		lockt_sysid = LM_NOSYSID;
582 	}
583 
584 	mutex_destroy(&rfs4_deleg_lock);
585 	mutex_destroy(&rfs4_state_lock);
586 	rw_destroy(&rfs4_deleg_policy_lock);
587 
588 	fem_free(deleg_rdops);
589 	fem_free(deleg_wrops);
590 }
591 
592 void
593 rfs4_init_compound_state(struct compound_state *cs)
594 {
595 	bzero(cs, sizeof (*cs));
596 	cs->cont = TRUE;
597 	cs->access = CS_ACCESS_DENIED;
598 	cs->deleg = FALSE;
599 	cs->mandlock = FALSE;
600 	cs->fh.nfs_fh4_val = cs->fhbuf;
601 }
602 
603 void
604 rfs4_grace_start(rfs4_servinst_t *sip)
605 {
606 	rw_enter(&sip->rwlock, RW_WRITER);
607 	sip->start_time = (time_t)TICK_TO_SEC(ddi_get_lbolt());
608 	sip->grace_period = rfs4_grace_period;
609 	rw_exit(&sip->rwlock);
610 }
611 
612 /*
613  * returns true if the instance's grace period has never been started
614  */
615 int
616 rfs4_servinst_grace_new(rfs4_servinst_t *sip)
617 {
618 	time_t start_time;
619 
620 	rw_enter(&sip->rwlock, RW_READER);
621 	start_time = sip->start_time;
622 	rw_exit(&sip->rwlock);
623 
624 	return (start_time == 0);
625 }
626 
627 /*
628  * Indicates if server instance is within the
629  * grace period.
630  */
631 int
632 rfs4_servinst_in_grace(rfs4_servinst_t *sip)
633 {
634 	time_t grace_expiry;
635 
636 	rw_enter(&sip->rwlock, RW_READER);
637 	grace_expiry = sip->start_time + sip->grace_period;
638 	rw_exit(&sip->rwlock);
639 
640 	return (((time_t)TICK_TO_SEC(ddi_get_lbolt())) < grace_expiry);
641 }
642 
643 int
644 rfs4_clnt_in_grace(rfs4_client_t *cp)
645 {
646 	ASSERT(rfs4_dbe_refcnt(cp->rc_dbe) > 0);
647 
648 	return (rfs4_servinst_in_grace(cp->rc_server_instance));
649 }
650 
651 /*
652  * reset all currently active grace periods
653  */
654 void
655 rfs4_grace_reset_all(void)
656 {
657 	rfs4_servinst_t *sip;
658 
659 	mutex_enter(&rfs4_servinst_lock);
660 	for (sip = rfs4_cur_servinst; sip != NULL; sip = sip->prev)
661 		if (rfs4_servinst_in_grace(sip))
662 			rfs4_grace_start(sip);
663 	mutex_exit(&rfs4_servinst_lock);
664 }
665 
666 /*
667  * start any new instances' grace periods
668  */
669 void
670 rfs4_grace_start_new(void)
671 {
672 	rfs4_servinst_t *sip;
673 
674 	mutex_enter(&rfs4_servinst_lock);
675 	for (sip = rfs4_cur_servinst; sip != NULL; sip = sip->prev)
676 		if (rfs4_servinst_grace_new(sip))
677 			rfs4_grace_start(sip);
678 	mutex_exit(&rfs4_servinst_lock);
679 }
680 
681 static rfs4_dss_path_t *
682 rfs4_dss_newpath(rfs4_servinst_t *sip, char *path, unsigned index)
683 {
684 	size_t len;
685 	rfs4_dss_path_t *dss_path;
686 
687 	dss_path = kmem_alloc(sizeof (rfs4_dss_path_t), KM_SLEEP);
688 
689 	/*
690 	 * Take a copy of the string, since the original may be overwritten.
691 	 * Sadly, no strdup() in the kernel.
692 	 */
693 	/* allow for NUL */
694 	len = strlen(path) + 1;
695 	dss_path->path = kmem_alloc(len, KM_SLEEP);
696 	(void) strlcpy(dss_path->path, path, len);
697 
698 	/* associate with servinst */
699 	dss_path->sip = sip;
700 	dss_path->index = index;
701 
702 	/*
703 	 * Add to list of served paths.
704 	 * No locking required, as we're only ever called at startup.
705 	 */
706 	if (rfs4_dss_pathlist == NULL) {
707 		/* this is the first dss_path_t */
708 
709 		/* needed for insque/remque */
710 		dss_path->next = dss_path->prev = dss_path;
711 
712 		rfs4_dss_pathlist = dss_path;
713 	} else {
714 		insque(dss_path, rfs4_dss_pathlist);
715 	}
716 
717 	return (dss_path);
718 }
719 
720 /*
721  * Create a new server instance, and make it the currently active instance.
722  * Note that starting the grace period too early will reduce the clients'
723  * recovery window.
724  */
725 void
726 rfs4_servinst_create(int start_grace, int dss_npaths, char **dss_paths)
727 {
728 	unsigned i;
729 	rfs4_servinst_t *sip;
730 	rfs4_oldstate_t *oldstate;
731 
732 	sip = kmem_alloc(sizeof (rfs4_servinst_t), KM_SLEEP);
733 	rw_init(&sip->rwlock, NULL, RW_DEFAULT, NULL);
734 
735 	sip->start_time = (time_t)0;
736 	sip->grace_period = (time_t)0;
737 	sip->next = NULL;
738 	sip->prev = NULL;
739 
740 	rw_init(&sip->oldstate_lock, NULL, RW_DEFAULT, NULL);
741 	/*
742 	 * This initial dummy entry is required to setup for insque/remque.
743 	 * It must be skipped over whenever the list is traversed.
744 	 */
745 	oldstate = kmem_alloc(sizeof (rfs4_oldstate_t), KM_SLEEP);
746 	/* insque/remque require initial list entry to be self-terminated */
747 	oldstate->next = oldstate;
748 	oldstate->prev = oldstate;
749 	sip->oldstate = oldstate;
750 
751 
752 	sip->dss_npaths = dss_npaths;
753 	sip->dss_paths = kmem_alloc(dss_npaths *
754 	    sizeof (rfs4_dss_path_t *), KM_SLEEP);
755 
756 	for (i = 0; i < dss_npaths; i++) {
757 		sip->dss_paths[i] = rfs4_dss_newpath(sip, dss_paths[i], i);
758 	}
759 
760 	mutex_enter(&rfs4_servinst_lock);
761 	if (rfs4_cur_servinst != NULL) {
762 		/* add to linked list */
763 		sip->prev = rfs4_cur_servinst;
764 		rfs4_cur_servinst->next = sip;
765 	}
766 	if (start_grace)
767 		rfs4_grace_start(sip);
768 	/* make the new instance "current" */
769 	rfs4_cur_servinst = sip;
770 
771 	mutex_exit(&rfs4_servinst_lock);
772 }
773 
774 /*
775  * In future, we might add a rfs4_servinst_destroy(sip) but, for now, destroy
776  * all instances directly.
777  */
778 void
779 rfs4_servinst_destroy_all(void)
780 {
781 	rfs4_servinst_t *sip, *prev, *current;
782 #ifdef DEBUG
783 	int n = 0;
784 #endif
785 
786 	mutex_enter(&rfs4_servinst_lock);
787 	ASSERT(rfs4_cur_servinst != NULL);
788 	current = rfs4_cur_servinst;
789 	rfs4_cur_servinst = NULL;
790 	for (sip = current; sip != NULL; sip = prev) {
791 		prev = sip->prev;
792 		rw_destroy(&sip->rwlock);
793 		if (sip->oldstate)
794 			kmem_free(sip->oldstate, sizeof (rfs4_oldstate_t));
795 		if (sip->dss_paths)
796 			kmem_free(sip->dss_paths,
797 			    sip->dss_npaths * sizeof (rfs4_dss_path_t *));
798 		kmem_free(sip, sizeof (rfs4_servinst_t));
799 #ifdef DEBUG
800 		n++;
801 #endif
802 	}
803 	mutex_exit(&rfs4_servinst_lock);
804 }
805 
806 /*
807  * Assign the current server instance to a client_t.
808  * Should be called with cp->rc_dbe held.
809  */
810 void
811 rfs4_servinst_assign(rfs4_client_t *cp, rfs4_servinst_t *sip)
812 {
813 	ASSERT(rfs4_dbe_refcnt(cp->rc_dbe) > 0);
814 
815 	/*
816 	 * The lock ensures that if the current instance is in the process
817 	 * of changing, we will see the new one.
818 	 */
819 	mutex_enter(&rfs4_servinst_lock);
820 	cp->rc_server_instance = sip;
821 	mutex_exit(&rfs4_servinst_lock);
822 }
823 
824 rfs4_servinst_t *
825 rfs4_servinst(rfs4_client_t *cp)
826 {
827 	ASSERT(rfs4_dbe_refcnt(cp->rc_dbe) > 0);
828 
829 	return (cp->rc_server_instance);
830 }
831 
832 /* ARGSUSED */
833 static void
834 nullfree(caddr_t resop)
835 {
836 }
837 
838 /*
839  * This is a fall-through for invalid or not implemented (yet) ops
840  */
841 /* ARGSUSED */
842 static void
843 rfs4_op_inval(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
844 	struct compound_state *cs)
845 {
846 	*cs->statusp = *((nfsstat4 *)&(resop)->nfs_resop4_u) = NFS4ERR_INVAL;
847 }
848 
849 /*
850  * Check if the security flavor, nfsnum, is in the flavor_list.
851  */
852 bool_t
853 in_flavor_list(int nfsnum, int *flavor_list, int count)
854 {
855 	int i;
856 
857 	for (i = 0; i < count; i++) {
858 		if (nfsnum == flavor_list[i])
859 			return (TRUE);
860 	}
861 	return (FALSE);
862 }
863 
864 /*
865  * Used by rfs4_op_secinfo to get the security information from the
866  * export structure associated with the component.
867  */
868 /* ARGSUSED */
869 static nfsstat4
870 do_rfs4_op_secinfo(struct compound_state *cs, char *nm, SECINFO4res *resp)
871 {
872 	int error, different_export = 0;
873 	vnode_t *dvp, *vp;
874 	struct exportinfo *exi = NULL;
875 	struct exportinfo *oexi = NULL;
876 	fid_t fid;
877 	uint_t count, i;
878 	secinfo4 *resok_val;
879 	struct secinfo *secp;
880 	seconfig_t *si;
881 	bool_t did_traverse = FALSE;
882 	int dotdot, walk;
883 
884 	dvp = cs->vp;
885 	dotdot = (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0');
886 
887 	/*
888 	 * If dotdotting, then need to check whether it's above the
889 	 * root of a filesystem, or above an export point.
890 	 */
891 	if (dotdot) {
892 
893 		/*
894 		 * If dotdotting at the root of a filesystem, then
895 		 * need to traverse back to the mounted-on filesystem
896 		 * and do the dotdot lookup there.
897 		 */
898 		if (cs->vp->v_flag & VROOT) {
899 
900 			/*
901 			 * If at the system root, then can
902 			 * go up no further.
903 			 */
904 			if (VN_CMP(dvp, rootdir))
905 				return (puterrno4(ENOENT));
906 
907 			/*
908 			 * Traverse back to the mounted-on filesystem
909 			 */
910 			dvp = untraverse(cs->vp);
911 
912 			/*
913 			 * Set the different_export flag so we remember
914 			 * to pick up a new exportinfo entry for
915 			 * this new filesystem.
916 			 */
917 			different_export = 1;
918 		} else {
919 
920 			/*
921 			 * If dotdotting above an export point then set
922 			 * the different_export to get new export info.
923 			 */
924 			different_export = nfs_exported(cs->exi, cs->vp);
925 		}
926 	}
927 
928 	/*
929 	 * Get the vnode for the component "nm".
930 	 */
931 	error = VOP_LOOKUP(dvp, nm, &vp, NULL, 0, NULL, cs->cr,
932 	    NULL, NULL, NULL);
933 	if (error)
934 		return (puterrno4(error));
935 
936 	/*
937 	 * If the vnode is in a pseudo filesystem, or if the security flavor
938 	 * used in the request is valid but not an explicitly shared flavor,
939 	 * or the access bit indicates that this is a limited access,
940 	 * check whether this vnode is visible.
941 	 */
942 	if (!different_export &&
943 	    (PSEUDO(cs->exi) || ! is_exported_sec(cs->nfsflavor, cs->exi) ||
944 	    cs->access & CS_ACCESS_LIMITED)) {
945 		if (! nfs_visible(cs->exi, vp, &different_export)) {
946 			VN_RELE(vp);
947 			return (puterrno4(ENOENT));
948 		}
949 	}
950 
951 	/*
952 	 * If it's a mountpoint, then traverse it.
953 	 */
954 	if (vn_ismntpt(vp)) {
955 		if ((error = traverse(&vp)) != 0) {
956 			VN_RELE(vp);
957 			return (puterrno4(error));
958 		}
959 		/* remember that we had to traverse mountpoint */
960 		did_traverse = TRUE;
961 		different_export = 1;
962 	} else if (vp->v_vfsp != dvp->v_vfsp) {
963 		/*
964 		 * If vp isn't a mountpoint and the vfs ptrs aren't the same,
965 		 * then vp is probably an LOFS object.  We don't need the
966 		 * realvp, we just need to know that we might have crossed
967 		 * a server fs boundary and need to call checkexport.
968 		 * (LOFS lookup hides server fs mountpoints, and actually calls
969 		 * traverse)
970 		 */
971 		different_export = 1;
972 	}
973 
974 	/*
975 	 * Get the export information for it.
976 	 */
977 	if (different_export) {
978 
979 		bzero(&fid, sizeof (fid));
980 		fid.fid_len = MAXFIDSZ;
981 		error = vop_fid_pseudo(vp, &fid);
982 		if (error) {
983 			VN_RELE(vp);
984 			return (puterrno4(error));
985 		}
986 
987 		if (dotdot)
988 			oexi = nfs_vptoexi(NULL, vp, cs->cr, &walk, NULL, TRUE);
989 		else
990 			oexi = checkexport(&vp->v_vfsp->vfs_fsid, &fid, vp);
991 
992 		if (oexi == NULL) {
993 			if (did_traverse == TRUE) {
994 				/*
995 				 * If this vnode is a mounted-on vnode,
996 				 * but the mounted-on file system is not
997 				 * exported, send back the secinfo for
998 				 * the exported node that the mounted-on
999 				 * vnode lives in.
1000 				 */
1001 				exi = cs->exi;
1002 			} else {
1003 				VN_RELE(vp);
1004 				return (puterrno4(EACCES));
1005 			}
1006 		} else {
1007 			exi = oexi;
1008 		}
1009 	} else {
1010 		exi = cs->exi;
1011 	}
1012 	ASSERT(exi != NULL);
1013 
1014 
1015 	/*
1016 	 * Create the secinfo result based on the security information
1017 	 * from the exportinfo structure (exi).
1018 	 *
1019 	 * Return all flavors for a pseudo node.
1020 	 * For a real export node, return the flavor that the client
1021 	 * has access with.
1022 	 */
1023 	rw_enter(&exported_lock, RW_READER);
1024 	if (PSEUDO(exi)) {
1025 		count = exi->exi_export.ex_seccnt; /* total sec count */
1026 		resok_val = kmem_alloc(count * sizeof (secinfo4), KM_SLEEP);
1027 		secp = exi->exi_export.ex_secinfo;
1028 
1029 		for (i = 0; i < count; i++) {
1030 			si = &secp[i].s_secinfo;
1031 			resok_val[i].flavor = si->sc_rpcnum;
1032 			if (resok_val[i].flavor == RPCSEC_GSS) {
1033 				rpcsec_gss_info *info;
1034 
1035 				info = &resok_val[i].flavor_info;
1036 				info->qop = si->sc_qop;
1037 				info->service = (rpc_gss_svc_t)si->sc_service;
1038 
1039 				/* get oid opaque data */
1040 				info->oid.sec_oid4_len =
1041 				    si->sc_gss_mech_type->length;
1042 				info->oid.sec_oid4_val = kmem_alloc(
1043 				    si->sc_gss_mech_type->length, KM_SLEEP);
1044 				bcopy(
1045 				    si->sc_gss_mech_type->elements,
1046 				    info->oid.sec_oid4_val,
1047 				    info->oid.sec_oid4_len);
1048 			}
1049 		}
1050 		resp->SECINFO4resok_len = count;
1051 		resp->SECINFO4resok_val = resok_val;
1052 	} else {
1053 		int ret_cnt = 0, k = 0;
1054 		int *flavor_list;
1055 
1056 		count = exi->exi_export.ex_seccnt; /* total sec count */
1057 		secp = exi->exi_export.ex_secinfo;
1058 
1059 		flavor_list = kmem_alloc(count * sizeof (int), KM_SLEEP);
1060 		/* find out which flavors to return */
1061 		for (i = 0; i < count; i ++) {
1062 			int access, flavor, perm;
1063 
1064 			flavor = secp[i].s_secinfo.sc_nfsnum;
1065 			perm = secp[i].s_flags;
1066 
1067 			access = nfsauth4_secinfo_access(exi, cs->req,
1068 			    flavor, perm, cs->basecr);
1069 
1070 			if (! (access & NFSAUTH_DENIED) &&
1071 			    ! (access & NFSAUTH_WRONGSEC)) {
1072 				flavor_list[ret_cnt] = flavor;
1073 				ret_cnt++;
1074 			}
1075 		}
1076 
1077 		/* Create the returning SECINFO value */
1078 		resok_val = kmem_alloc(ret_cnt * sizeof (secinfo4), KM_SLEEP);
1079 
1080 		for (i = 0; i < count; i++) {
1081 			/*
1082 			 * If the flavor is in the flavor list,
1083 			 * fill in resok_val.
1084 			 */
1085 			si = &secp[i].s_secinfo;
1086 			if (in_flavor_list(si->sc_nfsnum,
1087 			    flavor_list, ret_cnt)) {
1088 				resok_val[k].flavor = si->sc_rpcnum;
1089 				if (resok_val[k].flavor == RPCSEC_GSS) {
1090 					rpcsec_gss_info *info;
1091 
1092 					info = &resok_val[k].flavor_info;
1093 					info->qop = si->sc_qop;
1094 					info->service = (rpc_gss_svc_t)
1095 					    si->sc_service;
1096 
1097 					/* get oid opaque data */
1098 					info->oid.sec_oid4_len =
1099 					    si->sc_gss_mech_type->length;
1100 					info->oid.sec_oid4_val = kmem_alloc(
1101 					    si->sc_gss_mech_type->length,
1102 					    KM_SLEEP);
1103 					bcopy(si->sc_gss_mech_type->elements,
1104 					    info->oid.sec_oid4_val,
1105 					    info->oid.sec_oid4_len);
1106 				}
1107 				k++;
1108 			}
1109 			if (k >= ret_cnt)
1110 				break;
1111 		}
1112 		resp->SECINFO4resok_len = ret_cnt;
1113 		resp->SECINFO4resok_val = resok_val;
1114 		kmem_free(flavor_list, count * sizeof (int));
1115 	}
1116 	rw_exit(&exported_lock);
1117 	if (oexi != NULL)
1118 		exi_rele(oexi);
1119 
1120 	VN_RELE(vp);
1121 	return (NFS4_OK);
1122 }
1123 
1124 /*
1125  * SECINFO (Operation 33): Obtain required security information on
1126  * the component name in the format of (security-mechanism-oid, qop, service)
1127  * triplets.
1128  */
1129 /* ARGSUSED */
1130 static void
1131 rfs4_op_secinfo(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1132     struct compound_state *cs)
1133 {
1134 	SECINFO4args *args = &argop->nfs_argop4_u.opsecinfo;
1135 	SECINFO4res *resp = &resop->nfs_resop4_u.opsecinfo;
1136 	utf8string *utfnm = &args->name;
1137 	uint_t len;
1138 	char *nm;
1139 	struct sockaddr *ca;
1140 	char *name = NULL;
1141 	nfsstat4 status = NFS4_OK;
1142 
1143 	DTRACE_NFSV4_2(op__secinfo__start, struct compound_state *, cs,
1144 	    SECINFO4args *, args);
1145 
1146 	/*
1147 	 * Current file handle (cfh) should have been set before getting
1148 	 * into this function. If not, return error.
1149 	 */
1150 	if (cs->vp == NULL) {
1151 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
1152 		goto out;
1153 	}
1154 
1155 	if (cs->vp->v_type != VDIR) {
1156 		*cs->statusp = resp->status = NFS4ERR_NOTDIR;
1157 		goto out;
1158 	}
1159 
1160 	/*
1161 	 * Verify the component name. If failed, error out, but
1162 	 * do not error out if the component name is a "..".
1163 	 * SECINFO will return its parents secinfo data for SECINFO "..".
1164 	 */
1165 	status = utf8_dir_verify(utfnm);
1166 	if (status != NFS4_OK) {
1167 		if (utfnm->utf8string_len != 2 ||
1168 		    utfnm->utf8string_val[0] != '.' ||
1169 		    utfnm->utf8string_val[1] != '.') {
1170 			*cs->statusp = resp->status = status;
1171 			goto out;
1172 		}
1173 	}
1174 
1175 	nm = utf8_to_str(utfnm, &len, NULL);
1176 	if (nm == NULL) {
1177 		*cs->statusp = resp->status = NFS4ERR_INVAL;
1178 		goto out;
1179 	}
1180 
1181 	if (len > MAXNAMELEN) {
1182 		*cs->statusp = resp->status = NFS4ERR_NAMETOOLONG;
1183 		kmem_free(nm, len);
1184 		goto out;
1185 	}
1186 
1187 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
1188 	name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
1189 	    MAXPATHLEN  + 1);
1190 
1191 	if (name == NULL) {
1192 		*cs->statusp = resp->status = NFS4ERR_INVAL;
1193 		kmem_free(nm, len);
1194 		goto out;
1195 	}
1196 
1197 
1198 	*cs->statusp = resp->status = do_rfs4_op_secinfo(cs, name, resp);
1199 
1200 	if (name != nm)
1201 		kmem_free(name, MAXPATHLEN + 1);
1202 	kmem_free(nm, len);
1203 
1204 out:
1205 	DTRACE_NFSV4_2(op__secinfo__done, struct compound_state *, cs,
1206 	    SECINFO4res *, resp);
1207 }
1208 
1209 /*
1210  * Free SECINFO result.
1211  */
1212 /* ARGSUSED */
1213 static void
1214 rfs4_op_secinfo_free(nfs_resop4 *resop)
1215 {
1216 	SECINFO4res *resp = &resop->nfs_resop4_u.opsecinfo;
1217 	int count, i;
1218 	secinfo4 *resok_val;
1219 
1220 	/* If this is not an Ok result, nothing to free. */
1221 	if (resp->status != NFS4_OK) {
1222 		return;
1223 	}
1224 
1225 	count = resp->SECINFO4resok_len;
1226 	resok_val = resp->SECINFO4resok_val;
1227 
1228 	for (i = 0; i < count; i++) {
1229 		if (resok_val[i].flavor == RPCSEC_GSS) {
1230 			rpcsec_gss_info *info;
1231 
1232 			info = &resok_val[i].flavor_info;
1233 			kmem_free(info->oid.sec_oid4_val,
1234 			    info->oid.sec_oid4_len);
1235 		}
1236 	}
1237 	kmem_free(resok_val, count * sizeof (secinfo4));
1238 	resp->SECINFO4resok_len = 0;
1239 	resp->SECINFO4resok_val = NULL;
1240 }
1241 
1242 /* ARGSUSED */
1243 static void
1244 rfs4_op_access(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1245     struct compound_state *cs)
1246 {
1247 	ACCESS4args *args = &argop->nfs_argop4_u.opaccess;
1248 	ACCESS4res *resp = &resop->nfs_resop4_u.opaccess;
1249 	int error;
1250 	vnode_t *vp;
1251 	struct vattr va;
1252 	int checkwriteperm;
1253 	cred_t *cr = cs->cr;
1254 	bslabel_t *clabel, *slabel;
1255 	ts_label_t *tslabel;
1256 	boolean_t admin_low_client;
1257 
1258 	DTRACE_NFSV4_2(op__access__start, struct compound_state *, cs,
1259 	    ACCESS4args *, args);
1260 
1261 #if 0	/* XXX allow access even if !cs->access. Eventually only pseudo fs */
1262 	if (cs->access == CS_ACCESS_DENIED) {
1263 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
1264 		goto out;
1265 	}
1266 #endif
1267 	if (cs->vp == NULL) {
1268 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
1269 		goto out;
1270 	}
1271 
1272 	ASSERT(cr != NULL);
1273 
1274 	vp = cs->vp;
1275 
1276 	/*
1277 	 * If the file system is exported read only, it is not appropriate
1278 	 * to check write permissions for regular files and directories.
1279 	 * Special files are interpreted by the client, so the underlying
1280 	 * permissions are sent back to the client for interpretation.
1281 	 */
1282 	if (rdonly4(req, cs) &&
1283 	    (vp->v_type == VREG || vp->v_type == VDIR))
1284 		checkwriteperm = 0;
1285 	else
1286 		checkwriteperm = 1;
1287 
1288 	/*
1289 	 * XXX
1290 	 * We need the mode so that we can correctly determine access
1291 	 * permissions relative to a mandatory lock file.  Access to
1292 	 * mandatory lock files is denied on the server, so it might
1293 	 * as well be reflected to the server during the open.
1294 	 */
1295 	va.va_mask = AT_MODE;
1296 	error = VOP_GETATTR(vp, &va, 0, cr, NULL);
1297 	if (error) {
1298 		*cs->statusp = resp->status = puterrno4(error);
1299 		goto out;
1300 	}
1301 	resp->access = 0;
1302 	resp->supported = 0;
1303 
1304 	if (is_system_labeled()) {
1305 		ASSERT(req->rq_label != NULL);
1306 		clabel = req->rq_label;
1307 		DTRACE_PROBE2(tx__rfs4__log__info__opaccess__clabel, char *,
1308 		    "got client label from request(1)",
1309 		    struct svc_req *, req);
1310 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
1311 			if ((tslabel = nfs_getflabel(vp, cs->exi)) == NULL) {
1312 				*cs->statusp = resp->status = puterrno4(EACCES);
1313 				goto out;
1314 			}
1315 			slabel = label2bslabel(tslabel);
1316 			DTRACE_PROBE3(tx__rfs4__log__info__opaccess__slabel,
1317 			    char *, "got server label(1) for vp(2)",
1318 			    bslabel_t *, slabel, vnode_t *, vp);
1319 
1320 			admin_low_client = B_FALSE;
1321 		} else
1322 			admin_low_client = B_TRUE;
1323 	}
1324 
1325 	if (args->access & ACCESS4_READ) {
1326 		error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
1327 		if (!error && !MANDLOCK(vp, va.va_mode) &&
1328 		    (!is_system_labeled() || admin_low_client ||
1329 		    bldominates(clabel, slabel)))
1330 			resp->access |= ACCESS4_READ;
1331 		resp->supported |= ACCESS4_READ;
1332 	}
1333 	if ((args->access & ACCESS4_LOOKUP) && vp->v_type == VDIR) {
1334 		error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
1335 		if (!error && (!is_system_labeled() || admin_low_client ||
1336 		    bldominates(clabel, slabel)))
1337 			resp->access |= ACCESS4_LOOKUP;
1338 		resp->supported |= ACCESS4_LOOKUP;
1339 	}
1340 	if (checkwriteperm &&
1341 	    (args->access & (ACCESS4_MODIFY|ACCESS4_EXTEND))) {
1342 		error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
1343 		if (!error && !MANDLOCK(vp, va.va_mode) &&
1344 		    (!is_system_labeled() || admin_low_client ||
1345 		    blequal(clabel, slabel)))
1346 			resp->access |=
1347 			    (args->access & (ACCESS4_MODIFY | ACCESS4_EXTEND));
1348 		resp->supported |=
1349 		    resp->access & (ACCESS4_MODIFY | ACCESS4_EXTEND);
1350 	}
1351 
1352 	if (checkwriteperm &&
1353 	    (args->access & ACCESS4_DELETE) && vp->v_type == VDIR) {
1354 		error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
1355 		if (!error && (!is_system_labeled() || admin_low_client ||
1356 		    blequal(clabel, slabel)))
1357 			resp->access |= ACCESS4_DELETE;
1358 		resp->supported |= ACCESS4_DELETE;
1359 	}
1360 	if (args->access & ACCESS4_EXECUTE && vp->v_type != VDIR) {
1361 		error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
1362 		if (!error && !MANDLOCK(vp, va.va_mode) &&
1363 		    (!is_system_labeled() || admin_low_client ||
1364 		    bldominates(clabel, slabel)))
1365 			resp->access |= ACCESS4_EXECUTE;
1366 		resp->supported |= ACCESS4_EXECUTE;
1367 	}
1368 
1369 	if (is_system_labeled() && !admin_low_client)
1370 		label_rele(tslabel);
1371 
1372 	*cs->statusp = resp->status = NFS4_OK;
1373 out:
1374 	DTRACE_NFSV4_2(op__access__done, struct compound_state *, cs,
1375 	    ACCESS4res *, resp);
1376 }
1377 
1378 /* ARGSUSED */
1379 static void
1380 rfs4_op_commit(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1381     struct compound_state *cs)
1382 {
1383 	COMMIT4args *args = &argop->nfs_argop4_u.opcommit;
1384 	COMMIT4res *resp = &resop->nfs_resop4_u.opcommit;
1385 	int error;
1386 	vnode_t *vp = cs->vp;
1387 	cred_t *cr = cs->cr;
1388 	vattr_t va;
1389 
1390 	DTRACE_NFSV4_2(op__commit__start, struct compound_state *, cs,
1391 	    COMMIT4args *, args);
1392 
1393 	if (vp == NULL) {
1394 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
1395 		goto out;
1396 	}
1397 	if (cs->access == CS_ACCESS_DENIED) {
1398 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
1399 		goto out;
1400 	}
1401 
1402 	if (args->offset + args->count < args->offset) {
1403 		*cs->statusp = resp->status = NFS4ERR_INVAL;
1404 		goto out;
1405 	}
1406 
1407 	va.va_mask = AT_UID;
1408 	error = VOP_GETATTR(vp, &va, 0, cr, NULL);
1409 
1410 	/*
1411 	 * If we can't get the attributes, then we can't do the
1412 	 * right access checking.  So, we'll fail the request.
1413 	 */
1414 	if (error) {
1415 		*cs->statusp = resp->status = puterrno4(error);
1416 		goto out;
1417 	}
1418 	if (rdonly4(req, cs)) {
1419 		*cs->statusp = resp->status = NFS4ERR_ROFS;
1420 		goto out;
1421 	}
1422 
1423 	if (vp->v_type != VREG) {
1424 		if (vp->v_type == VDIR)
1425 			resp->status = NFS4ERR_ISDIR;
1426 		else
1427 			resp->status = NFS4ERR_INVAL;
1428 		*cs->statusp = resp->status;
1429 		goto out;
1430 	}
1431 
1432 	if (crgetuid(cr) != va.va_uid &&
1433 	    (error = VOP_ACCESS(vp, VWRITE, 0, cs->cr, NULL))) {
1434 		*cs->statusp = resp->status = puterrno4(error);
1435 		goto out;
1436 	}
1437 
1438 	error = VOP_FSYNC(vp, FSYNC, cr, NULL);
1439 
1440 	if (error) {
1441 		*cs->statusp = resp->status = puterrno4(error);
1442 		goto out;
1443 	}
1444 
1445 	*cs->statusp = resp->status = NFS4_OK;
1446 	resp->writeverf = Write4verf;
1447 out:
1448 	DTRACE_NFSV4_2(op__commit__done, struct compound_state *, cs,
1449 	    COMMIT4res *, resp);
1450 }
1451 
1452 /*
1453  * rfs4_op_mknod is called from rfs4_op_create after all initial verification
1454  * was completed. It does the nfsv4 create for special files.
1455  */
1456 /* ARGSUSED */
1457 static vnode_t *
1458 do_rfs4_op_mknod(CREATE4args *args, CREATE4res *resp, struct svc_req *req,
1459     struct compound_state *cs, vattr_t *vap, char *nm)
1460 {
1461 	int error;
1462 	cred_t *cr = cs->cr;
1463 	vnode_t *dvp = cs->vp;
1464 	vnode_t *vp = NULL;
1465 	int mode;
1466 	enum vcexcl excl;
1467 
1468 	switch (args->type) {
1469 	case NF4CHR:
1470 	case NF4BLK:
1471 		if (secpolicy_sys_devices(cr) != 0) {
1472 			*cs->statusp = resp->status = NFS4ERR_PERM;
1473 			return (NULL);
1474 		}
1475 		if (args->type == NF4CHR)
1476 			vap->va_type = VCHR;
1477 		else
1478 			vap->va_type = VBLK;
1479 		vap->va_rdev = makedevice(args->ftype4_u.devdata.specdata1,
1480 		    args->ftype4_u.devdata.specdata2);
1481 		vap->va_mask |= AT_RDEV;
1482 		break;
1483 	case NF4SOCK:
1484 		vap->va_type = VSOCK;
1485 		break;
1486 	case NF4FIFO:
1487 		vap->va_type = VFIFO;
1488 		break;
1489 	default:
1490 		*cs->statusp = resp->status = NFS4ERR_BADTYPE;
1491 		return (NULL);
1492 	}
1493 
1494 	/*
1495 	 * Must specify the mode.
1496 	 */
1497 	if (!(vap->va_mask & AT_MODE)) {
1498 		*cs->statusp = resp->status = NFS4ERR_INVAL;
1499 		return (NULL);
1500 	}
1501 
1502 	excl = EXCL;
1503 
1504 	mode = 0;
1505 
1506 	error = VOP_CREATE(dvp, nm, vap, excl, mode, &vp, cr, 0, NULL, NULL);
1507 	if (error) {
1508 		*cs->statusp = resp->status = puterrno4(error);
1509 		return (NULL);
1510 	}
1511 	return (vp);
1512 }
1513 
1514 /*
1515  * nfsv4 create is used to create non-regular files. For regular files,
1516  * use nfsv4 open.
1517  */
1518 /* ARGSUSED */
1519 static void
1520 rfs4_op_create(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1521     struct compound_state *cs)
1522 {
1523 	CREATE4args *args = &argop->nfs_argop4_u.opcreate;
1524 	CREATE4res *resp = &resop->nfs_resop4_u.opcreate;
1525 	int error;
1526 	struct vattr bva, iva, iva2, ava, *vap;
1527 	cred_t *cr = cs->cr;
1528 	vnode_t *dvp = cs->vp;
1529 	vnode_t *vp = NULL;
1530 	vnode_t *realvp;
1531 	char *nm, *lnm;
1532 	uint_t len, llen;
1533 	int syncval = 0;
1534 	struct nfs4_svgetit_arg sarg;
1535 	struct nfs4_ntov_table ntov;
1536 	struct statvfs64 sb;
1537 	nfsstat4 status;
1538 	struct sockaddr *ca;
1539 	char *name = NULL;
1540 	char *lname = NULL;
1541 
1542 	DTRACE_NFSV4_2(op__create__start, struct compound_state *, cs,
1543 	    CREATE4args *, args);
1544 
1545 	resp->attrset = 0;
1546 
1547 	if (dvp == NULL) {
1548 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
1549 		goto out;
1550 	}
1551 
1552 	/*
1553 	 * If there is an unshared filesystem mounted on this vnode,
1554 	 * do not allow to create an object in this directory.
1555 	 */
1556 	if (vn_ismntpt(dvp)) {
1557 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
1558 		goto out;
1559 	}
1560 
1561 	/* Verify that type is correct */
1562 	switch (args->type) {
1563 	case NF4LNK:
1564 	case NF4BLK:
1565 	case NF4CHR:
1566 	case NF4SOCK:
1567 	case NF4FIFO:
1568 	case NF4DIR:
1569 		break;
1570 	default:
1571 		*cs->statusp = resp->status = NFS4ERR_BADTYPE;
1572 		goto out;
1573 	};
1574 
1575 	if (cs->access == CS_ACCESS_DENIED) {
1576 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
1577 		goto out;
1578 	}
1579 	if (dvp->v_type != VDIR) {
1580 		*cs->statusp = resp->status = NFS4ERR_NOTDIR;
1581 		goto out;
1582 	}
1583 	status = utf8_dir_verify(&args->objname);
1584 	if (status != NFS4_OK) {
1585 		*cs->statusp = resp->status = status;
1586 		goto out;
1587 	}
1588 
1589 	if (rdonly4(req, cs)) {
1590 		*cs->statusp = resp->status = NFS4ERR_ROFS;
1591 		goto out;
1592 	}
1593 
1594 	/*
1595 	 * Name of newly created object
1596 	 */
1597 	nm = utf8_to_fn(&args->objname, &len, NULL);
1598 	if (nm == NULL) {
1599 		*cs->statusp = resp->status = NFS4ERR_INVAL;
1600 		goto out;
1601 	}
1602 
1603 	if (len > MAXNAMELEN) {
1604 		*cs->statusp = resp->status = NFS4ERR_NAMETOOLONG;
1605 		kmem_free(nm, len);
1606 		goto out;
1607 	}
1608 
1609 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
1610 	name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
1611 	    MAXPATHLEN  + 1);
1612 
1613 	if (name == NULL) {
1614 		*cs->statusp = resp->status = NFS4ERR_INVAL;
1615 		kmem_free(nm, len);
1616 		goto out;
1617 	}
1618 
1619 	resp->attrset = 0;
1620 
1621 	sarg.sbp = &sb;
1622 	sarg.is_referral = B_FALSE;
1623 	nfs4_ntov_table_init(&ntov);
1624 
1625 	status = do_rfs4_set_attrs(&resp->attrset,
1626 	    &args->createattrs, cs, &sarg, &ntov, NFS4ATTR_SETIT);
1627 
1628 	if (sarg.vap->va_mask == 0 && status == NFS4_OK)
1629 		status = NFS4ERR_INVAL;
1630 
1631 	if (status != NFS4_OK) {
1632 		*cs->statusp = resp->status = status;
1633 		if (name != nm)
1634 			kmem_free(name, MAXPATHLEN + 1);
1635 		kmem_free(nm, len);
1636 		nfs4_ntov_table_free(&ntov, &sarg);
1637 		resp->attrset = 0;
1638 		goto out;
1639 	}
1640 
1641 	/* Get "before" change value */
1642 	bva.va_mask = AT_CTIME|AT_SEQ|AT_MODE;
1643 	error = VOP_GETATTR(dvp, &bva, 0, cr, NULL);
1644 	if (error) {
1645 		*cs->statusp = resp->status = puterrno4(error);
1646 		if (name != nm)
1647 			kmem_free(name, MAXPATHLEN + 1);
1648 		kmem_free(nm, len);
1649 		nfs4_ntov_table_free(&ntov, &sarg);
1650 		resp->attrset = 0;
1651 		goto out;
1652 	}
1653 	NFS4_SET_FATTR4_CHANGE(resp->cinfo.before, bva.va_ctime)
1654 
1655 	vap = sarg.vap;
1656 
1657 	/*
1658 	 * Set the default initial values for attributes when the parent
1659 	 * directory does not have the VSUID/VSGID bit set and they have
1660 	 * not been specified in createattrs.
1661 	 */
1662 	if (!(bva.va_mode & VSUID) && (vap->va_mask & AT_UID) == 0) {
1663 		vap->va_uid = crgetuid(cr);
1664 		vap->va_mask |= AT_UID;
1665 	}
1666 	if (!(bva.va_mode & VSGID) && (vap->va_mask & AT_GID) == 0) {
1667 		vap->va_gid = crgetgid(cr);
1668 		vap->va_mask |= AT_GID;
1669 	}
1670 
1671 	vap->va_mask |= AT_TYPE;
1672 	switch (args->type) {
1673 	case NF4DIR:
1674 		vap->va_type = VDIR;
1675 		if ((vap->va_mask & AT_MODE) == 0) {
1676 			vap->va_mode = 0700;	/* default: owner rwx only */
1677 			vap->va_mask |= AT_MODE;
1678 		}
1679 		error = VOP_MKDIR(dvp, name, vap, &vp, cr, NULL, 0, NULL);
1680 		if (error)
1681 			break;
1682 
1683 		/*
1684 		 * Get the initial "after" sequence number, if it fails,
1685 		 * set to zero
1686 		 */
1687 		iva.va_mask = AT_SEQ;
1688 		if (VOP_GETATTR(dvp, &iva, 0, cs->cr, NULL))
1689 			iva.va_seq = 0;
1690 		break;
1691 	case NF4LNK:
1692 		vap->va_type = VLNK;
1693 		if ((vap->va_mask & AT_MODE) == 0) {
1694 			vap->va_mode = 0700;	/* default: owner rwx only */
1695 			vap->va_mask |= AT_MODE;
1696 		}
1697 
1698 		/*
1699 		 * symlink names must be treated as data
1700 		 */
1701 		lnm = utf8_to_str((utf8string *)&args->ftype4_u.linkdata,
1702 		    &llen, NULL);
1703 
1704 		if (lnm == NULL) {
1705 			*cs->statusp = resp->status = NFS4ERR_INVAL;
1706 			if (name != nm)
1707 				kmem_free(name, MAXPATHLEN + 1);
1708 			kmem_free(nm, len);
1709 			nfs4_ntov_table_free(&ntov, &sarg);
1710 			resp->attrset = 0;
1711 			goto out;
1712 		}
1713 
1714 		if (llen > MAXPATHLEN) {
1715 			*cs->statusp = resp->status = NFS4ERR_NAMETOOLONG;
1716 			if (name != nm)
1717 				kmem_free(name, MAXPATHLEN + 1);
1718 			kmem_free(nm, len);
1719 			kmem_free(lnm, llen);
1720 			nfs4_ntov_table_free(&ntov, &sarg);
1721 			resp->attrset = 0;
1722 			goto out;
1723 		}
1724 
1725 		lname = nfscmd_convname(ca, cs->exi, lnm,
1726 		    NFSCMD_CONV_INBOUND, MAXPATHLEN  + 1);
1727 
1728 		if (lname == NULL) {
1729 			*cs->statusp = resp->status = NFS4ERR_SERVERFAULT;
1730 			if (name != nm)
1731 				kmem_free(name, MAXPATHLEN + 1);
1732 			kmem_free(nm, len);
1733 			kmem_free(lnm, llen);
1734 			nfs4_ntov_table_free(&ntov, &sarg);
1735 			resp->attrset = 0;
1736 			goto out;
1737 		}
1738 
1739 		error = VOP_SYMLINK(dvp, name, vap, lname, cr, NULL, 0);
1740 		if (lname != lnm)
1741 			kmem_free(lname, MAXPATHLEN + 1);
1742 		kmem_free(lnm, llen);
1743 		if (error)
1744 			break;
1745 
1746 		/*
1747 		 * Get the initial "after" sequence number, if it fails,
1748 		 * set to zero
1749 		 */
1750 		iva.va_mask = AT_SEQ;
1751 		if (VOP_GETATTR(dvp, &iva, 0, cs->cr, NULL))
1752 			iva.va_seq = 0;
1753 
1754 		error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
1755 		    NULL, NULL, NULL);
1756 		if (error)
1757 			break;
1758 
1759 		/*
1760 		 * va_seq is not safe over VOP calls, check it again
1761 		 * if it has changed zero out iva to force atomic = FALSE.
1762 		 */
1763 		iva2.va_mask = AT_SEQ;
1764 		if (VOP_GETATTR(dvp, &iva2, 0, cs->cr, NULL) ||
1765 		    iva2.va_seq != iva.va_seq)
1766 			iva.va_seq = 0;
1767 		break;
1768 	default:
1769 		/*
1770 		 * probably a special file.
1771 		 */
1772 		if ((vap->va_mask & AT_MODE) == 0) {
1773 			vap->va_mode = 0600;	/* default: owner rw only */
1774 			vap->va_mask |= AT_MODE;
1775 		}
1776 		syncval = FNODSYNC;
1777 		/*
1778 		 * We know this will only generate one VOP call
1779 		 */
1780 		vp = do_rfs4_op_mknod(args, resp, req, cs, vap, name);
1781 
1782 		if (vp == NULL) {
1783 			if (name != nm)
1784 				kmem_free(name, MAXPATHLEN + 1);
1785 			kmem_free(nm, len);
1786 			nfs4_ntov_table_free(&ntov, &sarg);
1787 			resp->attrset = 0;
1788 			goto out;
1789 		}
1790 
1791 		/*
1792 		 * Get the initial "after" sequence number, if it fails,
1793 		 * set to zero
1794 		 */
1795 		iva.va_mask = AT_SEQ;
1796 		if (VOP_GETATTR(dvp, &iva, 0, cs->cr, NULL))
1797 			iva.va_seq = 0;
1798 
1799 		break;
1800 	}
1801 	if (name != nm)
1802 		kmem_free(name, MAXPATHLEN + 1);
1803 	kmem_free(nm, len);
1804 
1805 	if (error) {
1806 		*cs->statusp = resp->status = puterrno4(error);
1807 	}
1808 
1809 	/*
1810 	 * Force modified data and metadata out to stable storage.
1811 	 */
1812 	(void) VOP_FSYNC(dvp, 0, cr, NULL);
1813 
1814 	if (resp->status != NFS4_OK) {
1815 		if (vp != NULL)
1816 			VN_RELE(vp);
1817 		nfs4_ntov_table_free(&ntov, &sarg);
1818 		resp->attrset = 0;
1819 		goto out;
1820 	}
1821 
1822 	/*
1823 	 * Finish setup of cinfo response, "before" value already set.
1824 	 * Get "after" change value, if it fails, simply return the
1825 	 * before value.
1826 	 */
1827 	ava.va_mask = AT_CTIME|AT_SEQ;
1828 	if (VOP_GETATTR(dvp, &ava, 0, cr, NULL)) {
1829 		ava.va_ctime = bva.va_ctime;
1830 		ava.va_seq = 0;
1831 	}
1832 	NFS4_SET_FATTR4_CHANGE(resp->cinfo.after, ava.va_ctime);
1833 
1834 	/*
1835 	 * True verification that object was created with correct
1836 	 * attrs is impossible.  The attrs could have been changed
1837 	 * immediately after object creation.  If attributes did
1838 	 * not verify, the only recourse for the server is to
1839 	 * destroy the object.  Maybe if some attrs (like gid)
1840 	 * are set incorrectly, the object should be destroyed;
1841 	 * however, seems bad as a default policy.  Do we really
1842 	 * want to destroy an object over one of the times not
1843 	 * verifying correctly?  For these reasons, the server
1844 	 * currently sets bits in attrset for createattrs
1845 	 * that were set; however, no verification is done.
1846 	 *
1847 	 * vmask_to_nmask accounts for vattr bits set on create
1848 	 *	[do_rfs4_set_attrs() only sets resp bits for
1849 	 *	 non-vattr/vfs bits.]
1850 	 * Mask off any bits set by default so as not to return
1851 	 * more attrset bits than were requested in createattrs
1852 	 */
1853 	nfs4_vmask_to_nmask(sarg.vap->va_mask, &resp->attrset);
1854 	resp->attrset &= args->createattrs.attrmask;
1855 	nfs4_ntov_table_free(&ntov, &sarg);
1856 
1857 	error = makefh4(&cs->fh, vp, cs->exi);
1858 	if (error) {
1859 		*cs->statusp = resp->status = puterrno4(error);
1860 	}
1861 
1862 	/*
1863 	 * The cinfo.atomic = TRUE only if we got no errors, we have
1864 	 * non-zero va_seq's, and it has incremented by exactly one
1865 	 * during the creation and it didn't change during the VOP_LOOKUP
1866 	 * or VOP_FSYNC.
1867 	 */
1868 	if (!error && bva.va_seq && iva.va_seq && ava.va_seq &&
1869 	    iva.va_seq == (bva.va_seq + 1) && iva.va_seq == ava.va_seq)
1870 		resp->cinfo.atomic = TRUE;
1871 	else
1872 		resp->cinfo.atomic = FALSE;
1873 
1874 	/*
1875 	 * Force modified metadata out to stable storage.
1876 	 *
1877 	 * if a underlying vp exists, pass it to VOP_FSYNC
1878 	 */
1879 	if (VOP_REALVP(vp, &realvp, NULL) == 0)
1880 		(void) VOP_FSYNC(realvp, syncval, cr, NULL);
1881 	else
1882 		(void) VOP_FSYNC(vp, syncval, cr, NULL);
1883 
1884 	if (resp->status != NFS4_OK) {
1885 		VN_RELE(vp);
1886 		goto out;
1887 	}
1888 	if (cs->vp)
1889 		VN_RELE(cs->vp);
1890 
1891 	cs->vp = vp;
1892 	*cs->statusp = resp->status = NFS4_OK;
1893 out:
1894 	DTRACE_NFSV4_2(op__create__done, struct compound_state *, cs,
1895 	    CREATE4res *, resp);
1896 }
1897 
1898 /*ARGSUSED*/
1899 static void
1900 rfs4_op_delegpurge(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1901     struct compound_state *cs)
1902 {
1903 	DTRACE_NFSV4_2(op__delegpurge__start, struct compound_state *, cs,
1904 	    DELEGPURGE4args *, &argop->nfs_argop4_u.opdelegpurge);
1905 
1906 	rfs4_op_inval(argop, resop, req, cs);
1907 
1908 	DTRACE_NFSV4_2(op__delegpurge__done, struct compound_state *, cs,
1909 	    DELEGPURGE4res *, &resop->nfs_resop4_u.opdelegpurge);
1910 }
1911 
1912 /*ARGSUSED*/
1913 static void
1914 rfs4_op_delegreturn(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
1915     struct compound_state *cs)
1916 {
1917 	DELEGRETURN4args *args = &argop->nfs_argop4_u.opdelegreturn;
1918 	DELEGRETURN4res *resp = &resop->nfs_resop4_u.opdelegreturn;
1919 	rfs4_deleg_state_t *dsp;
1920 	nfsstat4 status;
1921 
1922 	DTRACE_NFSV4_2(op__delegreturn__start, struct compound_state *, cs,
1923 	    DELEGRETURN4args *, args);
1924 
1925 	status = rfs4_get_deleg_state(&args->deleg_stateid, &dsp);
1926 	resp->status = *cs->statusp = status;
1927 	if (status != NFS4_OK)
1928 		goto out;
1929 
1930 	/* Ensure specified filehandle matches */
1931 	if (cs->vp != dsp->rds_finfo->rf_vp) {
1932 		resp->status = *cs->statusp = NFS4ERR_BAD_STATEID;
1933 	} else
1934 		rfs4_return_deleg(dsp, FALSE);
1935 
1936 	rfs4_update_lease(dsp->rds_client);
1937 
1938 	rfs4_deleg_state_rele(dsp);
1939 out:
1940 	DTRACE_NFSV4_2(op__delegreturn__done, struct compound_state *, cs,
1941 	    DELEGRETURN4res *, resp);
1942 }
1943 
1944 /*
1945  * Check to see if a given "flavor" is an explicitly shared flavor.
1946  * The assumption of this routine is the "flavor" is already a valid
1947  * flavor in the secinfo list of "exi".
1948  *
1949  *	e.g.
1950  *		# share -o sec=flavor1 /export
1951  *		# share -o sec=flavor2 /export/home
1952  *
1953  *		flavor2 is not an explicitly shared flavor for /export,
1954  *		however it is in the secinfo list for /export thru the
1955  *		server namespace setup.
1956  */
1957 int
1958 is_exported_sec(int flavor, struct exportinfo *exi)
1959 {
1960 	int	i;
1961 	struct secinfo *sp;
1962 
1963 	rw_enter(&exported_lock, RW_READER);
1964 	sp = exi->exi_export.ex_secinfo;
1965 	for (i = 0; i < exi->exi_export.ex_seccnt; i++) {
1966 		if (flavor == sp[i].s_secinfo.sc_nfsnum ||
1967 		    sp[i].s_secinfo.sc_nfsnum == AUTH_NONE) {
1968 			int ret = SEC_REF_EXPORTED(&sp[i]);
1969 			rw_exit(&exported_lock);
1970 			return (ret);
1971 		}
1972 	}
1973 	rw_exit(&exported_lock);
1974 
1975 	/* Should not reach this point based on the assumption */
1976 	return (0);
1977 }
1978 
1979 /*
1980  * Check if the security flavor used in the request matches what is
1981  * required at the export point or at the root pseudo node (exi_root).
1982  *
1983  * returns 1 if there's a match or if exported with AUTH_NONE; 0 otherwise.
1984  *
1985  */
1986 static int
1987 secinfo_match_or_authnone(struct compound_state *cs)
1988 {
1989 	int	i;
1990 	struct secinfo *sp;
1991 
1992 	/*
1993 	 * Check cs->nfsflavor (from the request) against
1994 	 * the current export data in cs->exi.
1995 	 */
1996 	rw_enter(&exported_lock, RW_READER);
1997 	sp = cs->exi->exi_export.ex_secinfo;
1998 	for (i = 0; i < cs->exi->exi_export.ex_seccnt; i++) {
1999 		if (cs->nfsflavor == sp[i].s_secinfo.sc_nfsnum ||
2000 		    sp[i].s_secinfo.sc_nfsnum == AUTH_NONE) {
2001 			rw_exit(&exported_lock);
2002 			return (1);
2003 		}
2004 	}
2005 	rw_exit(&exported_lock);
2006 
2007 	return (0);
2008 }
2009 
2010 /*
2011  * Check the access authority for the client and return the correct error.
2012  */
2013 nfsstat4
2014 call_checkauth4(struct compound_state *cs, struct svc_req *req)
2015 {
2016 	int	authres;
2017 
2018 	/*
2019 	 * First, check if the security flavor used in the request
2020 	 * are among the flavors set in the server namespace.
2021 	 */
2022 	if (!secinfo_match_or_authnone(cs)) {
2023 		*cs->statusp = NFS4ERR_WRONGSEC;
2024 		return (*cs->statusp);
2025 	}
2026 
2027 	authres = checkauth4(cs, req);
2028 
2029 	if (authres > 0) {
2030 		*cs->statusp = NFS4_OK;
2031 		if (! (cs->access & CS_ACCESS_LIMITED))
2032 			cs->access = CS_ACCESS_OK;
2033 	} else if (authres == 0) {
2034 		*cs->statusp = NFS4ERR_ACCESS;
2035 	} else if (authres == -2) {
2036 		*cs->statusp = NFS4ERR_WRONGSEC;
2037 	} else {
2038 		*cs->statusp = NFS4ERR_DELAY;
2039 	}
2040 	return (*cs->statusp);
2041 }
2042 
2043 /*
2044  * bitmap4_to_attrmask is called by getattr and readdir.
2045  * It sets up the vattr mask and determines whether vfsstat call is needed
2046  * based on the input bitmap.
2047  * Returns nfsv4 status.
2048  */
2049 static nfsstat4
2050 bitmap4_to_attrmask(bitmap4 breq, struct nfs4_svgetit_arg *sargp)
2051 {
2052 	int i;
2053 	uint_t	va_mask;
2054 	struct statvfs64 *sbp = sargp->sbp;
2055 
2056 	sargp->sbp = NULL;
2057 	sargp->flag = 0;
2058 	sargp->rdattr_error = NFS4_OK;
2059 	sargp->mntdfid_set = FALSE;
2060 	if (sargp->cs->vp)
2061 		sargp->xattr = get_fh4_flag(&sargp->cs->fh,
2062 		    FH4_ATTRDIR | FH4_NAMEDATTR);
2063 	else
2064 		sargp->xattr = 0;
2065 
2066 	/*
2067 	 * Set rdattr_error_req to true if return error per
2068 	 * failed entry rather than fail the readdir.
2069 	 */
2070 	if (breq & FATTR4_RDATTR_ERROR_MASK)
2071 		sargp->rdattr_error_req = 1;
2072 	else
2073 		sargp->rdattr_error_req = 0;
2074 
2075 	/*
2076 	 * generate the va_mask
2077 	 * Handle the easy cases first
2078 	 */
2079 	switch (breq) {
2080 	case NFS4_NTOV_ATTR_MASK:
2081 		sargp->vap->va_mask = NFS4_NTOV_ATTR_AT_MASK;
2082 		return (NFS4_OK);
2083 
2084 	case NFS4_FS_ATTR_MASK:
2085 		sargp->vap->va_mask = NFS4_FS_ATTR_AT_MASK;
2086 		sargp->sbp = sbp;
2087 		return (NFS4_OK);
2088 
2089 	case NFS4_NTOV_ATTR_CACHE_MASK:
2090 		sargp->vap->va_mask = NFS4_NTOV_ATTR_CACHE_AT_MASK;
2091 		return (NFS4_OK);
2092 
2093 	case FATTR4_LEASE_TIME_MASK:
2094 		sargp->vap->va_mask = 0;
2095 		return (NFS4_OK);
2096 
2097 	default:
2098 		va_mask = 0;
2099 		for (i = 0; i < nfs4_ntov_map_size; i++) {
2100 			if ((breq & nfs4_ntov_map[i].fbit) &&
2101 			    nfs4_ntov_map[i].vbit)
2102 				va_mask |= nfs4_ntov_map[i].vbit;
2103 		}
2104 
2105 		/*
2106 		 * Check is vfsstat is needed
2107 		 */
2108 		if (breq & NFS4_FS_ATTR_MASK)
2109 			sargp->sbp = sbp;
2110 
2111 		sargp->vap->va_mask = va_mask;
2112 		return (NFS4_OK);
2113 	}
2114 	/* NOTREACHED */
2115 }
2116 
2117 /*
2118  * bitmap4_get_sysattrs is called by getattr and readdir.
2119  * It calls both VOP_GETATTR and VFS_STATVFS calls to get the attrs.
2120  * Returns nfsv4 status.
2121  */
2122 static nfsstat4
2123 bitmap4_get_sysattrs(struct nfs4_svgetit_arg *sargp)
2124 {
2125 	int error;
2126 	struct compound_state *cs = sargp->cs;
2127 	vnode_t *vp = cs->vp;
2128 
2129 	if (sargp->sbp != NULL) {
2130 		if (error = VFS_STATVFS(vp->v_vfsp, sargp->sbp)) {
2131 			sargp->sbp = NULL;	/* to identify error */
2132 			return (puterrno4(error));
2133 		}
2134 	}
2135 
2136 	return (rfs4_vop_getattr(vp, sargp->vap, 0, cs->cr));
2137 }
2138 
2139 static void
2140 nfs4_ntov_table_init(struct nfs4_ntov_table *ntovp)
2141 {
2142 	ntovp->na = kmem_zalloc(sizeof (union nfs4_attr_u) * nfs4_ntov_map_size,
2143 	    KM_SLEEP);
2144 	ntovp->attrcnt = 0;
2145 	ntovp->vfsstat = FALSE;
2146 }
2147 
2148 static void
2149 nfs4_ntov_table_free(struct nfs4_ntov_table *ntovp,
2150     struct nfs4_svgetit_arg *sargp)
2151 {
2152 	int i;
2153 	union nfs4_attr_u *na;
2154 	uint8_t *amap;
2155 
2156 	/*
2157 	 * XXX Should do the same checks for whether the bit is set
2158 	 */
2159 	for (i = 0, na = ntovp->na, amap = ntovp->amap;
2160 	    i < ntovp->attrcnt; i++, na++, amap++) {
2161 		(void) (*nfs4_ntov_map[*amap].sv_getit)(
2162 		    NFS4ATTR_FREEIT, sargp, na);
2163 	}
2164 	if ((sargp->op == NFS4ATTR_SETIT) || (sargp->op == NFS4ATTR_VERIT)) {
2165 		/*
2166 		 * xdr_free for getattr will be done later
2167 		 */
2168 		for (i = 0, na = ntovp->na, amap = ntovp->amap;
2169 		    i < ntovp->attrcnt; i++, na++, amap++) {
2170 			xdr_free(nfs4_ntov_map[*amap].xfunc, (caddr_t)na);
2171 		}
2172 	}
2173 	kmem_free(ntovp->na, sizeof (union nfs4_attr_u) * nfs4_ntov_map_size);
2174 }
2175 
2176 /*
2177  * do_rfs4_op_getattr gets the system attrs and converts into fattr4.
2178  */
2179 static nfsstat4
2180 do_rfs4_op_getattr(bitmap4 breq, fattr4 *fattrp,
2181     struct nfs4_svgetit_arg *sargp)
2182 {
2183 	int error = 0;
2184 	int i, k;
2185 	struct nfs4_ntov_table ntov;
2186 	XDR xdr;
2187 	ulong_t xdr_size;
2188 	char *xdr_attrs;
2189 	nfsstat4 status = NFS4_OK;
2190 	nfsstat4 prev_rdattr_error = sargp->rdattr_error;
2191 	union nfs4_attr_u *na;
2192 	uint8_t *amap;
2193 
2194 	sargp->op = NFS4ATTR_GETIT;
2195 	sargp->flag = 0;
2196 
2197 	fattrp->attrmask = 0;
2198 	/* if no bits requested, then return empty fattr4 */
2199 	if (breq == 0) {
2200 		fattrp->attrlist4_len = 0;
2201 		fattrp->attrlist4 = NULL;
2202 		return (NFS4_OK);
2203 	}
2204 
2205 	/*
2206 	 * return NFS4ERR_INVAL when client requests write-only attrs
2207 	 */
2208 	if (breq & (FATTR4_TIME_ACCESS_SET_MASK | FATTR4_TIME_MODIFY_SET_MASK))
2209 		return (NFS4ERR_INVAL);
2210 
2211 	nfs4_ntov_table_init(&ntov);
2212 	na = ntov.na;
2213 	amap = ntov.amap;
2214 
2215 	/*
2216 	 * Now loop to get or verify the attrs
2217 	 */
2218 	for (i = 0; i < nfs4_ntov_map_size; i++) {
2219 		if (breq & nfs4_ntov_map[i].fbit) {
2220 			if ((*nfs4_ntov_map[i].sv_getit)(
2221 			    NFS4ATTR_SUPPORTED, sargp, NULL) == 0) {
2222 
2223 				error = (*nfs4_ntov_map[i].sv_getit)(
2224 				    NFS4ATTR_GETIT, sargp, na);
2225 
2226 				/*
2227 				 * Possible error values:
2228 				 * >0 if sv_getit failed to
2229 				 * get the attr; 0 if succeeded;
2230 				 * <0 if rdattr_error and the
2231 				 * attribute cannot be returned.
2232 				 */
2233 				if (error && !(sargp->rdattr_error_req))
2234 					goto done;
2235 				/*
2236 				 * If error then just for entry
2237 				 */
2238 				if (error == 0) {
2239 					fattrp->attrmask |=
2240 					    nfs4_ntov_map[i].fbit;
2241 					*amap++ =
2242 					    (uint8_t)nfs4_ntov_map[i].nval;
2243 					na++;
2244 					(ntov.attrcnt)++;
2245 				} else if ((error > 0) &&
2246 				    (sargp->rdattr_error == NFS4_OK)) {
2247 					sargp->rdattr_error = puterrno4(error);
2248 				}
2249 				error = 0;
2250 			}
2251 		}
2252 	}
2253 
2254 	/*
2255 	 * If rdattr_error was set after the return value for it was assigned,
2256 	 * update it.
2257 	 */
2258 	if (prev_rdattr_error != sargp->rdattr_error) {
2259 		na = ntov.na;
2260 		amap = ntov.amap;
2261 		for (i = 0; i < ntov.attrcnt; i++, na++, amap++) {
2262 			k = *amap;
2263 			if (k < FATTR4_RDATTR_ERROR) {
2264 				continue;
2265 			}
2266 			if ((k == FATTR4_RDATTR_ERROR) &&
2267 			    ((*nfs4_ntov_map[k].sv_getit)(
2268 			    NFS4ATTR_SUPPORTED, sargp, NULL) == 0)) {
2269 
2270 				(void) (*nfs4_ntov_map[k].sv_getit)(
2271 				    NFS4ATTR_GETIT, sargp, na);
2272 			}
2273 			break;
2274 		}
2275 	}
2276 
2277 	xdr_size = 0;
2278 	na = ntov.na;
2279 	amap = ntov.amap;
2280 	for (i = 0; i < ntov.attrcnt; i++, na++, amap++) {
2281 		xdr_size += xdr_sizeof(nfs4_ntov_map[*amap].xfunc, na);
2282 	}
2283 
2284 	fattrp->attrlist4_len = xdr_size;
2285 	if (xdr_size) {
2286 		/* freed by rfs4_op_getattr_free() */
2287 		fattrp->attrlist4 = xdr_attrs = kmem_zalloc(xdr_size, KM_SLEEP);
2288 
2289 		xdrmem_create(&xdr, xdr_attrs, xdr_size, XDR_ENCODE);
2290 
2291 		na = ntov.na;
2292 		amap = ntov.amap;
2293 		for (i = 0; i < ntov.attrcnt; i++, na++, amap++) {
2294 			if (!(*nfs4_ntov_map[*amap].xfunc)(&xdr, na)) {
2295 				DTRACE_PROBE1(nfss__e__getattr4_encfail,
2296 				    int, *amap);
2297 				status = NFS4ERR_SERVERFAULT;
2298 				break;
2299 			}
2300 		}
2301 		/* xdrmem_destroy(&xdrs); */	/* NO-OP */
2302 	} else {
2303 		fattrp->attrlist4 = NULL;
2304 	}
2305 done:
2306 
2307 	nfs4_ntov_table_free(&ntov, sargp);
2308 
2309 	if (error != 0)
2310 		status = puterrno4(error);
2311 
2312 	return (status);
2313 }
2314 
2315 /* ARGSUSED */
2316 static void
2317 rfs4_op_getattr(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
2318     struct compound_state *cs)
2319 {
2320 	GETATTR4args *args = &argop->nfs_argop4_u.opgetattr;
2321 	GETATTR4res *resp = &resop->nfs_resop4_u.opgetattr;
2322 	struct nfs4_svgetit_arg sarg;
2323 	struct statvfs64 sb;
2324 	nfsstat4 status;
2325 
2326 	DTRACE_NFSV4_2(op__getattr__start, struct compound_state *, cs,
2327 	    GETATTR4args *, args);
2328 
2329 	if (cs->vp == NULL) {
2330 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
2331 		goto out;
2332 	}
2333 
2334 	if (cs->access == CS_ACCESS_DENIED) {
2335 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
2336 		goto out;
2337 	}
2338 
2339 	sarg.sbp = &sb;
2340 	sarg.cs = cs;
2341 	sarg.is_referral = B_FALSE;
2342 
2343 	status = bitmap4_to_attrmask(args->attr_request, &sarg);
2344 	if (status == NFS4_OK) {
2345 
2346 		status = bitmap4_get_sysattrs(&sarg);
2347 		if (status == NFS4_OK) {
2348 
2349 			/* Is this a referral? */
2350 			if (vn_is_nfs_reparse(cs->vp, cs->cr)) {
2351 				/* Older V4 Solaris client sees a link */
2352 				if (client_is_downrev(req))
2353 					sarg.vap->va_type = VLNK;
2354 				else
2355 					sarg.is_referral = B_TRUE;
2356 			}
2357 
2358 			status = do_rfs4_op_getattr(args->attr_request,
2359 			    &resp->obj_attributes, &sarg);
2360 		}
2361 	}
2362 	*cs->statusp = resp->status = status;
2363 out:
2364 	DTRACE_NFSV4_2(op__getattr__done, struct compound_state *, cs,
2365 	    GETATTR4res *, resp);
2366 }
2367 
2368 static void
2369 rfs4_op_getattr_free(nfs_resop4 *resop)
2370 {
2371 	GETATTR4res *resp = &resop->nfs_resop4_u.opgetattr;
2372 
2373 	nfs4_fattr4_free(&resp->obj_attributes);
2374 }
2375 
2376 /* ARGSUSED */
2377 static void
2378 rfs4_op_getfh(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
2379     struct compound_state *cs)
2380 {
2381 	GETFH4res *resp = &resop->nfs_resop4_u.opgetfh;
2382 
2383 	DTRACE_NFSV4_1(op__getfh__start, struct compound_state *, cs);
2384 
2385 	if (cs->vp == NULL) {
2386 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
2387 		goto out;
2388 	}
2389 	if (cs->access == CS_ACCESS_DENIED) {
2390 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
2391 		goto out;
2392 	}
2393 
2394 	/* check for reparse point at the share point */
2395 	if (cs->exi->exi_moved || vn_is_nfs_reparse(cs->exi->exi_vp, cs->cr)) {
2396 		/* it's all bad */
2397 		cs->exi->exi_moved = 1;
2398 		*cs->statusp = resp->status = NFS4ERR_MOVED;
2399 		DTRACE_PROBE2(nfs4serv__func__referral__shared__moved,
2400 		    vnode_t *, cs->vp, char *, "rfs4_op_getfh");
2401 		return;
2402 	}
2403 
2404 	/* check for reparse point at vp */
2405 	if (vn_is_nfs_reparse(cs->vp, cs->cr) && !client_is_downrev(req)) {
2406 		/* it's not all bad */
2407 		*cs->statusp = resp->status = NFS4ERR_MOVED;
2408 		DTRACE_PROBE2(nfs4serv__func__referral__moved,
2409 		    vnode_t *, cs->vp, char *, "rfs4_op_getfh");
2410 		return;
2411 	}
2412 
2413 	resp->object.nfs_fh4_val =
2414 	    kmem_alloc(cs->fh.nfs_fh4_len, KM_SLEEP);
2415 	nfs_fh4_copy(&cs->fh, &resp->object);
2416 	*cs->statusp = resp->status = NFS4_OK;
2417 out:
2418 	DTRACE_NFSV4_2(op__getfh__done, struct compound_state *, cs,
2419 	    GETFH4res *, resp);
2420 }
2421 
2422 static void
2423 rfs4_op_getfh_free(nfs_resop4 *resop)
2424 {
2425 	GETFH4res *resp = &resop->nfs_resop4_u.opgetfh;
2426 
2427 	if (resp->status == NFS4_OK &&
2428 	    resp->object.nfs_fh4_val != NULL) {
2429 		kmem_free(resp->object.nfs_fh4_val, resp->object.nfs_fh4_len);
2430 		resp->object.nfs_fh4_val = NULL;
2431 		resp->object.nfs_fh4_len = 0;
2432 	}
2433 }
2434 
2435 /*
2436  * illegal: args: void
2437  *	    res : status (NFS4ERR_OP_ILLEGAL)
2438  */
2439 /* ARGSUSED */
2440 static void
2441 rfs4_op_illegal(nfs_argop4 *argop, nfs_resop4 *resop,
2442     struct svc_req *req, struct compound_state *cs)
2443 {
2444 	ILLEGAL4res *resp = &resop->nfs_resop4_u.opillegal;
2445 
2446 	resop->resop = OP_ILLEGAL;
2447 	*cs->statusp = resp->status = NFS4ERR_OP_ILLEGAL;
2448 }
2449 
2450 /*
2451  * link: args: SAVED_FH: file, CURRENT_FH: target directory
2452  *	 res: status. If success - CURRENT_FH unchanged, return change_info
2453  */
2454 /* ARGSUSED */
2455 static void
2456 rfs4_op_link(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
2457     struct compound_state *cs)
2458 {
2459 	LINK4args *args = &argop->nfs_argop4_u.oplink;
2460 	LINK4res *resp = &resop->nfs_resop4_u.oplink;
2461 	int error;
2462 	vnode_t *vp;
2463 	vnode_t *dvp;
2464 	struct vattr bdva, idva, adva;
2465 	char *nm;
2466 	uint_t  len;
2467 	struct sockaddr *ca;
2468 	char *name = NULL;
2469 	nfsstat4 status;
2470 
2471 	DTRACE_NFSV4_2(op__link__start, struct compound_state *, cs,
2472 	    LINK4args *, args);
2473 
2474 	/* SAVED_FH: source object */
2475 	vp = cs->saved_vp;
2476 	if (vp == NULL) {
2477 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
2478 		goto out;
2479 	}
2480 
2481 	/* CURRENT_FH: target directory */
2482 	dvp = cs->vp;
2483 	if (dvp == NULL) {
2484 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
2485 		goto out;
2486 	}
2487 
2488 	/*
2489 	 * If there is a non-shared filesystem mounted on this vnode,
2490 	 * do not allow to link any file in this directory.
2491 	 */
2492 	if (vn_ismntpt(dvp)) {
2493 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
2494 		goto out;
2495 	}
2496 
2497 	if (cs->access == CS_ACCESS_DENIED) {
2498 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
2499 		goto out;
2500 	}
2501 
2502 	/* Check source object's type validity */
2503 	if (vp->v_type == VDIR) {
2504 		*cs->statusp = resp->status = NFS4ERR_ISDIR;
2505 		goto out;
2506 	}
2507 
2508 	/* Check target directory's type */
2509 	if (dvp->v_type != VDIR) {
2510 		*cs->statusp = resp->status = NFS4ERR_NOTDIR;
2511 		goto out;
2512 	}
2513 
2514 	if (cs->saved_exi != cs->exi) {
2515 		*cs->statusp = resp->status = NFS4ERR_XDEV;
2516 		goto out;
2517 	}
2518 
2519 	status = utf8_dir_verify(&args->newname);
2520 	if (status != NFS4_OK) {
2521 		*cs->statusp = resp->status = status;
2522 		goto out;
2523 	}
2524 
2525 	nm = utf8_to_fn(&args->newname, &len, NULL);
2526 	if (nm == NULL) {
2527 		*cs->statusp = resp->status = NFS4ERR_INVAL;
2528 		goto out;
2529 	}
2530 
2531 	if (len > MAXNAMELEN) {
2532 		*cs->statusp = resp->status = NFS4ERR_NAMETOOLONG;
2533 		kmem_free(nm, len);
2534 		goto out;
2535 	}
2536 
2537 	if (rdonly4(req, cs)) {
2538 		*cs->statusp = resp->status = NFS4ERR_ROFS;
2539 		kmem_free(nm, len);
2540 		goto out;
2541 	}
2542 
2543 	/* Get "before" change value */
2544 	bdva.va_mask = AT_CTIME|AT_SEQ;
2545 	error = VOP_GETATTR(dvp, &bdva, 0, cs->cr, NULL);
2546 	if (error) {
2547 		*cs->statusp = resp->status = puterrno4(error);
2548 		kmem_free(nm, len);
2549 		goto out;
2550 	}
2551 
2552 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2553 	name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
2554 	    MAXPATHLEN  + 1);
2555 
2556 	if (name == NULL) {
2557 		*cs->statusp = resp->status = NFS4ERR_INVAL;
2558 		kmem_free(nm, len);
2559 		goto out;
2560 	}
2561 
2562 	NFS4_SET_FATTR4_CHANGE(resp->cinfo.before, bdva.va_ctime)
2563 
2564 	error = VOP_LINK(dvp, vp, name, cs->cr, NULL, 0);
2565 
2566 	if (nm != name)
2567 		kmem_free(name, MAXPATHLEN + 1);
2568 	kmem_free(nm, len);
2569 
2570 	/*
2571 	 * Get the initial "after" sequence number, if it fails, set to zero
2572 	 */
2573 	idva.va_mask = AT_SEQ;
2574 	if (VOP_GETATTR(dvp, &idva, 0, cs->cr, NULL))
2575 		idva.va_seq = 0;
2576 
2577 	/*
2578 	 * Force modified data and metadata out to stable storage.
2579 	 */
2580 	(void) VOP_FSYNC(vp, FNODSYNC, cs->cr, NULL);
2581 	(void) VOP_FSYNC(dvp, 0, cs->cr, NULL);
2582 
2583 	if (error) {
2584 		*cs->statusp = resp->status = puterrno4(error);
2585 		goto out;
2586 	}
2587 
2588 	/*
2589 	 * Get "after" change value, if it fails, simply return the
2590 	 * before value.
2591 	 */
2592 	adva.va_mask = AT_CTIME|AT_SEQ;
2593 	if (VOP_GETATTR(dvp, &adva, 0, cs->cr, NULL)) {
2594 		adva.va_ctime = bdva.va_ctime;
2595 		adva.va_seq = 0;
2596 	}
2597 
2598 	NFS4_SET_FATTR4_CHANGE(resp->cinfo.after, adva.va_ctime)
2599 
2600 	/*
2601 	 * The cinfo.atomic = TRUE only if we have
2602 	 * non-zero va_seq's, and it has incremented by exactly one
2603 	 * during the VOP_LINK and it didn't change during the VOP_FSYNC.
2604 	 */
2605 	if (bdva.va_seq && idva.va_seq && adva.va_seq &&
2606 	    idva.va_seq == (bdva.va_seq + 1) && idva.va_seq == adva.va_seq)
2607 		resp->cinfo.atomic = TRUE;
2608 	else
2609 		resp->cinfo.atomic = FALSE;
2610 
2611 	*cs->statusp = resp->status = NFS4_OK;
2612 out:
2613 	DTRACE_NFSV4_2(op__link__done, struct compound_state *, cs,
2614 	    LINK4res *, resp);
2615 }
2616 
2617 /*
2618  * Used by rfs4_op_lookup and rfs4_op_lookupp to do the actual work.
2619  */
2620 
2621 /* ARGSUSED */
2622 static nfsstat4
2623 do_rfs4_op_lookup(char *nm, struct svc_req *req, struct compound_state *cs)
2624 {
2625 	int error;
2626 	int different_export = 0;
2627 	vnode_t *vp, *pre_tvp = NULL, *oldvp = NULL;
2628 	struct exportinfo *exi = NULL, *pre_exi = NULL;
2629 	nfsstat4 stat;
2630 	fid_t fid;
2631 	int attrdir, dotdot, walk;
2632 	bool_t is_newvp = FALSE;
2633 
2634 	if (cs->vp->v_flag & V_XATTRDIR) {
2635 		attrdir = 1;
2636 		ASSERT(get_fh4_flag(&cs->fh, FH4_ATTRDIR));
2637 	} else {
2638 		attrdir = 0;
2639 		ASSERT(! get_fh4_flag(&cs->fh, FH4_ATTRDIR));
2640 	}
2641 
2642 	dotdot = (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0');
2643 
2644 	/*
2645 	 * If dotdotting, then need to check whether it's
2646 	 * above the root of a filesystem, or above an
2647 	 * export point.
2648 	 */
2649 	if (dotdot) {
2650 
2651 		/*
2652 		 * If dotdotting at the root of a filesystem, then
2653 		 * need to traverse back to the mounted-on filesystem
2654 		 * and do the dotdot lookup there.
2655 		 */
2656 		if (cs->vp->v_flag & VROOT) {
2657 
2658 			/*
2659 			 * If at the system root, then can
2660 			 * go up no further.
2661 			 */
2662 			if (VN_CMP(cs->vp, rootdir))
2663 				return (puterrno4(ENOENT));
2664 
2665 			/*
2666 			 * Traverse back to the mounted-on filesystem
2667 			 */
2668 			cs->vp = untraverse(cs->vp);
2669 
2670 			/*
2671 			 * Set the different_export flag so we remember
2672 			 * to pick up a new exportinfo entry for
2673 			 * this new filesystem.
2674 			 */
2675 			different_export = 1;
2676 		} else {
2677 
2678 			/*
2679 			 * If dotdotting above an export point then set
2680 			 * the different_export to get new export info.
2681 			 */
2682 			different_export = nfs_exported(cs->exi, cs->vp);
2683 		}
2684 	}
2685 
2686 	error = VOP_LOOKUP(cs->vp, nm, &vp, NULL, 0, NULL, cs->cr,
2687 	    NULL, NULL, NULL);
2688 	if (error)
2689 		return (puterrno4(error));
2690 
2691 	/*
2692 	 * If the vnode is in a pseudo filesystem, check whether it is visible.
2693 	 *
2694 	 * XXX if the vnode is a symlink and it is not visible in
2695 	 * a pseudo filesystem, return ENOENT (not following symlink).
2696 	 * V4 client can not mount such symlink. This is a regression
2697 	 * from V2/V3.
2698 	 *
2699 	 * In the same exported filesystem, if the security flavor used
2700 	 * is not an explicitly shared flavor, limit the view to the visible
2701 	 * list entries only. This is not a WRONGSEC case because it's already
2702 	 * checked via PUTROOTFH/PUTPUBFH or PUTFH.
2703 	 */
2704 	if (!different_export &&
2705 	    (PSEUDO(cs->exi) || ! is_exported_sec(cs->nfsflavor, cs->exi) ||
2706 	    cs->access & CS_ACCESS_LIMITED)) {
2707 		if (! nfs_visible(cs->exi, vp, &different_export)) {
2708 			VN_RELE(vp);
2709 			return (puterrno4(ENOENT));
2710 		}
2711 	}
2712 
2713 	/*
2714 	 * If it's a mountpoint, then traverse it.
2715 	 */
2716 	if (vn_ismntpt(vp)) {
2717 		pre_exi = cs->exi;	/* save pre-traversed exportinfo */
2718 		pre_tvp = vp;		/* save pre-traversed vnode	*/
2719 
2720 		/*
2721 		 * hold pre_tvp to counteract rele by traverse.  We will
2722 		 * need pre_tvp below if checkexport fails
2723 		 */
2724 		VN_HOLD(pre_tvp);
2725 		if ((error = traverse(&vp)) != 0) {
2726 			VN_RELE(vp);
2727 			VN_RELE(pre_tvp);
2728 			return (puterrno4(error));
2729 		}
2730 		different_export = 1;
2731 	} else if (vp->v_vfsp != cs->vp->v_vfsp) {
2732 		/*
2733 		 * The vfsp comparison is to handle the case where
2734 		 * a LOFS mount is shared.  lo_lookup traverses mount points,
2735 		 * and NFS is unaware of local fs transistions because
2736 		 * v_vfsmountedhere isn't set.  For this special LOFS case,
2737 		 * the dir and the obj returned by lookup will have different
2738 		 * vfs ptrs.
2739 		 */
2740 		different_export = 1;
2741 	}
2742 
2743 	if (different_export) {
2744 
2745 		bzero(&fid, sizeof (fid));
2746 		fid.fid_len = MAXFIDSZ;
2747 		error = vop_fid_pseudo(vp, &fid);
2748 		if (error) {
2749 			VN_RELE(vp);
2750 			if (pre_tvp)
2751 				VN_RELE(pre_tvp);
2752 			return (puterrno4(error));
2753 		}
2754 
2755 		if (dotdot)
2756 			exi = nfs_vptoexi(NULL, vp, cs->cr, &walk, NULL, TRUE);
2757 		else
2758 			exi = checkexport(&vp->v_vfsp->vfs_fsid, &fid, vp);
2759 
2760 		if (exi == NULL) {
2761 			if (pre_tvp) {
2762 				/*
2763 				 * If this vnode is a mounted-on vnode,
2764 				 * but the mounted-on file system is not
2765 				 * exported, send back the filehandle for
2766 				 * the mounted-on vnode, not the root of
2767 				 * the mounted-on file system.
2768 				 */
2769 				VN_RELE(vp);
2770 				vp = pre_tvp;
2771 				exi = pre_exi;
2772 				if (exi != NULL)
2773 					exi_hold(exi);
2774 			} else {
2775 				VN_RELE(vp);
2776 				return (puterrno4(EACCES));
2777 			}
2778 		} else if (pre_tvp) {
2779 			/* we're done with pre_tvp now. release extra hold */
2780 			VN_RELE(pre_tvp);
2781 		}
2782 
2783 		if (cs->exi != NULL)
2784 			exi_rele(cs->exi);
2785 		cs->exi = exi;
2786 
2787 		/*
2788 		 * Now we do a checkauth4. The reason is that
2789 		 * this client/user may not have access to the new
2790 		 * exported file system, and if he does,
2791 		 * the client/user may be mapped to a different uid.
2792 		 *
2793 		 * We start with a new cr, because the checkauth4 done
2794 		 * in the PUT*FH operation over wrote the cred's uid,
2795 		 * gid, etc, and we want the real thing before calling
2796 		 * checkauth4()
2797 		 */
2798 		crfree(cs->cr);
2799 		cs->cr = crdup(cs->basecr);
2800 
2801 		oldvp = cs->vp;
2802 		cs->vp = vp;
2803 		is_newvp = TRUE;
2804 
2805 		stat = call_checkauth4(cs, req);
2806 		if (stat != NFS4_OK) {
2807 			VN_RELE(cs->vp);
2808 			cs->vp = oldvp;
2809 			return (stat);
2810 		}
2811 	}
2812 
2813 	/*
2814 	 * After various NFS checks, do a label check on the path
2815 	 * component. The label on this path should either be the
2816 	 * global zone's label or a zone's label. We are only
2817 	 * interested in the zone's label because exported files
2818 	 * in global zone is accessible (though read-only) to
2819 	 * clients. The exportability/visibility check is already
2820 	 * done before reaching this code.
2821 	 */
2822 	if (is_system_labeled()) {
2823 		bslabel_t *clabel;
2824 
2825 		ASSERT(req->rq_label != NULL);
2826 		clabel = req->rq_label;
2827 		DTRACE_PROBE2(tx__rfs4__log__info__oplookup__clabel, char *,
2828 		    "got client label from request(1)", struct svc_req *, req);
2829 
2830 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
2831 			if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
2832 			    cs->exi)) {
2833 				error = EACCES;
2834 				goto err_out;
2835 			}
2836 		} else {
2837 			/*
2838 			 * We grant access to admin_low label clients
2839 			 * only if the client is trusted, i.e. also
2840 			 * running Solaris Trusted Extension.
2841 			 */
2842 			struct sockaddr	*ca;
2843 			int		addr_type;
2844 			void		*ipaddr;
2845 			tsol_tpc_t	*tp;
2846 
2847 			ca = (struct sockaddr *)svc_getrpccaller(
2848 			    req->rq_xprt)->buf;
2849 			if (ca->sa_family == AF_INET) {
2850 				addr_type = IPV4_VERSION;
2851 				ipaddr = &((struct sockaddr_in *)ca)->sin_addr;
2852 			} else if (ca->sa_family == AF_INET6) {
2853 				addr_type = IPV6_VERSION;
2854 				ipaddr = &((struct sockaddr_in6 *)
2855 				    ca)->sin6_addr;
2856 			}
2857 			tp = find_tpc(ipaddr, addr_type, B_FALSE);
2858 			if (tp == NULL || tp->tpc_tp.tp_doi !=
2859 			    l_admin_low->tsl_doi || tp->tpc_tp.host_type !=
2860 			    SUN_CIPSO) {
2861 				if (tp != NULL)
2862 					TPC_RELE(tp);
2863 				error = EACCES;
2864 				goto err_out;
2865 			}
2866 			TPC_RELE(tp);
2867 		}
2868 	}
2869 
2870 	error = makefh4(&cs->fh, vp, cs->exi);
2871 
2872 err_out:
2873 	if (error) {
2874 		if (is_newvp) {
2875 			VN_RELE(cs->vp);
2876 			cs->vp = oldvp;
2877 		} else
2878 			VN_RELE(vp);
2879 		return (puterrno4(error));
2880 	}
2881 
2882 	if (!is_newvp) {
2883 		if (cs->vp)
2884 			VN_RELE(cs->vp);
2885 		cs->vp = vp;
2886 	} else if (oldvp)
2887 		VN_RELE(oldvp);
2888 
2889 	/*
2890 	 * if did lookup on attrdir and didn't lookup .., set named
2891 	 * attr fh flag
2892 	 */
2893 	if (attrdir && ! dotdot)
2894 		set_fh4_flag(&cs->fh, FH4_NAMEDATTR);
2895 
2896 	/* Assume false for now, open proc will set this */
2897 	cs->mandlock = FALSE;
2898 
2899 	return (NFS4_OK);
2900 }
2901 
2902 /* ARGSUSED */
2903 static void
2904 rfs4_op_lookup(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
2905     struct compound_state *cs)
2906 {
2907 	LOOKUP4args *args = &argop->nfs_argop4_u.oplookup;
2908 	LOOKUP4res *resp = &resop->nfs_resop4_u.oplookup;
2909 	char *nm;
2910 	uint_t len;
2911 	struct sockaddr *ca;
2912 	char *name = NULL;
2913 	nfsstat4 status;
2914 
2915 	DTRACE_NFSV4_2(op__lookup__start, struct compound_state *, cs,
2916 	    LOOKUP4args *, args);
2917 
2918 	if (cs->vp == NULL) {
2919 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
2920 		goto out;
2921 	}
2922 
2923 	if (cs->vp->v_type == VLNK) {
2924 		*cs->statusp = resp->status = NFS4ERR_SYMLINK;
2925 		goto out;
2926 	}
2927 
2928 	if (cs->vp->v_type != VDIR) {
2929 		*cs->statusp = resp->status = NFS4ERR_NOTDIR;
2930 		goto out;
2931 	}
2932 
2933 	status = utf8_dir_verify(&args->objname);
2934 	if (status != NFS4_OK) {
2935 		*cs->statusp = resp->status = status;
2936 		goto out;
2937 	}
2938 
2939 	nm = utf8_to_str(&args->objname, &len, NULL);
2940 	if (nm == NULL) {
2941 		*cs->statusp = resp->status = NFS4ERR_INVAL;
2942 		goto out;
2943 	}
2944 
2945 	if (len > MAXNAMELEN) {
2946 		*cs->statusp = resp->status = NFS4ERR_NAMETOOLONG;
2947 		kmem_free(nm, len);
2948 		goto out;
2949 	}
2950 
2951 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2952 	name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
2953 	    MAXPATHLEN  + 1);
2954 
2955 	if (name == NULL) {
2956 		*cs->statusp = resp->status = NFS4ERR_INVAL;
2957 		kmem_free(nm, len);
2958 		goto out;
2959 	}
2960 
2961 	*cs->statusp = resp->status = do_rfs4_op_lookup(name, req, cs);
2962 
2963 	if (name != nm)
2964 		kmem_free(name, MAXPATHLEN + 1);
2965 	kmem_free(nm, len);
2966 
2967 out:
2968 	DTRACE_NFSV4_2(op__lookup__done, struct compound_state *, cs,
2969 	    LOOKUP4res *, resp);
2970 }
2971 
2972 /* ARGSUSED */
2973 static void
2974 rfs4_op_lookupp(nfs_argop4 *args, nfs_resop4 *resop, struct svc_req *req,
2975     struct compound_state *cs)
2976 {
2977 	LOOKUPP4res *resp = &resop->nfs_resop4_u.oplookupp;
2978 
2979 	DTRACE_NFSV4_1(op__lookupp__start, struct compound_state *, cs);
2980 
2981 	if (cs->vp == NULL) {
2982 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
2983 		goto out;
2984 	}
2985 
2986 	if (cs->vp->v_type != VDIR) {
2987 		*cs->statusp = resp->status = NFS4ERR_NOTDIR;
2988 		goto out;
2989 	}
2990 
2991 	*cs->statusp = resp->status = do_rfs4_op_lookup("..", req, cs);
2992 
2993 	/*
2994 	 * From NFSV4 Specification, LOOKUPP should not check for
2995 	 * NFS4ERR_WRONGSEC. Retrun NFS4_OK instead.
2996 	 */
2997 	if (resp->status == NFS4ERR_WRONGSEC) {
2998 		*cs->statusp = resp->status = NFS4_OK;
2999 	}
3000 
3001 out:
3002 	DTRACE_NFSV4_2(op__lookupp__done, struct compound_state *, cs,
3003 	    LOOKUPP4res *, resp);
3004 }
3005 
3006 
3007 /*ARGSUSED2*/
3008 static void
3009 rfs4_op_openattr(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
3010     struct compound_state *cs)
3011 {
3012 	OPENATTR4args	*args = &argop->nfs_argop4_u.opopenattr;
3013 	OPENATTR4res	*resp = &resop->nfs_resop4_u.opopenattr;
3014 	vnode_t		*avp = NULL;
3015 	int		lookup_flags = LOOKUP_XATTR, error;
3016 	int		exp_ro = 0;
3017 
3018 	DTRACE_NFSV4_2(op__openattr__start, struct compound_state *, cs,
3019 	    OPENATTR4args *, args);
3020 
3021 	if (cs->vp == NULL) {
3022 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
3023 		goto out;
3024 	}
3025 
3026 	if ((cs->vp->v_vfsp->vfs_flag & VFS_XATTR) == 0 &&
3027 	    !vfs_has_feature(cs->vp->v_vfsp, VFSFT_SYSATTR_VIEWS)) {
3028 		*cs->statusp = resp->status = puterrno4(ENOTSUP);
3029 		goto out;
3030 	}
3031 
3032 	/*
3033 	 * If file system supports passing ACE mask to VOP_ACCESS then
3034 	 * check for ACE_READ_NAMED_ATTRS, otherwise do legacy checks
3035 	 */
3036 
3037 	if (vfs_has_feature(cs->vp->v_vfsp, VFSFT_ACEMASKONACCESS))
3038 		error = VOP_ACCESS(cs->vp, ACE_READ_NAMED_ATTRS,
3039 		    V_ACE_MASK, cs->cr, NULL);
3040 	else
3041 		error = ((VOP_ACCESS(cs->vp, VREAD, 0, cs->cr, NULL) != 0) &&
3042 		    (VOP_ACCESS(cs->vp, VWRITE, 0, cs->cr, NULL) != 0) &&
3043 		    (VOP_ACCESS(cs->vp, VEXEC, 0, cs->cr, NULL) != 0));
3044 
3045 	if (error) {
3046 		*cs->statusp = resp->status = puterrno4(EACCES);
3047 		goto out;
3048 	}
3049 
3050 	/*
3051 	 * The CREATE_XATTR_DIR VOP flag cannot be specified if
3052 	 * the file system is exported read-only -- regardless of
3053 	 * createdir flag.  Otherwise the attrdir would be created
3054 	 * (assuming server fs isn't mounted readonly locally).  If
3055 	 * VOP_LOOKUP returns ENOENT in this case, the error will
3056 	 * be translated into EROFS.  ENOSYS is mapped to ENOTSUP
3057 	 * because specfs has no VOP_LOOKUP op, so the macro would
3058 	 * return ENOSYS.  EINVAL is returned by all (current)
3059 	 * Solaris file system implementations when any of their
3060 	 * restrictions are violated (xattr(dir) can't have xattrdir).
3061 	 * Returning NOTSUPP is more appropriate in this case
3062 	 * because the object will never be able to have an attrdir.
3063 	 */
3064 	if (args->createdir && ! (exp_ro = rdonly4(req, cs)))
3065 		lookup_flags |= CREATE_XATTR_DIR;
3066 
3067 	error = VOP_LOOKUP(cs->vp, "", &avp, NULL, lookup_flags, NULL, cs->cr,
3068 	    NULL, NULL, NULL);
3069 
3070 	if (error) {
3071 		if (error == ENOENT && args->createdir && exp_ro)
3072 			*cs->statusp = resp->status = puterrno4(EROFS);
3073 		else if (error == EINVAL || error == ENOSYS)
3074 			*cs->statusp = resp->status = puterrno4(ENOTSUP);
3075 		else
3076 			*cs->statusp = resp->status = puterrno4(error);
3077 		goto out;
3078 	}
3079 
3080 	ASSERT(avp->v_flag & V_XATTRDIR);
3081 
3082 	error = makefh4(&cs->fh, avp, cs->exi);
3083 
3084 	if (error) {
3085 		VN_RELE(avp);
3086 		*cs->statusp = resp->status = puterrno4(error);
3087 		goto out;
3088 	}
3089 
3090 	VN_RELE(cs->vp);
3091 	cs->vp = avp;
3092 
3093 	/*
3094 	 * There is no requirement for an attrdir fh flag
3095 	 * because the attrdir has a vnode flag to distinguish
3096 	 * it from regular (non-xattr) directories.  The
3097 	 * FH4_ATTRDIR flag is set for future sanity checks.
3098 	 */
3099 	set_fh4_flag(&cs->fh, FH4_ATTRDIR);
3100 	*cs->statusp = resp->status = NFS4_OK;
3101 
3102 out:
3103 	DTRACE_NFSV4_2(op__openattr__done, struct compound_state *, cs,
3104 	    OPENATTR4res *, resp);
3105 }
3106 
3107 static int
3108 do_io(int direction, vnode_t *vp, struct uio *uio, int ioflag, cred_t *cred,
3109     caller_context_t *ct)
3110 {
3111 	int error;
3112 	int i;
3113 	clock_t delaytime;
3114 
3115 	delaytime = MSEC_TO_TICK_ROUNDUP(rfs4_lock_delay);
3116 
3117 	/*
3118 	 * Don't block on mandatory locks. If this routine returns
3119 	 * EAGAIN, the caller should return NFS4ERR_LOCKED.
3120 	 */
3121 	uio->uio_fmode = FNONBLOCK;
3122 
3123 	for (i = 0; i < rfs4_maxlock_tries; i++) {
3124 
3125 
3126 		if (direction == FREAD) {
3127 			(void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, ct);
3128 			error = VOP_READ(vp, uio, ioflag, cred, ct);
3129 			VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, ct);
3130 		} else {
3131 			(void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, ct);
3132 			error = VOP_WRITE(vp, uio, ioflag, cred, ct);
3133 			VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, ct);
3134 		}
3135 
3136 		if (error != EAGAIN)
3137 			break;
3138 
3139 		if (i < rfs4_maxlock_tries - 1) {
3140 			delay(delaytime);
3141 			delaytime *= 2;
3142 		}
3143 	}
3144 
3145 	return (error);
3146 }
3147 
3148 /* ARGSUSED */
3149 static void
3150 rfs4_op_read(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
3151     struct compound_state *cs)
3152 {
3153 	READ4args *args = &argop->nfs_argop4_u.opread;
3154 	READ4res *resp = &resop->nfs_resop4_u.opread;
3155 	int error;
3156 	int verror;
3157 	vnode_t *vp;
3158 	struct vattr va;
3159 	struct iovec iov, *iovp = NULL;
3160 	int iovcnt;
3161 	struct uio uio;
3162 	u_offset_t offset;
3163 	bool_t *deleg = &cs->deleg;
3164 	nfsstat4 stat;
3165 	int in_crit = 0;
3166 	mblk_t *mp = NULL;
3167 	int alloc_err = 0;
3168 	int rdma_used = 0;
3169 	int loaned_buffers;
3170 	caller_context_t ct;
3171 	struct uio *uiop;
3172 
3173 	DTRACE_NFSV4_2(op__read__start, struct compound_state *, cs,
3174 	    READ4args, args);
3175 
3176 	vp = cs->vp;
3177 	if (vp == NULL) {
3178 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
3179 		goto out;
3180 	}
3181 	if (cs->access == CS_ACCESS_DENIED) {
3182 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
3183 		goto out;
3184 	}
3185 
3186 	if ((stat = rfs4_check_stateid(FREAD, vp, &args->stateid, FALSE,
3187 	    deleg, TRUE, &ct)) != NFS4_OK) {
3188 		*cs->statusp = resp->status = stat;
3189 		goto out;
3190 	}
3191 
3192 	/*
3193 	 * Enter the critical region before calling VOP_RWLOCK
3194 	 * to avoid a deadlock with write requests.
3195 	 */
3196 	if (nbl_need_check(vp)) {
3197 		nbl_start_crit(vp, RW_READER);
3198 		in_crit = 1;
3199 		if (nbl_conflict(vp, NBL_READ, args->offset, args->count, 0,
3200 		    &ct)) {
3201 			*cs->statusp = resp->status = NFS4ERR_LOCKED;
3202 			goto out;
3203 		}
3204 	}
3205 
3206 	if ((stat = rfs4_check_stateid(FREAD, vp, &args->stateid, FALSE,
3207 	    deleg, TRUE, &ct)) != NFS4_OK) {
3208 		*cs->statusp = resp->status = stat;
3209 		goto out;
3210 	}
3211 
3212 	if (args->wlist) {
3213 		if (args->count > clist_len(args->wlist)) {
3214 			*cs->statusp = resp->status = NFS4ERR_INVAL;
3215 			goto out;
3216 		}
3217 		rdma_used = 1;
3218 	}
3219 
3220 	/* use loaned buffers for TCP */
3221 	loaned_buffers = (nfs_loaned_buffers && !rdma_used) ? 1 : 0;
3222 
3223 	va.va_mask = AT_MODE|AT_SIZE|AT_UID;
3224 	verror = VOP_GETATTR(vp, &va, 0, cs->cr, &ct);
3225 
3226 	/*
3227 	 * If we can't get the attributes, then we can't do the
3228 	 * right access checking.  So, we'll fail the request.
3229 	 */
3230 	if (verror) {
3231 		*cs->statusp = resp->status = puterrno4(verror);
3232 		goto out;
3233 	}
3234 
3235 	if (vp->v_type != VREG) {
3236 		*cs->statusp = resp->status =
3237 		    ((vp->v_type == VDIR) ? NFS4ERR_ISDIR : NFS4ERR_INVAL);
3238 		goto out;
3239 	}
3240 
3241 	if (crgetuid(cs->cr) != va.va_uid &&
3242 	    (error = VOP_ACCESS(vp, VREAD, 0, cs->cr, &ct)) &&
3243 	    (error = VOP_ACCESS(vp, VEXEC, 0, cs->cr, &ct))) {
3244 		*cs->statusp = resp->status = puterrno4(error);
3245 		goto out;
3246 	}
3247 
3248 	if (MANDLOCK(vp, va.va_mode)) { /* XXX - V4 supports mand locking */
3249 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
3250 		goto out;
3251 	}
3252 
3253 	offset = args->offset;
3254 	if (offset >= va.va_size) {
3255 		*cs->statusp = resp->status = NFS4_OK;
3256 		resp->eof = TRUE;
3257 		resp->data_len = 0;
3258 		resp->data_val = NULL;
3259 		resp->mblk = NULL;
3260 		/* RDMA */
3261 		resp->wlist = args->wlist;
3262 		resp->wlist_len = resp->data_len;
3263 		*cs->statusp = resp->status = NFS4_OK;
3264 		if (resp->wlist)
3265 			clist_zero_len(resp->wlist);
3266 		goto out;
3267 	}
3268 
3269 	if (args->count == 0) {
3270 		*cs->statusp = resp->status = NFS4_OK;
3271 		resp->eof = FALSE;
3272 		resp->data_len = 0;
3273 		resp->data_val = NULL;
3274 		resp->mblk = NULL;
3275 		/* RDMA */
3276 		resp->wlist = args->wlist;
3277 		resp->wlist_len = resp->data_len;
3278 		if (resp->wlist)
3279 			clist_zero_len(resp->wlist);
3280 		goto out;
3281 	}
3282 
3283 	/*
3284 	 * Do not allocate memory more than maximum allowed
3285 	 * transfer size
3286 	 */
3287 	if (args->count > rfs4_tsize(req))
3288 		args->count = rfs4_tsize(req);
3289 
3290 	if (loaned_buffers) {
3291 		uiop = (uio_t *)rfs_setup_xuio(vp);
3292 		ASSERT(uiop != NULL);
3293 		uiop->uio_segflg = UIO_SYSSPACE;
3294 		uiop->uio_loffset = args->offset;
3295 		uiop->uio_resid = args->count;
3296 
3297 		/* Jump to do the read if successful */
3298 		if (!VOP_REQZCBUF(vp, UIO_READ, (xuio_t *)uiop, cs->cr, &ct)) {
3299 			/*
3300 			 * Need to hold the vnode until after VOP_RETZCBUF()
3301 			 * is called.
3302 			 */
3303 			VN_HOLD(vp);
3304 			goto doio_read;
3305 		}
3306 
3307 		DTRACE_PROBE2(nfss__i__reqzcbuf_failed, int,
3308 		    uiop->uio_loffset, int, uiop->uio_resid);
3309 
3310 		uiop->uio_extflg = 0;
3311 
3312 		/* failure to setup for zero copy */
3313 		rfs_free_xuio((void *)uiop);
3314 		loaned_buffers = 0;
3315 	}
3316 
3317 	/*
3318 	 * If returning data via RDMA Write, then grab the chunk list. If we
3319 	 * aren't returning READ data w/RDMA_WRITE, then grab a mblk.
3320 	 */
3321 	if (rdma_used) {
3322 		mp = NULL;
3323 		(void) rdma_get_wchunk(req, &iov, args->wlist);
3324 		uio.uio_iov = &iov;
3325 		uio.uio_iovcnt = 1;
3326 	} else {
3327 		/*
3328 		 * mp will contain the data to be sent out in the read reply.
3329 		 * It will be freed after the reply has been sent.
3330 		 */
3331 		mp = rfs_read_alloc(args->count, &iovp, &iovcnt);
3332 		ASSERT(mp != NULL);
3333 		ASSERT(alloc_err == 0);
3334 		uio.uio_iov = iovp;
3335 		uio.uio_iovcnt = iovcnt;
3336 	}
3337 
3338 	uio.uio_segflg = UIO_SYSSPACE;
3339 	uio.uio_extflg = UIO_COPY_CACHED;
3340 	uio.uio_loffset = args->offset;
3341 	uio.uio_resid = args->count;
3342 	uiop = &uio;
3343 
3344 doio_read:
3345 	error = do_io(FREAD, vp, uiop, 0, cs->cr, &ct);
3346 
3347 	va.va_mask = AT_SIZE;
3348 	verror = VOP_GETATTR(vp, &va, 0, cs->cr, &ct);
3349 
3350 	if (error) {
3351 		if (mp)
3352 			freemsg(mp);
3353 		*cs->statusp = resp->status = puterrno4(error);
3354 		goto out;
3355 	}
3356 
3357 	/* make mblk using zc buffers */
3358 	if (loaned_buffers) {
3359 		mp = uio_to_mblk(uiop);
3360 		ASSERT(mp != NULL);
3361 	}
3362 
3363 	*cs->statusp = resp->status = NFS4_OK;
3364 
3365 	ASSERT(uiop->uio_resid >= 0);
3366 	resp->data_len = args->count - uiop->uio_resid;
3367 	if (mp) {
3368 		resp->data_val = (char *)mp->b_datap->db_base;
3369 		rfs_rndup_mblks(mp, resp->data_len, loaned_buffers);
3370 	} else {
3371 		resp->data_val = (caddr_t)iov.iov_base;
3372 	}
3373 
3374 	resp->mblk = mp;
3375 
3376 	if (!verror && offset + resp->data_len == va.va_size)
3377 		resp->eof = TRUE;
3378 	else
3379 		resp->eof = FALSE;
3380 
3381 	if (rdma_used) {
3382 		if (!rdma_setup_read_data4(args, resp)) {
3383 			*cs->statusp = resp->status = NFS4ERR_INVAL;
3384 		}
3385 	} else {
3386 		resp->wlist = NULL;
3387 	}
3388 
3389 out:
3390 	if (in_crit)
3391 		nbl_end_crit(vp);
3392 
3393 	if (iovp != NULL)
3394 		kmem_free(iovp, iovcnt * sizeof (struct iovec));
3395 
3396 	DTRACE_NFSV4_2(op__read__done, struct compound_state *, cs,
3397 	    READ4res *, resp);
3398 }
3399 
3400 static void
3401 rfs4_op_read_free(nfs_resop4 *resop)
3402 {
3403 	READ4res	*resp = &resop->nfs_resop4_u.opread;
3404 
3405 	if (resp->status == NFS4_OK && resp->mblk != NULL) {
3406 		freemsg(resp->mblk);
3407 		resp->mblk = NULL;
3408 		resp->data_val = NULL;
3409 		resp->data_len = 0;
3410 	}
3411 }
3412 
3413 static void
3414 rfs4_op_readdir_free(nfs_resop4 * resop)
3415 {
3416 	READDIR4res    *resp = &resop->nfs_resop4_u.opreaddir;
3417 
3418 	if (resp->status == NFS4_OK && resp->mblk != NULL) {
3419 		freeb(resp->mblk);
3420 		resp->mblk = NULL;
3421 		resp->data_len = 0;
3422 	}
3423 }
3424 
3425 
3426 /* ARGSUSED */
3427 static void
3428 rfs4_op_putpubfh(nfs_argop4 *args, nfs_resop4 *resop, struct svc_req *req,
3429     struct compound_state *cs)
3430 {
3431 	PUTPUBFH4res	*resp = &resop->nfs_resop4_u.opputpubfh;
3432 	int		error;
3433 	vnode_t		*vp;
3434 	struct exportinfo *exi, *sav_exi;
3435 	nfs_fh4_fmt_t	*fh_fmtp;
3436 
3437 	DTRACE_NFSV4_1(op__putpubfh__start, struct compound_state *, cs);
3438 
3439 	if (cs->vp) {
3440 		VN_RELE(cs->vp);
3441 		cs->vp = NULL;
3442 	}
3443 
3444 	if (cs->cr)
3445 		crfree(cs->cr);
3446 
3447 	cs->cr = crdup(cs->basecr);
3448 
3449 	rw_enter(&exported_lock, RW_READER);
3450 	exi = exi_public;
3451 	exi_hold(exi);
3452 	rw_exit(&exported_lock);
3453 
3454 	vp = exi->exi_vp;
3455 	if (vp == NULL) {
3456 		exi_rele(exi);
3457 		*cs->statusp = resp->status = NFS4ERR_SERVERFAULT;
3458 		goto out;
3459 	}
3460 
3461 	error = makefh4(&cs->fh, vp, exi);
3462 	if (error != 0) {
3463 		exi_rele(exi);
3464 		*cs->statusp = resp->status = puterrno4(error);
3465 		goto out;
3466 	}
3467 
3468 	sav_exi = cs->exi;
3469 	cs->exi = exi;
3470 
3471 	if (cs->exi == exi_root) {
3472 		/*
3473 		 * No filesystem is actually shared public, so we default
3474 		 * to exi_root. In this case, we must check whether root
3475 		 * is exported.
3476 		 */
3477 		fh_fmtp = (nfs_fh4_fmt_t *)cs->fh.nfs_fh4_val;
3478 
3479 		/*
3480 		 * if root filesystem is exported, the exportinfo struct that we
3481 		 * should use is what checkexport returns, because exi_root is
3482 		 * actually a mostly empty struct.
3483 		 */
3484 		exi = checkexport(&fh_fmtp->fh4_fsid,
3485 		    (fid_t *)&fh_fmtp->fh4_xlen, NULL);
3486 		if (exi != NULL) {
3487 			exi_rele(cs->exi);
3488 			cs->exi = exi;
3489 		}
3490 	}
3491 
3492 	if (is_system_labeled()) {
3493 		bslabel_t *clabel;
3494 
3495 		ASSERT(req->rq_label != NULL);
3496 		clabel = req->rq_label;
3497 		DTRACE_PROBE2(tx__rfs4__log__info__opputpubfh__clabel, char *,
3498 		    "got client label from request(1)",
3499 		    struct svc_req *, req);
3500 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
3501 			if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3502 			    cs->exi)) {
3503 				*cs->statusp = resp->status =
3504 				    NFS4ERR_SERVERFAULT;
3505 				if (sav_exi != NULL)
3506 					exi_rele(sav_exi);
3507 				goto out;
3508 			}
3509 		}
3510 	}
3511 
3512 	VN_HOLD(vp);
3513 	cs->vp = vp;
3514 
3515 	if ((resp->status = call_checkauth4(cs, req)) != NFS4_OK) {
3516 		VN_RELE(cs->vp);
3517 		cs->vp = NULL;
3518 		exi_rele(cs->exi);
3519 		cs->exi = sav_exi;
3520 		goto out;
3521 	}
3522 	if (sav_exi != NULL)
3523 		exi_rele(sav_exi);
3524 
3525 	*cs->statusp = resp->status = NFS4_OK;
3526 out:
3527 	DTRACE_NFSV4_2(op__putpubfh__done, struct compound_state *, cs,
3528 	    PUTPUBFH4res *, resp);
3529 }
3530 
3531 /*
3532  * XXX - issue with put*fh operations. Suppose /export/home is exported.
3533  * Suppose an NFS client goes to mount /export/home/joe. If /export, home,
3534  * or joe have restrictive search permissions, then we shouldn't let
3535  * the client get a file handle. This is easy to enforce. However, we
3536  * don't know what security flavor should be used until we resolve the
3537  * path name. Another complication is uid mapping. If root is
3538  * the user, then it will be mapped to the anonymous user by default,
3539  * but we won't know that till we've resolved the path name. And we won't
3540  * know what the anonymous user is.
3541  * Luckily, SECINFO is specified to take a full filename.
3542  * So what we will have to in rfs4_op_lookup is check that flavor of
3543  * the target object matches that of the request, and if root was the
3544  * caller, check for the root= and anon= options, and if necessary,
3545  * repeat the lookup using the right cred_t. But that's not done yet.
3546  */
3547 /* ARGSUSED */
3548 static void
3549 rfs4_op_putfh(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
3550     struct compound_state *cs)
3551 {
3552 	PUTFH4args *args = &argop->nfs_argop4_u.opputfh;
3553 	PUTFH4res *resp = &resop->nfs_resop4_u.opputfh;
3554 	nfs_fh4_fmt_t *fh_fmtp;
3555 
3556 	DTRACE_NFSV4_2(op__putfh__start, struct compound_state *, cs,
3557 	    PUTFH4args *, args);
3558 
3559 	if (cs->vp) {
3560 		VN_RELE(cs->vp);
3561 		cs->vp = NULL;
3562 	}
3563 
3564 	if (cs->cr) {
3565 		crfree(cs->cr);
3566 		cs->cr = NULL;
3567 	}
3568 
3569 
3570 	if (args->object.nfs_fh4_len < NFS_FH4_LEN) {
3571 		*cs->statusp = resp->status = NFS4ERR_BADHANDLE;
3572 		goto out;
3573 	}
3574 
3575 	fh_fmtp = (nfs_fh4_fmt_t *)args->object.nfs_fh4_val;
3576 	if (cs->exi != NULL)
3577 		exi_rele(cs->exi);
3578 	cs->exi = checkexport(&fh_fmtp->fh4_fsid, (fid_t *)&fh_fmtp->fh4_xlen,
3579 	    NULL);
3580 
3581 	if (cs->exi == NULL) {
3582 		*cs->statusp = resp->status = NFS4ERR_STALE;
3583 		goto out;
3584 	}
3585 
3586 	cs->cr = crdup(cs->basecr);
3587 
3588 	ASSERT(cs->cr != NULL);
3589 
3590 	if (! (cs->vp = nfs4_fhtovp(&args->object, cs->exi, &resp->status))) {
3591 		*cs->statusp = resp->status;
3592 		goto out;
3593 	}
3594 
3595 	if ((resp->status = call_checkauth4(cs, req)) != NFS4_OK) {
3596 		VN_RELE(cs->vp);
3597 		cs->vp = NULL;
3598 		goto out;
3599 	}
3600 
3601 	nfs_fh4_copy(&args->object, &cs->fh);
3602 	*cs->statusp = resp->status = NFS4_OK;
3603 	cs->deleg = FALSE;
3604 
3605 out:
3606 	DTRACE_NFSV4_2(op__putfh__done, struct compound_state *, cs,
3607 	    PUTFH4res *, resp);
3608 }
3609 
3610 /* ARGSUSED */
3611 static void
3612 rfs4_op_putrootfh(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
3613     struct compound_state *cs)
3614 {
3615 	PUTROOTFH4res *resp = &resop->nfs_resop4_u.opputrootfh;
3616 	int error;
3617 	fid_t fid;
3618 	struct exportinfo *exi, *sav_exi;
3619 
3620 	DTRACE_NFSV4_1(op__putrootfh__start, struct compound_state *, cs);
3621 
3622 	if (cs->vp) {
3623 		VN_RELE(cs->vp);
3624 		cs->vp = NULL;
3625 	}
3626 
3627 	if (cs->cr)
3628 		crfree(cs->cr);
3629 
3630 	cs->cr = crdup(cs->basecr);
3631 
3632 	/*
3633 	 * Using rootdir, the system root vnode,
3634 	 * get its fid.
3635 	 */
3636 	bzero(&fid, sizeof (fid));
3637 	fid.fid_len = MAXFIDSZ;
3638 	error = vop_fid_pseudo(rootdir, &fid);
3639 	if (error != 0) {
3640 		*cs->statusp = resp->status = puterrno4(error);
3641 		goto out;
3642 	}
3643 
3644 	/*
3645 	 * Then use the root fsid & fid it to find out if it's exported
3646 	 *
3647 	 * If the server root isn't exported directly, then
3648 	 * it should at least be a pseudo export based on
3649 	 * one or more exports further down in the server's
3650 	 * file tree.
3651 	 */
3652 	exi = checkexport(&rootdir->v_vfsp->vfs_fsid, &fid, NULL);
3653 	if (exi == NULL || exi->exi_export.ex_flags & EX_PUBLIC) {
3654 		NFS4_DEBUG(rfs4_debug,
3655 		    (CE_WARN, "rfs4_op_putrootfh: export check failure"));
3656 		*cs->statusp = resp->status = NFS4ERR_SERVERFAULT;
3657 		if (exi != NULL)
3658 			exi_rele(exi);
3659 		goto out;
3660 	}
3661 
3662 	/*
3663 	 * Now make a filehandle based on the root
3664 	 * export and root vnode.
3665 	 */
3666 	error = makefh4(&cs->fh, rootdir, exi);
3667 	if (error != 0) {
3668 		*cs->statusp = resp->status = puterrno4(error);
3669 		exi_rele(exi);
3670 		goto out;
3671 	}
3672 
3673 	sav_exi = cs->exi;
3674 	cs->exi = exi;
3675 
3676 	VN_HOLD(rootdir);
3677 	cs->vp = rootdir;
3678 
3679 	if ((resp->status = call_checkauth4(cs, req)) != NFS4_OK) {
3680 		VN_RELE(rootdir);
3681 		cs->vp = NULL;
3682 		exi_rele(exi);
3683 		cs->exi = sav_exi;
3684 		goto out;
3685 	}
3686 	if (sav_exi != NULL)
3687 		exi_rele(sav_exi);
3688 
3689 	*cs->statusp = resp->status = NFS4_OK;
3690 	cs->deleg = FALSE;
3691 out:
3692 	DTRACE_NFSV4_2(op__putrootfh__done, struct compound_state *, cs,
3693 	    PUTROOTFH4res *, resp);
3694 }
3695 
3696 /*
3697  * set_rdattr_params sets up the variables used to manage what information
3698  * to get for each directory entry.
3699  */
3700 static nfsstat4
3701 set_rdattr_params(struct nfs4_svgetit_arg *sargp,
3702     bitmap4 attrs, bool_t *need_to_lookup)
3703 {
3704 	uint_t	va_mask;
3705 	nfsstat4 status;
3706 	bitmap4 objbits;
3707 
3708 	status = bitmap4_to_attrmask(attrs, sargp);
3709 	if (status != NFS4_OK) {
3710 		/*
3711 		 * could not even figure attr mask
3712 		 */
3713 		return (status);
3714 	}
3715 	va_mask = sargp->vap->va_mask;
3716 
3717 	/*
3718 	 * dirent's d_ino is always correct value for mounted_on_fileid.
3719 	 * mntdfid_set is set once here, but mounted_on_fileid is
3720 	 * set in main dirent processing loop for each dirent.
3721 	 * The mntdfid_set is a simple optimization that lets the
3722 	 * server attr code avoid work when caller is readdir.
3723 	 */
3724 	sargp->mntdfid_set = TRUE;
3725 
3726 	/*
3727 	 * Lookup entry only if client asked for any of the following:
3728 	 * a) vattr attrs
3729 	 * b) vfs attrs
3730 	 * c) attrs w/per-object scope requested (change, filehandle, etc)
3731 	 *    other than mounted_on_fileid (which we can take from dirent)
3732 	 */
3733 	objbits = attrs ? attrs & NFS4_VP_ATTR_MASK : 0;
3734 
3735 	if (va_mask || sargp->sbp || (objbits & ~FATTR4_MOUNTED_ON_FILEID_MASK))
3736 		*need_to_lookup = TRUE;
3737 	else
3738 		*need_to_lookup = FALSE;
3739 
3740 	if (sargp->sbp == NULL)
3741 		return (NFS4_OK);
3742 
3743 	/*
3744 	 * If filesystem attrs are requested, get them now from the
3745 	 * directory vp, as most entries will have same filesystem. The only
3746 	 * exception are mounted over entries but we handle
3747 	 * those as we go (XXX mounted over detection not yet implemented).
3748 	 */
3749 	sargp->vap->va_mask = 0;	/* to avoid VOP_GETATTR */
3750 	status = bitmap4_get_sysattrs(sargp);
3751 	sargp->vap->va_mask = va_mask;
3752 
3753 	if ((status != NFS4_OK) && sargp->rdattr_error_req) {
3754 		/*
3755 		 * Failed to get filesystem attributes.
3756 		 * Return a rdattr_error for each entry, but don't fail.
3757 		 * However, don't get any obj-dependent attrs.
3758 		 */
3759 		sargp->rdattr_error = status;	/* for rdattr_error */
3760 		*need_to_lookup = FALSE;
3761 		/*
3762 		 * At least get fileid for regular readdir output
3763 		 */
3764 		sargp->vap->va_mask &= AT_NODEID;
3765 		status = NFS4_OK;
3766 	}
3767 
3768 	return (status);
3769 }
3770 
3771 /*
3772  * readlink: args: CURRENT_FH.
3773  *	res: status. If success - CURRENT_FH unchanged, return linktext.
3774  */
3775 
3776 /* ARGSUSED */
3777 static void
3778 rfs4_op_readlink(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
3779     struct compound_state *cs)
3780 {
3781 	READLINK4res *resp = &resop->nfs_resop4_u.opreadlink;
3782 	int error;
3783 	vnode_t *vp;
3784 	struct iovec iov;
3785 	struct vattr va;
3786 	struct uio uio;
3787 	char *data;
3788 	struct sockaddr *ca;
3789 	char *name = NULL;
3790 	int is_referral;
3791 
3792 	DTRACE_NFSV4_1(op__readlink__start, struct compound_state *, cs);
3793 
3794 	/* CURRENT_FH: directory */
3795 	vp = cs->vp;
3796 	if (vp == NULL) {
3797 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
3798 		goto out;
3799 	}
3800 
3801 	if (cs->access == CS_ACCESS_DENIED) {
3802 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
3803 		goto out;
3804 	}
3805 
3806 	/* Is it a referral? */
3807 	if (vn_is_nfs_reparse(vp, cs->cr) && client_is_downrev(req)) {
3808 
3809 		is_referral = 1;
3810 
3811 	} else {
3812 
3813 		is_referral = 0;
3814 
3815 		if (vp->v_type == VDIR) {
3816 			*cs->statusp = resp->status = NFS4ERR_ISDIR;
3817 			goto out;
3818 		}
3819 
3820 		if (vp->v_type != VLNK) {
3821 			*cs->statusp = resp->status = NFS4ERR_INVAL;
3822 			goto out;
3823 		}
3824 
3825 	}
3826 
3827 	va.va_mask = AT_MODE;
3828 	error = VOP_GETATTR(vp, &va, 0, cs->cr, NULL);
3829 	if (error) {
3830 		*cs->statusp = resp->status = puterrno4(error);
3831 		goto out;
3832 	}
3833 
3834 	if (MANDLOCK(vp, va.va_mode)) {
3835 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
3836 		goto out;
3837 	}
3838 
3839 	data = kmem_alloc(MAXPATHLEN + 1, KM_SLEEP);
3840 
3841 	if (is_referral) {
3842 		char *s;
3843 		size_t strsz;
3844 
3845 		/* Get an artificial symlink based on a referral */
3846 		s = build_symlink(vp, cs->cr, &strsz);
3847 		global_svstat_ptr[4][NFS_REFERLINKS].value.ui64++;
3848 		DTRACE_PROBE2(nfs4serv__func__referral__reflink,
3849 		    vnode_t *, vp, char *, s);
3850 		if (s == NULL)
3851 			error = EINVAL;
3852 		else {
3853 			error = 0;
3854 			(void) strlcpy(data, s, MAXPATHLEN + 1);
3855 			kmem_free(s, strsz);
3856 		}
3857 
3858 	} else {
3859 
3860 		iov.iov_base = data;
3861 		iov.iov_len = MAXPATHLEN;
3862 		uio.uio_iov = &iov;
3863 		uio.uio_iovcnt = 1;
3864 		uio.uio_segflg = UIO_SYSSPACE;
3865 		uio.uio_extflg = UIO_COPY_CACHED;
3866 		uio.uio_loffset = 0;
3867 		uio.uio_resid = MAXPATHLEN;
3868 
3869 		error = VOP_READLINK(vp, &uio, cs->cr, NULL);
3870 
3871 		if (!error)
3872 			*(data + MAXPATHLEN - uio.uio_resid) = '\0';
3873 	}
3874 
3875 	if (error) {
3876 		kmem_free((caddr_t)data, (uint_t)MAXPATHLEN + 1);
3877 		*cs->statusp = resp->status = puterrno4(error);
3878 		goto out;
3879 	}
3880 
3881 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3882 	name = nfscmd_convname(ca, cs->exi, data, NFSCMD_CONV_OUTBOUND,
3883 	    MAXPATHLEN  + 1);
3884 
3885 	if (name == NULL) {
3886 		/*
3887 		 * Even though the conversion failed, we return
3888 		 * something. We just don't translate it.
3889 		 */
3890 		name = data;
3891 	}
3892 
3893 	/*
3894 	 * treat link name as data
3895 	 */
3896 	(void) str_to_utf8(name, (utf8string *)&resp->link);
3897 
3898 	if (name != data)
3899 		kmem_free(name, MAXPATHLEN + 1);
3900 	kmem_free((caddr_t)data, (uint_t)MAXPATHLEN + 1);
3901 	*cs->statusp = resp->status = NFS4_OK;
3902 
3903 out:
3904 	DTRACE_NFSV4_2(op__readlink__done, struct compound_state *, cs,
3905 	    READLINK4res *, resp);
3906 }
3907 
3908 static void
3909 rfs4_op_readlink_free(nfs_resop4 *resop)
3910 {
3911 	READLINK4res *resp = &resop->nfs_resop4_u.opreadlink;
3912 	utf8string *symlink = (utf8string *)&resp->link;
3913 
3914 	if (symlink->utf8string_val) {
3915 		UTF8STRING_FREE(*symlink)
3916 	}
3917 }
3918 
3919 /*
3920  * release_lockowner:
3921  *	Release any state associated with the supplied
3922  *	lockowner. Note if any lo_state is holding locks we will not
3923  *	rele that lo_state and thus the lockowner will not be destroyed.
3924  *	A client using lock after the lock owner stateid has been released
3925  *	will suffer the consequence of NFS4ERR_BAD_STATEID and would have
3926  *	to reissue the lock with new_lock_owner set to TRUE.
3927  *	args: lock_owner
3928  *	res:  status
3929  */
3930 /* ARGSUSED */
3931 static void
3932 rfs4_op_release_lockowner(nfs_argop4 *argop, nfs_resop4 *resop,
3933     struct svc_req *req, struct compound_state *cs)
3934 {
3935 	RELEASE_LOCKOWNER4args *ap = &argop->nfs_argop4_u.oprelease_lockowner;
3936 	RELEASE_LOCKOWNER4res *resp = &resop->nfs_resop4_u.oprelease_lockowner;
3937 	rfs4_lockowner_t *lo;
3938 	rfs4_openowner_t *oo;
3939 	rfs4_state_t *sp;
3940 	rfs4_lo_state_t *lsp;
3941 	rfs4_client_t *cp;
3942 	bool_t create = FALSE;
3943 	locklist_t *llist;
3944 	sysid_t sysid;
3945 
3946 	DTRACE_NFSV4_2(op__release__lockowner__start, struct compound_state *,
3947 	    cs, RELEASE_LOCKOWNER4args *, ap);
3948 
3949 	/* Make sure there is a clientid around for this request */
3950 	cp = rfs4_findclient_by_id(ap->lock_owner.clientid, FALSE);
3951 
3952 	if (cp == NULL) {
3953 		*cs->statusp = resp->status =
3954 		    rfs4_check_clientid(&ap->lock_owner.clientid, 0);
3955 		goto out;
3956 	}
3957 	rfs4_client_rele(cp);
3958 
3959 	lo = rfs4_findlockowner(&ap->lock_owner, &create);
3960 	if (lo == NULL) {
3961 		*cs->statusp = resp->status = NFS4_OK;
3962 		goto out;
3963 	}
3964 	ASSERT(lo->rl_client != NULL);
3965 
3966 	/*
3967 	 * Check for EXPIRED client. If so will reap state with in a lease
3968 	 * period or on next set_clientid_confirm step
3969 	 */
3970 	if (rfs4_lease_expired(lo->rl_client)) {
3971 		rfs4_lockowner_rele(lo);
3972 		*cs->statusp = resp->status = NFS4ERR_EXPIRED;
3973 		goto out;
3974 	}
3975 
3976 	/*
3977 	 * If no sysid has been assigned, then no locks exist; just return.
3978 	 */
3979 	rfs4_dbe_lock(lo->rl_client->rc_dbe);
3980 	if (lo->rl_client->rc_sysidt == LM_NOSYSID) {
3981 		rfs4_lockowner_rele(lo);
3982 		rfs4_dbe_unlock(lo->rl_client->rc_dbe);
3983 		goto out;
3984 	}
3985 
3986 	sysid = lo->rl_client->rc_sysidt;
3987 	rfs4_dbe_unlock(lo->rl_client->rc_dbe);
3988 
3989 	/*
3990 	 * Mark the lockowner invalid.
3991 	 */
3992 	rfs4_dbe_hide(lo->rl_dbe);
3993 
3994 	/*
3995 	 * sysid-pid pair should now not be used since the lockowner is
3996 	 * invalid. If the client were to instantiate the lockowner again
3997 	 * it would be assigned a new pid. Thus we can get the list of
3998 	 * current locks.
3999 	 */
4000 
4001 	llist = flk_get_active_locks(sysid, lo->rl_pid);
4002 	/* If we are still holding locks fail */
4003 	if (llist != NULL) {
4004 
4005 		*cs->statusp = resp->status = NFS4ERR_LOCKS_HELD;
4006 
4007 		flk_free_locklist(llist);
4008 		/*
4009 		 * We need to unhide the lockowner so the client can
4010 		 * try it again. The bad thing here is if the client
4011 		 * has a logic error that took it here in the first place
4012 		 * he probably has lost accounting of the locks that it
4013 		 * is holding. So we may have dangling state until the
4014 		 * open owner state is reaped via close. One scenario
4015 		 * that could possibly occur is that the client has
4016 		 * sent the unlock request(s) in separate threads
4017 		 * and has not waited for the replies before sending the
4018 		 * RELEASE_LOCKOWNER request. Presumably, it would expect
4019 		 * and deal appropriately with NFS4ERR_LOCKS_HELD, by
4020 		 * reissuing the request.
4021 		 */
4022 		rfs4_dbe_unhide(lo->rl_dbe);
4023 		rfs4_lockowner_rele(lo);
4024 		goto out;
4025 	}
4026 
4027 	/*
4028 	 * For the corresponding client we need to check each open
4029 	 * owner for any opens that have lockowner state associated
4030 	 * with this lockowner.
4031 	 */
4032 
4033 	rfs4_dbe_lock(lo->rl_client->rc_dbe);
4034 	for (oo = list_head(&lo->rl_client->rc_openownerlist); oo != NULL;
4035 	    oo = list_next(&lo->rl_client->rc_openownerlist, oo)) {
4036 
4037 		rfs4_dbe_lock(oo->ro_dbe);
4038 		for (sp = list_head(&oo->ro_statelist); sp != NULL;
4039 		    sp = list_next(&oo->ro_statelist, sp)) {
4040 
4041 			rfs4_dbe_lock(sp->rs_dbe);
4042 			for (lsp = list_head(&sp->rs_lostatelist);
4043 			    lsp != NULL;
4044 			    lsp = list_next(&sp->rs_lostatelist, lsp)) {
4045 				if (lsp->rls_locker == lo) {
4046 					rfs4_dbe_lock(lsp->rls_dbe);
4047 					rfs4_dbe_invalidate(lsp->rls_dbe);
4048 					rfs4_dbe_unlock(lsp->rls_dbe);
4049 				}
4050 			}
4051 			rfs4_dbe_unlock(sp->rs_dbe);
4052 		}
4053 		rfs4_dbe_unlock(oo->ro_dbe);
4054 	}
4055 	rfs4_dbe_unlock(lo->rl_client->rc_dbe);
4056 
4057 	rfs4_lockowner_rele(lo);
4058 
4059 	*cs->statusp = resp->status = NFS4_OK;
4060 
4061 out:
4062 	DTRACE_NFSV4_2(op__release__lockowner__done, struct compound_state *,
4063 	    cs, RELEASE_LOCKOWNER4res *, resp);
4064 }
4065 
4066 /*
4067  * short utility function to lookup a file and recall the delegation
4068  */
4069 static rfs4_file_t *
4070 rfs4_lookup_and_findfile(vnode_t *dvp, char *nm, vnode_t **vpp,
4071     int *lkup_error, cred_t *cr)
4072 {
4073 	vnode_t *vp;
4074 	rfs4_file_t *fp = NULL;
4075 	bool_t fcreate = FALSE;
4076 	int error;
4077 
4078 	if (vpp)
4079 		*vpp = NULL;
4080 
4081 	if ((error = VOP_LOOKUP(dvp, nm, &vp, NULL, 0, NULL, cr, NULL, NULL,
4082 	    NULL)) == 0) {
4083 		if (vp->v_type == VREG)
4084 			fp = rfs4_findfile(vp, NULL, &fcreate);
4085 		if (vpp)
4086 			*vpp = vp;
4087 		else
4088 			VN_RELE(vp);
4089 	}
4090 
4091 	if (lkup_error)
4092 		*lkup_error = error;
4093 
4094 	return (fp);
4095 }
4096 
4097 /*
4098  * remove: args: CURRENT_FH: directory; name.
4099  *	res: status. If success - CURRENT_FH unchanged, return change_info
4100  *		for directory.
4101  */
4102 /* ARGSUSED */
4103 static void
4104 rfs4_op_remove(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
4105     struct compound_state *cs)
4106 {
4107 	REMOVE4args *args = &argop->nfs_argop4_u.opremove;
4108 	REMOVE4res *resp = &resop->nfs_resop4_u.opremove;
4109 	int error;
4110 	vnode_t *dvp, *vp;
4111 	struct vattr bdva, idva, adva;
4112 	char *nm;
4113 	uint_t len;
4114 	rfs4_file_t *fp;
4115 	int in_crit = 0;
4116 	bslabel_t *clabel;
4117 	struct sockaddr *ca;
4118 	char *name = NULL;
4119 	nfsstat4 status;
4120 
4121 	DTRACE_NFSV4_2(op__remove__start, struct compound_state *, cs,
4122 	    REMOVE4args *, args);
4123 
4124 	/* CURRENT_FH: directory */
4125 	dvp = cs->vp;
4126 	if (dvp == NULL) {
4127 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
4128 		goto out;
4129 	}
4130 
4131 	if (cs->access == CS_ACCESS_DENIED) {
4132 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
4133 		goto out;
4134 	}
4135 
4136 	/*
4137 	 * If there is an unshared filesystem mounted on this vnode,
4138 	 * Do not allow to remove anything in this directory.
4139 	 */
4140 	if (vn_ismntpt(dvp)) {
4141 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
4142 		goto out;
4143 	}
4144 
4145 	if (dvp->v_type != VDIR) {
4146 		*cs->statusp = resp->status = NFS4ERR_NOTDIR;
4147 		goto out;
4148 	}
4149 
4150 	status = utf8_dir_verify(&args->target);
4151 	if (status != NFS4_OK) {
4152 		*cs->statusp = resp->status = status;
4153 		goto out;
4154 	}
4155 
4156 	/*
4157 	 * Lookup the file so that we can check if it's a directory
4158 	 */
4159 	nm = utf8_to_fn(&args->target, &len, NULL);
4160 	if (nm == NULL) {
4161 		*cs->statusp = resp->status = NFS4ERR_INVAL;
4162 		goto out;
4163 	}
4164 
4165 	if (len > MAXNAMELEN) {
4166 		*cs->statusp = resp->status = NFS4ERR_NAMETOOLONG;
4167 		kmem_free(nm, len);
4168 		goto out;
4169 	}
4170 
4171 	if (rdonly4(req, cs)) {
4172 		*cs->statusp = resp->status = NFS4ERR_ROFS;
4173 		kmem_free(nm, len);
4174 		goto out;
4175 	}
4176 
4177 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
4178 	name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
4179 	    MAXPATHLEN  + 1);
4180 
4181 	if (name == NULL) {
4182 		*cs->statusp = resp->status = NFS4ERR_INVAL;
4183 		kmem_free(nm, len);
4184 		goto out;
4185 	}
4186 
4187 	/*
4188 	 * Lookup the file to determine type and while we are see if
4189 	 * there is a file struct around and check for delegation.
4190 	 * We don't need to acquire va_seq before this lookup, if
4191 	 * it causes an update, cinfo.before will not match, which will
4192 	 * trigger a cache flush even if atomic is TRUE.
4193 	 */
4194 	if (fp = rfs4_lookup_and_findfile(dvp, name, &vp, &error, cs->cr)) {
4195 		if (rfs4_check_delegated_byfp(FWRITE, fp, TRUE, TRUE, TRUE,
4196 		    NULL)) {
4197 			VN_RELE(vp);
4198 			rfs4_file_rele(fp);
4199 			*cs->statusp = resp->status = NFS4ERR_DELAY;
4200 			if (nm != name)
4201 				kmem_free(name, MAXPATHLEN + 1);
4202 			kmem_free(nm, len);
4203 			goto out;
4204 		}
4205 	}
4206 
4207 	/* Didn't find anything to remove */
4208 	if (vp == NULL) {
4209 		*cs->statusp = resp->status = error;
4210 		if (nm != name)
4211 			kmem_free(name, MAXPATHLEN + 1);
4212 		kmem_free(nm, len);
4213 		goto out;
4214 	}
4215 
4216 	if (nbl_need_check(vp)) {
4217 		nbl_start_crit(vp, RW_READER);
4218 		in_crit = 1;
4219 		if (nbl_conflict(vp, NBL_REMOVE, 0, 0, 0, NULL)) {
4220 			*cs->statusp = resp->status = NFS4ERR_FILE_OPEN;
4221 			if (nm != name)
4222 				kmem_free(name, MAXPATHLEN + 1);
4223 			kmem_free(nm, len);
4224 			nbl_end_crit(vp);
4225 			VN_RELE(vp);
4226 			if (fp) {
4227 				rfs4_clear_dont_grant(fp);
4228 				rfs4_file_rele(fp);
4229 			}
4230 			goto out;
4231 		}
4232 	}
4233 
4234 	/* check label before allowing removal */
4235 	if (is_system_labeled()) {
4236 		ASSERT(req->rq_label != NULL);
4237 		clabel = req->rq_label;
4238 		DTRACE_PROBE2(tx__rfs4__log__info__opremove__clabel, char *,
4239 		    "got client label from request(1)",
4240 		    struct svc_req *, req);
4241 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
4242 			if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
4243 			    cs->exi)) {
4244 				*cs->statusp = resp->status = NFS4ERR_ACCESS;
4245 				if (name != nm)
4246 					kmem_free(name, MAXPATHLEN + 1);
4247 				kmem_free(nm, len);
4248 				if (in_crit)
4249 					nbl_end_crit(vp);
4250 				VN_RELE(vp);
4251 				if (fp) {
4252 					rfs4_clear_dont_grant(fp);
4253 					rfs4_file_rele(fp);
4254 				}
4255 				goto out;
4256 			}
4257 		}
4258 	}
4259 
4260 	/* Get dir "before" change value */
4261 	bdva.va_mask = AT_CTIME|AT_SEQ;
4262 	error = VOP_GETATTR(dvp, &bdva, 0, cs->cr, NULL);
4263 	if (error) {
4264 		*cs->statusp = resp->status = puterrno4(error);
4265 		if (nm != name)
4266 			kmem_free(name, MAXPATHLEN + 1);
4267 		kmem_free(nm, len);
4268 		if (in_crit)
4269 			nbl_end_crit(vp);
4270 		VN_RELE(vp);
4271 		if (fp) {
4272 			rfs4_clear_dont_grant(fp);
4273 			rfs4_file_rele(fp);
4274 		}
4275 		goto out;
4276 	}
4277 	NFS4_SET_FATTR4_CHANGE(resp->cinfo.before, bdva.va_ctime)
4278 
4279 	/* Actually do the REMOVE operation */
4280 	if (vp->v_type == VDIR) {
4281 		/*
4282 		 * Can't remove a directory that has a mounted-on filesystem.
4283 		 */
4284 		if (vn_ismntpt(vp)) {
4285 			error = EACCES;
4286 		} else {
4287 			/*
4288 			 * System V defines rmdir to return EEXIST,
4289 			 * not ENOTEMPTY, if the directory is not
4290 			 * empty.  A System V NFS server needs to map
4291 			 * NFS4ERR_EXIST to NFS4ERR_NOTEMPTY to
4292 			 * transmit over the wire.
4293 			 */
4294 			if ((error = VOP_RMDIR(dvp, name, rootdir, cs->cr,
4295 			    NULL, 0)) == EEXIST)
4296 				error = ENOTEMPTY;
4297 		}
4298 
4299 		if (in_crit)
4300 			nbl_end_crit(vp);
4301 		VN_RELE(vp);
4302 	} else {
4303 		if (!in_crit)
4304 			VN_RELE(vp);
4305 		if ((error = VOP_REMOVE(dvp, name, cs->cr, NULL, 0)) == 0 &&
4306 		    fp != NULL) {
4307 			struct vattr va;
4308 			vnode_t *tvp;
4309 
4310 			rfs4_dbe_lock(fp->rf_dbe);
4311 			tvp = fp->rf_vp;
4312 			if (tvp)
4313 				VN_HOLD(tvp);
4314 			rfs4_dbe_unlock(fp->rf_dbe);
4315 
4316 			if (tvp) {
4317 				/*
4318 				 * This is va_seq safe because we are not
4319 				 * manipulating dvp.
4320 				 */
4321 				va.va_mask = AT_NLINK;
4322 				if (!VOP_GETATTR(tvp, &va, 0, cs->cr, NULL) &&
4323 				    va.va_nlink == 0) {
4324 					/* Remove state on file remove */
4325 					if (in_crit) {
4326 						nbl_end_crit(vp);
4327 						VN_RELE(vp);
4328 						in_crit = 0;
4329 					}
4330 					rfs4_close_all_state(fp);
4331 				}
4332 				VN_RELE(tvp);
4333 			}
4334 		}
4335 
4336 		if (in_crit) {
4337 			nbl_end_crit(vp);
4338 			VN_RELE(vp);
4339 		}
4340 	}
4341 
4342 	if (fp) {
4343 		rfs4_clear_dont_grant(fp);
4344 		rfs4_file_rele(fp);
4345 	}
4346 	if (nm != name)
4347 		kmem_free(name, MAXPATHLEN + 1);
4348 	kmem_free(nm, len);
4349 
4350 	if (error) {
4351 		*cs->statusp = resp->status = puterrno4(error);
4352 		goto out;
4353 	}
4354 
4355 	/*
4356 	 * Get the initial "after" sequence number, if it fails, set to zero
4357 	 */
4358 	idva.va_mask = AT_SEQ;
4359 	if (VOP_GETATTR(dvp, &idva, 0, cs->cr, NULL))
4360 		idva.va_seq = 0;
4361 
4362 	/*
4363 	 * Force modified data and metadata out to stable storage.
4364 	 */
4365 	(void) VOP_FSYNC(dvp, 0, cs->cr, NULL);
4366 
4367 	/*
4368 	 * Get "after" change value, if it fails, simply return the
4369 	 * before value.
4370 	 */
4371 	adva.va_mask = AT_CTIME|AT_SEQ;
4372 	if (VOP_GETATTR(dvp, &adva, 0, cs->cr, NULL)) {
4373 		adva.va_ctime = bdva.va_ctime;
4374 		adva.va_seq = 0;
4375 	}
4376 
4377 	NFS4_SET_FATTR4_CHANGE(resp->cinfo.after, adva.va_ctime)
4378 
4379 	/*
4380 	 * The cinfo.atomic = TRUE only if we have
4381 	 * non-zero va_seq's, and it has incremented by exactly one
4382 	 * during the VOP_REMOVE/RMDIR and it didn't change during
4383 	 * the VOP_FSYNC.
4384 	 */
4385 	if (bdva.va_seq && idva.va_seq && adva.va_seq &&
4386 	    idva.va_seq == (bdva.va_seq + 1) && idva.va_seq == adva.va_seq)
4387 		resp->cinfo.atomic = TRUE;
4388 	else
4389 		resp->cinfo.atomic = FALSE;
4390 
4391 	*cs->statusp = resp->status = NFS4_OK;
4392 
4393 out:
4394 	DTRACE_NFSV4_2(op__remove__done, struct compound_state *, cs,
4395 	    REMOVE4res *, resp);
4396 }
4397 
4398 /*
4399  * rename: args: SAVED_FH: from directory, CURRENT_FH: target directory,
4400  *		oldname and newname.
4401  *	res: status. If success - CURRENT_FH unchanged, return change_info
4402  *		for both from and target directories.
4403  */
4404 /* ARGSUSED */
4405 static void
4406 rfs4_op_rename(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
4407     struct compound_state *cs)
4408 {
4409 	RENAME4args *args = &argop->nfs_argop4_u.oprename;
4410 	RENAME4res *resp = &resop->nfs_resop4_u.oprename;
4411 	int error;
4412 	vnode_t *odvp;
4413 	vnode_t *ndvp;
4414 	vnode_t *srcvp, *targvp;
4415 	struct vattr obdva, oidva, oadva;
4416 	struct vattr nbdva, nidva, nadva;
4417 	char *onm, *nnm;
4418 	uint_t olen, nlen;
4419 	rfs4_file_t *fp, *sfp;
4420 	int in_crit_src, in_crit_targ;
4421 	int fp_rele_grant_hold, sfp_rele_grant_hold;
4422 	bslabel_t *clabel;
4423 	struct sockaddr *ca;
4424 	char *converted_onm = NULL;
4425 	char *converted_nnm = NULL;
4426 	nfsstat4 status;
4427 
4428 	DTRACE_NFSV4_2(op__rename__start, struct compound_state *, cs,
4429 	    RENAME4args *, args);
4430 
4431 	fp = sfp = NULL;
4432 	srcvp = targvp = NULL;
4433 	in_crit_src = in_crit_targ = 0;
4434 	fp_rele_grant_hold = sfp_rele_grant_hold = 0;
4435 
4436 	/* CURRENT_FH: target directory */
4437 	ndvp = cs->vp;
4438 	if (ndvp == NULL) {
4439 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
4440 		goto out;
4441 	}
4442 
4443 	/* SAVED_FH: from directory */
4444 	odvp = cs->saved_vp;
4445 	if (odvp == NULL) {
4446 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
4447 		goto out;
4448 	}
4449 
4450 	if (cs->access == CS_ACCESS_DENIED) {
4451 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
4452 		goto out;
4453 	}
4454 
4455 	/*
4456 	 * If there is an unshared filesystem mounted on this vnode,
4457 	 * do not allow to rename objects in this directory.
4458 	 */
4459 	if (vn_ismntpt(odvp)) {
4460 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
4461 		goto out;
4462 	}
4463 
4464 	/*
4465 	 * If there is an unshared filesystem mounted on this vnode,
4466 	 * do not allow to rename to this directory.
4467 	 */
4468 	if (vn_ismntpt(ndvp)) {
4469 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
4470 		goto out;
4471 	}
4472 
4473 	if (odvp->v_type != VDIR || ndvp->v_type != VDIR) {
4474 		*cs->statusp = resp->status = NFS4ERR_NOTDIR;
4475 		goto out;
4476 	}
4477 
4478 	if (cs->saved_exi != cs->exi) {
4479 		*cs->statusp = resp->status = NFS4ERR_XDEV;
4480 		goto out;
4481 	}
4482 
4483 	status = utf8_dir_verify(&args->oldname);
4484 	if (status != NFS4_OK) {
4485 		*cs->statusp = resp->status = status;
4486 		goto out;
4487 	}
4488 
4489 	status = utf8_dir_verify(&args->newname);
4490 	if (status != NFS4_OK) {
4491 		*cs->statusp = resp->status = status;
4492 		goto out;
4493 	}
4494 
4495 	onm = utf8_to_fn(&args->oldname, &olen, NULL);
4496 	if (onm == NULL) {
4497 		*cs->statusp = resp->status = NFS4ERR_INVAL;
4498 		goto out;
4499 	}
4500 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
4501 	nlen = MAXPATHLEN + 1;
4502 	converted_onm = nfscmd_convname(ca, cs->exi, onm, NFSCMD_CONV_INBOUND,
4503 	    nlen);
4504 
4505 	if (converted_onm == NULL) {
4506 		*cs->statusp = resp->status = NFS4ERR_INVAL;
4507 		kmem_free(onm, olen);
4508 		goto out;
4509 	}
4510 
4511 	nnm = utf8_to_fn(&args->newname, &nlen, NULL);
4512 	if (nnm == NULL) {
4513 		*cs->statusp = resp->status = NFS4ERR_INVAL;
4514 		if (onm != converted_onm)
4515 			kmem_free(converted_onm, MAXPATHLEN + 1);
4516 		kmem_free(onm, olen);
4517 		goto out;
4518 	}
4519 	converted_nnm = nfscmd_convname(ca, cs->exi, nnm, NFSCMD_CONV_INBOUND,
4520 	    MAXPATHLEN  + 1);
4521 
4522 	if (converted_nnm == NULL) {
4523 		*cs->statusp = resp->status = NFS4ERR_INVAL;
4524 		kmem_free(nnm, nlen);
4525 		nnm = NULL;
4526 		if (onm != converted_onm)
4527 			kmem_free(converted_onm, MAXPATHLEN + 1);
4528 		kmem_free(onm, olen);
4529 		goto out;
4530 	}
4531 
4532 
4533 	if (olen > MAXNAMELEN || nlen > MAXNAMELEN) {
4534 		*cs->statusp = resp->status = NFS4ERR_NAMETOOLONG;
4535 		kmem_free(onm, olen);
4536 		kmem_free(nnm, nlen);
4537 		goto out;
4538 	}
4539 
4540 
4541 	if (rdonly4(req, cs)) {
4542 		*cs->statusp = resp->status = NFS4ERR_ROFS;
4543 		if (onm != converted_onm)
4544 			kmem_free(converted_onm, MAXPATHLEN + 1);
4545 		kmem_free(onm, olen);
4546 		if (nnm != converted_nnm)
4547 			kmem_free(converted_nnm, MAXPATHLEN + 1);
4548 		kmem_free(nnm, nlen);
4549 		goto out;
4550 	}
4551 
4552 	/* check label of the target dir */
4553 	if (is_system_labeled()) {
4554 		ASSERT(req->rq_label != NULL);
4555 		clabel = req->rq_label;
4556 		DTRACE_PROBE2(tx__rfs4__log__info__oprename__clabel, char *,
4557 		    "got client label from request(1)",
4558 		    struct svc_req *, req);
4559 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
4560 			if (!do_rfs_label_check(clabel, ndvp,
4561 			    EQUALITY_CHECK, cs->exi)) {
4562 				*cs->statusp = resp->status = NFS4ERR_ACCESS;
4563 				goto err_out;
4564 			}
4565 		}
4566 	}
4567 
4568 	/*
4569 	 * Is the source a file and have a delegation?
4570 	 * We don't need to acquire va_seq before these lookups, if
4571 	 * it causes an update, cinfo.before will not match, which will
4572 	 * trigger a cache flush even if atomic is TRUE.
4573 	 */
4574 	if (sfp = rfs4_lookup_and_findfile(odvp, converted_onm, &srcvp,
4575 	    &error, cs->cr)) {
4576 		if (rfs4_check_delegated_byfp(FWRITE, sfp, TRUE, TRUE, TRUE,
4577 		    NULL)) {
4578 			*cs->statusp = resp->status = NFS4ERR_DELAY;
4579 			goto err_out;
4580 		}
4581 	}
4582 
4583 	if (srcvp == NULL) {
4584 		*cs->statusp = resp->status = puterrno4(error);
4585 		if (onm != converted_onm)
4586 			kmem_free(converted_onm, MAXPATHLEN + 1);
4587 		kmem_free(onm, olen);
4588 		if (nnm != converted_nnm)
4589 			kmem_free(converted_nnm, MAXPATHLEN + 1);
4590 		kmem_free(nnm, nlen);
4591 		goto out;
4592 	}
4593 
4594 	sfp_rele_grant_hold = 1;
4595 
4596 	/* Does the destination exist and a file and have a delegation? */
4597 	if (fp = rfs4_lookup_and_findfile(ndvp, converted_nnm, &targvp,
4598 	    NULL, cs->cr)) {
4599 		if (rfs4_check_delegated_byfp(FWRITE, fp, TRUE, TRUE, TRUE,
4600 		    NULL)) {
4601 			*cs->statusp = resp->status = NFS4ERR_DELAY;
4602 			goto err_out;
4603 		}
4604 	}
4605 	fp_rele_grant_hold = 1;
4606 
4607 
4608 	/* Check for NBMAND lock on both source and target */
4609 	if (nbl_need_check(srcvp)) {
4610 		nbl_start_crit(srcvp, RW_READER);
4611 		in_crit_src = 1;
4612 		if (nbl_conflict(srcvp, NBL_RENAME, 0, 0, 0, NULL)) {
4613 			*cs->statusp = resp->status = NFS4ERR_FILE_OPEN;
4614 			goto err_out;
4615 		}
4616 	}
4617 
4618 	if (targvp && nbl_need_check(targvp)) {
4619 		nbl_start_crit(targvp, RW_READER);
4620 		in_crit_targ = 1;
4621 		if (nbl_conflict(targvp, NBL_REMOVE, 0, 0, 0, NULL)) {
4622 			*cs->statusp = resp->status = NFS4ERR_FILE_OPEN;
4623 			goto err_out;
4624 		}
4625 	}
4626 
4627 	/* Get source "before" change value */
4628 	obdva.va_mask = AT_CTIME|AT_SEQ;
4629 	error = VOP_GETATTR(odvp, &obdva, 0, cs->cr, NULL);
4630 	if (!error) {
4631 		nbdva.va_mask = AT_CTIME|AT_SEQ;
4632 		error = VOP_GETATTR(ndvp, &nbdva, 0, cs->cr, NULL);
4633 	}
4634 	if (error) {
4635 		*cs->statusp = resp->status = puterrno4(error);
4636 		goto err_out;
4637 	}
4638 
4639 	NFS4_SET_FATTR4_CHANGE(resp->source_cinfo.before, obdva.va_ctime)
4640 	NFS4_SET_FATTR4_CHANGE(resp->target_cinfo.before, nbdva.va_ctime)
4641 
4642 	if ((error = VOP_RENAME(odvp, converted_onm, ndvp, converted_nnm,
4643 	    cs->cr, NULL, 0)) == 0 && fp != NULL) {
4644 		struct vattr va;
4645 		vnode_t *tvp;
4646 
4647 		rfs4_dbe_lock(fp->rf_dbe);
4648 		tvp = fp->rf_vp;
4649 		if (tvp)
4650 			VN_HOLD(tvp);
4651 		rfs4_dbe_unlock(fp->rf_dbe);
4652 
4653 		if (tvp) {
4654 			va.va_mask = AT_NLINK;
4655 			if (!VOP_GETATTR(tvp, &va, 0, cs->cr, NULL) &&
4656 			    va.va_nlink == 0) {
4657 				/* The file is gone and so should the state */
4658 				if (in_crit_targ) {
4659 					nbl_end_crit(targvp);
4660 					in_crit_targ = 0;
4661 				}
4662 				rfs4_close_all_state(fp);
4663 			}
4664 			VN_RELE(tvp);
4665 		}
4666 	}
4667 	if (error == 0)
4668 		vn_renamepath(ndvp, srcvp, nnm, nlen - 1);
4669 
4670 	if (in_crit_src)
4671 		nbl_end_crit(srcvp);
4672 	if (srcvp)
4673 		VN_RELE(srcvp);
4674 	if (in_crit_targ)
4675 		nbl_end_crit(targvp);
4676 	if (targvp)
4677 		VN_RELE(targvp);
4678 
4679 	if (sfp) {
4680 		rfs4_clear_dont_grant(sfp);
4681 		rfs4_file_rele(sfp);
4682 	}
4683 	if (fp) {
4684 		rfs4_clear_dont_grant(fp);
4685 		rfs4_file_rele(fp);
4686 	}
4687 
4688 	if (converted_onm != onm)
4689 		kmem_free(converted_onm, MAXPATHLEN + 1);
4690 	kmem_free(onm, olen);
4691 	if (converted_nnm != nnm)
4692 		kmem_free(converted_nnm, MAXPATHLEN + 1);
4693 	kmem_free(nnm, nlen);
4694 
4695 	/*
4696 	 * Get the initial "after" sequence number, if it fails, set to zero
4697 	 */
4698 	oidva.va_mask = AT_SEQ;
4699 	if (VOP_GETATTR(odvp, &oidva, 0, cs->cr, NULL))
4700 		oidva.va_seq = 0;
4701 
4702 	nidva.va_mask = AT_SEQ;
4703 	if (VOP_GETATTR(ndvp, &nidva, 0, cs->cr, NULL))
4704 		nidva.va_seq = 0;
4705 
4706 	/*
4707 	 * Force modified data and metadata out to stable storage.
4708 	 */
4709 	(void) VOP_FSYNC(odvp, 0, cs->cr, NULL);
4710 	(void) VOP_FSYNC(ndvp, 0, cs->cr, NULL);
4711 
4712 	if (error) {
4713 		*cs->statusp = resp->status = puterrno4(error);
4714 		goto out;
4715 	}
4716 
4717 	/*
4718 	 * Get "after" change values, if it fails, simply return the
4719 	 * before value.
4720 	 */
4721 	oadva.va_mask = AT_CTIME|AT_SEQ;
4722 	if (VOP_GETATTR(odvp, &oadva, 0, cs->cr, NULL)) {
4723 		oadva.va_ctime = obdva.va_ctime;
4724 		oadva.va_seq = 0;
4725 	}
4726 
4727 	nadva.va_mask = AT_CTIME|AT_SEQ;
4728 	if (VOP_GETATTR(odvp, &nadva, 0, cs->cr, NULL)) {
4729 		nadva.va_ctime = nbdva.va_ctime;
4730 		nadva.va_seq = 0;
4731 	}
4732 
4733 	NFS4_SET_FATTR4_CHANGE(resp->source_cinfo.after, oadva.va_ctime)
4734 	NFS4_SET_FATTR4_CHANGE(resp->target_cinfo.after, nadva.va_ctime)
4735 
4736 	/*
4737 	 * The cinfo.atomic = TRUE only if we have
4738 	 * non-zero va_seq's, and it has incremented by exactly one
4739 	 * during the VOP_RENAME and it didn't change during the VOP_FSYNC.
4740 	 */
4741 	if (obdva.va_seq && oidva.va_seq && oadva.va_seq &&
4742 	    oidva.va_seq == (obdva.va_seq + 1) && oidva.va_seq == oadva.va_seq)
4743 		resp->source_cinfo.atomic = TRUE;
4744 	else
4745 		resp->source_cinfo.atomic = FALSE;
4746 
4747 	if (nbdva.va_seq && nidva.va_seq && nadva.va_seq &&
4748 	    nidva.va_seq == (nbdva.va_seq + 1) && nidva.va_seq == nadva.va_seq)
4749 		resp->target_cinfo.atomic = TRUE;
4750 	else
4751 		resp->target_cinfo.atomic = FALSE;
4752 
4753 #ifdef	VOLATILE_FH_TEST
4754 	{
4755 	extern void add_volrnm_fh(struct exportinfo *, vnode_t *);
4756 
4757 	/*
4758 	 * Add the renamed file handle to the volatile rename list
4759 	 */
4760 	if (cs->exi->exi_export.ex_flags & EX_VOLRNM) {
4761 		/* file handles may expire on rename */
4762 		vnode_t *vp;
4763 
4764 		nnm = utf8_to_fn(&args->newname, &nlen, NULL);
4765 		/*
4766 		 * Already know that nnm will be a valid string
4767 		 */
4768 		error = VOP_LOOKUP(ndvp, nnm, &vp, NULL, 0, NULL, cs->cr,
4769 		    NULL, NULL, NULL);
4770 		kmem_free(nnm, nlen);
4771 		if (!error) {
4772 			add_volrnm_fh(cs->exi, vp);
4773 			VN_RELE(vp);
4774 		}
4775 	}
4776 	}
4777 #endif	/* VOLATILE_FH_TEST */
4778 
4779 	*cs->statusp = resp->status = NFS4_OK;
4780 out:
4781 	DTRACE_NFSV4_2(op__rename__done, struct compound_state *, cs,
4782 	    RENAME4res *, resp);
4783 	return;
4784 
4785 err_out:
4786 	if (onm != converted_onm)
4787 		kmem_free(converted_onm, MAXPATHLEN + 1);
4788 	if (onm != NULL)
4789 		kmem_free(onm, olen);
4790 	if (nnm != converted_nnm)
4791 		kmem_free(converted_nnm, MAXPATHLEN + 1);
4792 	if (nnm != NULL)
4793 		kmem_free(nnm, nlen);
4794 
4795 	if (in_crit_src) nbl_end_crit(srcvp);
4796 	if (in_crit_targ) nbl_end_crit(targvp);
4797 	if (targvp) VN_RELE(targvp);
4798 	if (srcvp) VN_RELE(srcvp);
4799 	if (sfp) {
4800 		if (sfp_rele_grant_hold) rfs4_clear_dont_grant(sfp);
4801 		rfs4_file_rele(sfp);
4802 	}
4803 	if (fp) {
4804 		if (fp_rele_grant_hold) rfs4_clear_dont_grant(fp);
4805 		rfs4_file_rele(fp);
4806 	}
4807 
4808 	DTRACE_NFSV4_2(op__rename__done, struct compound_state *, cs,
4809 	    RENAME4res *, resp);
4810 }
4811 
4812 /* ARGSUSED */
4813 static void
4814 rfs4_op_renew(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
4815     struct compound_state *cs)
4816 {
4817 	RENEW4args *args = &argop->nfs_argop4_u.oprenew;
4818 	RENEW4res *resp = &resop->nfs_resop4_u.oprenew;
4819 	rfs4_client_t *cp;
4820 
4821 	DTRACE_NFSV4_2(op__renew__start, struct compound_state *, cs,
4822 	    RENEW4args *, args);
4823 
4824 	if ((cp = rfs4_findclient_by_id(args->clientid, FALSE)) == NULL) {
4825 		*cs->statusp = resp->status =
4826 		    rfs4_check_clientid(&args->clientid, 0);
4827 		goto out;
4828 	}
4829 
4830 	if (rfs4_lease_expired(cp)) {
4831 		rfs4_client_rele(cp);
4832 		*cs->statusp = resp->status = NFS4ERR_EXPIRED;
4833 		goto out;
4834 	}
4835 
4836 	rfs4_update_lease(cp);
4837 
4838 	mutex_enter(cp->rc_cbinfo.cb_lock);
4839 	if (cp->rc_cbinfo.cb_notified_of_cb_path_down == FALSE) {
4840 		cp->rc_cbinfo.cb_notified_of_cb_path_down = TRUE;
4841 		*cs->statusp = resp->status = NFS4ERR_CB_PATH_DOWN;
4842 	} else {
4843 		*cs->statusp = resp->status = NFS4_OK;
4844 	}
4845 	mutex_exit(cp->rc_cbinfo.cb_lock);
4846 
4847 	rfs4_client_rele(cp);
4848 
4849 out:
4850 	DTRACE_NFSV4_2(op__renew__done, struct compound_state *, cs,
4851 	    RENEW4res *, resp);
4852 }
4853 
4854 /* ARGSUSED */
4855 static void
4856 rfs4_op_restorefh(nfs_argop4 *args, nfs_resop4 *resop, struct svc_req *req,
4857     struct compound_state *cs)
4858 {
4859 	RESTOREFH4res *resp = &resop->nfs_resop4_u.oprestorefh;
4860 
4861 	DTRACE_NFSV4_1(op__restorefh__start, struct compound_state *, cs);
4862 
4863 	/* No need to check cs->access - we are not accessing any object */
4864 	if ((cs->saved_vp == NULL) || (cs->saved_fh.nfs_fh4_val == NULL)) {
4865 		*cs->statusp = resp->status = NFS4ERR_RESTOREFH;
4866 		goto out;
4867 	}
4868 	if (cs->vp != NULL) {
4869 		VN_RELE(cs->vp);
4870 	}
4871 	cs->vp = cs->saved_vp;
4872 	cs->saved_vp = NULL;
4873 	if (cs->exi != NULL)
4874 		exi_rele(cs->exi);
4875 	cs->exi = cs->saved_exi;
4876 	if (cs->exi != NULL)
4877 		exi_hold(cs->exi);
4878 	nfs_fh4_copy(&cs->saved_fh, &cs->fh);
4879 	*cs->statusp = resp->status = NFS4_OK;
4880 	cs->deleg = FALSE;
4881 
4882 out:
4883 	DTRACE_NFSV4_2(op__restorefh__done, struct compound_state *, cs,
4884 	    RESTOREFH4res *, resp);
4885 }
4886 
4887 /* ARGSUSED */
4888 static void
4889 rfs4_op_savefh(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
4890     struct compound_state *cs)
4891 {
4892 	SAVEFH4res *resp = &resop->nfs_resop4_u.opsavefh;
4893 
4894 	DTRACE_NFSV4_1(op__savefh__start, struct compound_state *, cs);
4895 
4896 	/* No need to check cs->access - we are not accessing any object */
4897 	if (cs->vp == NULL) {
4898 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
4899 		goto out;
4900 	}
4901 	if (cs->saved_vp != NULL) {
4902 		VN_RELE(cs->saved_vp);
4903 	}
4904 	cs->saved_vp = cs->vp;
4905 	VN_HOLD(cs->saved_vp);
4906 	if (cs->saved_exi != NULL)
4907 		exi_rele(cs->saved_exi);
4908 	cs->saved_exi = cs->exi;
4909 	if (cs->saved_exi != NULL)
4910 		exi_hold(cs->saved_exi);
4911 	/*
4912 	 * since SAVEFH is fairly rare, don't alloc space for its fh
4913 	 * unless necessary.
4914 	 */
4915 	if (cs->saved_fh.nfs_fh4_val == NULL) {
4916 		cs->saved_fh.nfs_fh4_val = kmem_alloc(NFS4_FHSIZE, KM_SLEEP);
4917 	}
4918 	nfs_fh4_copy(&cs->fh, &cs->saved_fh);
4919 	*cs->statusp = resp->status = NFS4_OK;
4920 
4921 out:
4922 	DTRACE_NFSV4_2(op__savefh__done, struct compound_state *, cs,
4923 	    SAVEFH4res *, resp);
4924 }
4925 
4926 /*
4927  * rfs4_verify_attr is called when nfsv4 Setattr failed, but we wish to
4928  * return the bitmap of attrs that were set successfully. It is also
4929  * called by Verify/Nverify to test the vattr/vfsstat attrs. It should
4930  * always be called only after rfs4_do_set_attrs().
4931  *
4932  * Verify that the attributes are same as the expected ones. sargp->vap
4933  * and sargp->sbp contain the input attributes as translated from fattr4.
4934  *
4935  * This function verifies only the attrs that correspond to a vattr or
4936  * vfsstat struct. That is because of the extra step needed to get the
4937  * corresponding system structs. Other attributes have already been set or
4938  * verified by do_rfs4_set_attrs.
4939  *
4940  * Return 0 if all attrs match, -1 if some don't, error if error processing.
4941  */
4942 static int
4943 rfs4_verify_attr(struct nfs4_svgetit_arg *sargp,
4944     bitmap4 *resp, struct nfs4_ntov_table *ntovp)
4945 {
4946 	int error, ret_error = 0;
4947 	int i, k;
4948 	uint_t sva_mask = sargp->vap->va_mask;
4949 	uint_t vbit;
4950 	union nfs4_attr_u *na;
4951 	uint8_t *amap;
4952 	bool_t getsb = ntovp->vfsstat;
4953 
4954 	if (sva_mask != 0) {
4955 		/*
4956 		 * Okay to overwrite sargp->vap because we verify based
4957 		 * on the incoming values.
4958 		 */
4959 		ret_error = VOP_GETATTR(sargp->cs->vp, sargp->vap, 0,
4960 		    sargp->cs->cr, NULL);
4961 		if (ret_error) {
4962 			if (resp == NULL)
4963 				return (ret_error);
4964 			/*
4965 			 * Must return bitmap of successful attrs
4966 			 */
4967 			sva_mask = 0;	/* to prevent checking vap later */
4968 		} else {
4969 			/*
4970 			 * Some file systems clobber va_mask. it is probably
4971 			 * wrong of them to do so, nonethless we practice
4972 			 * defensive coding.
4973 			 * See bug id 4276830.
4974 			 */
4975 			sargp->vap->va_mask = sva_mask;
4976 		}
4977 	}
4978 
4979 	if (getsb) {
4980 		/*
4981 		 * Now get the superblock and loop on the bitmap, as there is
4982 		 * no simple way of translating from superblock to bitmap4.
4983 		 */
4984 		ret_error = VFS_STATVFS(sargp->cs->vp->v_vfsp, sargp->sbp);
4985 		if (ret_error) {
4986 			if (resp == NULL)
4987 				goto errout;
4988 			getsb = FALSE;
4989 		}
4990 	}
4991 
4992 	/*
4993 	 * Now loop and verify each attribute which getattr returned
4994 	 * whether it's the same as the input.
4995 	 */
4996 	if (resp == NULL && !getsb && (sva_mask == 0))
4997 		goto errout;
4998 
4999 	na = ntovp->na;
5000 	amap = ntovp->amap;
5001 	k = 0;
5002 	for (i = 0; i < ntovp->attrcnt; i++, na++, amap++) {
5003 		k = *amap;
5004 		ASSERT(nfs4_ntov_map[k].nval == k);
5005 		vbit = nfs4_ntov_map[k].vbit;
5006 
5007 		/*
5008 		 * If vattr attribute but VOP_GETATTR failed, or it's
5009 		 * superblock attribute but VFS_STATVFS failed, skip
5010 		 */
5011 		if (vbit) {
5012 			if ((vbit & sva_mask) == 0)
5013 				continue;
5014 		} else if (!(getsb && nfs4_ntov_map[k].vfsstat)) {
5015 			continue;
5016 		}
5017 		error = (*nfs4_ntov_map[k].sv_getit)(NFS4ATTR_VERIT, sargp, na);
5018 		if (resp != NULL) {
5019 			if (error)
5020 				ret_error = -1;	/* not all match */
5021 			else	/* update response bitmap */
5022 				*resp |= nfs4_ntov_map[k].fbit;
5023 			continue;
5024 		}
5025 		if (error) {
5026 			ret_error = -1;	/* not all match */
5027 			break;
5028 		}
5029 	}
5030 errout:
5031 	return (ret_error);
5032 }
5033 
5034 /*
5035  * Decode the attribute to be set/verified. If the attr requires a sys op
5036  * (VOP_GETATTR, VFS_VFSSTAT), and the request is to verify, then don't
5037  * call the sv_getit function for it, because the sys op hasn't yet been done.
5038  * Return 0 for success, error code if failed.
5039  *
5040  * Note: the decoded arg is not freed here but in nfs4_ntov_table_free.
5041  */
5042 static int
5043 decode_fattr4_attr(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sargp,
5044     int k, XDR *xdrp, bitmap4 *resp_bval, union nfs4_attr_u *nap)
5045 {
5046 	int error = 0;
5047 	bool_t set_later;
5048 
5049 	sargp->vap->va_mask |= nfs4_ntov_map[k].vbit;
5050 
5051 	if ((*nfs4_ntov_map[k].xfunc)(xdrp, nap)) {
5052 		set_later = nfs4_ntov_map[k].vbit || nfs4_ntov_map[k].vfsstat;
5053 		/*
5054 		 * don't verify yet if a vattr or sb dependent attr,
5055 		 * because we don't have their sys values yet.
5056 		 * Will be done later.
5057 		 */
5058 		if (! (set_later && (cmd == NFS4ATTR_VERIT))) {
5059 			/*
5060 			 * ACLs are a special case, since setting the MODE
5061 			 * conflicts with setting the ACL.  We delay setting
5062 			 * the ACL until all other attributes have been set.
5063 			 * The ACL gets set in do_rfs4_op_setattr().
5064 			 */
5065 			if (nfs4_ntov_map[k].fbit != FATTR4_ACL_MASK) {
5066 				error = (*nfs4_ntov_map[k].sv_getit)(cmd,
5067 				    sargp, nap);
5068 				if (error) {
5069 					xdr_free(nfs4_ntov_map[k].xfunc,
5070 					    (caddr_t)nap);
5071 				}
5072 			}
5073 		}
5074 	} else {
5075 #ifdef  DEBUG
5076 		cmn_err(CE_NOTE, "decode_fattr4_attr: error "
5077 		    "decoding attribute %d\n", k);
5078 #endif
5079 		error = EINVAL;
5080 	}
5081 	if (!error && resp_bval && !set_later) {
5082 		*resp_bval |= nfs4_ntov_map[k].fbit;
5083 	}
5084 
5085 	return (error);
5086 }
5087 
5088 /*
5089  * Set vattr based on incoming fattr4 attrs - used by setattr.
5090  * Set response mask. Ignore any values that are not writable vattr attrs.
5091  */
5092 static nfsstat4
5093 do_rfs4_set_attrs(bitmap4 *resp, fattr4 *fattrp, struct compound_state *cs,
5094     struct nfs4_svgetit_arg *sargp, struct nfs4_ntov_table *ntovp,
5095     nfs4_attr_cmd_t cmd)
5096 {
5097 	int error = 0;
5098 	int i;
5099 	char *attrs = fattrp->attrlist4;
5100 	uint32_t attrslen = fattrp->attrlist4_len;
5101 	XDR xdr;
5102 	nfsstat4 status = NFS4_OK;
5103 	vnode_t *vp = cs->vp;
5104 	union nfs4_attr_u *na;
5105 	uint8_t *amap;
5106 
5107 #ifndef lint
5108 	/*
5109 	 * Make sure that maximum attribute number can be expressed as an
5110 	 * 8 bit quantity.
5111 	 */
5112 	ASSERT(NFS4_MAXNUM_ATTRS <= (UINT8_MAX + 1));
5113 #endif
5114 
5115 	if (vp == NULL) {
5116 		if (resp)
5117 			*resp = 0;
5118 		return (NFS4ERR_NOFILEHANDLE);
5119 	}
5120 	if (cs->access == CS_ACCESS_DENIED) {
5121 		if (resp)
5122 			*resp = 0;
5123 		return (NFS4ERR_ACCESS);
5124 	}
5125 
5126 	sargp->op = cmd;
5127 	sargp->cs = cs;
5128 	sargp->flag = 0;	/* may be set later */
5129 	sargp->vap->va_mask = 0;
5130 	sargp->rdattr_error = NFS4_OK;
5131 	sargp->rdattr_error_req = FALSE;
5132 	/* sargp->sbp is set by the caller */
5133 
5134 	xdrmem_create(&xdr, attrs, attrslen, XDR_DECODE);
5135 
5136 	na = ntovp->na;
5137 	amap = ntovp->amap;
5138 
5139 	/*
5140 	 * The following loop iterates on the nfs4_ntov_map checking
5141 	 * if the fbit is set in the requested bitmap.
5142 	 * If set then we process the arguments using the
5143 	 * rfs4_fattr4 conversion functions to populate the setattr
5144 	 * vattr and va_mask. Any settable attrs that are not using vattr
5145 	 * will be set in this loop.
5146 	 */
5147 	for (i = 0; i < nfs4_ntov_map_size; i++) {
5148 		if (!(fattrp->attrmask & nfs4_ntov_map[i].fbit)) {
5149 			continue;
5150 		}
5151 		/*
5152 		 * If setattr, must be a writable attr.
5153 		 * If verify/nverify, must be a readable attr.
5154 		 */
5155 		if ((error = (*nfs4_ntov_map[i].sv_getit)(
5156 		    NFS4ATTR_SUPPORTED, sargp, NULL)) != 0) {
5157 			/*
5158 			 * Client tries to set/verify an
5159 			 * unsupported attribute, tries to set
5160 			 * a read only attr or verify a write
5161 			 * only one - error!
5162 			 */
5163 			break;
5164 		}
5165 		/*
5166 		 * Decode the attribute to set/verify
5167 		 */
5168 		error = decode_fattr4_attr(cmd, sargp, nfs4_ntov_map[i].nval,
5169 		    &xdr, resp ? resp : NULL, na);
5170 		if (error)
5171 			break;
5172 		*amap++ = (uint8_t)nfs4_ntov_map[i].nval;
5173 		na++;
5174 		(ntovp->attrcnt)++;
5175 		if (nfs4_ntov_map[i].vfsstat)
5176 			ntovp->vfsstat = TRUE;
5177 	}
5178 
5179 	if (error != 0)
5180 		status = (error == ENOTSUP ? NFS4ERR_ATTRNOTSUPP :
5181 		    puterrno4(error));
5182 	/* xdrmem_destroy(&xdrs); */	/* NO-OP */
5183 	return (status);
5184 }
5185 
5186 static nfsstat4
5187 do_rfs4_op_setattr(bitmap4 *resp, fattr4 *fattrp, struct compound_state *cs,
5188     stateid4 *stateid)
5189 {
5190 	int error = 0;
5191 	struct nfs4_svgetit_arg sarg;
5192 	bool_t trunc;
5193 
5194 	nfsstat4 status = NFS4_OK;
5195 	cred_t *cr = cs->cr;
5196 	vnode_t *vp = cs->vp;
5197 	struct nfs4_ntov_table ntov;
5198 	struct statvfs64 sb;
5199 	struct vattr bva;
5200 	struct flock64 bf;
5201 	int in_crit = 0;
5202 	uint_t saved_mask = 0;
5203 	caller_context_t ct;
5204 
5205 	*resp = 0;
5206 	sarg.sbp = &sb;
5207 	sarg.is_referral = B_FALSE;
5208 	nfs4_ntov_table_init(&ntov);
5209 	status = do_rfs4_set_attrs(resp, fattrp, cs, &sarg, &ntov,
5210 	    NFS4ATTR_SETIT);
5211 	if (status != NFS4_OK) {
5212 		/*
5213 		 * failed set attrs
5214 		 */
5215 		goto done;
5216 	}
5217 	if ((sarg.vap->va_mask == 0) &&
5218 	    (! (fattrp->attrmask & FATTR4_ACL_MASK))) {
5219 		/*
5220 		 * no further work to be done
5221 		 */
5222 		goto done;
5223 	}
5224 
5225 	/*
5226 	 * If we got a request to set the ACL and the MODE, only
5227 	 * allow changing VSUID, VSGID, and VSVTX.  Attempting
5228 	 * to change any other bits, along with setting an ACL,
5229 	 * gives NFS4ERR_INVAL.
5230 	 */
5231 	if ((fattrp->attrmask & FATTR4_ACL_MASK) &&
5232 	    (fattrp->attrmask & FATTR4_MODE_MASK)) {
5233 		vattr_t va;
5234 
5235 		va.va_mask = AT_MODE;
5236 		error = VOP_GETATTR(vp, &va, 0, cs->cr, NULL);
5237 		if (error) {
5238 			status = puterrno4(error);
5239 			goto done;
5240 		}
5241 		if ((sarg.vap->va_mode ^ va.va_mode) &
5242 		    ~(VSUID | VSGID | VSVTX)) {
5243 			status = NFS4ERR_INVAL;
5244 			goto done;
5245 		}
5246 	}
5247 
5248 	/* Check stateid only if size has been set */
5249 	if (sarg.vap->va_mask & AT_SIZE) {
5250 		trunc = (sarg.vap->va_size == 0);
5251 		status = rfs4_check_stateid(FWRITE, cs->vp, stateid,
5252 		    trunc, &cs->deleg, sarg.vap->va_mask & AT_SIZE, &ct);
5253 		if (status != NFS4_OK)
5254 			goto done;
5255 	} else {
5256 		ct.cc_sysid = 0;
5257 		ct.cc_pid = 0;
5258 		ct.cc_caller_id = nfs4_srv_caller_id;
5259 		ct.cc_flags = CC_DONTBLOCK;
5260 	}
5261 
5262 	/* XXX start of possible race with delegations */
5263 
5264 	/*
5265 	 * We need to specially handle size changes because it is
5266 	 * possible for the client to create a file with read-only
5267 	 * modes, but with the file opened for writing. If the client
5268 	 * then tries to set the file size, e.g. ftruncate(3C),
5269 	 * fcntl(F_FREESP), the normal access checking done in
5270 	 * VOP_SETATTR would prevent the client from doing it even though
5271 	 * it should be allowed to do so.  To get around this, we do the
5272 	 * access checking for ourselves and use VOP_SPACE which doesn't
5273 	 * do the access checking.
5274 	 * Also the client should not be allowed to change the file
5275 	 * size if there is a conflicting non-blocking mandatory lock in
5276 	 * the region of the change.
5277 	 */
5278 	if (vp->v_type == VREG && (sarg.vap->va_mask & AT_SIZE)) {
5279 		u_offset_t offset;
5280 		ssize_t length;
5281 
5282 		/*
5283 		 * ufs_setattr clears AT_SIZE from vap->va_mask, but
5284 		 * before returning, sarg.vap->va_mask is used to
5285 		 * generate the setattr reply bitmap.  We also clear
5286 		 * AT_SIZE below before calling VOP_SPACE.  For both
5287 		 * of these cases, the va_mask needs to be saved here
5288 		 * and restored after calling VOP_SETATTR.
5289 		 */
5290 		saved_mask = sarg.vap->va_mask;
5291 
5292 		/*
5293 		 * Check any possible conflict due to NBMAND locks.
5294 		 * Get into critical region before VOP_GETATTR, so the
5295 		 * size attribute is valid when checking conflicts.
5296 		 */
5297 		if (nbl_need_check(vp)) {
5298 			nbl_start_crit(vp, RW_READER);
5299 			in_crit = 1;
5300 		}
5301 
5302 		bva.va_mask = AT_UID|AT_SIZE;
5303 		if (error = VOP_GETATTR(vp, &bva, 0, cr, &ct)) {
5304 			status = puterrno4(error);
5305 			goto done;
5306 		}
5307 
5308 		if (in_crit) {
5309 			if (sarg.vap->va_size < bva.va_size) {
5310 				offset = sarg.vap->va_size;
5311 				length = bva.va_size - sarg.vap->va_size;
5312 			} else {
5313 				offset = bva.va_size;
5314 				length = sarg.vap->va_size - bva.va_size;
5315 			}
5316 			if (nbl_conflict(vp, NBL_WRITE, offset, length, 0,
5317 			    &ct)) {
5318 				status = NFS4ERR_LOCKED;
5319 				goto done;
5320 			}
5321 		}
5322 
5323 		if (crgetuid(cr) == bva.va_uid) {
5324 			sarg.vap->va_mask &= ~AT_SIZE;
5325 			bf.l_type = F_WRLCK;
5326 			bf.l_whence = 0;
5327 			bf.l_start = (off64_t)sarg.vap->va_size;
5328 			bf.l_len = 0;
5329 			bf.l_sysid = 0;
5330 			bf.l_pid = 0;
5331 			error = VOP_SPACE(vp, F_FREESP, &bf, FWRITE,
5332 			    (offset_t)sarg.vap->va_size, cr, &ct);
5333 		}
5334 	}
5335 
5336 	if (!error && sarg.vap->va_mask != 0)
5337 		error = VOP_SETATTR(vp, sarg.vap, sarg.flag, cr, &ct);
5338 
5339 	/* restore va_mask -- ufs_setattr clears AT_SIZE */
5340 	if (saved_mask & AT_SIZE)
5341 		sarg.vap->va_mask |= AT_SIZE;
5342 
5343 	/*
5344 	 * If an ACL was being set, it has been delayed until now,
5345 	 * in order to set the mode (via the VOP_SETATTR() above) first.
5346 	 */
5347 	if ((! error) && (fattrp->attrmask & FATTR4_ACL_MASK)) {
5348 		int i;
5349 
5350 		for (i = 0; i < NFS4_MAXNUM_ATTRS; i++)
5351 			if (ntov.amap[i] == FATTR4_ACL)
5352 				break;
5353 		if (i < NFS4_MAXNUM_ATTRS) {
5354 			error = (*nfs4_ntov_map[FATTR4_ACL].sv_getit)(
5355 			    NFS4ATTR_SETIT, &sarg, &ntov.na[i]);
5356 			if (error == 0) {
5357 				*resp |= FATTR4_ACL_MASK;
5358 			} else if (error == ENOTSUP) {
5359 				(void) rfs4_verify_attr(&sarg, resp, &ntov);
5360 				status = NFS4ERR_ATTRNOTSUPP;
5361 				goto done;
5362 			}
5363 		} else {
5364 			NFS4_DEBUG(rfs4_debug,
5365 			    (CE_NOTE, "do_rfs4_op_setattr: "
5366 			    "unable to find ACL in fattr4"));
5367 			error = EINVAL;
5368 		}
5369 	}
5370 
5371 	if (error) {
5372 		/* check if a monitor detected a delegation conflict */
5373 		if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK))
5374 			status = NFS4ERR_DELAY;
5375 		else
5376 			status = puterrno4(error);
5377 
5378 		/*
5379 		 * Set the response bitmap when setattr failed.
5380 		 * If VOP_SETATTR partially succeeded, test by doing a
5381 		 * VOP_GETATTR on the object and comparing the data
5382 		 * to the setattr arguments.
5383 		 */
5384 		(void) rfs4_verify_attr(&sarg, resp, &ntov);
5385 	} else {
5386 		/*
5387 		 * Force modified metadata out to stable storage.
5388 		 */
5389 		(void) VOP_FSYNC(vp, FNODSYNC, cr, &ct);
5390 		/*
5391 		 * Set response bitmap
5392 		 */
5393 		nfs4_vmask_to_nmask_set(sarg.vap->va_mask, resp);
5394 	}
5395 
5396 /* Return early and already have a NFSv4 error */
5397 done:
5398 	/*
5399 	 * Except for nfs4_vmask_to_nmask_set(), vattr --> fattr
5400 	 * conversion sets both readable and writeable NFS4 attrs
5401 	 * for AT_MTIME and AT_ATIME.  The line below masks out
5402 	 * unrequested attrs from the setattr result bitmap.  This
5403 	 * is placed after the done: label to catch the ATTRNOTSUP
5404 	 * case.
5405 	 */
5406 	*resp &= fattrp->attrmask;
5407 
5408 	if (in_crit)
5409 		nbl_end_crit(vp);
5410 
5411 	nfs4_ntov_table_free(&ntov, &sarg);
5412 
5413 	return (status);
5414 }
5415 
5416 /* ARGSUSED */
5417 static void
5418 rfs4_op_setattr(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
5419     struct compound_state *cs)
5420 {
5421 	SETATTR4args *args = &argop->nfs_argop4_u.opsetattr;
5422 	SETATTR4res *resp = &resop->nfs_resop4_u.opsetattr;
5423 	bslabel_t *clabel;
5424 
5425 	DTRACE_NFSV4_2(op__setattr__start, struct compound_state *, cs,
5426 	    SETATTR4args *, args);
5427 
5428 	if (cs->vp == NULL) {
5429 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
5430 		goto out;
5431 	}
5432 
5433 	/*
5434 	 * If there is an unshared filesystem mounted on this vnode,
5435 	 * do not allow to setattr on this vnode.
5436 	 */
5437 	if (vn_ismntpt(cs->vp)) {
5438 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
5439 		goto out;
5440 	}
5441 
5442 	resp->attrsset = 0;
5443 
5444 	if (rdonly4(req, cs)) {
5445 		*cs->statusp = resp->status = NFS4ERR_ROFS;
5446 		goto out;
5447 	}
5448 
5449 	/* check label before setting attributes */
5450 	if (is_system_labeled()) {
5451 		ASSERT(req->rq_label != NULL);
5452 		clabel = req->rq_label;
5453 		DTRACE_PROBE2(tx__rfs4__log__info__opsetattr__clabel, char *,
5454 		    "got client label from request(1)",
5455 		    struct svc_req *, req);
5456 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
5457 			if (!do_rfs_label_check(clabel, cs->vp,
5458 			    EQUALITY_CHECK, cs->exi)) {
5459 				*cs->statusp = resp->status = NFS4ERR_ACCESS;
5460 				goto out;
5461 			}
5462 		}
5463 	}
5464 
5465 	*cs->statusp = resp->status =
5466 	    do_rfs4_op_setattr(&resp->attrsset, &args->obj_attributes, cs,
5467 	    &args->stateid);
5468 
5469 out:
5470 	DTRACE_NFSV4_2(op__setattr__done, struct compound_state *, cs,
5471 	    SETATTR4res *, resp);
5472 }
5473 
5474 /* ARGSUSED */
5475 static void
5476 rfs4_op_verify(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
5477     struct compound_state *cs)
5478 {
5479 	/*
5480 	 * verify and nverify are exactly the same, except that nverify
5481 	 * succeeds when some argument changed, and verify succeeds when
5482 	 * when none changed.
5483 	 */
5484 
5485 	VERIFY4args  *args = &argop->nfs_argop4_u.opverify;
5486 	VERIFY4res *resp = &resop->nfs_resop4_u.opverify;
5487 
5488 	int error;
5489 	struct nfs4_svgetit_arg sarg;
5490 	struct statvfs64 sb;
5491 	struct nfs4_ntov_table ntov;
5492 
5493 	DTRACE_NFSV4_2(op__verify__start, struct compound_state *, cs,
5494 	    VERIFY4args *, args);
5495 
5496 	if (cs->vp == NULL) {
5497 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
5498 		goto out;
5499 	}
5500 
5501 	sarg.sbp = &sb;
5502 	sarg.is_referral = B_FALSE;
5503 	nfs4_ntov_table_init(&ntov);
5504 	resp->status = do_rfs4_set_attrs(NULL, &args->obj_attributes, cs,
5505 	    &sarg, &ntov, NFS4ATTR_VERIT);
5506 	if (resp->status != NFS4_OK) {
5507 		/*
5508 		 * do_rfs4_set_attrs will try to verify systemwide attrs,
5509 		 * so could return -1 for "no match".
5510 		 */
5511 		if (resp->status == -1)
5512 			resp->status = NFS4ERR_NOT_SAME;
5513 		goto done;
5514 	}
5515 	error = rfs4_verify_attr(&sarg, NULL, &ntov);
5516 	switch (error) {
5517 	case 0:
5518 		resp->status = NFS4_OK;
5519 		break;
5520 	case -1:
5521 		resp->status = NFS4ERR_NOT_SAME;
5522 		break;
5523 	default:
5524 		resp->status = puterrno4(error);
5525 		break;
5526 	}
5527 done:
5528 	*cs->statusp = resp->status;
5529 	nfs4_ntov_table_free(&ntov, &sarg);
5530 out:
5531 	DTRACE_NFSV4_2(op__verify__done, struct compound_state *, cs,
5532 	    VERIFY4res *, resp);
5533 }
5534 
5535 /* ARGSUSED */
5536 static void
5537 rfs4_op_nverify(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
5538     struct compound_state *cs)
5539 {
5540 	/*
5541 	 * verify and nverify are exactly the same, except that nverify
5542 	 * succeeds when some argument changed, and verify succeeds when
5543 	 * when none changed.
5544 	 */
5545 
5546 	NVERIFY4args  *args = &argop->nfs_argop4_u.opnverify;
5547 	NVERIFY4res *resp = &resop->nfs_resop4_u.opnverify;
5548 
5549 	int error;
5550 	struct nfs4_svgetit_arg sarg;
5551 	struct statvfs64 sb;
5552 	struct nfs4_ntov_table ntov;
5553 
5554 	DTRACE_NFSV4_2(op__nverify__start, struct compound_state *, cs,
5555 	    NVERIFY4args *, args);
5556 
5557 	if (cs->vp == NULL) {
5558 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
5559 		DTRACE_NFSV4_2(op__nverify__done, struct compound_state *, cs,
5560 		    NVERIFY4res *, resp);
5561 		return;
5562 	}
5563 	sarg.sbp = &sb;
5564 	sarg.is_referral = B_FALSE;
5565 	nfs4_ntov_table_init(&ntov);
5566 	resp->status = do_rfs4_set_attrs(NULL, &args->obj_attributes, cs,
5567 	    &sarg, &ntov, NFS4ATTR_VERIT);
5568 	if (resp->status != NFS4_OK) {
5569 		/*
5570 		 * do_rfs4_set_attrs will try to verify systemwide attrs,
5571 		 * so could return -1 for "no match".
5572 		 */
5573 		if (resp->status == -1)
5574 			resp->status = NFS4_OK;
5575 		goto done;
5576 	}
5577 	error = rfs4_verify_attr(&sarg, NULL, &ntov);
5578 	switch (error) {
5579 	case 0:
5580 		resp->status = NFS4ERR_SAME;
5581 		break;
5582 	case -1:
5583 		resp->status = NFS4_OK;
5584 		break;
5585 	default:
5586 		resp->status = puterrno4(error);
5587 		break;
5588 	}
5589 done:
5590 	*cs->statusp = resp->status;
5591 	nfs4_ntov_table_free(&ntov, &sarg);
5592 
5593 	DTRACE_NFSV4_2(op__nverify__done, struct compound_state *, cs,
5594 	    NVERIFY4res *, resp);
5595 }
5596 
5597 /*
5598  * XXX - This should live in an NFS header file.
5599  */
5600 #define	MAX_IOVECS	12
5601 
5602 /* ARGSUSED */
5603 static void
5604 rfs4_op_write(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req,
5605     struct compound_state *cs)
5606 {
5607 	WRITE4args *args = &argop->nfs_argop4_u.opwrite;
5608 	WRITE4res *resp = &resop->nfs_resop4_u.opwrite;
5609 	int error;
5610 	vnode_t *vp;
5611 	struct vattr bva;
5612 	u_offset_t rlimit;
5613 	struct uio uio;
5614 	struct iovec iov[MAX_IOVECS];
5615 	struct iovec *iovp;
5616 	int iovcnt;
5617 	int ioflag;
5618 	cred_t *savecred, *cr;
5619 	bool_t *deleg = &cs->deleg;
5620 	nfsstat4 stat;
5621 	int in_crit = 0;
5622 	caller_context_t ct;
5623 
5624 	DTRACE_NFSV4_2(op__write__start, struct compound_state *, cs,
5625 	    WRITE4args *, args);
5626 
5627 	vp = cs->vp;
5628 	if (vp == NULL) {
5629 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
5630 		goto out;
5631 	}
5632 	if (cs->access == CS_ACCESS_DENIED) {
5633 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
5634 		goto out;
5635 	}
5636 
5637 	cr = cs->cr;
5638 
5639 	if ((stat = rfs4_check_stateid(FWRITE, vp, &args->stateid, FALSE,
5640 	    deleg, TRUE, &ct)) != NFS4_OK) {
5641 		*cs->statusp = resp->status = stat;
5642 		goto out;
5643 	}
5644 
5645 	/*
5646 	 * We have to enter the critical region before calling VOP_RWLOCK
5647 	 * to avoid a deadlock with ufs.
5648 	 */
5649 	if (nbl_need_check(vp)) {
5650 		nbl_start_crit(vp, RW_READER);
5651 		in_crit = 1;
5652 		if (nbl_conflict(vp, NBL_WRITE,
5653 		    args->offset, args->data_len, 0, &ct)) {
5654 			*cs->statusp = resp->status = NFS4ERR_LOCKED;
5655 			goto out;
5656 		}
5657 	}
5658 
5659 	bva.va_mask = AT_MODE | AT_UID;
5660 	error = VOP_GETATTR(vp, &bva, 0, cr, &ct);
5661 
5662 	/*
5663 	 * If we can't get the attributes, then we can't do the
5664 	 * right access checking.  So, we'll fail the request.
5665 	 */
5666 	if (error) {
5667 		*cs->statusp = resp->status = puterrno4(error);
5668 		goto out;
5669 	}
5670 
5671 	if (rdonly4(req, cs)) {
5672 		*cs->statusp = resp->status = NFS4ERR_ROFS;
5673 		goto out;
5674 	}
5675 
5676 	if (vp->v_type != VREG) {
5677 		*cs->statusp = resp->status =
5678 		    ((vp->v_type == VDIR) ? NFS4ERR_ISDIR : NFS4ERR_INVAL);
5679 		goto out;
5680 	}
5681 
5682 	if (crgetuid(cr) != bva.va_uid &&
5683 	    (error = VOP_ACCESS(vp, VWRITE, 0, cr, &ct))) {
5684 		*cs->statusp = resp->status = puterrno4(error);
5685 		goto out;
5686 	}
5687 
5688 	if (MANDLOCK(vp, bva.va_mode)) {
5689 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
5690 		goto out;
5691 	}
5692 
5693 	if (args->data_len == 0) {
5694 		*cs->statusp = resp->status = NFS4_OK;
5695 		resp->count = 0;
5696 		resp->committed = args->stable;
5697 		resp->writeverf = Write4verf;
5698 		goto out;
5699 	}
5700 
5701 	if (args->mblk != NULL) {
5702 		mblk_t *m;
5703 		uint_t bytes, round_len;
5704 
5705 		iovcnt = 0;
5706 		bytes = 0;
5707 		round_len = roundup(args->data_len, BYTES_PER_XDR_UNIT);
5708 		for (m = args->mblk;
5709 		    m != NULL && bytes < round_len;
5710 		    m = m->b_cont) {
5711 			iovcnt++;
5712 			bytes += MBLKL(m);
5713 		}
5714 #ifdef DEBUG
5715 		/* should have ended on an mblk boundary */
5716 		if (bytes != round_len) {
5717 			printf("bytes=0x%x, round_len=0x%x, req len=0x%x\n",
5718 			    bytes, round_len, args->data_len);
5719 			printf("args=%p, args->mblk=%p, m=%p", (void *)args,
5720 			    (void *)args->mblk, (void *)m);
5721 			ASSERT(bytes == round_len);
5722 		}
5723 #endif
5724 		if (iovcnt <= MAX_IOVECS) {
5725 			iovp = iov;
5726 		} else {
5727 			iovp = kmem_alloc(sizeof (*iovp) * iovcnt, KM_SLEEP);
5728 		}
5729 		mblk_to_iov(args->mblk, iovcnt, iovp);
5730 	} else if (args->rlist != NULL) {
5731 		iovcnt = 1;
5732 		iovp = iov;
5733 		iovp->iov_base = (char *)((args->rlist)->u.c_daddr3);
5734 		iovp->iov_len = args->data_len;
5735 	} else {
5736 		iovcnt = 1;
5737 		iovp = iov;
5738 		iovp->iov_base = args->data_val;
5739 		iovp->iov_len = args->data_len;
5740 	}
5741 
5742 	uio.uio_iov = iovp;
5743 	uio.uio_iovcnt = iovcnt;
5744 
5745 	uio.uio_segflg = UIO_SYSSPACE;
5746 	uio.uio_extflg = UIO_COPY_DEFAULT;
5747 	uio.uio_loffset = args->offset;
5748 	uio.uio_resid = args->data_len;
5749 	uio.uio_llimit = curproc->p_fsz_ctl;
5750 	rlimit = uio.uio_llimit - args->offset;
5751 	if (rlimit < (u_offset_t)uio.uio_resid)
5752 		uio.uio_resid = (int)rlimit;
5753 
5754 	if (args->stable == UNSTABLE4)
5755 		ioflag = 0;
5756 	else if (args->stable == FILE_SYNC4)
5757 		ioflag = FSYNC;
5758 	else if (args->stable == DATA_SYNC4)
5759 		ioflag = FDSYNC;
5760 	else {
5761 		if (iovp != iov)
5762 			kmem_free(iovp, sizeof (*iovp) * iovcnt);
5763 		*cs->statusp = resp->status = NFS4ERR_INVAL;
5764 		goto out;
5765 	}
5766 
5767 	/*
5768 	 * We're changing creds because VM may fault and we need
5769 	 * the cred of the current thread to be used if quota
5770 	 * checking is enabled.
5771 	 */
5772 	savecred = curthread->t_cred;
5773 	curthread->t_cred = cr;
5774 	error = do_io(FWRITE, vp, &uio, ioflag, cr, &ct);
5775 	curthread->t_cred = savecred;
5776 
5777 	if (iovp != iov)
5778 		kmem_free(iovp, sizeof (*iovp) * iovcnt);
5779 
5780 	if (error) {
5781 		*cs->statusp = resp->status = puterrno4(error);
5782 		goto out;
5783 	}
5784 
5785 	*cs->statusp = resp->status = NFS4_OK;
5786 	resp->count = args->data_len - uio.uio_resid;
5787 
5788 	if (ioflag == 0)
5789 		resp->committed = UNSTABLE4;
5790 	else
5791 		resp->committed = FILE_SYNC4;
5792 
5793 	resp->writeverf = Write4verf;
5794 
5795 out:
5796 	if (in_crit)
5797 		nbl_end_crit(vp);
5798 
5799 	DTRACE_NFSV4_2(op__write__done, struct compound_state *, cs,
5800 	    WRITE4res *, resp);
5801 }
5802 
5803 
5804 /* XXX put in a header file */
5805 extern int	sec_svc_getcred(struct svc_req *, cred_t *,  caddr_t *, int *);
5806 
5807 void
5808 rfs4_compound(COMPOUND4args *args, COMPOUND4res *resp, struct exportinfo *exi,
5809     struct svc_req *req, cred_t *cr, int *rv)
5810 {
5811 	uint_t i;
5812 	struct compound_state cs;
5813 
5814 	if (rv != NULL)
5815 		*rv = 0;
5816 	rfs4_init_compound_state(&cs);
5817 	/*
5818 	 * Form a reply tag by copying over the reqeuest tag.
5819 	 */
5820 	resp->tag.utf8string_val =
5821 	    kmem_alloc(args->tag.utf8string_len, KM_SLEEP);
5822 	resp->tag.utf8string_len = args->tag.utf8string_len;
5823 	bcopy(args->tag.utf8string_val, resp->tag.utf8string_val,
5824 	    resp->tag.utf8string_len);
5825 
5826 	cs.statusp = &resp->status;
5827 	cs.req = req;
5828 	resp->array = NULL;
5829 	resp->array_len = 0;
5830 
5831 	/*
5832 	 * XXX for now, minorversion should be zero
5833 	 */
5834 	if (args->minorversion != NFS4_MINORVERSION) {
5835 		DTRACE_NFSV4_2(compound__start, struct compound_state *,
5836 		    &cs, COMPOUND4args *, args);
5837 		resp->status = NFS4ERR_MINOR_VERS_MISMATCH;
5838 		DTRACE_NFSV4_2(compound__done, struct compound_state *,
5839 		    &cs, COMPOUND4res *, resp);
5840 		return;
5841 	}
5842 
5843 	if (args->array_len == 0) {
5844 		resp->status = NFS4_OK;
5845 		return;
5846 	}
5847 
5848 	ASSERT(exi == NULL);
5849 	ASSERT(cr == NULL);
5850 
5851 	cr = crget();
5852 	ASSERT(cr != NULL);
5853 
5854 	if (sec_svc_getcred(req, cr, &cs.principal, &cs.nfsflavor) == 0) {
5855 		DTRACE_NFSV4_2(compound__start, struct compound_state *,
5856 		    &cs, COMPOUND4args *, args);
5857 		crfree(cr);
5858 		DTRACE_NFSV4_2(compound__done, struct compound_state *,
5859 		    &cs, COMPOUND4res *, resp);
5860 		svcerr_badcred(req->rq_xprt);
5861 		if (rv != NULL)
5862 			*rv = 1;
5863 		return;
5864 	}
5865 	resp->array_len = args->array_len;
5866 	resp->array = kmem_zalloc(args->array_len * sizeof (nfs_resop4),
5867 	    KM_SLEEP);
5868 
5869 	cs.basecr = cr;
5870 
5871 	DTRACE_NFSV4_2(compound__start, struct compound_state *, &cs,
5872 	    COMPOUND4args *, args);
5873 
5874 	/*
5875 	 * If this is the first compound we've seen, we need to start all
5876 	 * new instances' grace periods.
5877 	 */
5878 	if (rfs4_seen_first_compound == 0) {
5879 		rfs4_grace_start_new();
5880 		/*
5881 		 * This must be set after rfs4_grace_start_new(), otherwise
5882 		 * another thread could proceed past here before the former
5883 		 * is finished.
5884 		 */
5885 		rfs4_seen_first_compound = 1;
5886 	}
5887 
5888 	for (i = 0; i < args->array_len && cs.cont; i++) {
5889 		nfs_argop4 *argop;
5890 		nfs_resop4 *resop;
5891 		uint_t op;
5892 
5893 		argop = &args->array[i];
5894 		resop = &resp->array[i];
5895 		resop->resop = argop->argop;
5896 		op = (uint_t)resop->resop;
5897 
5898 		if (op < rfsv4disp_cnt) {
5899 			/*
5900 			 * Count the individual ops here; NULL and COMPOUND
5901 			 * are counted in common_dispatch()
5902 			 */
5903 			rfsproccnt_v4_ptr[op].value.ui64++;
5904 
5905 			NFS4_DEBUG(rfs4_debug > 1,
5906 			    (CE_NOTE, "Executing %s", rfs4_op_string[op]));
5907 			(*rfsv4disptab[op].dis_proc)(argop, resop, req, &cs);
5908 			NFS4_DEBUG(rfs4_debug > 1, (CE_NOTE, "%s returned %d",
5909 			    rfs4_op_string[op], *cs.statusp));
5910 			if (*cs.statusp != NFS4_OK)
5911 				cs.cont = FALSE;
5912 		} else {
5913 			/*
5914 			 * This is effectively dead code since XDR code
5915 			 * will have already returned BADXDR if op doesn't
5916 			 * decode to legal value.  This only done for a
5917 			 * day when XDR code doesn't verify v4 opcodes.
5918 			 */
5919 			op = OP_ILLEGAL;
5920 			rfsproccnt_v4_ptr[OP_ILLEGAL_IDX].value.ui64++;
5921 
5922 			rfs4_op_illegal(argop, resop, req, &cs);
5923 			cs.cont = FALSE;
5924 		}
5925 
5926 		/*
5927 		 * If not at last op, and if we are to stop, then
5928 		 * compact the results array.
5929 		 */
5930 		if ((i + 1) < args->array_len && !cs.cont) {
5931 			nfs_resop4 *new_res = kmem_alloc(
5932 			    (i+1) * sizeof (nfs_resop4), KM_SLEEP);
5933 			bcopy(resp->array,
5934 			    new_res, (i+1) * sizeof (nfs_resop4));
5935 			kmem_free(resp->array,
5936 			    args->array_len * sizeof (nfs_resop4));
5937 
5938 			resp->array_len =  i + 1;
5939 			resp->array = new_res;
5940 		}
5941 	}
5942 
5943 
5944 	DTRACE_NFSV4_2(compound__done, struct compound_state *, &cs,
5945 	    COMPOUND4res *, resp);
5946 
5947 	if (cs.exi != NULL)
5948 		exi_rele(cs.exi);
5949 	if (cs.saved_exi != NULL)
5950 		exi_rele(cs.saved_exi);
5951 	if (cs.vp != NULL)
5952 		VN_RELE(cs.vp);
5953 	if (cs.saved_vp != NULL)
5954 		VN_RELE(cs.saved_vp);
5955 	if (cs.saved_fh.nfs_fh4_val != NULL)
5956 		kmem_free(cs.saved_fh.nfs_fh4_val, NFS4_FHSIZE);
5957 
5958 	if (cs.basecr)
5959 		crfree(cs.basecr);
5960 	if (cs.cr)
5961 		crfree(cs.cr);
5962 	/*
5963 	 * done with this compound request, free the label
5964 	 */
5965 
5966 	if (req->rq_label != NULL) {
5967 		kmem_free(req->rq_label, sizeof (bslabel_t));
5968 		req->rq_label = NULL;
5969 	}
5970 }
5971 
5972 /*
5973  * XXX because of what appears to be duplicate calls to rfs4_compound_free
5974  * XXX zero out the tag and array values. Need to investigate why the
5975  * XXX calls occur, but at least prevent the panic for now.
5976  */
5977 void
5978 rfs4_compound_free(COMPOUND4res *resp)
5979 {
5980 	uint_t i;
5981 
5982 	if (resp->tag.utf8string_val) {
5983 		UTF8STRING_FREE(resp->tag)
5984 	}
5985 
5986 	for (i = 0; i < resp->array_len; i++) {
5987 		nfs_resop4 *resop;
5988 		uint_t op;
5989 
5990 		resop = &resp->array[i];
5991 		op = (uint_t)resop->resop;
5992 		if (op < rfsv4disp_cnt) {
5993 			(*rfsv4disptab[op].dis_resfree)(resop);
5994 		}
5995 	}
5996 	if (resp->array != NULL) {
5997 		kmem_free(resp->array, resp->array_len * sizeof (nfs_resop4));
5998 	}
5999 }
6000 
6001 /*
6002  * Process the value of the compound request rpc flags, as a bit-AND
6003  * of the individual per-op flags (idempotent, allowork, publicfh_ok)
6004  */
6005 void
6006 rfs4_compound_flagproc(COMPOUND4args *args, int *flagp)
6007 {
6008 	int i;
6009 	int flag = RPC_ALL;
6010 
6011 	for (i = 0; flag && i < args->array_len; i++) {
6012 		uint_t op;
6013 
6014 		op = (uint_t)args->array[i].argop;
6015 
6016 		if (op < rfsv4disp_cnt)
6017 			flag &= rfsv4disptab[op].dis_flags;
6018 		else
6019 			flag = 0;
6020 	}
6021 	*flagp = flag;
6022 }
6023 
6024 nfsstat4
6025 rfs4_client_sysid(rfs4_client_t *cp, sysid_t *sp)
6026 {
6027 	nfsstat4 e;
6028 
6029 	rfs4_dbe_lock(cp->rc_dbe);
6030 
6031 	if (cp->rc_sysidt != LM_NOSYSID) {
6032 		*sp = cp->rc_sysidt;
6033 		e = NFS4_OK;
6034 
6035 	} else if ((cp->rc_sysidt = lm_alloc_sysidt()) != LM_NOSYSID) {
6036 		*sp = cp->rc_sysidt;
6037 		e = NFS4_OK;
6038 
6039 		NFS4_DEBUG(rfs4_debug, (CE_NOTE,
6040 		    "rfs4_client_sysid: allocated 0x%x\n", *sp));
6041 	} else
6042 		e = NFS4ERR_DELAY;
6043 
6044 	rfs4_dbe_unlock(cp->rc_dbe);
6045 	return (e);
6046 }
6047 
6048 #if defined(DEBUG) && ! defined(lint)
6049 static void lock_print(char *str, int operation, struct flock64 *flk)
6050 {
6051 	char *op, *type;
6052 
6053 	switch (operation) {
6054 	case F_GETLK: op = "F_GETLK";
6055 		break;
6056 	case F_SETLK: op = "F_SETLK";
6057 		break;
6058 	case F_SETLK_NBMAND: op = "F_SETLK_NBMAND";
6059 		break;
6060 	default: op = "F_UNKNOWN";
6061 		break;
6062 	}
6063 	switch (flk->l_type) {
6064 	case F_UNLCK: type = "F_UNLCK";
6065 		break;
6066 	case F_RDLCK: type = "F_RDLCK";
6067 		break;
6068 	case F_WRLCK: type = "F_WRLCK";
6069 		break;
6070 	default: type = "F_UNKNOWN";
6071 		break;
6072 	}
6073 
6074 	ASSERT(flk->l_whence == 0);
6075 	cmn_err(CE_NOTE, "%s:  %s, type = %s, off = %llx len = %llx pid = %d",
6076 	    str, op, type, (longlong_t)flk->l_start,
6077 	    flk->l_len ? (longlong_t)flk->l_len : ~0LL, flk->l_pid);
6078 }
6079 
6080 #define	LOCK_PRINT(d, s, t, f) if (d) lock_print(s, t, f)
6081 #else
6082 #define	LOCK_PRINT(d, s, t, f)
6083 #endif
6084 
6085 /*ARGSUSED*/
6086 static bool_t
6087 creds_ok(cred_set_t cr_set, struct svc_req *req, struct compound_state *cs)
6088 {
6089 	return (TRUE);
6090 }
6091 
6092 /*
6093  * Look up the pathname using the vp in cs as the directory vnode.
6094  * cs->vp will be the vnode for the file on success
6095  */
6096 
6097 static nfsstat4
6098 rfs4_lookup(component4 *component, struct svc_req *req,
6099     struct compound_state *cs)
6100 {
6101 	char *nm;
6102 	uint32_t len;
6103 	nfsstat4 status;
6104 	struct sockaddr *ca;
6105 	char *name;
6106 
6107 	if (cs->vp == NULL) {
6108 		return (NFS4ERR_NOFILEHANDLE);
6109 	}
6110 	if (cs->vp->v_type != VDIR) {
6111 		return (NFS4ERR_NOTDIR);
6112 	}
6113 
6114 	status = utf8_dir_verify(component);
6115 	if (status != NFS4_OK)
6116 		return (status);
6117 
6118 	nm = utf8_to_fn(component, &len, NULL);
6119 	if (nm == NULL) {
6120 		return (NFS4ERR_INVAL);
6121 	}
6122 
6123 	if (len > MAXNAMELEN) {
6124 		kmem_free(nm, len);
6125 		return (NFS4ERR_NAMETOOLONG);
6126 	}
6127 
6128 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
6129 	name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
6130 	    MAXPATHLEN + 1);
6131 
6132 	if (name == NULL) {
6133 		kmem_free(nm, len);
6134 		return (NFS4ERR_INVAL);
6135 	}
6136 
6137 	status = do_rfs4_op_lookup(name, req, cs);
6138 
6139 	if (name != nm)
6140 		kmem_free(name, MAXPATHLEN + 1);
6141 
6142 	kmem_free(nm, len);
6143 
6144 	return (status);
6145 }
6146 
6147 static nfsstat4
6148 rfs4_lookupfile(component4 *component, struct svc_req *req,
6149     struct compound_state *cs, uint32_t access, change_info4 *cinfo)
6150 {
6151 	nfsstat4 status;
6152 	vnode_t *dvp = cs->vp;
6153 	vattr_t bva, ava, fva;
6154 	int error;
6155 
6156 	/* Get "before" change value */
6157 	bva.va_mask = AT_CTIME|AT_SEQ;
6158 	error = VOP_GETATTR(dvp, &bva, 0, cs->cr, NULL);
6159 	if (error)
6160 		return (puterrno4(error));
6161 
6162 	/* rfs4_lookup may VN_RELE directory */
6163 	VN_HOLD(dvp);
6164 
6165 	status = rfs4_lookup(component, req, cs);
6166 	if (status != NFS4_OK) {
6167 		VN_RELE(dvp);
6168 		return (status);
6169 	}
6170 
6171 	/*
6172 	 * Get "after" change value, if it fails, simply return the
6173 	 * before value.
6174 	 */
6175 	ava.va_mask = AT_CTIME|AT_SEQ;
6176 	if (VOP_GETATTR(dvp, &ava, 0, cs->cr, NULL)) {
6177 		ava.va_ctime = bva.va_ctime;
6178 		ava.va_seq = 0;
6179 	}
6180 	VN_RELE(dvp);
6181 
6182 	/*
6183 	 * Validate the file is a file
6184 	 */
6185 	fva.va_mask = AT_TYPE|AT_MODE;
6186 	error = VOP_GETATTR(cs->vp, &fva, 0, cs->cr, NULL);
6187 	if (error)
6188 		return (puterrno4(error));
6189 
6190 	if (fva.va_type != VREG) {
6191 		if (fva.va_type == VDIR)
6192 			return (NFS4ERR_ISDIR);
6193 		if (fva.va_type == VLNK)
6194 			return (NFS4ERR_SYMLINK);
6195 		return (NFS4ERR_INVAL);
6196 	}
6197 
6198 	NFS4_SET_FATTR4_CHANGE(cinfo->before, bva.va_ctime);
6199 	NFS4_SET_FATTR4_CHANGE(cinfo->after, ava.va_ctime);
6200 
6201 	/*
6202 	 * It is undefined if VOP_LOOKUP will change va_seq, so
6203 	 * cinfo.atomic = TRUE only if we have
6204 	 * non-zero va_seq's, and they have not changed.
6205 	 */
6206 	if (bva.va_seq && ava.va_seq && ava.va_seq == bva.va_seq)
6207 		cinfo->atomic = TRUE;
6208 	else
6209 		cinfo->atomic = FALSE;
6210 
6211 	/* Check for mandatory locking */
6212 	cs->mandlock = MANDLOCK(cs->vp, fva.va_mode);
6213 	return (check_open_access(access, cs, req));
6214 }
6215 
6216 static nfsstat4
6217 create_vnode(vnode_t *dvp, char *nm,  vattr_t *vap, createmode4 mode,
6218     timespec32_t *mtime, cred_t *cr, vnode_t **vpp, bool_t *created)
6219 {
6220 	int error;
6221 	nfsstat4 status = NFS4_OK;
6222 	vattr_t va;
6223 
6224 tryagain:
6225 
6226 	/*
6227 	 * The file open mode used is VWRITE.  If the client needs
6228 	 * some other semantic, then it should do the access checking
6229 	 * itself.  It would have been nice to have the file open mode
6230 	 * passed as part of the arguments.
6231 	 */
6232 
6233 	*created = TRUE;
6234 	error = VOP_CREATE(dvp, nm, vap, EXCL, VWRITE, vpp, cr, 0, NULL, NULL);
6235 
6236 	if (error) {
6237 		*created = FALSE;
6238 
6239 		/*
6240 		 * If we got something other than file already exists
6241 		 * then just return this error.  Otherwise, we got
6242 		 * EEXIST.  If we were doing a GUARDED create, then
6243 		 * just return this error.  Otherwise, we need to
6244 		 * make sure that this wasn't a duplicate of an
6245 		 * exclusive create request.
6246 		 *
6247 		 * The assumption is made that a non-exclusive create
6248 		 * request will never return EEXIST.
6249 		 */
6250 
6251 		if (error != EEXIST || mode == GUARDED4) {
6252 			status = puterrno4(error);
6253 			return (status);
6254 		}
6255 		error = VOP_LOOKUP(dvp, nm, vpp, NULL, 0, NULL, cr,
6256 		    NULL, NULL, NULL);
6257 
6258 		if (error) {
6259 			/*
6260 			 * We couldn't find the file that we thought that
6261 			 * we just created.  So, we'll just try creating
6262 			 * it again.
6263 			 */
6264 			if (error == ENOENT)
6265 				goto tryagain;
6266 
6267 			status = puterrno4(error);
6268 			return (status);
6269 		}
6270 
6271 		if (mode == UNCHECKED4) {
6272 			/* existing object must be regular file */
6273 			if ((*vpp)->v_type != VREG) {
6274 				if ((*vpp)->v_type == VDIR)
6275 					status = NFS4ERR_ISDIR;
6276 				else if ((*vpp)->v_type == VLNK)
6277 					status = NFS4ERR_SYMLINK;
6278 				else
6279 					status = NFS4ERR_INVAL;
6280 				VN_RELE(*vpp);
6281 				return (status);
6282 			}
6283 
6284 			return (NFS4_OK);
6285 		}
6286 
6287 		/* Check for duplicate request */
6288 		ASSERT(mtime != 0);
6289 		va.va_mask = AT_MTIME;
6290 		error = VOP_GETATTR(*vpp, &va, 0, cr, NULL);
6291 		if (!error) {
6292 			/* We found the file */
6293 			if (va.va_mtime.tv_sec != mtime->tv_sec ||
6294 			    va.va_mtime.tv_nsec != mtime->tv_nsec) {
6295 				/* but its not our creation */
6296 				VN_RELE(*vpp);
6297 				return (NFS4ERR_EXIST);
6298 			}
6299 			*created = TRUE; /* retrans of create == created */
6300 			return (NFS4_OK);
6301 		}
6302 		VN_RELE(*vpp);
6303 		return (NFS4ERR_EXIST);
6304 	}
6305 
6306 	return (NFS4_OK);
6307 }
6308 
6309 static nfsstat4
6310 check_open_access(uint32_t access, struct compound_state *cs,
6311     struct svc_req *req)
6312 {
6313 	int error;
6314 	vnode_t *vp;
6315 	bool_t readonly;
6316 	cred_t *cr = cs->cr;
6317 
6318 	/* For now we don't allow mandatory locking as per V2/V3 */
6319 	if (cs->access == CS_ACCESS_DENIED || cs->mandlock) {
6320 		return (NFS4ERR_ACCESS);
6321 	}
6322 
6323 	vp = cs->vp;
6324 	ASSERT(cr != NULL && vp->v_type == VREG);
6325 
6326 	/*
6327 	 * If the file system is exported read only and we are trying
6328 	 * to open for write, then return NFS4ERR_ROFS
6329 	 */
6330 
6331 	readonly = rdonly4(req, cs);
6332 
6333 	if ((access & OPEN4_SHARE_ACCESS_WRITE) && readonly)
6334 		return (NFS4ERR_ROFS);
6335 
6336 	if (access & OPEN4_SHARE_ACCESS_READ) {
6337 		if ((VOP_ACCESS(vp, VREAD, 0, cr, NULL) != 0) &&
6338 		    (VOP_ACCESS(vp, VEXEC, 0, cr, NULL) != 0)) {
6339 			return (NFS4ERR_ACCESS);
6340 		}
6341 	}
6342 
6343 	if (access & OPEN4_SHARE_ACCESS_WRITE) {
6344 		error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
6345 		if (error)
6346 			return (NFS4ERR_ACCESS);
6347 	}
6348 
6349 	return (NFS4_OK);
6350 }
6351 
6352 static nfsstat4
6353 rfs4_createfile(OPEN4args *args, struct svc_req *req, struct compound_state *cs,
6354     change_info4 *cinfo, bitmap4 *attrset, clientid4 clientid)
6355 {
6356 	struct nfs4_svgetit_arg sarg;
6357 	struct nfs4_ntov_table ntov;
6358 
6359 	bool_t ntov_table_init = FALSE;
6360 	struct statvfs64 sb;
6361 	nfsstat4 status;
6362 	vnode_t *vp;
6363 	vattr_t bva, ava, iva, cva, *vap;
6364 	vnode_t *dvp;
6365 	timespec32_t *mtime;
6366 	char *nm = NULL;
6367 	uint_t buflen;
6368 	bool_t created;
6369 	bool_t setsize = FALSE;
6370 	len_t reqsize;
6371 	int error;
6372 	bool_t trunc;
6373 	caller_context_t ct;
6374 	component4 *component;
6375 	bslabel_t *clabel;
6376 	struct sockaddr *ca;
6377 	char *name = NULL;
6378 
6379 	sarg.sbp = &sb;
6380 	sarg.is_referral = B_FALSE;
6381 
6382 	dvp = cs->vp;
6383 
6384 	/* Check if the file system is read only */
6385 	if (rdonly4(req, cs))
6386 		return (NFS4ERR_ROFS);
6387 
6388 	/* check the label of including directory */
6389 	if (is_system_labeled()) {
6390 		ASSERT(req->rq_label != NULL);
6391 		clabel = req->rq_label;
6392 		DTRACE_PROBE2(tx__rfs4__log__info__opremove__clabel, char *,
6393 		    "got client label from request(1)",
6394 		    struct svc_req *, req);
6395 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
6396 			if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
6397 			    cs->exi)) {
6398 				return (NFS4ERR_ACCESS);
6399 			}
6400 		}
6401 	}
6402 
6403 	/*
6404 	 * Get the last component of path name in nm. cs will reference
6405 	 * the including directory on success.
6406 	 */
6407 	component = &args->open_claim4_u.file;
6408 	status = utf8_dir_verify(component);
6409 	if (status != NFS4_OK)
6410 		return (status);
6411 
6412 	nm = utf8_to_fn(component, &buflen, NULL);
6413 
6414 	if (nm == NULL)
6415 		return (NFS4ERR_RESOURCE);
6416 
6417 	if (buflen > MAXNAMELEN) {
6418 		kmem_free(nm, buflen);
6419 		return (NFS4ERR_NAMETOOLONG);
6420 	}
6421 
6422 	bva.va_mask = AT_TYPE|AT_CTIME|AT_SEQ;
6423 	error = VOP_GETATTR(dvp, &bva, 0, cs->cr, NULL);
6424 	if (error) {
6425 		kmem_free(nm, buflen);
6426 		return (puterrno4(error));
6427 	}
6428 
6429 	if (bva.va_type != VDIR) {
6430 		kmem_free(nm, buflen);
6431 		return (NFS4ERR_NOTDIR);
6432 	}
6433 
6434 	NFS4_SET_FATTR4_CHANGE(cinfo->before, bva.va_ctime)
6435 
6436 	switch (args->mode) {
6437 	case GUARDED4:
6438 		/*FALLTHROUGH*/
6439 	case UNCHECKED4:
6440 		nfs4_ntov_table_init(&ntov);
6441 		ntov_table_init = TRUE;
6442 
6443 		*attrset = 0;
6444 		status = do_rfs4_set_attrs(attrset,
6445 		    &args->createhow4_u.createattrs,
6446 		    cs, &sarg, &ntov, NFS4ATTR_SETIT);
6447 
6448 		if (status == NFS4_OK && (sarg.vap->va_mask & AT_TYPE) &&
6449 		    sarg.vap->va_type != VREG) {
6450 			if (sarg.vap->va_type == VDIR)
6451 				status = NFS4ERR_ISDIR;
6452 			else if (sarg.vap->va_type == VLNK)
6453 				status = NFS4ERR_SYMLINK;
6454 			else
6455 				status = NFS4ERR_INVAL;
6456 		}
6457 
6458 		if (status != NFS4_OK) {
6459 			kmem_free(nm, buflen);
6460 			nfs4_ntov_table_free(&ntov, &sarg);
6461 			*attrset = 0;
6462 			return (status);
6463 		}
6464 
6465 		vap = sarg.vap;
6466 		vap->va_type = VREG;
6467 		vap->va_mask |= AT_TYPE;
6468 
6469 		if ((vap->va_mask & AT_MODE) == 0) {
6470 			vap->va_mask |= AT_MODE;
6471 			vap->va_mode = (mode_t)0600;
6472 		}
6473 
6474 		if (vap->va_mask & AT_SIZE) {
6475 
6476 			/* Disallow create with a non-zero size */
6477 
6478 			if ((reqsize = sarg.vap->va_size) != 0) {
6479 				kmem_free(nm, buflen);
6480 				nfs4_ntov_table_free(&ntov, &sarg);
6481 				*attrset = 0;
6482 				return (NFS4ERR_INVAL);
6483 			}
6484 			setsize = TRUE;
6485 		}
6486 		break;
6487 
6488 	case EXCLUSIVE4:
6489 		/* prohibit EXCL create of named attributes */
6490 		if (dvp->v_flag & V_XATTRDIR) {
6491 			kmem_free(nm, buflen);
6492 			*attrset = 0;
6493 			return (NFS4ERR_INVAL);
6494 		}
6495 
6496 		cva.va_mask = AT_TYPE | AT_MTIME | AT_MODE;
6497 		cva.va_type = VREG;
6498 		/*
6499 		 * Ensure no time overflows. Assumes underlying
6500 		 * filesystem supports at least 32 bits.
6501 		 * Truncate nsec to usec resolution to allow valid
6502 		 * compares even if the underlying filesystem truncates.
6503 		 */
6504 		mtime = (timespec32_t *)&args->createhow4_u.createverf;
6505 		cva.va_mtime.tv_sec = mtime->tv_sec % TIME32_MAX;
6506 		cva.va_mtime.tv_nsec = (mtime->tv_nsec / 1000) * 1000;
6507 		cva.va_mode = (mode_t)0;
6508 		vap = &cva;
6509 
6510 		/*
6511 		 * For EXCL create, attrset is set to the server attr
6512 		 * used to cache the client's verifier.
6513 		 */
6514 		*attrset = FATTR4_TIME_MODIFY_MASK;
6515 		break;
6516 	}
6517 
6518 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
6519 	name = nfscmd_convname(ca, cs->exi, nm, NFSCMD_CONV_INBOUND,
6520 	    MAXPATHLEN  + 1);
6521 
6522 	if (name == NULL) {
6523 		kmem_free(nm, buflen);
6524 		return (NFS4ERR_SERVERFAULT);
6525 	}
6526 
6527 	status = create_vnode(dvp, name, vap, args->mode, mtime,
6528 	    cs->cr, &vp, &created);
6529 	if (nm != name)
6530 		kmem_free(name, MAXPATHLEN + 1);
6531 	kmem_free(nm, buflen);
6532 
6533 	if (status != NFS4_OK) {
6534 		if (ntov_table_init)
6535 			nfs4_ntov_table_free(&ntov, &sarg);
6536 		*attrset = 0;
6537 		return (status);
6538 	}
6539 
6540 	trunc = (setsize && !created);
6541 
6542 	if (args->mode != EXCLUSIVE4) {
6543 		bitmap4 createmask = args->createhow4_u.createattrs.attrmask;
6544 
6545 		/*
6546 		 * True verification that object was created with correct
6547 		 * attrs is impossible.  The attrs could have been changed
6548 		 * immediately after object creation.  If attributes did
6549 		 * not verify, the only recourse for the server is to
6550 		 * destroy the object.  Maybe if some attrs (like gid)
6551 		 * are set incorrectly, the object should be destroyed;
6552 		 * however, seems bad as a default policy.  Do we really
6553 		 * want to destroy an object over one of the times not
6554 		 * verifying correctly?  For these reasons, the server
6555 		 * currently sets bits in attrset for createattrs
6556 		 * that were set; however, no verification is done.
6557 		 *
6558 		 * vmask_to_nmask accounts for vattr bits set on create
6559 		 *	[do_rfs4_set_attrs() only sets resp bits for
6560 		 *	 non-vattr/vfs bits.]
6561 		 * Mask off any bits we set by default so as not to return
6562 		 * more attrset bits than were requested in createattrs
6563 		 */
6564 		if (created) {
6565 			nfs4_vmask_to_nmask(sarg.vap->va_mask, attrset);
6566 			*attrset &= createmask;
6567 		} else {
6568 			/*
6569 			 * We did not create the vnode (we tried but it
6570 			 * already existed).  In this case, the only createattr
6571 			 * that the spec allows the server to set is size,
6572 			 * and even then, it can only be set if it is 0.
6573 			 */
6574 			*attrset = 0;
6575 			if (trunc)
6576 				*attrset = FATTR4_SIZE_MASK;
6577 		}
6578 	}
6579 	if (ntov_table_init)
6580 		nfs4_ntov_table_free(&ntov, &sarg);
6581 
6582 	/*
6583 	 * Get the initial "after" sequence number, if it fails,
6584 	 * set to zero, time to before.
6585 	 */
6586 	iva.va_mask = AT_CTIME|AT_SEQ;
6587 	if (VOP_GETATTR(dvp, &iva, 0, cs->cr, NULL)) {
6588 		iva.va_seq = 0;
6589 		iva.va_ctime = bva.va_ctime;
6590 	}
6591 
6592 	/*
6593 	 * create_vnode attempts to create the file exclusive,
6594 	 * if it already exists the VOP_CREATE will fail and
6595 	 * may not increase va_seq. It is atomic if
6596 	 * we haven't changed the directory, but if it has changed
6597 	 * we don't know what changed it.
6598 	 */
6599 	if (!created) {
6600 		if (bva.va_seq && iva.va_seq &&
6601 		    bva.va_seq == iva.va_seq)
6602 			cinfo->atomic = TRUE;
6603 		else
6604 			cinfo->atomic = FALSE;
6605 		NFS4_SET_FATTR4_CHANGE(cinfo->after, iva.va_ctime);
6606 	} else {
6607 		/*
6608 		 * The entry was created, we need to sync the
6609 		 * directory metadata.
6610 		 */
6611 		(void) VOP_FSYNC(dvp, 0, cs->cr, NULL);
6612 
6613 		/*
6614 		 * Get "after" change value, if it fails, simply return the
6615 		 * before value.
6616 		 */
6617 		ava.va_mask = AT_CTIME|AT_SEQ;
6618 		if (VOP_GETATTR(dvp, &ava, 0, cs->cr, NULL)) {
6619 			ava.va_ctime = bva.va_ctime;
6620 			ava.va_seq = 0;
6621 		}
6622 
6623 		NFS4_SET_FATTR4_CHANGE(cinfo->after, ava.va_ctime);
6624 
6625 		/*
6626 		 * The cinfo->atomic = TRUE only if we have
6627 		 * non-zero va_seq's, and it has incremented by exactly one
6628 		 * during the create_vnode and it didn't
6629 		 * change during the VOP_FSYNC.
6630 		 */
6631 		if (bva.va_seq && iva.va_seq && ava.va_seq &&
6632 		    iva.va_seq == (bva.va_seq + 1) && iva.va_seq == ava.va_seq)
6633 			cinfo->atomic = TRUE;
6634 		else
6635 			cinfo->atomic = FALSE;
6636 	}
6637 
6638 	/* Check for mandatory locking and that the size gets set. */
6639 	cva.va_mask = AT_MODE;
6640 	if (setsize)
6641 		cva.va_mask |= AT_SIZE;
6642 
6643 	/* Assume the worst */
6644 	cs->mandlock = TRUE;
6645 
6646 	if (VOP_GETATTR(vp, &cva, 0, cs->cr, NULL) == 0) {
6647 		cs->mandlock = MANDLOCK(cs->vp, cva.va_mode);
6648 
6649 		/*
6650 		 * Truncate the file if necessary; this would be
6651 		 * the case for create over an existing file.
6652 		 */
6653 
6654 		if (trunc) {
6655 			int in_crit = 0;
6656 			rfs4_file_t *fp;
6657 			bool_t create = FALSE;
6658 
6659 			/*
6660 			 * We are writing over an existing file.
6661 			 * Check to see if we need to recall a delegation.
6662 			 */
6663 			rfs4_hold_deleg_policy();
6664 			if ((fp = rfs4_findfile(vp, NULL, &create)) != NULL) {
6665 				if (rfs4_check_delegated_byfp(FWRITE, fp,
6666 				    (reqsize == 0), FALSE, FALSE, &clientid)) {
6667 					rfs4_file_rele(fp);
6668 					rfs4_rele_deleg_policy();
6669 					VN_RELE(vp);
6670 					*attrset = 0;
6671 					return (NFS4ERR_DELAY);
6672 				}
6673 				rfs4_file_rele(fp);
6674 			}
6675 			rfs4_rele_deleg_policy();
6676 
6677 			if (nbl_need_check(vp)) {
6678 				in_crit = 1;
6679 
6680 				ASSERT(reqsize == 0);
6681 
6682 				nbl_start_crit(vp, RW_READER);
6683 				if (nbl_conflict(vp, NBL_WRITE, 0,
6684 				    cva.va_size, 0, NULL)) {
6685 					in_crit = 0;
6686 					nbl_end_crit(vp);
6687 					VN_RELE(vp);
6688 					*attrset = 0;
6689 					return (NFS4ERR_ACCESS);
6690 				}
6691 			}
6692 			ct.cc_sysid = 0;
6693 			ct.cc_pid = 0;
6694 			ct.cc_caller_id = nfs4_srv_caller_id;
6695 			ct.cc_flags = CC_DONTBLOCK;
6696 
6697 			cva.va_mask = AT_SIZE;
6698 			cva.va_size = reqsize;
6699 			(void) VOP_SETATTR(vp, &cva, 0, cs->cr, &ct);
6700 			if (in_crit)
6701 				nbl_end_crit(vp);
6702 		}
6703 	}
6704 
6705 	error = makefh4(&cs->fh, vp, cs->exi);
6706 
6707 	/*
6708 	 * Force modified data and metadata out to stable storage.
6709 	 */
6710 	(void) VOP_FSYNC(vp, FNODSYNC, cs->cr, NULL);
6711 
6712 	if (error) {
6713 		VN_RELE(vp);
6714 		*attrset = 0;
6715 		return (puterrno4(error));
6716 	}
6717 
6718 	/* if parent dir is attrdir, set namedattr fh flag */
6719 	if (dvp->v_flag & V_XATTRDIR)
6720 		set_fh4_flag(&cs->fh, FH4_NAMEDATTR);
6721 
6722 	if (cs->vp)
6723 		VN_RELE(cs->vp);
6724 
6725 	cs->vp = vp;
6726 
6727 	/*
6728 	 * if we did not create the file, we will need to check
6729 	 * the access bits on the file
6730 	 */
6731 
6732 	if (!created) {
6733 		if (setsize)
6734 			args->share_access |= OPEN4_SHARE_ACCESS_WRITE;
6735 		status = check_open_access(args->share_access, cs, req);
6736 		if (status != NFS4_OK)
6737 			*attrset = 0;
6738 	}
6739 	return (status);
6740 }
6741 
6742 /*ARGSUSED*/
6743 static void
6744 rfs4_do_open(struct compound_state *cs, struct svc_req *req,
6745     rfs4_openowner_t *oo, delegreq_t deleg,
6746     uint32_t access, uint32_t deny,
6747     OPEN4res *resp, int deleg_cur)
6748 {
6749 	/* XXX Currently not using req  */
6750 	rfs4_state_t *sp;
6751 	rfs4_file_t *fp;
6752 	bool_t screate = TRUE;
6753 	bool_t fcreate = TRUE;
6754 	uint32_t open_a, share_a;
6755 	uint32_t open_d, share_d;
6756 	rfs4_deleg_state_t *dsp;
6757 	sysid_t sysid;
6758 	nfsstat4 status;
6759 	caller_context_t ct;
6760 	int fflags = 0;
6761 	int recall = 0;
6762 	int err;
6763 	int first_open;
6764 
6765 	/* get the file struct and hold a lock on it during initial open */
6766 	fp = rfs4_findfile_withlock(cs->vp, &cs->fh, &fcreate);
6767 	if (fp == NULL) {
6768 		resp->status = NFS4ERR_RESOURCE;
6769 		DTRACE_PROBE1(nfss__e__do__open1, nfsstat4, resp->status);
6770 		return;
6771 	}
6772 
6773 	sp = rfs4_findstate_by_owner_file(oo, fp, &screate);
6774 	if (sp == NULL) {
6775 		resp->status = NFS4ERR_RESOURCE;
6776 		DTRACE_PROBE1(nfss__e__do__open2, nfsstat4, resp->status);
6777 		/* No need to keep any reference */
6778 		rw_exit(&fp->rf_file_rwlock);
6779 		rfs4_file_rele(fp);
6780 		return;
6781 	}
6782 
6783 	/* try to get the sysid before continuing */
6784 	if ((status = rfs4_client_sysid(oo->ro_client, &sysid)) != NFS4_OK) {
6785 		resp->status = status;
6786 		rfs4_file_rele(fp);
6787 		/* Not a fully formed open; "close" it */
6788 		if (screate == TRUE)
6789 			rfs4_state_close(sp, FALSE, FALSE, cs->cr);
6790 		rfs4_state_rele(sp);
6791 		return;
6792 	}
6793 
6794 	/* Calculate the fflags for this OPEN. */
6795 	if (access & OPEN4_SHARE_ACCESS_READ)
6796 		fflags |= FREAD;
6797 	if (access & OPEN4_SHARE_ACCESS_WRITE)
6798 		fflags |= FWRITE;
6799 
6800 	rfs4_dbe_lock(sp->rs_dbe);
6801 
6802 	/*
6803 	 * Calculate the new deny and access mode that this open is adding to
6804 	 * the file for this open owner;
6805 	 */
6806 	open_d = (deny & ~sp->rs_open_deny);
6807 	open_a = (access & ~sp->rs_open_access);
6808 
6809 	/*
6810 	 * Calculate the new share access and share deny modes that this open
6811 	 * is adding to the file for this open owner;
6812 	 */
6813 	share_a = (access & ~sp->rs_share_access);
6814 	share_d = (deny & ~sp->rs_share_deny);
6815 
6816 	first_open = (sp->rs_open_access & OPEN4_SHARE_ACCESS_BOTH) == 0;
6817 
6818 	/*
6819 	 * Check to see the client has already sent an open for this
6820 	 * open owner on this file with the same share/deny modes.
6821 	 * If so, we don't need to check for a conflict and we don't
6822 	 * need to add another shrlock.  If not, then we need to
6823 	 * check for conflicts in deny and access before checking for
6824 	 * conflicts in delegation.  We don't want to recall a
6825 	 * delegation based on an open that will eventually fail based
6826 	 * on shares modes.
6827 	 */
6828 
6829 	if (share_a || share_d) {
6830 		if ((err = rfs4_share(sp, access, deny)) != 0) {
6831 			rfs4_dbe_unlock(sp->rs_dbe);
6832 			resp->status = err;
6833 
6834 			rfs4_file_rele(fp);
6835 			/* Not a fully formed open; "close" it */
6836 			if (screate == TRUE)
6837 				rfs4_state_close(sp, FALSE, FALSE, cs->cr);
6838 			rfs4_state_rele(sp);
6839 			return;
6840 		}
6841 	}
6842 
6843 	rfs4_dbe_lock(fp->rf_dbe);
6844 
6845 	/*
6846 	 * Check to see if this file is delegated and if so, if a
6847 	 * recall needs to be done.
6848 	 */
6849 	if (rfs4_check_recall(sp, access)) {
6850 		rfs4_dbe_unlock(fp->rf_dbe);
6851 		rfs4_dbe_unlock(sp->rs_dbe);
6852 		rfs4_recall_deleg(fp, FALSE, sp->rs_owner->ro_client);
6853 		delay(NFS4_DELEGATION_CONFLICT_DELAY);
6854 		rfs4_dbe_lock(sp->rs_dbe);
6855 
6856 		/* if state closed while lock was dropped */
6857 		if (sp->rs_closed) {
6858 			if (share_a || share_d)
6859 				(void) rfs4_unshare(sp);
6860 			rfs4_dbe_unlock(sp->rs_dbe);
6861 			rfs4_file_rele(fp);
6862 			/* Not a fully formed open; "close" it */
6863 			if (screate == TRUE)
6864 				rfs4_state_close(sp, FALSE, FALSE, cs->cr);
6865 			rfs4_state_rele(sp);
6866 			resp->status = NFS4ERR_OLD_STATEID;
6867 			return;
6868 		}
6869 
6870 		rfs4_dbe_lock(fp->rf_dbe);
6871 		/* Let's see if the delegation was returned */
6872 		if (rfs4_check_recall(sp, access)) {
6873 			rfs4_dbe_unlock(fp->rf_dbe);
6874 			if (share_a || share_d)
6875 				(void) rfs4_unshare(sp);
6876 			rfs4_dbe_unlock(sp->rs_dbe);
6877 			rfs4_file_rele(fp);
6878 			rfs4_update_lease(sp->rs_owner->ro_client);
6879 
6880 			/* Not a fully formed open; "close" it */
6881 			if (screate == TRUE)
6882 				rfs4_state_close(sp, FALSE, FALSE, cs->cr);
6883 			rfs4_state_rele(sp);
6884 			resp->status = NFS4ERR_DELAY;
6885 			return;
6886 		}
6887 	}
6888 	/*
6889 	 * the share check passed and any delegation conflict has been
6890 	 * taken care of, now call vop_open.
6891 	 * if this is the first open then call vop_open with fflags.
6892 	 * if not, call vn_open_upgrade with just the upgrade flags.
6893 	 *
6894 	 * if the file has been opened already, it will have the current
6895 	 * access mode in the state struct.  if it has no share access, then
6896 	 * this is a new open.
6897 	 *
6898 	 * However, if this is open with CLAIM_DLEGATE_CUR, then don't
6899 	 * call VOP_OPEN(), just do the open upgrade.
6900 	 */
6901 	if (first_open && !deleg_cur) {
6902 		ct.cc_sysid = sysid;
6903 		ct.cc_pid = rfs4_dbe_getid(sp->rs_owner->ro_dbe);
6904 		ct.cc_caller_id = nfs4_srv_caller_id;
6905 		ct.cc_flags = CC_DONTBLOCK;
6906 		err = VOP_OPEN(&cs->vp, fflags, cs->cr, &ct);
6907 		if (err) {
6908 			rfs4_dbe_unlock(fp->rf_dbe);
6909 			if (share_a || share_d)
6910 				(void) rfs4_unshare(sp);
6911 			rfs4_dbe_unlock(sp->rs_dbe);
6912 			rfs4_file_rele(fp);
6913 
6914 			/* Not a fully formed open; "close" it */
6915 			if (screate == TRUE)
6916 				rfs4_state_close(sp, FALSE, FALSE, cs->cr);
6917 			rfs4_state_rele(sp);
6918 			/* check if a monitor detected a delegation conflict */
6919 			if (err == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK))
6920 				resp->status = NFS4ERR_DELAY;
6921 			else
6922 				resp->status = NFS4ERR_SERVERFAULT;
6923 			return;
6924 		}
6925 	} else { /* open upgrade */
6926 		/*
6927 		 * calculate the fflags for the new mode that is being added
6928 		 * by this upgrade.
6929 		 */
6930 		fflags = 0;
6931 		if (open_a & OPEN4_SHARE_ACCESS_READ)
6932 			fflags |= FREAD;
6933 		if (open_a & OPEN4_SHARE_ACCESS_WRITE)
6934 			fflags |= FWRITE;
6935 		vn_open_upgrade(cs->vp, fflags);
6936 	}
6937 	sp->rs_open_access |= access;
6938 	sp->rs_open_deny |= deny;
6939 
6940 	if (open_d & OPEN4_SHARE_DENY_READ)
6941 		fp->rf_deny_read++;
6942 	if (open_d & OPEN4_SHARE_DENY_WRITE)
6943 		fp->rf_deny_write++;
6944 	fp->rf_share_deny |= deny;
6945 
6946 	if (open_a & OPEN4_SHARE_ACCESS_READ)
6947 		fp->rf_access_read++;
6948 	if (open_a & OPEN4_SHARE_ACCESS_WRITE)
6949 		fp->rf_access_write++;
6950 	fp->rf_share_access |= access;
6951 
6952 	/*
6953 	 * Check for delegation here. if the deleg argument is not
6954 	 * DELEG_ANY, then this is a reclaim from a client and
6955 	 * we must honor the delegation requested. If necessary we can
6956 	 * set the recall flag.
6957 	 */
6958 
6959 	dsp = rfs4_grant_delegation(deleg, sp, &recall);
6960 
6961 	cs->deleg = (fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_WRITE);
6962 
6963 	next_stateid(&sp->rs_stateid);
6964 
6965 	resp->stateid = sp->rs_stateid.stateid;
6966 
6967 	rfs4_dbe_unlock(fp->rf_dbe);
6968 	rfs4_dbe_unlock(sp->rs_dbe);
6969 
6970 	if (dsp) {
6971 		rfs4_set_deleg_response(dsp, &resp->delegation, NULL, recall);
6972 		rfs4_deleg_state_rele(dsp);
6973 	}
6974 
6975 	rfs4_file_rele(fp);
6976 	rfs4_state_rele(sp);
6977 
6978 	resp->status = NFS4_OK;
6979 }
6980 
6981 /*ARGSUSED*/
6982 static void
6983 rfs4_do_opennull(struct compound_state *cs, struct svc_req *req,
6984     OPEN4args *args, rfs4_openowner_t *oo, OPEN4res *resp)
6985 {
6986 	change_info4 *cinfo = &resp->cinfo;
6987 	bitmap4 *attrset = &resp->attrset;
6988 
6989 	if (args->opentype == OPEN4_NOCREATE)
6990 		resp->status = rfs4_lookupfile(&args->open_claim4_u.file,
6991 		    req, cs, args->share_access, cinfo);
6992 	else {
6993 		/* inhibit delegation grants during exclusive create */
6994 
6995 		if (args->mode == EXCLUSIVE4)
6996 			rfs4_disable_delegation();
6997 
6998 		resp->status = rfs4_createfile(args, req, cs, cinfo, attrset,
6999 		    oo->ro_client->rc_clientid);
7000 	}
7001 
7002 	if (resp->status == NFS4_OK) {
7003 
7004 		/* cs->vp cs->fh now reference the desired file */
7005 
7006 		rfs4_do_open(cs, req, oo,
7007 		    oo->ro_need_confirm ? DELEG_NONE : DELEG_ANY,
7008 		    args->share_access, args->share_deny, resp, 0);
7009 
7010 		/*
7011 		 * If rfs4_createfile set attrset, we must
7012 		 * clear this attrset before the response is copied.
7013 		 */
7014 		if (resp->status != NFS4_OK && resp->attrset) {
7015 			resp->attrset = 0;
7016 		}
7017 	}
7018 	else
7019 		*cs->statusp = resp->status;
7020 
7021 	if (args->mode == EXCLUSIVE4)
7022 		rfs4_enable_delegation();
7023 }
7024 
7025 /*ARGSUSED*/
7026 static void
7027 rfs4_do_openprev(struct compound_state *cs, struct svc_req *req,
7028     OPEN4args *args, rfs4_openowner_t *oo, OPEN4res *resp)
7029 {
7030 	change_info4 *cinfo = &resp->cinfo;
7031 	vattr_t va;
7032 	vtype_t v_type = cs->vp->v_type;
7033 	int error = 0;
7034 
7035 	/* Verify that we have a regular file */
7036 	if (v_type != VREG) {
7037 		if (v_type == VDIR)
7038 			resp->status = NFS4ERR_ISDIR;
7039 		else if (v_type == VLNK)
7040 			resp->status = NFS4ERR_SYMLINK;
7041 		else
7042 			resp->status = NFS4ERR_INVAL;
7043 		return;
7044 	}
7045 
7046 	va.va_mask = AT_MODE|AT_UID;
7047 	error = VOP_GETATTR(cs->vp, &va, 0, cs->cr, NULL);
7048 	if (error) {
7049 		resp->status = puterrno4(error);
7050 		return;
7051 	}
7052 
7053 	cs->mandlock = MANDLOCK(cs->vp, va.va_mode);
7054 
7055 	/*
7056 	 * Check if we have access to the file, Note the the file
7057 	 * could have originally been open UNCHECKED or GUARDED
7058 	 * with mode bits that will now fail, but there is nothing
7059 	 * we can really do about that except in the case that the
7060 	 * owner of the file is the one requesting the open.
7061 	 */
7062 	if (crgetuid(cs->cr) != va.va_uid) {
7063 		resp->status = check_open_access(args->share_access, cs, req);
7064 		if (resp->status != NFS4_OK) {
7065 			return;
7066 		}
7067 	}
7068 
7069 	/*
7070 	 * cinfo on a CLAIM_PREVIOUS is undefined, initialize to zero
7071 	 */
7072 	cinfo->before = 0;
7073 	cinfo->after = 0;
7074 	cinfo->atomic = FALSE;
7075 
7076 	rfs4_do_open(cs, req, oo,
7077 	    NFS4_DELEG4TYPE2REQTYPE(args->open_claim4_u.delegate_type),
7078 	    args->share_access, args->share_deny, resp, 0);
7079 }
7080 
7081 static void
7082 rfs4_do_opendelcur(struct compound_state *cs, struct svc_req *req,
7083     OPEN4args *args, rfs4_openowner_t *oo, OPEN4res *resp)
7084 {
7085 	int error;
7086 	nfsstat4 status;
7087 	stateid4 stateid =
7088 	    args->open_claim4_u.delegate_cur_info.delegate_stateid;
7089 	rfs4_deleg_state_t *dsp;
7090 
7091 	/*
7092 	 * Find the state info from the stateid and confirm that the
7093 	 * file is delegated.  If the state openowner is the same as
7094 	 * the supplied openowner we're done. If not, get the file
7095 	 * info from the found state info. Use that file info to
7096 	 * create the state for this lock owner. Note solaris doen't
7097 	 * really need the pathname to find the file. We may want to
7098 	 * lookup the pathname and make sure that the vp exist and
7099 	 * matches the vp in the file structure. However it is
7100 	 * possible that the pathname nolonger exists (local process
7101 	 * unlinks the file), so this may not be that useful.
7102 	 */
7103 
7104 	status = rfs4_get_deleg_state(&stateid, &dsp);
7105 	if (status != NFS4_OK) {
7106 		resp->status = status;
7107 		return;
7108 	}
7109 
7110 	ASSERT(dsp->rds_finfo->rf_dinfo.rd_dtype != OPEN_DELEGATE_NONE);
7111 
7112 	/*
7113 	 * New lock owner, create state. Since this was probably called
7114 	 * in response to a CB_RECALL we set deleg to DELEG_NONE
7115 	 */
7116 
7117 	ASSERT(cs->vp != NULL);
7118 	VN_RELE(cs->vp);
7119 	VN_HOLD(dsp->rds_finfo->rf_vp);
7120 	cs->vp = dsp->rds_finfo->rf_vp;
7121 
7122 	if (error = makefh4(&cs->fh, cs->vp, cs->exi)) {
7123 		rfs4_deleg_state_rele(dsp);
7124 		*cs->statusp = resp->status = puterrno4(error);
7125 		return;
7126 	}
7127 
7128 	/* Mark progress for delegation returns */
7129 	dsp->rds_finfo->rf_dinfo.rd_time_lastwrite = gethrestime_sec();
7130 	rfs4_deleg_state_rele(dsp);
7131 	rfs4_do_open(cs, req, oo, DELEG_NONE,
7132 	    args->share_access, args->share_deny, resp, 1);
7133 }
7134 
7135 /*ARGSUSED*/
7136 static void
7137 rfs4_do_opendelprev(struct compound_state *cs, struct svc_req *req,
7138     OPEN4args *args, rfs4_openowner_t *oo, OPEN4res *resp)
7139 {
7140 	/*
7141 	 * Lookup the pathname, it must already exist since this file
7142 	 * was delegated.
7143 	 *
7144 	 * Find the file and state info for this vp and open owner pair.
7145 	 *	check that they are in fact delegated.
7146 	 *	check that the state access and deny modes are the same.
7147 	 *
7148 	 * Return the delgation possibly seting the recall flag.
7149 	 */
7150 	rfs4_file_t *fp;
7151 	rfs4_state_t *sp;
7152 	bool_t create = FALSE;
7153 	bool_t dcreate = FALSE;
7154 	rfs4_deleg_state_t *dsp;
7155 	nfsace4 *ace;
7156 
7157 	/* Note we ignore oflags */
7158 	resp->status = rfs4_lookupfile(&args->open_claim4_u.file_delegate_prev,
7159 	    req, cs, args->share_access, &resp->cinfo);
7160 
7161 	if (resp->status != NFS4_OK) {
7162 		return;
7163 	}
7164 
7165 	/* get the file struct and hold a lock on it during initial open */
7166 	fp = rfs4_findfile_withlock(cs->vp, NULL, &create);
7167 	if (fp == NULL) {
7168 		resp->status = NFS4ERR_RESOURCE;
7169 		DTRACE_PROBE1(nfss__e__do_opendelprev1, nfsstat4, resp->status);
7170 		return;
7171 	}
7172 
7173 	sp = rfs4_findstate_by_owner_file(oo, fp, &create);
7174 	if (sp == NULL) {
7175 		resp->status = NFS4ERR_SERVERFAULT;
7176 		DTRACE_PROBE1(nfss__e__do_opendelprev2, nfsstat4, resp->status);
7177 		rw_exit(&fp->rf_file_rwlock);
7178 		rfs4_file_rele(fp);
7179 		return;
7180 	}
7181 
7182 	rfs4_dbe_lock(sp->rs_dbe);
7183 	rfs4_dbe_lock(fp->rf_dbe);
7184 	if (args->share_access != sp->rs_share_access ||
7185 	    args->share_deny != sp->rs_share_deny ||
7186 	    sp->rs_finfo->rf_dinfo.rd_dtype == OPEN_DELEGATE_NONE) {
7187 		NFS4_DEBUG(rfs4_debug,
7188 		    (CE_NOTE, "rfs4_do_opendelprev: state mixup"));
7189 		rfs4_dbe_unlock(fp->rf_dbe);
7190 		rfs4_dbe_unlock(sp->rs_dbe);
7191 		rfs4_file_rele(fp);
7192 		rfs4_state_rele(sp);
7193 		resp->status = NFS4ERR_SERVERFAULT;
7194 		return;
7195 	}
7196 	rfs4_dbe_unlock(fp->rf_dbe);
7197 	rfs4_dbe_unlock(sp->rs_dbe);
7198 
7199 	dsp = rfs4_finddeleg(sp, &dcreate);
7200 	if (dsp == NULL) {
7201 		rfs4_state_rele(sp);
7202 		rfs4_file_rele(fp);
7203 		resp->status = NFS4ERR_SERVERFAULT;
7204 		return;
7205 	}
7206 
7207 	next_stateid(&sp->rs_stateid);
7208 
7209 	resp->stateid = sp->rs_stateid.stateid;
7210 
7211 	resp->delegation.delegation_type = dsp->rds_dtype;
7212 
7213 	if (dsp->rds_dtype == OPEN_DELEGATE_READ) {
7214 		open_read_delegation4 *rv =
7215 		    &resp->delegation.open_delegation4_u.read;
7216 
7217 		rv->stateid = dsp->rds_delegid.stateid;
7218 		rv->recall = FALSE; /* no policy in place to set to TRUE */
7219 		ace = &rv->permissions;
7220 	} else {
7221 		open_write_delegation4 *rv =
7222 		    &resp->delegation.open_delegation4_u.write;
7223 
7224 		rv->stateid = dsp->rds_delegid.stateid;
7225 		rv->recall = FALSE;  /* no policy in place to set to TRUE */
7226 		ace = &rv->permissions;
7227 		rv->space_limit.limitby = NFS_LIMIT_SIZE;
7228 		rv->space_limit.nfs_space_limit4_u.filesize = UINT64_MAX;
7229 	}
7230 
7231 	/* XXX For now */
7232 	ace->type = ACE4_ACCESS_ALLOWED_ACE_TYPE;
7233 	ace->flag = 0;
7234 	ace->access_mask = 0;
7235 	ace->who.utf8string_len = 0;
7236 	ace->who.utf8string_val = 0;
7237 
7238 	rfs4_deleg_state_rele(dsp);
7239 	rfs4_state_rele(sp);
7240 	rfs4_file_rele(fp);
7241 }
7242 
7243 typedef enum {
7244 	NFS4_CHKSEQ_OKAY = 0,
7245 	NFS4_CHKSEQ_REPLAY = 1,
7246 	NFS4_CHKSEQ_BAD = 2
7247 } rfs4_chkseq_t;
7248 
7249 /*
7250  * Generic function for sequence number checks.
7251  */
7252 static rfs4_chkseq_t
7253 rfs4_check_seqid(seqid4 seqid, nfs_resop4 *lastop,
7254     seqid4 rqst_seq, nfs_resop4 *resop, bool_t copyres)
7255 {
7256 	/* Same sequence ids and matching operations? */
7257 	if (seqid == rqst_seq && resop->resop == lastop->resop) {
7258 		if (copyres == TRUE) {
7259 			rfs4_free_reply(resop);
7260 			rfs4_copy_reply(resop, lastop);
7261 		}
7262 		NFS4_DEBUG(rfs4_debug, (CE_NOTE,
7263 		    "Replayed SEQID %d\n", seqid));
7264 		return (NFS4_CHKSEQ_REPLAY);
7265 	}
7266 
7267 	/* If the incoming sequence is not the next expected then it is bad */
7268 	if (rqst_seq != seqid + 1) {
7269 		if (rqst_seq == seqid) {
7270 			NFS4_DEBUG(rfs4_debug,
7271 			    (CE_NOTE, "BAD SEQID: Replayed sequence id "
7272 			    "but last op was %d current op is %d\n",
7273 			    lastop->resop, resop->resop));
7274 			return (NFS4_CHKSEQ_BAD);
7275 		}
7276 		NFS4_DEBUG(rfs4_debug,
7277 		    (CE_NOTE, "BAD SEQID: got %u expecting %u\n",
7278 		    rqst_seq, seqid));
7279 		return (NFS4_CHKSEQ_BAD);
7280 	}
7281 
7282 	/* Everything okay -- next expected */
7283 	return (NFS4_CHKSEQ_OKAY);
7284 }
7285 
7286 
7287 static rfs4_chkseq_t
7288 rfs4_check_open_seqid(seqid4 seqid, rfs4_openowner_t *op, nfs_resop4 *resop)
7289 {
7290 	rfs4_chkseq_t rc;
7291 
7292 	rfs4_dbe_lock(op->ro_dbe);
7293 	rc = rfs4_check_seqid(op->ro_open_seqid, &op->ro_reply, seqid, resop,
7294 	    TRUE);
7295 	rfs4_dbe_unlock(op->ro_dbe);
7296 
7297 	if (rc == NFS4_CHKSEQ_OKAY)
7298 		rfs4_update_lease(op->ro_client);
7299 
7300 	return (rc);
7301 }
7302 
7303 static rfs4_chkseq_t
7304 rfs4_check_olo_seqid(seqid4 olo_seqid, rfs4_openowner_t *op, nfs_resop4 *resop)
7305 {
7306 	rfs4_chkseq_t rc;
7307 
7308 	rfs4_dbe_lock(op->ro_dbe);
7309 	rc = rfs4_check_seqid(op->ro_open_seqid, &op->ro_reply,
7310 	    olo_seqid, resop, FALSE);
7311 	rfs4_dbe_unlock(op->ro_dbe);
7312 
7313 	return (rc);
7314 }
7315 
7316 static rfs4_chkseq_t
7317 rfs4_check_lock_seqid(seqid4 seqid, rfs4_lo_state_t *lsp, nfs_resop4 *resop)
7318 {
7319 	rfs4_chkseq_t rc = NFS4_CHKSEQ_OKAY;
7320 
7321 	rfs4_dbe_lock(lsp->rls_dbe);
7322 	if (!lsp->rls_skip_seqid_check)
7323 		rc = rfs4_check_seqid(lsp->rls_seqid, &lsp->rls_reply, seqid,
7324 		    resop, TRUE);
7325 	rfs4_dbe_unlock(lsp->rls_dbe);
7326 
7327 	return (rc);
7328 }
7329 
7330 static void
7331 rfs4_op_open(nfs_argop4 *argop, nfs_resop4 *resop,
7332     struct svc_req *req, struct compound_state *cs)
7333 {
7334 	OPEN4args *args = &argop->nfs_argop4_u.opopen;
7335 	OPEN4res *resp = &resop->nfs_resop4_u.opopen;
7336 	open_owner4 *owner = &args->owner;
7337 	open_claim_type4 claim = args->claim;
7338 	rfs4_client_t *cp;
7339 	rfs4_openowner_t *oo;
7340 	bool_t create;
7341 	bool_t replay = FALSE;
7342 	int can_reclaim;
7343 
7344 	DTRACE_NFSV4_2(op__open__start, struct compound_state *, cs,
7345 	    OPEN4args *, args);
7346 
7347 	if (cs->vp == NULL) {
7348 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
7349 		goto end;
7350 	}
7351 
7352 	/*
7353 	 * Need to check clientid and lease expiration first based on
7354 	 * error ordering and incrementing sequence id.
7355 	 */
7356 	cp = rfs4_findclient_by_id(owner->clientid, FALSE);
7357 	if (cp == NULL) {
7358 		*cs->statusp = resp->status =
7359 		    rfs4_check_clientid(&owner->clientid, 0);
7360 		goto end;
7361 	}
7362 
7363 	if (rfs4_lease_expired(cp)) {
7364 		rfs4_client_close(cp);
7365 		*cs->statusp = resp->status = NFS4ERR_EXPIRED;
7366 		goto end;
7367 	}
7368 	can_reclaim = cp->rc_can_reclaim;
7369 
7370 	/*
7371 	 * Find the open_owner for use from this point forward.  Take
7372 	 * care in updating the sequence id based on the type of error
7373 	 * being returned.
7374 	 */
7375 retry:
7376 	create = TRUE;
7377 	oo = rfs4_findopenowner(owner, &create, args->seqid);
7378 	if (oo == NULL) {
7379 		*cs->statusp = resp->status = NFS4ERR_RESOURCE;
7380 		rfs4_client_rele(cp);
7381 		goto end;
7382 	}
7383 
7384 	/* Hold off access to the sequence space while the open is done */
7385 	rfs4_sw_enter(&oo->ro_sw);
7386 
7387 	/*
7388 	 * If the open_owner existed before at the server, then check
7389 	 * the sequence id.
7390 	 */
7391 	if (!create && !oo->ro_postpone_confirm) {
7392 		switch (rfs4_check_open_seqid(args->seqid, oo, resop)) {
7393 		case NFS4_CHKSEQ_BAD:
7394 			if ((args->seqid > oo->ro_open_seqid) &&
7395 			    oo->ro_need_confirm) {
7396 				rfs4_free_opens(oo, TRUE, FALSE);
7397 				rfs4_sw_exit(&oo->ro_sw);
7398 				rfs4_openowner_rele(oo);
7399 				goto retry;
7400 			}
7401 			resp->status = NFS4ERR_BAD_SEQID;
7402 			goto out;
7403 		case NFS4_CHKSEQ_REPLAY: /* replay of previous request */
7404 			replay = TRUE;
7405 			goto out;
7406 		default:
7407 			break;
7408 		}
7409 
7410 		/*
7411 		 * Sequence was ok and open owner exists
7412 		 * check to see if we have yet to see an
7413 		 * open_confirm.
7414 		 */
7415 		if (oo->ro_need_confirm) {
7416 			rfs4_free_opens(oo, TRUE, FALSE);
7417 			rfs4_sw_exit(&oo->ro_sw);
7418 			rfs4_openowner_rele(oo);
7419 			goto retry;
7420 		}
7421 	}
7422 	/* Grace only applies to regular-type OPENs */
7423 	if (rfs4_clnt_in_grace(cp) &&
7424 	    (claim == CLAIM_NULL || claim == CLAIM_DELEGATE_CUR)) {
7425 		*cs->statusp = resp->status = NFS4ERR_GRACE;
7426 		goto out;
7427 	}
7428 
7429 	/*
7430 	 * If previous state at the server existed then can_reclaim
7431 	 * will be set. If not reply NFS4ERR_NO_GRACE to the
7432 	 * client.
7433 	 */
7434 	if (rfs4_clnt_in_grace(cp) && claim == CLAIM_PREVIOUS && !can_reclaim) {
7435 		*cs->statusp = resp->status = NFS4ERR_NO_GRACE;
7436 		goto out;
7437 	}
7438 
7439 
7440 	/*
7441 	 * Reject the open if the client has missed the grace period
7442 	 */
7443 	if (!rfs4_clnt_in_grace(cp) && claim == CLAIM_PREVIOUS) {
7444 		*cs->statusp = resp->status = NFS4ERR_NO_GRACE;
7445 		goto out;
7446 	}
7447 
7448 	/* Couple of up-front bookkeeping items */
7449 	if (oo->ro_need_confirm) {
7450 		/*
7451 		 * If this is a reclaim OPEN then we should not ask
7452 		 * for a confirmation of the open_owner per the
7453 		 * protocol specification.
7454 		 */
7455 		if (claim == CLAIM_PREVIOUS)
7456 			oo->ro_need_confirm = FALSE;
7457 		else
7458 			resp->rflags |= OPEN4_RESULT_CONFIRM;
7459 	}
7460 	resp->rflags |= OPEN4_RESULT_LOCKTYPE_POSIX;
7461 
7462 	/*
7463 	 * If there is an unshared filesystem mounted on this vnode,
7464 	 * do not allow to open/create in this directory.
7465 	 */
7466 	if (vn_ismntpt(cs->vp)) {
7467 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
7468 		goto out;
7469 	}
7470 
7471 	/*
7472 	 * access must READ, WRITE, or BOTH.  No access is invalid.
7473 	 * deny can be READ, WRITE, BOTH, or NONE.
7474 	 * bits not defined for access/deny are invalid.
7475 	 */
7476 	if (! (args->share_access & OPEN4_SHARE_ACCESS_BOTH) ||
7477 	    (args->share_access & ~OPEN4_SHARE_ACCESS_BOTH) ||
7478 	    (args->share_deny & ~OPEN4_SHARE_DENY_BOTH)) {
7479 		*cs->statusp = resp->status = NFS4ERR_INVAL;
7480 		goto out;
7481 	}
7482 
7483 
7484 	/*
7485 	 * make sure attrset is zero before response is built.
7486 	 */
7487 	resp->attrset = 0;
7488 
7489 	switch (claim) {
7490 	case CLAIM_NULL:
7491 		rfs4_do_opennull(cs, req, args, oo, resp);
7492 		break;
7493 	case CLAIM_PREVIOUS:
7494 		rfs4_do_openprev(cs, req, args, oo, resp);
7495 		break;
7496 	case CLAIM_DELEGATE_CUR:
7497 		rfs4_do_opendelcur(cs, req, args, oo, resp);
7498 		break;
7499 	case CLAIM_DELEGATE_PREV:
7500 		rfs4_do_opendelprev(cs, req, args, oo, resp);
7501 		break;
7502 	default:
7503 		resp->status = NFS4ERR_INVAL;
7504 		break;
7505 	}
7506 
7507 out:
7508 	rfs4_client_rele(cp);
7509 
7510 	/* Catch sequence id handling here to make it a little easier */
7511 	switch (resp->status) {
7512 	case NFS4ERR_BADXDR:
7513 	case NFS4ERR_BAD_SEQID:
7514 	case NFS4ERR_BAD_STATEID:
7515 	case NFS4ERR_NOFILEHANDLE:
7516 	case NFS4ERR_RESOURCE:
7517 	case NFS4ERR_STALE_CLIENTID:
7518 	case NFS4ERR_STALE_STATEID:
7519 		/*
7520 		 * The protocol states that if any of these errors are
7521 		 * being returned, the sequence id should not be
7522 		 * incremented.  Any other return requires an
7523 		 * increment.
7524 		 */
7525 		break;
7526 	default:
7527 		/* Always update the lease in this case */
7528 		rfs4_update_lease(oo->ro_client);
7529 
7530 		/* Regular response - copy the result */
7531 		if (!replay)
7532 			rfs4_update_open_resp(oo, resop, &cs->fh);
7533 
7534 		/*
7535 		 * REPLAY case: Only if the previous response was OK
7536 		 * do we copy the filehandle.  If not OK, no
7537 		 * filehandle to copy.
7538 		 */
7539 		if (replay == TRUE &&
7540 		    resp->status == NFS4_OK &&
7541 		    oo->ro_reply_fh.nfs_fh4_val) {
7542 			/*
7543 			 * If this is a replay, we must restore the
7544 			 * current filehandle/vp to that of what was
7545 			 * returned originally.  Try our best to do
7546 			 * it.
7547 			 */
7548 			nfs_fh4_fmt_t *fh_fmtp =
7549 			    (nfs_fh4_fmt_t *)oo->ro_reply_fh.nfs_fh4_val;
7550 
7551 			if (cs->exi != NULL)
7552 				exi_rele(cs->exi);
7553 			cs->exi = checkexport(&fh_fmtp->fh4_fsid,
7554 			    (fid_t *)&fh_fmtp->fh4_xlen, NULL);
7555 
7556 			if (cs->exi == NULL) {
7557 				resp->status = NFS4ERR_STALE;
7558 				goto finish;
7559 			}
7560 
7561 			VN_RELE(cs->vp);
7562 
7563 			cs->vp = nfs4_fhtovp(&oo->ro_reply_fh, cs->exi,
7564 			    &resp->status);
7565 
7566 			if (cs->vp == NULL)
7567 				goto finish;
7568 
7569 			nfs_fh4_copy(&oo->ro_reply_fh, &cs->fh);
7570 		}
7571 
7572 		/*
7573 		 * If this was a replay, no need to update the
7574 		 * sequence id. If the open_owner was not created on
7575 		 * this pass, then update.  The first use of an
7576 		 * open_owner will not bump the sequence id.
7577 		 */
7578 		if (replay == FALSE && !create)
7579 			rfs4_update_open_sequence(oo);
7580 		/*
7581 		 * If the client is receiving an error and the
7582 		 * open_owner needs to be confirmed, there is no way
7583 		 * to notify the client of this fact ignoring the fact
7584 		 * that the server has no method of returning a
7585 		 * stateid to confirm.  Therefore, the server needs to
7586 		 * mark this open_owner in a way as to avoid the
7587 		 * sequence id checking the next time the client uses
7588 		 * this open_owner.
7589 		 */
7590 		if (resp->status != NFS4_OK && oo->ro_need_confirm)
7591 			oo->ro_postpone_confirm = TRUE;
7592 		/*
7593 		 * If OK response then clear the postpone flag and
7594 		 * reset the sequence id to keep in sync with the
7595 		 * client.
7596 		 */
7597 		if (resp->status == NFS4_OK && oo->ro_postpone_confirm) {
7598 			oo->ro_postpone_confirm = FALSE;
7599 			oo->ro_open_seqid = args->seqid;
7600 		}
7601 		break;
7602 	}
7603 
7604 finish:
7605 	*cs->statusp = resp->status;
7606 
7607 	rfs4_sw_exit(&oo->ro_sw);
7608 	rfs4_openowner_rele(oo);
7609 
7610 end:
7611 	DTRACE_NFSV4_2(op__open__done, struct compound_state *, cs,
7612 	    OPEN4res *, resp);
7613 }
7614 
7615 /*ARGSUSED*/
7616 void
7617 rfs4_op_open_confirm(nfs_argop4 *argop, nfs_resop4 *resop,
7618     struct svc_req *req, struct compound_state *cs)
7619 {
7620 	OPEN_CONFIRM4args *args = &argop->nfs_argop4_u.opopen_confirm;
7621 	OPEN_CONFIRM4res *resp = &resop->nfs_resop4_u.opopen_confirm;
7622 	rfs4_state_t *sp;
7623 	nfsstat4 status;
7624 
7625 	DTRACE_NFSV4_2(op__open__confirm__start, struct compound_state *, cs,
7626 	    OPEN_CONFIRM4args *, args);
7627 
7628 	if (cs->vp == NULL) {
7629 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
7630 		goto out;
7631 	}
7632 
7633 	if (cs->vp->v_type != VREG) {
7634 		*cs->statusp = resp->status =
7635 		    cs->vp->v_type == VDIR ? NFS4ERR_ISDIR : NFS4ERR_INVAL;
7636 		return;
7637 	}
7638 
7639 	status = rfs4_get_state(&args->open_stateid, &sp, RFS4_DBS_VALID);
7640 	if (status != NFS4_OK) {
7641 		*cs->statusp = resp->status = status;
7642 		goto out;
7643 	}
7644 
7645 	/* Ensure specified filehandle matches */
7646 	if (cs->vp != sp->rs_finfo->rf_vp) {
7647 		rfs4_state_rele(sp);
7648 		*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
7649 		goto out;
7650 	}
7651 
7652 	/* hold off other access to open_owner while we tinker */
7653 	rfs4_sw_enter(&sp->rs_owner->ro_sw);
7654 
7655 	switch (rfs4_check_stateid_seqid(sp, &args->open_stateid)) {
7656 	case NFS4_CHECK_STATEID_OKAY:
7657 		if (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
7658 		    resop) != 0) {
7659 			*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
7660 			break;
7661 		}
7662 		/*
7663 		 * If it is the appropriate stateid and determined to
7664 		 * be "OKAY" then this means that the stateid does not
7665 		 * need to be confirmed and the client is in error for
7666 		 * sending an OPEN_CONFIRM.
7667 		 */
7668 		*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
7669 		break;
7670 	case NFS4_CHECK_STATEID_OLD:
7671 		*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
7672 		break;
7673 	case NFS4_CHECK_STATEID_BAD:
7674 		*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
7675 		break;
7676 	case NFS4_CHECK_STATEID_EXPIRED:
7677 		*cs->statusp = resp->status = NFS4ERR_EXPIRED;
7678 		break;
7679 	case NFS4_CHECK_STATEID_CLOSED:
7680 		*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
7681 		break;
7682 	case NFS4_CHECK_STATEID_REPLAY:
7683 		switch (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
7684 		    resop)) {
7685 		case NFS4_CHKSEQ_OKAY:
7686 			/*
7687 			 * This is replayed stateid; if seqid matches
7688 			 * next expected, then client is using wrong seqid.
7689 			 */
7690 			/* fall through */
7691 		case NFS4_CHKSEQ_BAD:
7692 			*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
7693 			break;
7694 		case NFS4_CHKSEQ_REPLAY:
7695 			/*
7696 			 * Note this case is the duplicate case so
7697 			 * resp->status is already set.
7698 			 */
7699 			*cs->statusp = resp->status;
7700 			rfs4_update_lease(sp->rs_owner->ro_client);
7701 			break;
7702 		}
7703 		break;
7704 	case NFS4_CHECK_STATEID_UNCONFIRMED:
7705 		if (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
7706 		    resop) != NFS4_CHKSEQ_OKAY) {
7707 			*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
7708 			break;
7709 		}
7710 		*cs->statusp = resp->status = NFS4_OK;
7711 
7712 		next_stateid(&sp->rs_stateid);
7713 		resp->open_stateid = sp->rs_stateid.stateid;
7714 		sp->rs_owner->ro_need_confirm = FALSE;
7715 		rfs4_update_lease(sp->rs_owner->ro_client);
7716 		rfs4_update_open_sequence(sp->rs_owner);
7717 		rfs4_update_open_resp(sp->rs_owner, resop, NULL);
7718 		break;
7719 	default:
7720 		ASSERT(FALSE);
7721 		*cs->statusp = resp->status = NFS4ERR_SERVERFAULT;
7722 		break;
7723 	}
7724 	rfs4_sw_exit(&sp->rs_owner->ro_sw);
7725 	rfs4_state_rele(sp);
7726 
7727 out:
7728 	DTRACE_NFSV4_2(op__open__confirm__done, struct compound_state *, cs,
7729 	    OPEN_CONFIRM4res *, resp);
7730 }
7731 
7732 /*ARGSUSED*/
7733 void
7734 rfs4_op_open_downgrade(nfs_argop4 *argop, nfs_resop4 *resop,
7735     struct svc_req *req, struct compound_state *cs)
7736 {
7737 	OPEN_DOWNGRADE4args *args = &argop->nfs_argop4_u.opopen_downgrade;
7738 	OPEN_DOWNGRADE4res *resp = &resop->nfs_resop4_u.opopen_downgrade;
7739 	uint32_t access = args->share_access;
7740 	uint32_t deny = args->share_deny;
7741 	nfsstat4 status;
7742 	rfs4_state_t *sp;
7743 	rfs4_file_t *fp;
7744 	int fflags = 0;
7745 
7746 	DTRACE_NFSV4_2(op__open__downgrade__start, struct compound_state *, cs,
7747 	    OPEN_DOWNGRADE4args *, args);
7748 
7749 	if (cs->vp == NULL) {
7750 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
7751 		goto out;
7752 	}
7753 
7754 	if (cs->vp->v_type != VREG) {
7755 		*cs->statusp = resp->status = NFS4ERR_INVAL;
7756 		return;
7757 	}
7758 
7759 	status = rfs4_get_state(&args->open_stateid, &sp, RFS4_DBS_VALID);
7760 	if (status != NFS4_OK) {
7761 		*cs->statusp = resp->status = status;
7762 		goto out;
7763 	}
7764 
7765 	/* Ensure specified filehandle matches */
7766 	if (cs->vp != sp->rs_finfo->rf_vp) {
7767 		rfs4_state_rele(sp);
7768 		*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
7769 		goto out;
7770 	}
7771 
7772 	/* hold off other access to open_owner while we tinker */
7773 	rfs4_sw_enter(&sp->rs_owner->ro_sw);
7774 
7775 	switch (rfs4_check_stateid_seqid(sp, &args->open_stateid)) {
7776 	case NFS4_CHECK_STATEID_OKAY:
7777 		if (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
7778 		    resop) != NFS4_CHKSEQ_OKAY) {
7779 			*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
7780 			goto end;
7781 		}
7782 		break;
7783 	case NFS4_CHECK_STATEID_OLD:
7784 		*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
7785 		goto end;
7786 	case NFS4_CHECK_STATEID_BAD:
7787 		*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
7788 		goto end;
7789 	case NFS4_CHECK_STATEID_EXPIRED:
7790 		*cs->statusp = resp->status = NFS4ERR_EXPIRED;
7791 		goto end;
7792 	case NFS4_CHECK_STATEID_CLOSED:
7793 		*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
7794 		goto end;
7795 	case NFS4_CHECK_STATEID_UNCONFIRMED:
7796 		*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
7797 		goto end;
7798 	case NFS4_CHECK_STATEID_REPLAY:
7799 		/* Check the sequence id for the open owner */
7800 		switch (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
7801 		    resop)) {
7802 		case NFS4_CHKSEQ_OKAY:
7803 			/*
7804 			 * This is replayed stateid; if seqid matches
7805 			 * next expected, then client is using wrong seqid.
7806 			 */
7807 			/* fall through */
7808 		case NFS4_CHKSEQ_BAD:
7809 			*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
7810 			goto end;
7811 		case NFS4_CHKSEQ_REPLAY:
7812 			/*
7813 			 * Note this case is the duplicate case so
7814 			 * resp->status is already set.
7815 			 */
7816 			*cs->statusp = resp->status;
7817 			rfs4_update_lease(sp->rs_owner->ro_client);
7818 			goto end;
7819 		}
7820 		break;
7821 	default:
7822 		ASSERT(FALSE);
7823 		break;
7824 	}
7825 
7826 	rfs4_dbe_lock(sp->rs_dbe);
7827 	/*
7828 	 * Check that the new access modes and deny modes are valid.
7829 	 * Check that no invalid bits are set.
7830 	 */
7831 	if ((access & ~(OPEN4_SHARE_ACCESS_READ | OPEN4_SHARE_ACCESS_WRITE)) ||
7832 	    (deny & ~(OPEN4_SHARE_DENY_READ | OPEN4_SHARE_DENY_WRITE))) {
7833 		*cs->statusp = resp->status = NFS4ERR_INVAL;
7834 		rfs4_update_open_sequence(sp->rs_owner);
7835 		rfs4_dbe_unlock(sp->rs_dbe);
7836 		goto end;
7837 	}
7838 
7839 	/*
7840 	 * The new modes must be a subset of the current modes and
7841 	 * the access must specify at least one mode. To test that
7842 	 * the new mode is a subset of the current modes we bitwise
7843 	 * AND them together and check that the result equals the new
7844 	 * mode. For example:
7845 	 * New mode, access == R and current mode, sp->rs_open_access  == RW
7846 	 * access & sp->rs_open_access == R == access, so the new access mode
7847 	 * is valid. Consider access == RW, sp->rs_open_access = R
7848 	 * access & sp->rs_open_access == R != access, so the new access mode
7849 	 * is invalid.
7850 	 */
7851 	if ((access & sp->rs_open_access) != access ||
7852 	    (deny & sp->rs_open_deny) != deny ||
7853 	    (access &
7854 	    (OPEN4_SHARE_ACCESS_READ | OPEN4_SHARE_ACCESS_WRITE)) == 0) {
7855 		*cs->statusp = resp->status = NFS4ERR_INVAL;
7856 		rfs4_update_open_sequence(sp->rs_owner);
7857 		rfs4_dbe_unlock(sp->rs_dbe);
7858 		goto end;
7859 	}
7860 
7861 	/*
7862 	 * Release any share locks associated with this stateID.
7863 	 * Strictly speaking, this violates the spec because the
7864 	 * spec effectively requires that open downgrade be atomic.
7865 	 * At present, fs_shrlock does not have this capability.
7866 	 */
7867 	(void) rfs4_unshare(sp);
7868 
7869 	status = rfs4_share(sp, access, deny);
7870 	if (status != NFS4_OK) {
7871 		*cs->statusp = resp->status = NFS4ERR_SERVERFAULT;
7872 		rfs4_update_open_sequence(sp->rs_owner);
7873 		rfs4_dbe_unlock(sp->rs_dbe);
7874 		goto end;
7875 	}
7876 
7877 	fp = sp->rs_finfo;
7878 	rfs4_dbe_lock(fp->rf_dbe);
7879 
7880 	/*
7881 	 * If the current mode has deny read and the new mode
7882 	 * does not, decrement the number of deny read mode bits
7883 	 * and if it goes to zero turn off the deny read bit
7884 	 * on the file.
7885 	 */
7886 	if ((sp->rs_open_deny & OPEN4_SHARE_DENY_READ) &&
7887 	    (deny & OPEN4_SHARE_DENY_READ) == 0) {
7888 		fp->rf_deny_read--;
7889 		if (fp->rf_deny_read == 0)
7890 			fp->rf_share_deny &= ~OPEN4_SHARE_DENY_READ;
7891 	}
7892 
7893 	/*
7894 	 * If the current mode has deny write and the new mode
7895 	 * does not, decrement the number of deny write mode bits
7896 	 * and if it goes to zero turn off the deny write bit
7897 	 * on the file.
7898 	 */
7899 	if ((sp->rs_open_deny & OPEN4_SHARE_DENY_WRITE) &&
7900 	    (deny & OPEN4_SHARE_DENY_WRITE) == 0) {
7901 		fp->rf_deny_write--;
7902 		if (fp->rf_deny_write == 0)
7903 			fp->rf_share_deny &= ~OPEN4_SHARE_DENY_WRITE;
7904 	}
7905 
7906 	/*
7907 	 * If the current mode has access read and the new mode
7908 	 * does not, decrement the number of access read mode bits
7909 	 * and if it goes to zero turn off the access read bit
7910 	 * on the file.  set fflags to FREAD for the call to
7911 	 * vn_open_downgrade().
7912 	 */
7913 	if ((sp->rs_open_access & OPEN4_SHARE_ACCESS_READ) &&
7914 	    (access & OPEN4_SHARE_ACCESS_READ) == 0) {
7915 		fp->rf_access_read--;
7916 		if (fp->rf_access_read == 0)
7917 			fp->rf_share_access &= ~OPEN4_SHARE_ACCESS_READ;
7918 		fflags |= FREAD;
7919 	}
7920 
7921 	/*
7922 	 * If the current mode has access write and the new mode
7923 	 * does not, decrement the number of access write mode bits
7924 	 * and if it goes to zero turn off the access write bit
7925 	 * on the file.  set fflags to FWRITE for the call to
7926 	 * vn_open_downgrade().
7927 	 */
7928 	if ((sp->rs_open_access & OPEN4_SHARE_ACCESS_WRITE) &&
7929 	    (access & OPEN4_SHARE_ACCESS_WRITE) == 0) {
7930 		fp->rf_access_write--;
7931 		if (fp->rf_access_write == 0)
7932 			fp->rf_share_deny &= ~OPEN4_SHARE_ACCESS_WRITE;
7933 		fflags |= FWRITE;
7934 	}
7935 
7936 	/* Check that the file is still accessible */
7937 	ASSERT(fp->rf_share_access);
7938 
7939 	rfs4_dbe_unlock(fp->rf_dbe);
7940 
7941 	/* now set the new open access and deny modes */
7942 	sp->rs_open_access = access;
7943 	sp->rs_open_deny = deny;
7944 
7945 	/*
7946 	 * we successfully downgraded the share lock, now we need to downgrade
7947 	 * the open. it is possible that the downgrade was only for a deny
7948 	 * mode and we have nothing else to do.
7949 	 */
7950 	if ((fflags & (FREAD|FWRITE)) != 0)
7951 		vn_open_downgrade(cs->vp, fflags);
7952 
7953 	/* Update the stateid */
7954 	next_stateid(&sp->rs_stateid);
7955 	resp->open_stateid = sp->rs_stateid.stateid;
7956 
7957 	rfs4_dbe_unlock(sp->rs_dbe);
7958 
7959 	*cs->statusp = resp->status = NFS4_OK;
7960 	/* Update the lease */
7961 	rfs4_update_lease(sp->rs_owner->ro_client);
7962 	/* And the sequence */
7963 	rfs4_update_open_sequence(sp->rs_owner);
7964 	rfs4_update_open_resp(sp->rs_owner, resop, NULL);
7965 
7966 end:
7967 	rfs4_sw_exit(&sp->rs_owner->ro_sw);
7968 	rfs4_state_rele(sp);
7969 out:
7970 	DTRACE_NFSV4_2(op__open__downgrade__done, struct compound_state *, cs,
7971 	    OPEN_DOWNGRADE4res *, resp);
7972 }
7973 
7974 static void *
7975 memstr(const void *s1, const char *s2, size_t n)
7976 {
7977 	size_t l = strlen(s2);
7978 	char *p = (char *)s1;
7979 
7980 	while (n >= l) {
7981 		if (bcmp(p, s2, l) == 0)
7982 			return (p);
7983 		p++;
7984 		n--;
7985 	}
7986 
7987 	return (NULL);
7988 }
7989 
7990 /*
7991  * The logic behind this function is detailed in the NFSv4 RFC in the
7992  * SETCLIENTID operation description under IMPLEMENTATION.  Refer to
7993  * that section for explicit guidance to server behavior for
7994  * SETCLIENTID.
7995  */
7996 void
7997 rfs4_op_setclientid(nfs_argop4 *argop, nfs_resop4 *resop,
7998     struct svc_req *req, struct compound_state *cs)
7999 {
8000 	SETCLIENTID4args *args = &argop->nfs_argop4_u.opsetclientid;
8001 	SETCLIENTID4res *res = &resop->nfs_resop4_u.opsetclientid;
8002 	rfs4_client_t *cp, *newcp, *cp_confirmed, *cp_unconfirmed;
8003 	rfs4_clntip_t *ci;
8004 	bool_t create;
8005 	char *addr, *netid;
8006 	int len;
8007 
8008 	DTRACE_NFSV4_2(op__setclientid__start, struct compound_state *, cs,
8009 	    SETCLIENTID4args *, args);
8010 retry:
8011 	newcp = cp_confirmed = cp_unconfirmed = NULL;
8012 
8013 	/*
8014 	 * Save the caller's IP address
8015 	 */
8016 	args->client.cl_addr =
8017 	    (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
8018 
8019 	/*
8020 	 * Record if it is a Solaris client that cannot handle referrals.
8021 	 */
8022 	if (memstr(args->client.id_val, "Solaris", args->client.id_len) &&
8023 	    !memstr(args->client.id_val, "+referrals", args->client.id_len)) {
8024 		/* Add a "yes, it's downrev" record */
8025 		create = TRUE;
8026 		ci = rfs4_find_clntip(args->client.cl_addr, &create);
8027 		ASSERT(ci != NULL);
8028 		rfs4_dbe_rele(ci->ri_dbe);
8029 	} else {
8030 		/* Remove any previous record */
8031 		rfs4_invalidate_clntip(args->client.cl_addr);
8032 	}
8033 
8034 	/*
8035 	 * In search of an EXISTING client matching the incoming
8036 	 * request to establish a new client identifier at the server
8037 	 */
8038 	create = TRUE;
8039 	cp = rfs4_findclient(&args->client, &create, NULL);
8040 
8041 	/* Should never happen */
8042 	ASSERT(cp != NULL);
8043 
8044 	if (cp == NULL) {
8045 		*cs->statusp = res->status = NFS4ERR_SERVERFAULT;
8046 		goto out;
8047 	}
8048 
8049 	/*
8050 	 * Easiest case. Client identifier is newly created and is
8051 	 * unconfirmed.  Also note that for this case, no other
8052 	 * entries exist for the client identifier.  Nothing else to
8053 	 * check.  Just setup the response and respond.
8054 	 */
8055 	if (create) {
8056 		*cs->statusp = res->status = NFS4_OK;
8057 		res->SETCLIENTID4res_u.resok4.clientid = cp->rc_clientid;
8058 		res->SETCLIENTID4res_u.resok4.setclientid_confirm =
8059 		    cp->rc_confirm_verf;
8060 		/* Setup callback information; CB_NULL confirmation later */
8061 		rfs4_client_setcb(cp, &args->callback, args->callback_ident);
8062 
8063 		rfs4_client_rele(cp);
8064 		goto out;
8065 	}
8066 
8067 	/*
8068 	 * An existing, confirmed client may exist but it may not have
8069 	 * been active for at least one lease period.  If so, then
8070 	 * "close" the client and create a new client identifier
8071 	 */
8072 	if (rfs4_lease_expired(cp)) {
8073 		rfs4_client_close(cp);
8074 		goto retry;
8075 	}
8076 
8077 	if (cp->rc_need_confirm == TRUE)
8078 		cp_unconfirmed = cp;
8079 	else
8080 		cp_confirmed = cp;
8081 
8082 	cp = NULL;
8083 
8084 	/*
8085 	 * We have a confirmed client, now check for an
8086 	 * unconfimred entry
8087 	 */
8088 	if (cp_confirmed) {
8089 		/* If creds don't match then client identifier is inuse */
8090 		if (!creds_ok(cp_confirmed->rc_cr_set, req, cs)) {
8091 			rfs4_cbinfo_t *cbp;
8092 			/*
8093 			 * Some one else has established this client
8094 			 * id. Try and say * who they are. We will use
8095 			 * the call back address supplied by * the
8096 			 * first client.
8097 			 */
8098 			*cs->statusp = res->status = NFS4ERR_CLID_INUSE;
8099 
8100 			addr = netid = NULL;
8101 
8102 			cbp = &cp_confirmed->rc_cbinfo;
8103 			if (cbp->cb_callback.cb_location.r_addr &&
8104 			    cbp->cb_callback.cb_location.r_netid) {
8105 				cb_client4 *cbcp = &cbp->cb_callback;
8106 
8107 				len = strlen(cbcp->cb_location.r_addr)+1;
8108 				addr = kmem_alloc(len, KM_SLEEP);
8109 				bcopy(cbcp->cb_location.r_addr, addr, len);
8110 				len = strlen(cbcp->cb_location.r_netid)+1;
8111 				netid = kmem_alloc(len, KM_SLEEP);
8112 				bcopy(cbcp->cb_location.r_netid, netid, len);
8113 			}
8114 
8115 			res->SETCLIENTID4res_u.client_using.r_addr = addr;
8116 			res->SETCLIENTID4res_u.client_using.r_netid = netid;
8117 
8118 			rfs4_client_rele(cp_confirmed);
8119 		}
8120 
8121 		/*
8122 		 * Confirmed, creds match, and verifier matches; must
8123 		 * be an update of the callback info
8124 		 */
8125 		if (cp_confirmed->rc_nfs_client.verifier ==
8126 		    args->client.verifier) {
8127 			/* Setup callback information */
8128 			rfs4_client_setcb(cp_confirmed, &args->callback,
8129 			    args->callback_ident);
8130 
8131 			/* everything okay -- move ahead */
8132 			*cs->statusp = res->status = NFS4_OK;
8133 			res->SETCLIENTID4res_u.resok4.clientid =
8134 			    cp_confirmed->rc_clientid;
8135 
8136 			/* update the confirm_verifier and return it */
8137 			rfs4_client_scv_next(cp_confirmed);
8138 			res->SETCLIENTID4res_u.resok4.setclientid_confirm =
8139 			    cp_confirmed->rc_confirm_verf;
8140 
8141 			rfs4_client_rele(cp_confirmed);
8142 			goto out;
8143 		}
8144 
8145 		/*
8146 		 * Creds match but the verifier doesn't.  Must search
8147 		 * for an unconfirmed client that would be replaced by
8148 		 * this request.
8149 		 */
8150 		create = FALSE;
8151 		cp_unconfirmed = rfs4_findclient(&args->client, &create,
8152 		    cp_confirmed);
8153 	}
8154 
8155 	/*
8156 	 * At this point, we have taken care of the brand new client
8157 	 * struct, INUSE case, update of an existing, and confirmed
8158 	 * client struct.
8159 	 */
8160 
8161 	/*
8162 	 * check to see if things have changed while we originally
8163 	 * picked up the client struct.  If they have, then return and
8164 	 * retry the processing of this SETCLIENTID request.
8165 	 */
8166 	if (cp_unconfirmed) {
8167 		rfs4_dbe_lock(cp_unconfirmed->rc_dbe);
8168 		if (!cp_unconfirmed->rc_need_confirm) {
8169 			rfs4_dbe_unlock(cp_unconfirmed->rc_dbe);
8170 			rfs4_client_rele(cp_unconfirmed);
8171 			if (cp_confirmed)
8172 				rfs4_client_rele(cp_confirmed);
8173 			goto retry;
8174 		}
8175 		/* do away with the old unconfirmed one */
8176 		rfs4_dbe_invalidate(cp_unconfirmed->rc_dbe);
8177 		rfs4_dbe_unlock(cp_unconfirmed->rc_dbe);
8178 		rfs4_client_rele(cp_unconfirmed);
8179 		cp_unconfirmed = NULL;
8180 	}
8181 
8182 	/*
8183 	 * This search will temporarily hide the confirmed client
8184 	 * struct while a new client struct is created as the
8185 	 * unconfirmed one.
8186 	 */
8187 	create = TRUE;
8188 	newcp = rfs4_findclient(&args->client, &create, cp_confirmed);
8189 
8190 	ASSERT(newcp != NULL);
8191 
8192 	if (newcp == NULL) {
8193 		*cs->statusp = res->status = NFS4ERR_SERVERFAULT;
8194 		rfs4_client_rele(cp_confirmed);
8195 		goto out;
8196 	}
8197 
8198 	/*
8199 	 * If one was not created, then a similar request must be in
8200 	 * process so release and start over with this one
8201 	 */
8202 	if (create != TRUE) {
8203 		rfs4_client_rele(newcp);
8204 		if (cp_confirmed)
8205 			rfs4_client_rele(cp_confirmed);
8206 		goto retry;
8207 	}
8208 
8209 	*cs->statusp = res->status = NFS4_OK;
8210 	res->SETCLIENTID4res_u.resok4.clientid = newcp->rc_clientid;
8211 	res->SETCLIENTID4res_u.resok4.setclientid_confirm =
8212 	    newcp->rc_confirm_verf;
8213 	/* Setup callback information; CB_NULL confirmation later */
8214 	rfs4_client_setcb(newcp, &args->callback, args->callback_ident);
8215 
8216 	newcp->rc_cp_confirmed = cp_confirmed;
8217 
8218 	rfs4_client_rele(newcp);
8219 
8220 out:
8221 	DTRACE_NFSV4_2(op__setclientid__done, struct compound_state *, cs,
8222 	    SETCLIENTID4res *, res);
8223 }
8224 
8225 /*ARGSUSED*/
8226 void
8227 rfs4_op_setclientid_confirm(nfs_argop4 *argop, nfs_resop4 *resop,
8228     struct svc_req *req, struct compound_state *cs)
8229 {
8230 	SETCLIENTID_CONFIRM4args *args =
8231 	    &argop->nfs_argop4_u.opsetclientid_confirm;
8232 	SETCLIENTID_CONFIRM4res *res =
8233 	    &resop->nfs_resop4_u.opsetclientid_confirm;
8234 	rfs4_client_t *cp, *cptoclose = NULL;
8235 
8236 	DTRACE_NFSV4_2(op__setclientid__confirm__start,
8237 	    struct compound_state *, cs,
8238 	    SETCLIENTID_CONFIRM4args *, args);
8239 
8240 	*cs->statusp = res->status = NFS4_OK;
8241 
8242 	cp = rfs4_findclient_by_id(args->clientid, TRUE);
8243 
8244 	if (cp == NULL) {
8245 		*cs->statusp = res->status =
8246 		    rfs4_check_clientid(&args->clientid, 1);
8247 		goto out;
8248 	}
8249 
8250 	if (!creds_ok(cp, req, cs)) {
8251 		*cs->statusp = res->status = NFS4ERR_CLID_INUSE;
8252 		rfs4_client_rele(cp);
8253 		goto out;
8254 	}
8255 
8256 	/* If the verifier doesn't match, the record doesn't match */
8257 	if (cp->rc_confirm_verf != args->setclientid_confirm) {
8258 		*cs->statusp = res->status = NFS4ERR_STALE_CLIENTID;
8259 		rfs4_client_rele(cp);
8260 		goto out;
8261 	}
8262 
8263 	rfs4_dbe_lock(cp->rc_dbe);
8264 	cp->rc_need_confirm = FALSE;
8265 	if (cp->rc_cp_confirmed) {
8266 		cptoclose = cp->rc_cp_confirmed;
8267 		cptoclose->rc_ss_remove = 1;
8268 		cp->rc_cp_confirmed = NULL;
8269 	}
8270 
8271 	/*
8272 	 * Update the client's associated server instance, if it's changed
8273 	 * since the client was created.
8274 	 */
8275 	if (rfs4_servinst(cp) != rfs4_cur_servinst)
8276 		rfs4_servinst_assign(cp, rfs4_cur_servinst);
8277 
8278 	/*
8279 	 * Record clientid in stable storage.
8280 	 * Must be done after server instance has been assigned.
8281 	 */
8282 	rfs4_ss_clid(cp);
8283 
8284 	rfs4_dbe_unlock(cp->rc_dbe);
8285 
8286 	if (cptoclose)
8287 		/* don't need to rele, client_close does it */
8288 		rfs4_client_close(cptoclose);
8289 
8290 	/* If needed, initiate CB_NULL call for callback path */
8291 	rfs4_deleg_cb_check(cp);
8292 	rfs4_update_lease(cp);
8293 
8294 	/*
8295 	 * Check to see if client can perform reclaims
8296 	 */
8297 	rfs4_ss_chkclid(cp);
8298 
8299 	rfs4_client_rele(cp);
8300 
8301 out:
8302 	DTRACE_NFSV4_2(op__setclientid__confirm__done,
8303 	    struct compound_state *, cs,
8304 	    SETCLIENTID_CONFIRM4 *, res);
8305 }
8306 
8307 
8308 /*ARGSUSED*/
8309 void
8310 rfs4_op_close(nfs_argop4 *argop, nfs_resop4 *resop,
8311     struct svc_req *req, struct compound_state *cs)
8312 {
8313 	CLOSE4args *args = &argop->nfs_argop4_u.opclose;
8314 	CLOSE4res *resp = &resop->nfs_resop4_u.opclose;
8315 	rfs4_state_t *sp;
8316 	nfsstat4 status;
8317 
8318 	DTRACE_NFSV4_2(op__close__start, struct compound_state *, cs,
8319 	    CLOSE4args *, args);
8320 
8321 	if (cs->vp == NULL) {
8322 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
8323 		goto out;
8324 	}
8325 
8326 	status = rfs4_get_state(&args->open_stateid, &sp, RFS4_DBS_INVALID);
8327 	if (status != NFS4_OK) {
8328 		*cs->statusp = resp->status = status;
8329 		goto out;
8330 	}
8331 
8332 	/* Ensure specified filehandle matches */
8333 	if (cs->vp != sp->rs_finfo->rf_vp) {
8334 		rfs4_state_rele(sp);
8335 		*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
8336 		goto out;
8337 	}
8338 
8339 	/* hold off other access to open_owner while we tinker */
8340 	rfs4_sw_enter(&sp->rs_owner->ro_sw);
8341 
8342 	switch (rfs4_check_stateid_seqid(sp, &args->open_stateid)) {
8343 	case NFS4_CHECK_STATEID_OKAY:
8344 		if (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
8345 		    resop) != NFS4_CHKSEQ_OKAY) {
8346 			*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
8347 			goto end;
8348 		}
8349 		break;
8350 	case NFS4_CHECK_STATEID_OLD:
8351 		*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
8352 		goto end;
8353 	case NFS4_CHECK_STATEID_BAD:
8354 		*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
8355 		goto end;
8356 	case NFS4_CHECK_STATEID_EXPIRED:
8357 		*cs->statusp = resp->status = NFS4ERR_EXPIRED;
8358 		goto end;
8359 	case NFS4_CHECK_STATEID_CLOSED:
8360 		*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
8361 		goto end;
8362 	case NFS4_CHECK_STATEID_UNCONFIRMED:
8363 		*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
8364 		goto end;
8365 	case NFS4_CHECK_STATEID_REPLAY:
8366 		/* Check the sequence id for the open owner */
8367 		switch (rfs4_check_open_seqid(args->seqid, sp->rs_owner,
8368 		    resop)) {
8369 		case NFS4_CHKSEQ_OKAY:
8370 			/*
8371 			 * This is replayed stateid; if seqid matches
8372 			 * next expected, then client is using wrong seqid.
8373 			 */
8374 			/* FALL THROUGH */
8375 		case NFS4_CHKSEQ_BAD:
8376 			*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
8377 			goto end;
8378 		case NFS4_CHKSEQ_REPLAY:
8379 			/*
8380 			 * Note this case is the duplicate case so
8381 			 * resp->status is already set.
8382 			 */
8383 			*cs->statusp = resp->status;
8384 			rfs4_update_lease(sp->rs_owner->ro_client);
8385 			goto end;
8386 		}
8387 		break;
8388 	default:
8389 		ASSERT(FALSE);
8390 		break;
8391 	}
8392 
8393 	rfs4_dbe_lock(sp->rs_dbe);
8394 
8395 	/* Update the stateid. */
8396 	next_stateid(&sp->rs_stateid);
8397 	resp->open_stateid = sp->rs_stateid.stateid;
8398 
8399 	rfs4_dbe_unlock(sp->rs_dbe);
8400 
8401 	rfs4_update_lease(sp->rs_owner->ro_client);
8402 	rfs4_update_open_sequence(sp->rs_owner);
8403 	rfs4_update_open_resp(sp->rs_owner, resop, NULL);
8404 
8405 	rfs4_state_close(sp, FALSE, FALSE, cs->cr);
8406 
8407 	*cs->statusp = resp->status = status;
8408 
8409 end:
8410 	rfs4_sw_exit(&sp->rs_owner->ro_sw);
8411 	rfs4_state_rele(sp);
8412 out:
8413 	DTRACE_NFSV4_2(op__close__done, struct compound_state *, cs,
8414 	    CLOSE4res *, resp);
8415 }
8416 
8417 /*
8418  * Manage the counts on the file struct and close all file locks
8419  */
8420 /*ARGSUSED*/
8421 void
8422 rfs4_release_share_lock_state(rfs4_state_t *sp, cred_t *cr,
8423     bool_t close_of_client)
8424 {
8425 	rfs4_file_t *fp = sp->rs_finfo;
8426 	rfs4_lo_state_t *lsp;
8427 	int fflags = 0;
8428 
8429 	/*
8430 	 * If this call is part of the larger closing down of client
8431 	 * state then it is just easier to release all locks
8432 	 * associated with this client instead of going through each
8433 	 * individual file and cleaning locks there.
8434 	 */
8435 	if (close_of_client) {
8436 		if (sp->rs_owner->ro_client->rc_unlksys_completed == FALSE &&
8437 		    !list_is_empty(&sp->rs_lostatelist) &&
8438 		    sp->rs_owner->ro_client->rc_sysidt != LM_NOSYSID) {
8439 			/* Is the PxFS kernel module loaded? */
8440 			if (lm_remove_file_locks != NULL) {
8441 				int new_sysid;
8442 
8443 				/* Encode the cluster nodeid in new sysid */
8444 				new_sysid = sp->rs_owner->ro_client->rc_sysidt;
8445 				lm_set_nlmid_flk(&new_sysid);
8446 
8447 				/*
8448 				 * This PxFS routine removes file locks for a
8449 				 * client over all nodes of a cluster.
8450 				 */
8451 				NFS4_DEBUG(rfs4_debug, (CE_NOTE,
8452 				    "lm_remove_file_locks(sysid=0x%x)\n",
8453 				    new_sysid));
8454 				(*lm_remove_file_locks)(new_sysid);
8455 			} else {
8456 				struct flock64 flk;
8457 
8458 				/* Release all locks for this client */
8459 				flk.l_type = F_UNLKSYS;
8460 				flk.l_whence = 0;
8461 				flk.l_start = 0;
8462 				flk.l_len = 0;
8463 				flk.l_sysid =
8464 				    sp->rs_owner->ro_client->rc_sysidt;
8465 				flk.l_pid = 0;
8466 				(void) VOP_FRLOCK(sp->rs_finfo->rf_vp, F_SETLK,
8467 				    &flk, F_REMOTELOCK | FREAD | FWRITE,
8468 				    (u_offset_t)0, NULL, CRED(), NULL);
8469 			}
8470 
8471 			sp->rs_owner->ro_client->rc_unlksys_completed = TRUE;
8472 		}
8473 	}
8474 
8475 	/*
8476 	 * Release all locks on this file by this lock owner or at
8477 	 * least mark the locks as having been released
8478 	 */
8479 	for (lsp = list_head(&sp->rs_lostatelist); lsp != NULL;
8480 	    lsp = list_next(&sp->rs_lostatelist, lsp)) {
8481 		lsp->rls_locks_cleaned = TRUE;
8482 
8483 		/* Was this already taken care of above? */
8484 		if (!close_of_client &&
8485 		    sp->rs_owner->ro_client->rc_sysidt != LM_NOSYSID)
8486 			(void) cleanlocks(sp->rs_finfo->rf_vp,
8487 			    lsp->rls_locker->rl_pid,
8488 			    lsp->rls_locker->rl_client->rc_sysidt);
8489 	}
8490 
8491 	/*
8492 	 * Release any shrlocks associated with this open state ID.
8493 	 * This must be done before the rfs4_state gets marked closed.
8494 	 */
8495 	if (sp->rs_owner->ro_client->rc_sysidt != LM_NOSYSID)
8496 		(void) rfs4_unshare(sp);
8497 
8498 	if (sp->rs_open_access) {
8499 		rfs4_dbe_lock(fp->rf_dbe);
8500 
8501 		/*
8502 		 * Decrement the count for each access and deny bit that this
8503 		 * state has contributed to the file.
8504 		 * If the file counts go to zero
8505 		 * clear the appropriate bit in the appropriate mask.
8506 		 */
8507 		if (sp->rs_open_access & OPEN4_SHARE_ACCESS_READ) {
8508 			fp->rf_access_read--;
8509 			fflags |= FREAD;
8510 			if (fp->rf_access_read == 0)
8511 				fp->rf_share_access &= ~OPEN4_SHARE_ACCESS_READ;
8512 		}
8513 		if (sp->rs_open_access & OPEN4_SHARE_ACCESS_WRITE) {
8514 			fp->rf_access_write--;
8515 			fflags |= FWRITE;
8516 			if (fp->rf_access_write == 0)
8517 				fp->rf_share_access &=
8518 				    ~OPEN4_SHARE_ACCESS_WRITE;
8519 		}
8520 		if (sp->rs_open_deny & OPEN4_SHARE_DENY_READ) {
8521 			fp->rf_deny_read--;
8522 			if (fp->rf_deny_read == 0)
8523 				fp->rf_share_deny &= ~OPEN4_SHARE_DENY_READ;
8524 		}
8525 		if (sp->rs_open_deny & OPEN4_SHARE_DENY_WRITE) {
8526 			fp->rf_deny_write--;
8527 			if (fp->rf_deny_write == 0)
8528 				fp->rf_share_deny &= ~OPEN4_SHARE_DENY_WRITE;
8529 		}
8530 
8531 		(void) VOP_CLOSE(fp->rf_vp, fflags, 1, (offset_t)0, cr, NULL);
8532 
8533 		rfs4_dbe_unlock(fp->rf_dbe);
8534 
8535 		sp->rs_open_access = 0;
8536 		sp->rs_open_deny = 0;
8537 	}
8538 }
8539 
8540 /*
8541  * lock_denied: Fill in a LOCK4deneid structure given an flock64 structure.
8542  */
8543 static nfsstat4
8544 lock_denied(LOCK4denied *dp, struct flock64 *flk)
8545 {
8546 	rfs4_lockowner_t *lo;
8547 	rfs4_client_t *cp;
8548 	uint32_t len;
8549 
8550 	lo = rfs4_findlockowner_by_pid(flk->l_pid);
8551 	if (lo != NULL) {
8552 		cp = lo->rl_client;
8553 		if (rfs4_lease_expired(cp)) {
8554 			rfs4_lockowner_rele(lo);
8555 			rfs4_dbe_hold(cp->rc_dbe);
8556 			rfs4_client_close(cp);
8557 			return (NFS4ERR_EXPIRED);
8558 		}
8559 		dp->owner.clientid = lo->rl_owner.clientid;
8560 		len = lo->rl_owner.owner_len;
8561 		dp->owner.owner_val = kmem_alloc(len, KM_SLEEP);
8562 		bcopy(lo->rl_owner.owner_val, dp->owner.owner_val, len);
8563 		dp->owner.owner_len = len;
8564 		rfs4_lockowner_rele(lo);
8565 		goto finish;
8566 	}
8567 
8568 	/*
8569 	 * Its not a NFS4 lock. We take advantage that the upper 32 bits
8570 	 * of the client id contain the boot time for a NFS4 lock. So we
8571 	 * fabricate and identity by setting clientid to the sysid, and
8572 	 * the lock owner to the pid.
8573 	 */
8574 	dp->owner.clientid = flk->l_sysid;
8575 	len = sizeof (pid_t);
8576 	dp->owner.owner_len = len;
8577 	dp->owner.owner_val = kmem_alloc(len, KM_SLEEP);
8578 	bcopy(&flk->l_pid, dp->owner.owner_val, len);
8579 finish:
8580 	dp->offset = flk->l_start;
8581 	dp->length = flk->l_len;
8582 
8583 	if (flk->l_type == F_RDLCK)
8584 		dp->locktype = READ_LT;
8585 	else if (flk->l_type == F_WRLCK)
8586 		dp->locktype = WRITE_LT;
8587 	else
8588 		return (NFS4ERR_INVAL);	/* no mapping from POSIX ltype to v4 */
8589 
8590 	return (NFS4_OK);
8591 }
8592 
8593 static int
8594 setlock(vnode_t *vp, struct flock64 *flock, int flag, cred_t *cred)
8595 {
8596 	int error;
8597 	struct flock64 flk;
8598 	int i;
8599 	clock_t delaytime;
8600 	int cmd;
8601 
8602 	cmd = nbl_need_check(vp) ? F_SETLK_NBMAND : F_SETLK;
8603 retry:
8604 	delaytime = MSEC_TO_TICK_ROUNDUP(rfs4_lock_delay);
8605 
8606 	for (i = 0; i < rfs4_maxlock_tries; i++) {
8607 		LOCK_PRINT(rfs4_debug, "setlock", cmd, flock);
8608 		error = VOP_FRLOCK(vp, cmd,
8609 		    flock, flag, (u_offset_t)0, NULL, cred, NULL);
8610 
8611 		if (error != EAGAIN && error != EACCES)
8612 			break;
8613 
8614 		if (i < rfs4_maxlock_tries - 1) {
8615 			delay(delaytime);
8616 			delaytime *= 2;
8617 		}
8618 	}
8619 
8620 	if (error == EAGAIN || error == EACCES) {
8621 		/* Get the owner of the lock */
8622 		flk = *flock;
8623 		LOCK_PRINT(rfs4_debug, "setlock", F_GETLK, &flk);
8624 		if (VOP_FRLOCK(vp, F_GETLK, &flk, flag,
8625 		    (u_offset_t)0, NULL, cred, NULL) == 0) {
8626 			if (flk.l_type == F_UNLCK) {
8627 				/* No longer locked, retry */
8628 				goto retry;
8629 			}
8630 			*flock = flk;
8631 			LOCK_PRINT(rfs4_debug, "setlock(blocking lock)",
8632 			    F_GETLK, &flk);
8633 		}
8634 	}
8635 
8636 	return (error);
8637 }
8638 
8639 /*ARGSUSED*/
8640 static nfsstat4
8641 rfs4_do_lock(rfs4_lo_state_t *lsp, nfs_lock_type4 locktype,
8642     offset4 offset, length4 length, cred_t *cred, nfs_resop4 *resop)
8643 {
8644 	nfsstat4 status;
8645 	rfs4_lockowner_t *lo = lsp->rls_locker;
8646 	rfs4_state_t *sp = lsp->rls_state;
8647 	struct flock64 flock;
8648 	int16_t ltype;
8649 	int flag;
8650 	int error;
8651 	sysid_t sysid;
8652 	LOCK4res *lres;
8653 
8654 	if (rfs4_lease_expired(lo->rl_client)) {
8655 		return (NFS4ERR_EXPIRED);
8656 	}
8657 
8658 	if ((status = rfs4_client_sysid(lo->rl_client, &sysid)) != NFS4_OK)
8659 		return (status);
8660 
8661 	/* Check for zero length. To lock to end of file use all ones for V4 */
8662 	if (length == 0)
8663 		return (NFS4ERR_INVAL);
8664 	else if (length == (length4)(~0))
8665 		length = 0;		/* Posix to end of file  */
8666 
8667 retry:
8668 	rfs4_dbe_lock(sp->rs_dbe);
8669 	if (sp->rs_closed) {
8670 		rfs4_dbe_unlock(sp->rs_dbe);
8671 		return (NFS4ERR_OLD_STATEID);
8672 	}
8673 
8674 	if (resop->resop != OP_LOCKU) {
8675 		switch (locktype) {
8676 		case READ_LT:
8677 		case READW_LT:
8678 			if ((sp->rs_share_access
8679 			    & OPEN4_SHARE_ACCESS_READ) == 0) {
8680 				rfs4_dbe_unlock(sp->rs_dbe);
8681 
8682 				return (NFS4ERR_OPENMODE);
8683 			}
8684 			ltype = F_RDLCK;
8685 			break;
8686 		case WRITE_LT:
8687 		case WRITEW_LT:
8688 			if ((sp->rs_share_access
8689 			    & OPEN4_SHARE_ACCESS_WRITE) == 0) {
8690 				rfs4_dbe_unlock(sp->rs_dbe);
8691 
8692 				return (NFS4ERR_OPENMODE);
8693 			}
8694 			ltype = F_WRLCK;
8695 			break;
8696 		}
8697 	} else
8698 		ltype = F_UNLCK;
8699 
8700 	flock.l_type = ltype;
8701 	flock.l_whence = 0;		/* SEEK_SET */
8702 	flock.l_start = offset;
8703 	flock.l_len = length;
8704 	flock.l_sysid = sysid;
8705 	flock.l_pid = lsp->rls_locker->rl_pid;
8706 
8707 	/* Note that length4 is uint64_t but l_len and l_start are off64_t */
8708 	if (flock.l_len < 0 || flock.l_start < 0) {
8709 		rfs4_dbe_unlock(sp->rs_dbe);
8710 		return (NFS4ERR_INVAL);
8711 	}
8712 
8713 	/*
8714 	 * N.B. FREAD has the same value as OPEN4_SHARE_ACCESS_READ and
8715 	 * FWRITE has the same value as OPEN4_SHARE_ACCESS_WRITE.
8716 	 */
8717 	flag = (int)sp->rs_share_access | F_REMOTELOCK;
8718 
8719 	error = setlock(sp->rs_finfo->rf_vp, &flock, flag, cred);
8720 	if (error == 0) {
8721 		rfs4_dbe_lock(lsp->rls_dbe);
8722 		next_stateid(&lsp->rls_lockid);
8723 		rfs4_dbe_unlock(lsp->rls_dbe);
8724 	}
8725 
8726 	rfs4_dbe_unlock(sp->rs_dbe);
8727 
8728 	/*
8729 	 * N.B. We map error values to nfsv4 errors. This is differrent
8730 	 * than puterrno4 routine.
8731 	 */
8732 	switch (error) {
8733 	case 0:
8734 		status = NFS4_OK;
8735 		break;
8736 	case EAGAIN:
8737 	case EACCES:		/* Old value */
8738 		/* Can only get here if op is OP_LOCK */
8739 		ASSERT(resop->resop == OP_LOCK);
8740 		lres = &resop->nfs_resop4_u.oplock;
8741 		status = NFS4ERR_DENIED;
8742 		if (lock_denied(&lres->LOCK4res_u.denied, &flock)
8743 		    == NFS4ERR_EXPIRED)
8744 			goto retry;
8745 		break;
8746 	case ENOLCK:
8747 		status = NFS4ERR_DELAY;
8748 		break;
8749 	case EOVERFLOW:
8750 		status = NFS4ERR_INVAL;
8751 		break;
8752 	case EINVAL:
8753 		status = NFS4ERR_NOTSUPP;
8754 		break;
8755 	default:
8756 		status = NFS4ERR_SERVERFAULT;
8757 		break;
8758 	}
8759 
8760 	return (status);
8761 }
8762 
8763 /*ARGSUSED*/
8764 void
8765 rfs4_op_lock(nfs_argop4 *argop, nfs_resop4 *resop,
8766     struct svc_req *req, struct compound_state *cs)
8767 {
8768 	LOCK4args *args = &argop->nfs_argop4_u.oplock;
8769 	LOCK4res *resp = &resop->nfs_resop4_u.oplock;
8770 	nfsstat4 status;
8771 	stateid4 *stateid;
8772 	rfs4_lockowner_t *lo;
8773 	rfs4_client_t *cp;
8774 	rfs4_state_t *sp = NULL;
8775 	rfs4_lo_state_t *lsp = NULL;
8776 	bool_t ls_sw_held = FALSE;
8777 	bool_t create = TRUE;
8778 	bool_t lcreate = TRUE;
8779 	bool_t dup_lock = FALSE;
8780 	int rc;
8781 
8782 	DTRACE_NFSV4_2(op__lock__start, struct compound_state *, cs,
8783 	    LOCK4args *, args);
8784 
8785 	if (cs->vp == NULL) {
8786 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
8787 		DTRACE_NFSV4_2(op__lock__done, struct compound_state *,
8788 		    cs, LOCK4res *, resp);
8789 		return;
8790 	}
8791 
8792 	if (args->locker.new_lock_owner) {
8793 		/* Create a new lockowner for this instance */
8794 		open_to_lock_owner4 *olo = &args->locker.locker4_u.open_owner;
8795 
8796 		NFS4_DEBUG(rfs4_debug, (CE_NOTE, "Creating new lock owner"));
8797 
8798 		stateid = &olo->open_stateid;
8799 		status = rfs4_get_state(stateid, &sp, RFS4_DBS_VALID);
8800 		if (status != NFS4_OK) {
8801 			NFS4_DEBUG(rfs4_debug,
8802 			    (CE_NOTE, "Get state failed in lock %d", status));
8803 			*cs->statusp = resp->status = status;
8804 			DTRACE_NFSV4_2(op__lock__done, struct compound_state *,
8805 			    cs, LOCK4res *, resp);
8806 			return;
8807 		}
8808 
8809 		/* Ensure specified filehandle matches */
8810 		if (cs->vp != sp->rs_finfo->rf_vp) {
8811 			rfs4_state_rele(sp);
8812 			*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
8813 			DTRACE_NFSV4_2(op__lock__done, struct compound_state *,
8814 			    cs, LOCK4res *, resp);
8815 			return;
8816 		}
8817 
8818 		/* hold off other access to open_owner while we tinker */
8819 		rfs4_sw_enter(&sp->rs_owner->ro_sw);
8820 
8821 		switch (rc = rfs4_check_stateid_seqid(sp, stateid)) {
8822 		case NFS4_CHECK_STATEID_OLD:
8823 			*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
8824 			goto end;
8825 		case NFS4_CHECK_STATEID_BAD:
8826 			*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
8827 			goto end;
8828 		case NFS4_CHECK_STATEID_EXPIRED:
8829 			*cs->statusp = resp->status = NFS4ERR_EXPIRED;
8830 			goto end;
8831 		case NFS4_CHECK_STATEID_UNCONFIRMED:
8832 			*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
8833 			goto end;
8834 		case NFS4_CHECK_STATEID_CLOSED:
8835 			*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
8836 			goto end;
8837 		case NFS4_CHECK_STATEID_OKAY:
8838 		case NFS4_CHECK_STATEID_REPLAY:
8839 			switch (rfs4_check_olo_seqid(olo->open_seqid,
8840 			    sp->rs_owner, resop)) {
8841 			case NFS4_CHKSEQ_OKAY:
8842 				if (rc == NFS4_CHECK_STATEID_OKAY)
8843 					break;
8844 				/*
8845 				 * This is replayed stateid; if seqid
8846 				 * matches next expected, then client
8847 				 * is using wrong seqid.
8848 				 */
8849 				/* FALLTHROUGH */
8850 			case NFS4_CHKSEQ_BAD:
8851 				*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
8852 				goto end;
8853 			case NFS4_CHKSEQ_REPLAY:
8854 				/* This is a duplicate LOCK request */
8855 				dup_lock = TRUE;
8856 
8857 				/*
8858 				 * For a duplicate we do not want to
8859 				 * create a new lockowner as it should
8860 				 * already exist.
8861 				 * Turn off the lockowner create flag.
8862 				 */
8863 				lcreate = FALSE;
8864 			}
8865 			break;
8866 		}
8867 
8868 		lo = rfs4_findlockowner(&olo->lock_owner, &lcreate);
8869 		if (lo == NULL) {
8870 			NFS4_DEBUG(rfs4_debug,
8871 			    (CE_NOTE, "rfs4_op_lock: no lock owner"));
8872 			*cs->statusp = resp->status = NFS4ERR_RESOURCE;
8873 			goto end;
8874 		}
8875 
8876 		lsp = rfs4_findlo_state_by_owner(lo, sp, &create);
8877 		if (lsp == NULL) {
8878 			rfs4_update_lease(sp->rs_owner->ro_client);
8879 			/*
8880 			 * Only update theh open_seqid if this is not
8881 			 * a duplicate request
8882 			 */
8883 			if (dup_lock == FALSE) {
8884 				rfs4_update_open_sequence(sp->rs_owner);
8885 			}
8886 
8887 			NFS4_DEBUG(rfs4_debug,
8888 			    (CE_NOTE, "rfs4_op_lock: no state"));
8889 			*cs->statusp = resp->status = NFS4ERR_SERVERFAULT;
8890 			rfs4_update_open_resp(sp->rs_owner, resop, NULL);
8891 			rfs4_lockowner_rele(lo);
8892 			goto end;
8893 		}
8894 
8895 		/*
8896 		 * This is the new_lock_owner branch and the client is
8897 		 * supposed to be associating a new lock_owner with
8898 		 * the open file at this point.  If we find that a
8899 		 * lock_owner/state association already exists and a
8900 		 * successful LOCK request was returned to the client,
8901 		 * an error is returned to the client since this is
8902 		 * not appropriate.  The client should be using the
8903 		 * existing lock_owner branch.
8904 		 */
8905 		if (dup_lock == FALSE && create == FALSE) {
8906 			if (lsp->rls_lock_completed == TRUE) {
8907 				*cs->statusp =
8908 				    resp->status = NFS4ERR_BAD_SEQID;
8909 				rfs4_lockowner_rele(lo);
8910 				goto end;
8911 			}
8912 		}
8913 
8914 		rfs4_update_lease(sp->rs_owner->ro_client);
8915 
8916 		/*
8917 		 * Only update theh open_seqid if this is not
8918 		 * a duplicate request
8919 		 */
8920 		if (dup_lock == FALSE) {
8921 			rfs4_update_open_sequence(sp->rs_owner);
8922 		}
8923 
8924 		/*
8925 		 * If this is a duplicate lock request, just copy the
8926 		 * previously saved reply and return.
8927 		 */
8928 		if (dup_lock == TRUE) {
8929 			/* verify that lock_seqid's match */
8930 			if (lsp->rls_seqid != olo->lock_seqid) {
8931 				NFS4_DEBUG(rfs4_debug,
8932 				    (CE_NOTE, "rfs4_op_lock: Dup-Lock seqid bad"
8933 				    "lsp->seqid=%d old->seqid=%d",
8934 				    lsp->rls_seqid, olo->lock_seqid));
8935 				*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
8936 			} else {
8937 				rfs4_copy_reply(resop, &lsp->rls_reply);
8938 				/*
8939 				 * Make sure to copy the just
8940 				 * retrieved reply status into the
8941 				 * overall compound status
8942 				 */
8943 				*cs->statusp = resp->status;
8944 			}
8945 			rfs4_lockowner_rele(lo);
8946 			goto end;
8947 		}
8948 
8949 		rfs4_dbe_lock(lsp->rls_dbe);
8950 
8951 		/* Make sure to update the lock sequence id */
8952 		lsp->rls_seqid = olo->lock_seqid;
8953 
8954 		NFS4_DEBUG(rfs4_debug,
8955 		    (CE_NOTE, "Lock seqid established as %d", lsp->rls_seqid));
8956 
8957 		/*
8958 		 * This is used to signify the newly created lockowner
8959 		 * stateid and its sequence number.  The checks for
8960 		 * sequence number and increment don't occur on the
8961 		 * very first lock request for a lockowner.
8962 		 */
8963 		lsp->rls_skip_seqid_check = TRUE;
8964 
8965 		/* hold off other access to lsp while we tinker */
8966 		rfs4_sw_enter(&lsp->rls_sw);
8967 		ls_sw_held = TRUE;
8968 
8969 		rfs4_dbe_unlock(lsp->rls_dbe);
8970 
8971 		rfs4_lockowner_rele(lo);
8972 	} else {
8973 		stateid = &args->locker.locker4_u.lock_owner.lock_stateid;
8974 		/* get lsp and hold the lock on the underlying file struct */
8975 		if ((status = rfs4_get_lo_state(stateid, &lsp, TRUE))
8976 		    != NFS4_OK) {
8977 			*cs->statusp = resp->status = status;
8978 			DTRACE_NFSV4_2(op__lock__done, struct compound_state *,
8979 			    cs, LOCK4res *, resp);
8980 			return;
8981 		}
8982 		create = FALSE;	/* We didn't create lsp */
8983 
8984 		/* Ensure specified filehandle matches */
8985 		if (cs->vp != lsp->rls_state->rs_finfo->rf_vp) {
8986 			rfs4_lo_state_rele(lsp, TRUE);
8987 			*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
8988 			DTRACE_NFSV4_2(op__lock__done, struct compound_state *,
8989 			    cs, LOCK4res *, resp);
8990 			return;
8991 		}
8992 
8993 		/* hold off other access to lsp while we tinker */
8994 		rfs4_sw_enter(&lsp->rls_sw);
8995 		ls_sw_held = TRUE;
8996 
8997 		switch (rfs4_check_lo_stateid_seqid(lsp, stateid)) {
8998 		/*
8999 		 * The stateid looks like it was okay (expected to be
9000 		 * the next one)
9001 		 */
9002 		case NFS4_CHECK_STATEID_OKAY:
9003 			/*
9004 			 * The sequence id is now checked.  Determine
9005 			 * if this is a replay or if it is in the
9006 			 * expected (next) sequence.  In the case of a
9007 			 * replay, there are two replay conditions
9008 			 * that may occur.  The first is the normal
9009 			 * condition where a LOCK is done with a
9010 			 * NFS4_OK response and the stateid is
9011 			 * updated.  That case is handled below when
9012 			 * the stateid is identified as a REPLAY.  The
9013 			 * second is the case where an error is
9014 			 * returned, like NFS4ERR_DENIED, and the
9015 			 * sequence number is updated but the stateid
9016 			 * is not updated.  This second case is dealt
9017 			 * with here.  So it may seem odd that the
9018 			 * stateid is okay but the sequence id is a
9019 			 * replay but it is okay.
9020 			 */
9021 			switch (rfs4_check_lock_seqid(
9022 			    args->locker.locker4_u.lock_owner.lock_seqid,
9023 			    lsp, resop)) {
9024 			case NFS4_CHKSEQ_REPLAY:
9025 				if (resp->status != NFS4_OK) {
9026 					/*
9027 					 * Here is our replay and need
9028 					 * to verify that the last
9029 					 * response was an error.
9030 					 */
9031 					*cs->statusp = resp->status;
9032 					goto end;
9033 				}
9034 				/*
9035 				 * This is done since the sequence id
9036 				 * looked like a replay but it didn't
9037 				 * pass our check so a BAD_SEQID is
9038 				 * returned as a result.
9039 				 */
9040 				/*FALLTHROUGH*/
9041 			case NFS4_CHKSEQ_BAD:
9042 				*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
9043 				goto end;
9044 			case NFS4_CHKSEQ_OKAY:
9045 				/* Everything looks okay move ahead */
9046 				break;
9047 			}
9048 			break;
9049 		case NFS4_CHECK_STATEID_OLD:
9050 			*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
9051 			goto end;
9052 		case NFS4_CHECK_STATEID_BAD:
9053 			*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
9054 			goto end;
9055 		case NFS4_CHECK_STATEID_EXPIRED:
9056 			*cs->statusp = resp->status = NFS4ERR_EXPIRED;
9057 			goto end;
9058 		case NFS4_CHECK_STATEID_CLOSED:
9059 			*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
9060 			goto end;
9061 		case NFS4_CHECK_STATEID_REPLAY:
9062 			switch (rfs4_check_lock_seqid(
9063 			    args->locker.locker4_u.lock_owner.lock_seqid,
9064 			    lsp, resop)) {
9065 			case NFS4_CHKSEQ_OKAY:
9066 				/*
9067 				 * This is a replayed stateid; if
9068 				 * seqid matches the next expected,
9069 				 * then client is using wrong seqid.
9070 				 */
9071 			case NFS4_CHKSEQ_BAD:
9072 				*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
9073 				goto end;
9074 			case NFS4_CHKSEQ_REPLAY:
9075 				rfs4_update_lease(lsp->rls_locker->rl_client);
9076 				*cs->statusp = status = resp->status;
9077 				goto end;
9078 			}
9079 			break;
9080 		default:
9081 			ASSERT(FALSE);
9082 			break;
9083 		}
9084 
9085 		rfs4_update_lock_sequence(lsp);
9086 		rfs4_update_lease(lsp->rls_locker->rl_client);
9087 	}
9088 
9089 	/*
9090 	 * NFS4 only allows locking on regular files, so
9091 	 * verify type of object.
9092 	 */
9093 	if (cs->vp->v_type != VREG) {
9094 		if (cs->vp->v_type == VDIR)
9095 			status = NFS4ERR_ISDIR;
9096 		else
9097 			status = NFS4ERR_INVAL;
9098 		goto out;
9099 	}
9100 
9101 	cp = lsp->rls_state->rs_owner->ro_client;
9102 
9103 	if (rfs4_clnt_in_grace(cp) && !args->reclaim) {
9104 		status = NFS4ERR_GRACE;
9105 		goto out;
9106 	}
9107 
9108 	if (rfs4_clnt_in_grace(cp) && args->reclaim && !cp->rc_can_reclaim) {
9109 		status = NFS4ERR_NO_GRACE;
9110 		goto out;
9111 	}
9112 
9113 	if (!rfs4_clnt_in_grace(cp) && args->reclaim) {
9114 		status = NFS4ERR_NO_GRACE;
9115 		goto out;
9116 	}
9117 
9118 	if (lsp->rls_state->rs_finfo->rf_dinfo.rd_dtype == OPEN_DELEGATE_WRITE)
9119 		cs->deleg = TRUE;
9120 
9121 	status = rfs4_do_lock(lsp, args->locktype,
9122 	    args->offset, args->length, cs->cr, resop);
9123 
9124 out:
9125 	lsp->rls_skip_seqid_check = FALSE;
9126 
9127 	*cs->statusp = resp->status = status;
9128 
9129 	if (status == NFS4_OK) {
9130 		resp->LOCK4res_u.lock_stateid = lsp->rls_lockid.stateid;
9131 		lsp->rls_lock_completed = TRUE;
9132 	}
9133 	/*
9134 	 * Only update the "OPEN" response here if this was a new
9135 	 * lock_owner
9136 	 */
9137 	if (sp)
9138 		rfs4_update_open_resp(sp->rs_owner, resop, NULL);
9139 
9140 	rfs4_update_lock_resp(lsp, resop);
9141 
9142 end:
9143 	if (lsp) {
9144 		if (ls_sw_held)
9145 			rfs4_sw_exit(&lsp->rls_sw);
9146 		/*
9147 		 * If an sp obtained, then the lsp does not represent
9148 		 * a lock on the file struct.
9149 		 */
9150 		if (sp != NULL)
9151 			rfs4_lo_state_rele(lsp, FALSE);
9152 		else
9153 			rfs4_lo_state_rele(lsp, TRUE);
9154 	}
9155 	if (sp) {
9156 		rfs4_sw_exit(&sp->rs_owner->ro_sw);
9157 		rfs4_state_rele(sp);
9158 	}
9159 
9160 	DTRACE_NFSV4_2(op__lock__done, struct compound_state *, cs,
9161 	    LOCK4res *, resp);
9162 }
9163 
9164 /* free function for LOCK/LOCKT */
9165 static void
9166 lock_denied_free(nfs_resop4 *resop)
9167 {
9168 	LOCK4denied *dp = NULL;
9169 
9170 	switch (resop->resop) {
9171 	case OP_LOCK:
9172 		if (resop->nfs_resop4_u.oplock.status == NFS4ERR_DENIED)
9173 			dp = &resop->nfs_resop4_u.oplock.LOCK4res_u.denied;
9174 		break;
9175 	case OP_LOCKT:
9176 		if (resop->nfs_resop4_u.oplockt.status == NFS4ERR_DENIED)
9177 			dp = &resop->nfs_resop4_u.oplockt.denied;
9178 		break;
9179 	default:
9180 		break;
9181 	}
9182 
9183 	if (dp)
9184 		kmem_free(dp->owner.owner_val, dp->owner.owner_len);
9185 }
9186 
9187 /*ARGSUSED*/
9188 void
9189 rfs4_op_locku(nfs_argop4 *argop, nfs_resop4 *resop,
9190     struct svc_req *req, struct compound_state *cs)
9191 {
9192 	LOCKU4args *args = &argop->nfs_argop4_u.oplocku;
9193 	LOCKU4res *resp = &resop->nfs_resop4_u.oplocku;
9194 	nfsstat4 status;
9195 	stateid4 *stateid = &args->lock_stateid;
9196 	rfs4_lo_state_t *lsp;
9197 
9198 	DTRACE_NFSV4_2(op__locku__start, struct compound_state *, cs,
9199 	    LOCKU4args *, args);
9200 
9201 	if (cs->vp == NULL) {
9202 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
9203 		DTRACE_NFSV4_2(op__locku__done, struct compound_state *, cs,
9204 		    LOCKU4res *, resp);
9205 		return;
9206 	}
9207 
9208 	if ((status = rfs4_get_lo_state(stateid, &lsp, TRUE)) != NFS4_OK) {
9209 		*cs->statusp = resp->status = status;
9210 		DTRACE_NFSV4_2(op__locku__done, struct compound_state *, cs,
9211 		    LOCKU4res *, resp);
9212 		return;
9213 	}
9214 
9215 	/* Ensure specified filehandle matches */
9216 	if (cs->vp != lsp->rls_state->rs_finfo->rf_vp) {
9217 		rfs4_lo_state_rele(lsp, TRUE);
9218 		*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
9219 		DTRACE_NFSV4_2(op__locku__done, struct compound_state *, cs,
9220 		    LOCKU4res *, resp);
9221 		return;
9222 	}
9223 
9224 	/* hold off other access to lsp while we tinker */
9225 	rfs4_sw_enter(&lsp->rls_sw);
9226 
9227 	switch (rfs4_check_lo_stateid_seqid(lsp, stateid)) {
9228 	case NFS4_CHECK_STATEID_OKAY:
9229 		if (rfs4_check_lock_seqid(args->seqid, lsp, resop)
9230 		    != NFS4_CHKSEQ_OKAY) {
9231 			*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
9232 			goto end;
9233 		}
9234 		break;
9235 	case NFS4_CHECK_STATEID_OLD:
9236 		*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
9237 		goto end;
9238 	case NFS4_CHECK_STATEID_BAD:
9239 		*cs->statusp = resp->status = NFS4ERR_BAD_STATEID;
9240 		goto end;
9241 	case NFS4_CHECK_STATEID_EXPIRED:
9242 		*cs->statusp = resp->status = NFS4ERR_EXPIRED;
9243 		goto end;
9244 	case NFS4_CHECK_STATEID_CLOSED:
9245 		*cs->statusp = resp->status = NFS4ERR_OLD_STATEID;
9246 		goto end;
9247 	case NFS4_CHECK_STATEID_REPLAY:
9248 		switch (rfs4_check_lock_seqid(args->seqid, lsp, resop)) {
9249 		case NFS4_CHKSEQ_OKAY:
9250 				/*
9251 				 * This is a replayed stateid; if
9252 				 * seqid matches the next expected,
9253 				 * then client is using wrong seqid.
9254 				 */
9255 		case NFS4_CHKSEQ_BAD:
9256 			*cs->statusp = resp->status = NFS4ERR_BAD_SEQID;
9257 			goto end;
9258 		case NFS4_CHKSEQ_REPLAY:
9259 			rfs4_update_lease(lsp->rls_locker->rl_client);
9260 			*cs->statusp = status = resp->status;
9261 			goto end;
9262 		}
9263 		break;
9264 	default:
9265 		ASSERT(FALSE);
9266 		break;
9267 	}
9268 
9269 	rfs4_update_lock_sequence(lsp);
9270 	rfs4_update_lease(lsp->rls_locker->rl_client);
9271 
9272 	/*
9273 	 * NFS4 only allows locking on regular files, so
9274 	 * verify type of object.
9275 	 */
9276 	if (cs->vp->v_type != VREG) {
9277 		if (cs->vp->v_type == VDIR)
9278 			status = NFS4ERR_ISDIR;
9279 		else
9280 			status = NFS4ERR_INVAL;
9281 		goto out;
9282 	}
9283 
9284 	if (rfs4_clnt_in_grace(lsp->rls_state->rs_owner->ro_client)) {
9285 		status = NFS4ERR_GRACE;
9286 		goto out;
9287 	}
9288 
9289 	status = rfs4_do_lock(lsp, args->locktype,
9290 	    args->offset, args->length, cs->cr, resop);
9291 
9292 out:
9293 	*cs->statusp = resp->status = status;
9294 
9295 	if (status == NFS4_OK)
9296 		resp->lock_stateid = lsp->rls_lockid.stateid;
9297 
9298 	rfs4_update_lock_resp(lsp, resop);
9299 
9300 end:
9301 	rfs4_sw_exit(&lsp->rls_sw);
9302 	rfs4_lo_state_rele(lsp, TRUE);
9303 
9304 	DTRACE_NFSV4_2(op__locku__done, struct compound_state *, cs,
9305 	    LOCKU4res *, resp);
9306 }
9307 
9308 /*
9309  * LOCKT is a best effort routine, the client can not be guaranteed that
9310  * the status return is still in effect by the time the reply is received.
9311  * They are numerous race conditions in this routine, but we are not required
9312  * and can not be accurate.
9313  */
9314 /*ARGSUSED*/
9315 void
9316 rfs4_op_lockt(nfs_argop4 *argop, nfs_resop4 *resop,
9317     struct svc_req *req, struct compound_state *cs)
9318 {
9319 	LOCKT4args *args = &argop->nfs_argop4_u.oplockt;
9320 	LOCKT4res *resp = &resop->nfs_resop4_u.oplockt;
9321 	rfs4_lockowner_t *lo;
9322 	rfs4_client_t *cp;
9323 	bool_t create = FALSE;
9324 	struct flock64 flk;
9325 	int error;
9326 	int flag = FREAD | FWRITE;
9327 	int ltype;
9328 	length4 posix_length;
9329 	sysid_t sysid;
9330 	pid_t pid;
9331 
9332 	DTRACE_NFSV4_2(op__lockt__start, struct compound_state *, cs,
9333 	    LOCKT4args *, args);
9334 
9335 	if (cs->vp == NULL) {
9336 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
9337 		goto out;
9338 	}
9339 
9340 	/*
9341 	 * NFS4 only allows locking on regular files, so
9342 	 * verify type of object.
9343 	 */
9344 	if (cs->vp->v_type != VREG) {
9345 		if (cs->vp->v_type == VDIR)
9346 			*cs->statusp = resp->status = NFS4ERR_ISDIR;
9347 		else
9348 			*cs->statusp = resp->status =  NFS4ERR_INVAL;
9349 		goto out;
9350 	}
9351 
9352 	/*
9353 	 * Check out the clientid to ensure the server knows about it
9354 	 * so that we correctly inform the client of a server reboot.
9355 	 */
9356 	if ((cp = rfs4_findclient_by_id(args->owner.clientid, FALSE))
9357 	    == NULL) {
9358 		*cs->statusp = resp->status =
9359 		    rfs4_check_clientid(&args->owner.clientid, 0);
9360 		goto out;
9361 	}
9362 	if (rfs4_lease_expired(cp)) {
9363 		rfs4_client_close(cp);
9364 		/*
9365 		 * Protocol doesn't allow returning NFS4ERR_STALE as
9366 		 * other operations do on this check so STALE_CLIENTID
9367 		 * is returned instead
9368 		 */
9369 		*cs->statusp = resp->status = NFS4ERR_STALE_CLIENTID;
9370 		goto out;
9371 	}
9372 
9373 	if (rfs4_clnt_in_grace(cp) && !(cp->rc_can_reclaim)) {
9374 		*cs->statusp = resp->status = NFS4ERR_GRACE;
9375 		rfs4_client_rele(cp);
9376 		goto out;
9377 	}
9378 	rfs4_client_rele(cp);
9379 
9380 	resp->status = NFS4_OK;
9381 
9382 	switch (args->locktype) {
9383 	case READ_LT:
9384 	case READW_LT:
9385 		ltype = F_RDLCK;
9386 		break;
9387 	case WRITE_LT:
9388 	case WRITEW_LT:
9389 		ltype = F_WRLCK;
9390 		break;
9391 	}
9392 
9393 	posix_length = args->length;
9394 	/* Check for zero length. To lock to end of file use all ones for V4 */
9395 	if (posix_length == 0) {
9396 		*cs->statusp = resp->status = NFS4ERR_INVAL;
9397 		goto out;
9398 	} else if (posix_length == (length4)(~0)) {
9399 		posix_length = 0;	/* Posix to end of file  */
9400 	}
9401 
9402 	/* Find or create a lockowner */
9403 	lo = rfs4_findlockowner(&args->owner, &create);
9404 
9405 	if (lo) {
9406 		pid = lo->rl_pid;
9407 		if ((resp->status =
9408 		    rfs4_client_sysid(lo->rl_client, &sysid)) != NFS4_OK)
9409 			goto err;
9410 	} else {
9411 		pid = 0;
9412 		sysid = lockt_sysid;
9413 	}
9414 retry:
9415 	flk.l_type = ltype;
9416 	flk.l_whence = 0;		/* SEEK_SET */
9417 	flk.l_start = args->offset;
9418 	flk.l_len = posix_length;
9419 	flk.l_sysid = sysid;
9420 	flk.l_pid = pid;
9421 	flag |= F_REMOTELOCK;
9422 
9423 	LOCK_PRINT(rfs4_debug, "rfs4_op_lockt", F_GETLK, &flk);
9424 
9425 	/* Note that length4 is uint64_t but l_len and l_start are off64_t */
9426 	if (flk.l_len < 0 || flk.l_start < 0) {
9427 		resp->status = NFS4ERR_INVAL;
9428 		goto err;
9429 	}
9430 	error = VOP_FRLOCK(cs->vp, F_GETLK, &flk, flag, (u_offset_t)0,
9431 	    NULL, cs->cr, NULL);
9432 
9433 	/*
9434 	 * N.B. We map error values to nfsv4 errors. This is differrent
9435 	 * than puterrno4 routine.
9436 	 */
9437 	switch (error) {
9438 	case 0:
9439 		if (flk.l_type == F_UNLCK)
9440 			resp->status = NFS4_OK;
9441 		else {
9442 			if (lock_denied(&resp->denied, &flk) == NFS4ERR_EXPIRED)
9443 				goto retry;
9444 			resp->status = NFS4ERR_DENIED;
9445 		}
9446 		break;
9447 	case EOVERFLOW:
9448 		resp->status = NFS4ERR_INVAL;
9449 		break;
9450 	case EINVAL:
9451 		resp->status = NFS4ERR_NOTSUPP;
9452 		break;
9453 	default:
9454 		cmn_err(CE_WARN, "rfs4_op_lockt: unexpected errno (%d)",
9455 		    error);
9456 		resp->status = NFS4ERR_SERVERFAULT;
9457 		break;
9458 	}
9459 
9460 err:
9461 	if (lo)
9462 		rfs4_lockowner_rele(lo);
9463 	*cs->statusp = resp->status;
9464 out:
9465 	DTRACE_NFSV4_2(op__lockt__done, struct compound_state *, cs,
9466 	    LOCKT4res *, resp);
9467 }
9468 
9469 int
9470 rfs4_share(rfs4_state_t *sp, uint32_t access, uint32_t deny)
9471 {
9472 	int err;
9473 	int cmd;
9474 	vnode_t *vp;
9475 	struct shrlock shr;
9476 	struct shr_locowner shr_loco;
9477 	int fflags = 0;
9478 
9479 	ASSERT(rfs4_dbe_islocked(sp->rs_dbe));
9480 	ASSERT(sp->rs_owner->ro_client->rc_sysidt != LM_NOSYSID);
9481 
9482 	if (sp->rs_closed)
9483 		return (NFS4ERR_OLD_STATEID);
9484 
9485 	vp = sp->rs_finfo->rf_vp;
9486 	ASSERT(vp);
9487 
9488 	shr.s_access = shr.s_deny = 0;
9489 
9490 	if (access & OPEN4_SHARE_ACCESS_READ) {
9491 		fflags |= FREAD;
9492 		shr.s_access |= F_RDACC;
9493 	}
9494 	if (access & OPEN4_SHARE_ACCESS_WRITE) {
9495 		fflags |= FWRITE;
9496 		shr.s_access |= F_WRACC;
9497 	}
9498 	ASSERT(shr.s_access);
9499 
9500 	if (deny & OPEN4_SHARE_DENY_READ)
9501 		shr.s_deny |= F_RDDNY;
9502 	if (deny & OPEN4_SHARE_DENY_WRITE)
9503 		shr.s_deny |= F_WRDNY;
9504 
9505 	shr.s_pid = rfs4_dbe_getid(sp->rs_owner->ro_dbe);
9506 	shr.s_sysid = sp->rs_owner->ro_client->rc_sysidt;
9507 	shr_loco.sl_pid = shr.s_pid;
9508 	shr_loco.sl_id = shr.s_sysid;
9509 	shr.s_owner = (caddr_t)&shr_loco;
9510 	shr.s_own_len = sizeof (shr_loco);
9511 
9512 	cmd = nbl_need_check(vp) ? F_SHARE_NBMAND : F_SHARE;
9513 
9514 	err = VOP_SHRLOCK(vp, cmd, &shr, fflags, CRED(), NULL);
9515 	if (err != 0) {
9516 		if (err == EAGAIN)
9517 			err = NFS4ERR_SHARE_DENIED;
9518 		else
9519 			err = puterrno4(err);
9520 		return (err);
9521 	}
9522 
9523 	sp->rs_share_access |= access;
9524 	sp->rs_share_deny |= deny;
9525 
9526 	return (0);
9527 }
9528 
9529 int
9530 rfs4_unshare(rfs4_state_t *sp)
9531 {
9532 	int err;
9533 	struct shrlock shr;
9534 	struct shr_locowner shr_loco;
9535 
9536 	ASSERT(rfs4_dbe_islocked(sp->rs_dbe));
9537 
9538 	if (sp->rs_closed || sp->rs_share_access == 0)
9539 		return (0);
9540 
9541 	ASSERT(sp->rs_owner->ro_client->rc_sysidt != LM_NOSYSID);
9542 	ASSERT(sp->rs_finfo->rf_vp);
9543 
9544 	shr.s_access = shr.s_deny = 0;
9545 	shr.s_pid = rfs4_dbe_getid(sp->rs_owner->ro_dbe);
9546 	shr.s_sysid = sp->rs_owner->ro_client->rc_sysidt;
9547 	shr_loco.sl_pid = shr.s_pid;
9548 	shr_loco.sl_id = shr.s_sysid;
9549 	shr.s_owner = (caddr_t)&shr_loco;
9550 	shr.s_own_len = sizeof (shr_loco);
9551 
9552 	err = VOP_SHRLOCK(sp->rs_finfo->rf_vp, F_UNSHARE, &shr, 0, CRED(),
9553 	    NULL);
9554 	if (err != 0) {
9555 		err = puterrno4(err);
9556 		return (err);
9557 	}
9558 
9559 	sp->rs_share_access = 0;
9560 	sp->rs_share_deny = 0;
9561 
9562 	return (0);
9563 
9564 }
9565 
9566 static int
9567 rdma_setup_read_data4(READ4args *args, READ4res *rok)
9568 {
9569 	struct clist	*wcl;
9570 	count4		count = rok->data_len;
9571 	int		wlist_len;
9572 
9573 	wcl = args->wlist;
9574 	if (rdma_setup_read_chunks(wcl, count, &wlist_len) == FALSE) {
9575 		return (FALSE);
9576 	}
9577 	wcl = args->wlist;
9578 	rok->wlist_len = wlist_len;
9579 	rok->wlist = wcl;
9580 	return (TRUE);
9581 }
9582 
9583 /* tunable to disable server referrals */
9584 int rfs4_no_referrals = 0;
9585 
9586 /*
9587  * Find an NFS record in reparse point data.
9588  * Returns 0 for success and <0 or an errno value on failure.
9589  */
9590 int
9591 vn_find_nfs_record(vnode_t *vp, nvlist_t **nvlp, char **svcp, char **datap)
9592 {
9593 	int err;
9594 	char *stype, *val;
9595 	nvlist_t *nvl;
9596 	nvpair_t *curr;
9597 
9598 	if ((nvl = reparse_init()) == NULL)
9599 		return (-1);
9600 
9601 	if ((err = reparse_vnode_parse(vp, nvl)) != 0) {
9602 		reparse_free(nvl);
9603 		return (err);
9604 	}
9605 
9606 	curr = NULL;
9607 	while ((curr = nvlist_next_nvpair(nvl, curr)) != NULL) {
9608 		if ((stype = nvpair_name(curr)) == NULL) {
9609 			reparse_free(nvl);
9610 			return (-2);
9611 		}
9612 		if (strncasecmp(stype, "NFS", 3) == 0)
9613 			break;
9614 	}
9615 
9616 	if ((curr == NULL) ||
9617 	    (nvpair_value_string(curr, &val))) {
9618 		reparse_free(nvl);
9619 		return (-3);
9620 	}
9621 	*nvlp = nvl;
9622 	*svcp = stype;
9623 	*datap = val;
9624 	return (0);
9625 }
9626 
9627 int
9628 vn_is_nfs_reparse(vnode_t *vp, cred_t *cr)
9629 {
9630 	nvlist_t *nvl;
9631 	char *s, *d;
9632 
9633 	if (rfs4_no_referrals != 0)
9634 		return (B_FALSE);
9635 
9636 	if (vn_is_reparse(vp, cr, NULL) == B_FALSE)
9637 		return (B_FALSE);
9638 
9639 	if (vn_find_nfs_record(vp, &nvl, &s, &d) != 0)
9640 		return (B_FALSE);
9641 
9642 	reparse_free(nvl);
9643 
9644 	return (B_TRUE);
9645 }
9646 
9647 /*
9648  * There is a user-level copy of this routine in ref_subr.c.
9649  * Changes should be kept in sync.
9650  */
9651 static int
9652 nfs4_create_components(char *path, component4 *comp4)
9653 {
9654 	int slen, plen, ncomp;
9655 	char *ori_path, *nxtc, buf[MAXNAMELEN];
9656 
9657 	if (path == NULL)
9658 		return (0);
9659 
9660 	plen = strlen(path) + 1;	/* include the terminator */
9661 	ori_path = path;
9662 	ncomp = 0;
9663 
9664 	/* count number of components in the path */
9665 	for (nxtc = path; nxtc < ori_path + plen; nxtc++) {
9666 		if (*nxtc == '/' || *nxtc == '\0' || *nxtc == '\n') {
9667 			if ((slen = nxtc - path) == 0) {
9668 				path = nxtc + 1;
9669 				continue;
9670 			}
9671 
9672 			if (comp4 != NULL) {
9673 				bcopy(path, buf, slen);
9674 				buf[slen] = '\0';
9675 				(void) str_to_utf8(buf, &comp4[ncomp]);
9676 			}
9677 
9678 			ncomp++;	/* 1 valid component */
9679 			path = nxtc + 1;
9680 		}
9681 		if (*nxtc == '\0' || *nxtc == '\n')
9682 			break;
9683 	}
9684 
9685 	return (ncomp);
9686 }
9687 
9688 /*
9689  * There is a user-level copy of this routine in ref_subr.c.
9690  * Changes should be kept in sync.
9691  */
9692 static int
9693 make_pathname4(char *path, pathname4 *pathname)
9694 {
9695 	int ncomp;
9696 	component4 *comp4;
9697 
9698 	if (pathname == NULL)
9699 		return (0);
9700 
9701 	if (path == NULL) {
9702 		pathname->pathname4_val = NULL;
9703 		pathname->pathname4_len = 0;
9704 		return (0);
9705 	}
9706 
9707 	/* count number of components to alloc buffer */
9708 	if ((ncomp = nfs4_create_components(path, NULL)) == 0) {
9709 		pathname->pathname4_val = NULL;
9710 		pathname->pathname4_len = 0;
9711 		return (0);
9712 	}
9713 	comp4 = kmem_zalloc(ncomp * sizeof (component4), KM_SLEEP);
9714 
9715 	/* copy components into allocated buffer */
9716 	ncomp = nfs4_create_components(path, comp4);
9717 
9718 	pathname->pathname4_val = comp4;
9719 	pathname->pathname4_len = ncomp;
9720 
9721 	return (ncomp);
9722 }
9723 
9724 #define	xdr_fs_locations4 xdr_fattr4_fs_locations
9725 
9726 fs_locations4 *
9727 fetch_referral(vnode_t *vp, cred_t *cr)
9728 {
9729 	nvlist_t *nvl;
9730 	char *stype, *sdata;
9731 	fs_locations4 *result;
9732 	char buf[1024];
9733 	size_t bufsize;
9734 	XDR xdr;
9735 	int err;
9736 
9737 	/*
9738 	 * Check attrs to ensure it's a reparse point
9739 	 */
9740 	if (vn_is_reparse(vp, cr, NULL) == B_FALSE)
9741 		return (NULL);
9742 
9743 	/*
9744 	 * Look for an NFS record and get the type and data
9745 	 */
9746 	if (vn_find_nfs_record(vp, &nvl, &stype, &sdata) != 0)
9747 		return (NULL);
9748 
9749 	/*
9750 	 * With the type and data, upcall to get the referral
9751 	 */
9752 	bufsize = sizeof (buf);
9753 	bzero(buf, sizeof (buf));
9754 	err = reparse_kderef((const char *)stype, (const char *)sdata,
9755 	    buf, &bufsize);
9756 	reparse_free(nvl);
9757 
9758 	DTRACE_PROBE4(nfs4serv__func__referral__upcall,
9759 	    char *, stype, char *, sdata, char *, buf, int, err);
9760 	if (err) {
9761 		cmn_err(CE_NOTE,
9762 		    "reparsed daemon not running: unable to get referral (%d)",
9763 		    err);
9764 		return (NULL);
9765 	}
9766 
9767 	/*
9768 	 * We get an XDR'ed record back from the kderef call
9769 	 */
9770 	xdrmem_create(&xdr, buf, bufsize, XDR_DECODE);
9771 	result = kmem_alloc(sizeof (fs_locations4), KM_SLEEP);
9772 	err = xdr_fs_locations4(&xdr, result);
9773 	XDR_DESTROY(&xdr);
9774 	if (err != TRUE) {
9775 		DTRACE_PROBE1(nfs4serv__func__referral__upcall__xdrfail,
9776 		    int, err);
9777 		return (NULL);
9778 	}
9779 
9780 	/*
9781 	 * Look at path to recover fs_root, ignoring the leading '/'
9782 	 */
9783 	(void) make_pathname4(vp->v_path, &result->fs_root);
9784 
9785 	return (result);
9786 }
9787 
9788 char *
9789 build_symlink(vnode_t *vp, cred_t *cr, size_t *strsz)
9790 {
9791 	fs_locations4 *fsl;
9792 	fs_location4 *fs;
9793 	char *server, *path, *symbuf;
9794 	static char *prefix = "/net/";
9795 	int i, size, npaths;
9796 	uint_t len;
9797 
9798 	/* Get the referral */
9799 	if ((fsl = fetch_referral(vp, cr)) == NULL)
9800 		return (NULL);
9801 
9802 	/* Deal with only the first location and first server */
9803 	fs = &fsl->locations_val[0];
9804 	server = utf8_to_str(&fs->server_val[0], &len, NULL);
9805 	if (server == NULL) {
9806 		rfs4_free_fs_locations4(fsl);
9807 		kmem_free(fsl, sizeof (fs_locations4));
9808 		return (NULL);
9809 	}
9810 
9811 	/* Figure out size for "/net/" + host + /path/path/path + NULL */
9812 	size = strlen(prefix) + len;
9813 	for (i = 0; i < fs->rootpath.pathname4_len; i++)
9814 		size += fs->rootpath.pathname4_val[i].utf8string_len + 1;
9815 
9816 	/* Allocate the symlink buffer and fill it */
9817 	symbuf = kmem_zalloc(size, KM_SLEEP);
9818 	(void) strcat(symbuf, prefix);
9819 	(void) strcat(symbuf, server);
9820 	kmem_free(server, len);
9821 
9822 	npaths = 0;
9823 	for (i = 0; i < fs->rootpath.pathname4_len; i++) {
9824 		path = utf8_to_str(&fs->rootpath.pathname4_val[i], &len, NULL);
9825 		if (path == NULL)
9826 			continue;
9827 		(void) strcat(symbuf, "/");
9828 		(void) strcat(symbuf, path);
9829 		npaths++;
9830 		kmem_free(path, len);
9831 	}
9832 
9833 	rfs4_free_fs_locations4(fsl);
9834 	kmem_free(fsl, sizeof (fs_locations4));
9835 
9836 	if (strsz != NULL)
9837 		*strsz = size;
9838 	return (symbuf);
9839 }
9840 
9841 /*
9842  * Check to see if we have a downrev Solaris client, so that we
9843  * can send it a symlink instead of a referral.
9844  */
9845 int
9846 client_is_downrev(struct svc_req *req)
9847 {
9848 	struct sockaddr *ca;
9849 	rfs4_clntip_t *ci;
9850 	bool_t create = FALSE;
9851 	int is_downrev;
9852 
9853 	ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
9854 	ASSERT(ca);
9855 	ci = rfs4_find_clntip(ca, &create);
9856 	if (ci == NULL)
9857 		return (0);
9858 	is_downrev = ci->ri_no_referrals;
9859 	rfs4_dbe_rele(ci->ri_dbe);
9860 	return (is_downrev);
9861 }
9862