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