xref: /illumos-gate/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c (revision 48bbca816818409505a6e214d0911fda44e622e3)
1 /*
2  * Copyright (c) 2000-2001 Boris Popov
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *    This product includes software developed by Boris Popov.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $Id: smbfs_vnops.c,v 1.128.36.1 2005/05/27 02:35:28 lindak Exp $
33  */
34 
35 /*
36  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
37  */
38 
39 #include <sys/systm.h>
40 #include <sys/cred.h>
41 #include <sys/vnode.h>
42 #include <sys/vfs.h>
43 #include <sys/filio.h>
44 #include <sys/uio.h>
45 #include <sys/dirent.h>
46 #include <sys/errno.h>
47 #include <sys/sunddi.h>
48 #include <sys/sysmacros.h>
49 #include <sys/kmem.h>
50 #include <sys/cmn_err.h>
51 #include <sys/vfs_opreg.h>
52 #include <sys/policy.h>
53 
54 #include <netsmb/smb_osdep.h>
55 #include <netsmb/smb.h>
56 #include <netsmb/smb_conn.h>
57 #include <netsmb/smb_subr.h>
58 
59 #include <smbfs/smbfs.h>
60 #include <smbfs/smbfs_node.h>
61 #include <smbfs/smbfs_subr.h>
62 
63 #include <sys/fs/smbfs_ioctl.h>
64 #include <fs/fs_subr.h>
65 
66 /*
67  * We assign directory offsets like the NFS client, where the
68  * offset increments by _one_ after each directory entry.
69  * Further, the entries "." and ".." are always at offsets
70  * zero and one (respectively) and the "real" entries from
71  * the server appear at offsets starting with two.  This
72  * macro is used to initialize the n_dirofs field after
73  * setting n_dirseq with a _findopen call.
74  */
75 #define	FIRST_DIROFS	2
76 
77 /*
78  * These characters are illegal in NTFS file names.
79  * ref: http://support.microsoft.com/kb/147438
80  *
81  * Careful!  The check in the XATTR case skips the
82  * first character to allow colon in XATTR names.
83  */
84 static const char illegal_chars[] = {
85 	':',	/* colon - keep this first! */
86 	'\\',	/* back slash */
87 	'/',	/* slash */
88 	'*',	/* asterisk */
89 	'?',	/* question mark */
90 	'"',	/* double quote */
91 	'<',	/* less than sign */
92 	'>',	/* greater than sign */
93 	'|',	/* vertical bar */
94 	0
95 };
96 
97 /*
98  * Turning this on causes nodes to be created in the cache
99  * during directory listings, normally avoiding a second
100  * OtW attribute fetch just after a readdir.
101  */
102 int smbfs_fastlookup = 1;
103 
104 /* local static function defines */
105 
106 static int	smbfslookup_cache(vnode_t *, char *, int, vnode_t **,
107 			cred_t *);
108 static int	smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr,
109 			int cache_ok, caller_context_t *);
110 static int	smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm,
111 			cred_t *cr, caller_context_t *);
112 static int	smbfssetattr(vnode_t *, struct vattr *, int, cred_t *);
113 static int	smbfs_accessx(void *, int, cred_t *);
114 static int	smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
115 			caller_context_t *);
116 static void	smbfs_rele_fid(smbnode_t *, struct smb_cred *);
117 static uint32_t xvattr_to_dosattr(smbnode_t *, struct vattr *);
118 
119 /*
120  * These are the vnode ops routines which implement the vnode interface to
121  * the networked file system.  These routines just take their parameters,
122  * make them look networkish by putting the right info into interface structs,
123  * and then calling the appropriate remote routine(s) to do the work.
124  *
125  * Note on directory name lookup cacheing:  If we detect a stale fhandle,
126  * we purge the directory cache relative to that vnode.  This way, the
127  * user won't get burned by the cache repeatedly.  See <smbfs/smbnode.h> for
128  * more details on smbnode locking.
129  */
130 
131 static int	smbfs_open(vnode_t **, int, cred_t *, caller_context_t *);
132 static int	smbfs_close(vnode_t *, int, int, offset_t, cred_t *,
133 			caller_context_t *);
134 static int	smbfs_read(vnode_t *, struct uio *, int, cred_t *,
135 			caller_context_t *);
136 static int	smbfs_write(vnode_t *, struct uio *, int, cred_t *,
137 			caller_context_t *);
138 static int	smbfs_ioctl(vnode_t *, int, intptr_t, int, cred_t *, int *,
139 			caller_context_t *);
140 static int	smbfs_getattr(vnode_t *, struct vattr *, int, cred_t *,
141 			caller_context_t *);
142 static int	smbfs_setattr(vnode_t *, struct vattr *, int, cred_t *,
143 			caller_context_t *);
144 static int	smbfs_access(vnode_t *, int, int, cred_t *, caller_context_t *);
145 static int	smbfs_fsync(vnode_t *, int, cred_t *, caller_context_t *);
146 static void	smbfs_inactive(vnode_t *, cred_t *, caller_context_t *);
147 static int	smbfs_lookup(vnode_t *, char *, vnode_t **, struct pathname *,
148 			int, vnode_t *, cred_t *, caller_context_t *,
149 			int *, pathname_t *);
150 static int	smbfs_create(vnode_t *, char *, struct vattr *, enum vcexcl,
151 			int, vnode_t **, cred_t *, int, caller_context_t *,
152 			vsecattr_t *);
153 static int	smbfs_remove(vnode_t *, char *, cred_t *, caller_context_t *,
154 			int);
155 static int	smbfs_rename(vnode_t *, char *, vnode_t *, char *, cred_t *,
156 			caller_context_t *, int);
157 static int	smbfs_mkdir(vnode_t *, char *, struct vattr *, vnode_t **,
158 			cred_t *, caller_context_t *, int, vsecattr_t *);
159 static int	smbfs_rmdir(vnode_t *, char *, vnode_t *, cred_t *,
160 			caller_context_t *, int);
161 static int	smbfs_readdir(vnode_t *, struct uio *, cred_t *, int *,
162 			caller_context_t *, int);
163 static int	smbfs_rwlock(vnode_t *, int, caller_context_t *);
164 static void	smbfs_rwunlock(vnode_t *, int, caller_context_t *);
165 static int	smbfs_seek(vnode_t *, offset_t, offset_t *, caller_context_t *);
166 static int	smbfs_frlock(vnode_t *, int, struct flock64 *, int, offset_t,
167 			struct flk_callback *, cred_t *, caller_context_t *);
168 static int	smbfs_space(vnode_t *, int, struct flock64 *, int, offset_t,
169 			cred_t *, caller_context_t *);
170 static int	smbfs_pathconf(vnode_t *, int, ulong_t *, cred_t *,
171 			caller_context_t *);
172 static int	smbfs_setsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
173 			caller_context_t *);
174 static int	smbfs_getsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
175 			caller_context_t *);
176 static int	smbfs_shrlock(vnode_t *, int, struct shrlock *, int, cred_t *,
177 			caller_context_t *);
178 
179 /* Dummy function to use until correct function is ported in */
180 int noop_vnodeop() {
181 	return (0);
182 }
183 
184 struct vnodeops *smbfs_vnodeops = NULL;
185 
186 /*
187  * Most unimplemented ops will return ENOSYS because of fs_nosys().
188  * The only ops where that won't work are ACCESS (due to open(2)
189  * failures) and ... (anything else left?)
190  */
191 const fs_operation_def_t smbfs_vnodeops_template[] = {
192 	{ VOPNAME_OPEN,		{ .vop_open = smbfs_open } },
193 	{ VOPNAME_CLOSE,	{ .vop_close = smbfs_close } },
194 	{ VOPNAME_READ,		{ .vop_read = smbfs_read } },
195 	{ VOPNAME_WRITE,	{ .vop_write = smbfs_write } },
196 	{ VOPNAME_IOCTL,	{ .vop_ioctl = smbfs_ioctl } },
197 	{ VOPNAME_GETATTR,	{ .vop_getattr = smbfs_getattr } },
198 	{ VOPNAME_SETATTR,	{ .vop_setattr = smbfs_setattr } },
199 	{ VOPNAME_ACCESS,	{ .vop_access = smbfs_access } },
200 	{ VOPNAME_LOOKUP,	{ .vop_lookup = smbfs_lookup } },
201 	{ VOPNAME_CREATE,	{ .vop_create = smbfs_create } },
202 	{ VOPNAME_REMOVE,	{ .vop_remove = smbfs_remove } },
203 	{ VOPNAME_LINK,		{ .error = fs_nosys } }, /* smbfs_link, */
204 	{ VOPNAME_RENAME,	{ .vop_rename = smbfs_rename } },
205 	{ VOPNAME_MKDIR,	{ .vop_mkdir = smbfs_mkdir } },
206 	{ VOPNAME_RMDIR,	{ .vop_rmdir = smbfs_rmdir } },
207 	{ VOPNAME_READDIR,	{ .vop_readdir = smbfs_readdir } },
208 	{ VOPNAME_SYMLINK,	{ .error = fs_nosys } }, /* smbfs_symlink, */
209 	{ VOPNAME_READLINK,	{ .error = fs_nosys } }, /* smbfs_readlink, */
210 	{ VOPNAME_FSYNC,	{ .vop_fsync = smbfs_fsync } },
211 	{ VOPNAME_INACTIVE,	{ .vop_inactive = smbfs_inactive } },
212 	{ VOPNAME_FID,		{ .error = fs_nosys } }, /* smbfs_fid, */
213 	{ VOPNAME_RWLOCK,	{ .vop_rwlock = smbfs_rwlock } },
214 	{ VOPNAME_RWUNLOCK,	{ .vop_rwunlock = smbfs_rwunlock } },
215 	{ VOPNAME_SEEK,		{ .vop_seek = smbfs_seek } },
216 	{ VOPNAME_FRLOCK,	{ .vop_frlock = smbfs_frlock } },
217 	{ VOPNAME_SPACE,	{ .vop_space = smbfs_space } },
218 	{ VOPNAME_REALVP,	{ .error = fs_nosys } }, /* smbfs_realvp, */
219 	{ VOPNAME_GETPAGE,	{ .error = fs_nosys } }, /* smbfs_getpage, */
220 	{ VOPNAME_PUTPAGE,	{ .error = fs_nosys } }, /* smbfs_putpage, */
221 	{ VOPNAME_MAP,		{ .error = fs_nosys } }, /* smbfs_map, */
222 	{ VOPNAME_ADDMAP,	{ .error = fs_nosys } }, /* smbfs_addmap, */
223 	{ VOPNAME_DELMAP,	{ .error = fs_nosys } }, /* smbfs_delmap, */
224 	{ VOPNAME_DUMP,		{ .error = fs_nosys } }, /* smbfs_dump, */
225 	{ VOPNAME_PATHCONF,	{ .vop_pathconf = smbfs_pathconf } },
226 	{ VOPNAME_PAGEIO,	{ .error = fs_nosys } }, /* smbfs_pageio, */
227 	{ VOPNAME_SETSECATTR,	{ .vop_setsecattr = smbfs_setsecattr } },
228 	{ VOPNAME_GETSECATTR,	{ .vop_getsecattr = smbfs_getsecattr } },
229 	{ VOPNAME_SHRLOCK,	{ .vop_shrlock = smbfs_shrlock } },
230 	{ NULL, NULL }
231 };
232 
233 /*
234  * XXX
235  * When new and relevant functionality is enabled, we should be
236  * calling vfs_set_feature() to inform callers that pieces of
237  * functionality are available, per PSARC 2007/227.
238  */
239 /* ARGSUSED */
240 static int
241 smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
242 {
243 	smbnode_t	*np;
244 	vnode_t		*vp;
245 	smbfattr_t	fa;
246 	u_int32_t	rights, rightsrcvd;
247 	u_int16_t	fid, oldfid;
248 	int		oldgenid;
249 	struct smb_cred scred;
250 	smbmntinfo_t	*smi;
251 	smb_share_t	*ssp;
252 	cred_t		*oldcr;
253 	int		tmperror;
254 	int		error = 0;
255 
256 	vp = *vpp;
257 	np = VTOSMB(vp);
258 	smi = VTOSMI(vp);
259 	ssp = smi->smi_share;
260 
261 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
262 		return (EIO);
263 
264 	if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
265 		return (EIO);
266 
267 	if (vp->v_type != VREG && vp->v_type != VDIR) { /* XXX VLNK? */
268 		SMBVDEBUG("open eacces vtype=%d\n", vp->v_type);
269 		return (EACCES);
270 	}
271 
272 	/*
273 	 * Get exclusive access to n_fid and related stuff.
274 	 * No returns after this until out.
275 	 */
276 	if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
277 		return (EINTR);
278 	smb_credinit(&scred, cr);
279 
280 	/*
281 	 * Keep track of the vnode type at first open.
282 	 * It may change later, and we need close to do
283 	 * cleanup for the type we opened.  Also deny
284 	 * open of new types until old type is closed.
285 	 * XXX: Per-open instance nodes whould help.
286 	 */
287 	if (np->n_ovtype == VNON) {
288 		ASSERT(np->n_dirrefs == 0);
289 		ASSERT(np->n_fidrefs == 0);
290 	} else if (np->n_ovtype != vp->v_type) {
291 		SMBVDEBUG("open n_ovtype=%d v_type=%d\n",
292 		    np->n_ovtype, vp->v_type);
293 		error = EACCES;
294 		goto out;
295 	}
296 
297 	/*
298 	 * Directory open.  See smbfs_readvdir()
299 	 */
300 	if (vp->v_type == VDIR) {
301 		if (np->n_dirseq == NULL) {
302 			/* first open */
303 			error = smbfs_smb_findopen(np, "*", 1,
304 			    SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR,
305 			    &scred, &np->n_dirseq);
306 			if (error != 0)
307 				goto out;
308 		}
309 		np->n_dirofs = FIRST_DIROFS;
310 		np->n_dirrefs++;
311 		goto have_fid;
312 	}
313 
314 	/*
315 	 * If caller specified O_TRUNC/FTRUNC, then be sure to set
316 	 * FWRITE (to drive successful setattr(size=0) after open)
317 	 */
318 	if (flag & FTRUNC)
319 		flag |= FWRITE;
320 
321 	/*
322 	 * If we already have it open, and the FID is still valid,
323 	 * check whether the rights are sufficient for FID reuse.
324 	 */
325 	if (np->n_fidrefs > 0 &&
326 	    np->n_vcgenid == ssp->ss_vcgenid) {
327 		int upgrade = 0;
328 
329 		if ((flag & FWRITE) &&
330 		    !(np->n_rights & SA_RIGHT_FILE_WRITE_DATA))
331 			upgrade = 1;
332 		if ((flag & FREAD) &&
333 		    !(np->n_rights & SA_RIGHT_FILE_READ_DATA))
334 			upgrade = 1;
335 		if (!upgrade) {
336 			/*
337 			 *  the existing open is good enough
338 			 */
339 			np->n_fidrefs++;
340 			goto have_fid;
341 		}
342 	}
343 	rights = np->n_fidrefs ? np->n_rights : 0;
344 
345 	/*
346 	 * we always ask for READ_CONTROL so we can always get the
347 	 * owner/group IDs to satisfy a stat.  Ditto attributes.
348 	 */
349 	rights |= (STD_RIGHT_READ_CONTROL_ACCESS |
350 	    SA_RIGHT_FILE_READ_ATTRIBUTES);
351 	if ((flag & FREAD))
352 		rights |= SA_RIGHT_FILE_READ_DATA;
353 	if ((flag & FWRITE))
354 		rights |= SA_RIGHT_FILE_WRITE_DATA |
355 		    SA_RIGHT_FILE_APPEND_DATA |
356 		    SA_RIGHT_FILE_WRITE_ATTRIBUTES;
357 
358 	bzero(&fa, sizeof (fa));
359 	error = smbfs_smb_open(np,
360 	    NULL, 0, 0, /* name nmlen xattr */
361 	    rights, &scred,
362 	    &fid, &rightsrcvd, &fa);
363 	if (error)
364 		goto out;
365 	smbfs_attrcache_fa(vp, &fa);
366 
367 	/*
368 	 * We have a new FID and access rights.
369 	 */
370 	oldfid = np->n_fid;
371 	oldgenid = np->n_vcgenid;
372 	np->n_fid = fid;
373 	np->n_vcgenid = ssp->ss_vcgenid;
374 	np->n_rights = rightsrcvd;
375 	np->n_fidrefs++;
376 	if (np->n_fidrefs > 1 &&
377 	    oldgenid == ssp->ss_vcgenid) {
378 		/*
379 		 * We already had it open (presumably because
380 		 * it was open with insufficient rights.)
381 		 * Close old wire-open.
382 		 */
383 		tmperror = smbfs_smb_close(ssp,
384 		    oldfid, NULL, &scred);
385 		if (tmperror)
386 			SMBVDEBUG("error %d closing %s\n",
387 			    tmperror, np->n_rpath);
388 	}
389 
390 	/*
391 	 * This thread did the open.
392 	 * Save our credentials too.
393 	 */
394 	mutex_enter(&np->r_statelock);
395 	oldcr = np->r_cred;
396 	np->r_cred = cr;
397 	crhold(cr);
398 	if (oldcr)
399 		crfree(oldcr);
400 	mutex_exit(&np->r_statelock);
401 
402 have_fid:
403 	/*
404 	 * Keep track of the vnode type at first open.
405 	 * (see comments above)
406 	 */
407 	if (np->n_ovtype == VNON)
408 		np->n_ovtype = vp->v_type;
409 
410 out:
411 	smb_credrele(&scred);
412 	smbfs_rw_exit(&np->r_lkserlock);
413 	return (error);
414 }
415 
416 /*ARGSUSED*/
417 static int
418 smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
419 	caller_context_t *ct)
420 {
421 	smbnode_t	*np;
422 	smbmntinfo_t	*smi;
423 	struct smb_cred scred;
424 
425 	np = VTOSMB(vp);
426 	smi = VTOSMI(vp);
427 
428 	/*
429 	 * Don't "bail out" for VFS_UNMOUNTED here,
430 	 * as we want to do cleanup, etc.
431 	 */
432 
433 	/*
434 	 * zone_enter(2) prevents processes from changing zones with SMBFS files
435 	 * open; if we happen to get here from the wrong zone we can't do
436 	 * anything over the wire.
437 	 */
438 	if (smi->smi_zone_ref.zref_zone != curproc->p_zone) {
439 		/*
440 		 * We could attempt to clean up locks, except we're sure
441 		 * that the current process didn't acquire any locks on
442 		 * the file: any attempt to lock a file belong to another zone
443 		 * will fail, and one can't lock an SMBFS file and then change
444 		 * zones, as that fails too.
445 		 *
446 		 * Returning an error here is the sane thing to do.  A
447 		 * subsequent call to VN_RELE() which translates to a
448 		 * smbfs_inactive() will clean up state: if the zone of the
449 		 * vnode's origin is still alive and kicking, an async worker
450 		 * thread will handle the request (from the correct zone), and
451 		 * everything (minus the final smbfs_getattr_otw() call) should
452 		 * be OK. If the zone is going away smbfs_async_inactive() will
453 		 * throw away cached pages inline.
454 		 */
455 		return (EIO);
456 	}
457 
458 	/*
459 	 * If we are using local locking for this filesystem, then
460 	 * release all of the SYSV style record locks.  Otherwise,
461 	 * we are doing network locking and we need to release all
462 	 * of the network locks.  All of the locks held by this
463 	 * process on this file are released no matter what the
464 	 * incoming reference count is.
465 	 */
466 	if (smi->smi_flags & SMI_LLOCK) {
467 		pid_t pid = ddi_get_pid();
468 		cleanlocks(vp, pid, 0);
469 		cleanshares(vp, pid);
470 	}
471 
472 	/*
473 	 * This (passed in) count is the ref. count from the
474 	 * user's file_t before the closef call (fio.c).
475 	 * We only care when the reference goes away.
476 	 */
477 	if (count > 1)
478 		return (0);
479 
480 	/*
481 	 * Decrement the reference count for the FID
482 	 * and possibly do the OtW close.
483 	 *
484 	 * Exclusive lock for modifying n_fid stuff.
485 	 * Don't want this one ever interruptible.
486 	 */
487 	(void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
488 	smb_credinit(&scred, cr);
489 
490 	smbfs_rele_fid(np, &scred);
491 
492 	smb_credrele(&scred);
493 	smbfs_rw_exit(&np->r_lkserlock);
494 
495 	return (0);
496 }
497 
498 /*
499  * Helper for smbfs_close.  Decrement the reference count
500  * for an SMB-level file or directory ID, and when the last
501  * reference for the fid goes away, do the OtW close.
502  * Also called in smbfs_inactive (defensive cleanup).
503  */
504 static void
505 smbfs_rele_fid(smbnode_t *np, struct smb_cred *scred)
506 {
507 	smb_share_t	*ssp;
508 	cred_t		*oldcr;
509 	struct smbfs_fctx *fctx;
510 	int		error;
511 	uint16_t ofid;
512 
513 	ssp = np->n_mount->smi_share;
514 	error = 0;
515 
516 	/* Make sure we serialize for n_dirseq use. */
517 	ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER));
518 
519 	/*
520 	 * Note that vp->v_type may change if a remote node
521 	 * is deleted and recreated as a different type, and
522 	 * our getattr may change v_type accordingly.
523 	 * Now use n_ovtype to keep track of the v_type
524 	 * we had during open (see comments above).
525 	 */
526 	switch (np->n_ovtype) {
527 	case VDIR:
528 		ASSERT(np->n_dirrefs > 0);
529 		if (--np->n_dirrefs)
530 			return;
531 		if ((fctx = np->n_dirseq) != NULL) {
532 			np->n_dirseq = NULL;
533 			np->n_dirofs = 0;
534 			error = smbfs_smb_findclose(fctx, scred);
535 		}
536 		break;
537 
538 	case VREG:
539 		ASSERT(np->n_fidrefs > 0);
540 		if (--np->n_fidrefs)
541 			return;
542 		if ((ofid = np->n_fid) != SMB_FID_UNUSED) {
543 			np->n_fid = SMB_FID_UNUSED;
544 			/* After reconnect, n_fid is invalid */
545 			if (np->n_vcgenid == ssp->ss_vcgenid) {
546 				error = smbfs_smb_close(
547 				    ssp, ofid, NULL, scred);
548 			}
549 		}
550 		break;
551 
552 	default:
553 		SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype);
554 		break;
555 	}
556 	if (error) {
557 		SMBVDEBUG("error %d closing %s\n",
558 		    error, np->n_rpath);
559 	}
560 
561 	/* Allow next open to use any v_type. */
562 	np->n_ovtype = VNON;
563 
564 	/*
565 	 * Other "last close" stuff.
566 	 */
567 	mutex_enter(&np->r_statelock);
568 	if (np->n_flag & NATTRCHANGED)
569 		smbfs_attrcache_rm_locked(np);
570 	oldcr = np->r_cred;
571 	np->r_cred = NULL;
572 	mutex_exit(&np->r_statelock);
573 	if (oldcr != NULL)
574 		crfree(oldcr);
575 }
576 
577 /* ARGSUSED */
578 static int
579 smbfs_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
580 	caller_context_t *ct)
581 {
582 	struct smb_cred scred;
583 	struct vattr	va;
584 	smbnode_t	*np;
585 	smbmntinfo_t	*smi;
586 	smb_share_t	*ssp;
587 	offset_t	endoff;
588 	ssize_t		past_eof;
589 	int		error;
590 
591 	np = VTOSMB(vp);
592 	smi = VTOSMI(vp);
593 	ssp = smi->smi_share;
594 
595 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
596 		return (EIO);
597 
598 	if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
599 		return (EIO);
600 
601 	ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
602 
603 	if (vp->v_type != VREG)
604 		return (EISDIR);
605 
606 	if (uiop->uio_resid == 0)
607 		return (0);
608 
609 	/*
610 	 * Like NFS3, just check for 63-bit overflow.
611 	 * Our SMB layer takes care to return EFBIG
612 	 * when it has to fallback to a 32-bit call.
613 	 */
614 	endoff = uiop->uio_loffset + uiop->uio_resid;
615 	if (uiop->uio_loffset < 0 || endoff < 0)
616 		return (EINVAL);
617 
618 	/* get vnode attributes from server */
619 	va.va_mask = AT_SIZE | AT_MTIME;
620 	if (error = smbfsgetattr(vp, &va, cr))
621 		return (error);
622 
623 	/* Update mtime with mtime from server here? */
624 
625 	/* if offset is beyond EOF, read nothing */
626 	if (uiop->uio_loffset >= va.va_size)
627 		return (0);
628 
629 	/*
630 	 * Limit the read to the remaining file size.
631 	 * Do this by temporarily reducing uio_resid
632 	 * by the amount the lies beyoned the EOF.
633 	 */
634 	if (endoff > va.va_size) {
635 		past_eof = (ssize_t)(endoff - va.va_size);
636 		uiop->uio_resid -= past_eof;
637 	} else
638 		past_eof = 0;
639 
640 	/* Shared lock for n_fid use in smb_rwuio */
641 	if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
642 		return (EINTR);
643 	smb_credinit(&scred, cr);
644 
645 	/* After reconnect, n_fid is invalid */
646 	if (np->n_vcgenid != ssp->ss_vcgenid)
647 		error = ESTALE;
648 	else
649 		error = smb_rwuio(ssp, np->n_fid, UIO_READ,
650 		    uiop, &scred, smb_timo_read);
651 
652 	smb_credrele(&scred);
653 	smbfs_rw_exit(&np->r_lkserlock);
654 
655 	/* undo adjustment of resid */
656 	uiop->uio_resid += past_eof;
657 
658 	return (error);
659 }
660 
661 
662 /* ARGSUSED */
663 static int
664 smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
665 	caller_context_t *ct)
666 {
667 	struct smb_cred scred;
668 	struct vattr	va;
669 	smbnode_t	*np;
670 	smbmntinfo_t	*smi;
671 	smb_share_t	*ssp;
672 	offset_t	endoff, limit;
673 	ssize_t		past_limit;
674 	int		error, timo;
675 
676 	np = VTOSMB(vp);
677 	smi = VTOSMI(vp);
678 	ssp = smi->smi_share;
679 
680 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
681 		return (EIO);
682 
683 	if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
684 		return (EIO);
685 
686 	ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER));
687 
688 	if (vp->v_type != VREG)
689 		return (EISDIR);
690 
691 	if (uiop->uio_resid == 0)
692 		return (0);
693 
694 	/*
695 	 * Handle ioflag bits: (FAPPEND|FSYNC|FDSYNC)
696 	 */
697 	if (ioflag & (FAPPEND | FSYNC)) {
698 		if (np->n_flag & NMODIFIED) {
699 			smbfs_attrcache_remove(np);
700 			/* XXX: smbfs_vinvalbuf? */
701 		}
702 	}
703 	if (ioflag & FAPPEND) {
704 		/*
705 		 * File size can be changed by another client
706 		 */
707 		va.va_mask = AT_SIZE;
708 		if (error = smbfsgetattr(vp, &va, cr))
709 			return (error);
710 		uiop->uio_loffset = va.va_size;
711 	}
712 
713 	/*
714 	 * Like NFS3, just check for 63-bit overflow.
715 	 */
716 	endoff = uiop->uio_loffset + uiop->uio_resid;
717 	if (uiop->uio_loffset < 0 || endoff < 0)
718 		return (EINVAL);
719 
720 	/*
721 	 * Check to make sure that the process will not exceed
722 	 * its limit on file size.  It is okay to write up to
723 	 * the limit, but not beyond.  Thus, the write which
724 	 * reaches the limit will be short and the next write
725 	 * will return an error.
726 	 *
727 	 * So if we're starting at or beyond the limit, EFBIG.
728 	 * Otherwise, temporarily reduce resid to the amount
729 	 * the falls after the limit.
730 	 */
731 	limit = uiop->uio_llimit;
732 	if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
733 		limit = MAXOFFSET_T;
734 	if (uiop->uio_loffset >= limit)
735 		return (EFBIG);
736 	if (endoff > limit) {
737 		past_limit = (ssize_t)(endoff - limit);
738 		uiop->uio_resid -= past_limit;
739 	} else
740 		past_limit = 0;
741 
742 	/* Timeout: longer for append. */
743 	timo = smb_timo_write;
744 	if (endoff > np->r_size)
745 		timo = smb_timo_append;
746 
747 	/* Shared lock for n_fid use in smb_rwuio */
748 	if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
749 		return (EINTR);
750 	smb_credinit(&scred, cr);
751 
752 	/* After reconnect, n_fid is invalid */
753 	if (np->n_vcgenid != ssp->ss_vcgenid)
754 		error = ESTALE;
755 	else
756 		error = smb_rwuio(ssp, np->n_fid, UIO_WRITE,
757 		    uiop, &scred, timo);
758 
759 	if (error == 0) {
760 		mutex_enter(&np->r_statelock);
761 		np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
762 		if (uiop->uio_loffset > (offset_t)np->r_size)
763 			np->r_size = (len_t)uiop->uio_loffset;
764 		mutex_exit(&np->r_statelock);
765 		if (ioflag & (FSYNC|FDSYNC)) {
766 			/* Don't error the I/O if this fails. */
767 			(void) smbfs_smb_flush(np, &scred);
768 		}
769 	}
770 
771 	smb_credrele(&scred);
772 	smbfs_rw_exit(&np->r_lkserlock);
773 
774 	/* undo adjustment of resid */
775 	uiop->uio_resid += past_limit;
776 
777 	return (error);
778 }
779 
780 
781 /* ARGSUSED */
782 static int
783 smbfs_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag,
784 	cred_t *cr, int *rvalp,	caller_context_t *ct)
785 {
786 	int		error;
787 	smbmntinfo_t 	*smi;
788 
789 	smi = VTOSMI(vp);
790 
791 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
792 		return (EIO);
793 
794 	if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
795 		return (EIO);
796 
797 	switch (cmd) {
798 		/* First three from ZFS. XXX - need these? */
799 
800 	case _FIOFFS:
801 		error = smbfs_fsync(vp, 0, cr, ct);
802 		break;
803 
804 		/*
805 		 * The following two ioctls are used by bfu.
806 		 * Silently ignore to avoid bfu errors.
807 		 */
808 	case _FIOGDIO:
809 	case _FIOSDIO:
810 		error = 0;
811 		break;
812 
813 #ifdef NOT_YET	/* XXX - from the NFS code. */
814 	case _FIODIRECTIO:
815 		error = smbfs_directio(vp, (int)arg, cr);
816 #endif
817 
818 		/*
819 		 * Allow get/set with "raw" security descriptor (SD) data.
820 		 * Useful for testing, diagnosing idmap problems, etc.
821 		 */
822 	case SMBFSIO_GETSD:
823 		error = smbfs_acl_iocget(vp, arg, flag, cr);
824 		break;
825 
826 	case SMBFSIO_SETSD:
827 		error = smbfs_acl_iocset(vp, arg, flag, cr);
828 		break;
829 
830 	default:
831 		error = ENOTTY;
832 		break;
833 	}
834 
835 	return (error);
836 }
837 
838 
839 /*
840  * Return either cached or remote attributes. If get remote attr
841  * use them to check and invalidate caches, then cache the new attributes.
842  */
843 /* ARGSUSED */
844 static int
845 smbfs_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
846 	caller_context_t *ct)
847 {
848 	smbnode_t *np;
849 	smbmntinfo_t *smi;
850 
851 	smi = VTOSMI(vp);
852 
853 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
854 		return (EIO);
855 
856 	if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
857 		return (EIO);
858 
859 	/*
860 	 * If it has been specified that the return value will
861 	 * just be used as a hint, and we are only being asked
862 	 * for size, fsid or rdevid, then return the client's
863 	 * notion of these values without checking to make sure
864 	 * that the attribute cache is up to date.
865 	 * The whole point is to avoid an over the wire GETATTR
866 	 * call.
867 	 */
868 	np = VTOSMB(vp);
869 	if (flags & ATTR_HINT) {
870 		if (vap->va_mask ==
871 		    (vap->va_mask & (AT_SIZE | AT_FSID | AT_RDEV))) {
872 			mutex_enter(&np->r_statelock);
873 			if (vap->va_mask | AT_SIZE)
874 				vap->va_size = np->r_size;
875 			if (vap->va_mask | AT_FSID)
876 				vap->va_fsid = vp->v_vfsp->vfs_dev;
877 			if (vap->va_mask | AT_RDEV)
878 				vap->va_rdev = vp->v_rdev;
879 			mutex_exit(&np->r_statelock);
880 			return (0);
881 		}
882 	}
883 
884 	return (smbfsgetattr(vp, vap, cr));
885 }
886 
887 /* smbfsgetattr() in smbfs_client.c */
888 
889 /*ARGSUSED4*/
890 static int
891 smbfs_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr,
892 		caller_context_t *ct)
893 {
894 	vfs_t		*vfsp;
895 	smbmntinfo_t	*smi;
896 	int		error;
897 	uint_t		mask;
898 	struct vattr	oldva;
899 
900 	vfsp = vp->v_vfsp;
901 	smi = VFTOSMI(vfsp);
902 
903 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
904 		return (EIO);
905 
906 	if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
907 		return (EIO);
908 
909 	mask = vap->va_mask;
910 	if (mask & AT_NOSET)
911 		return (EINVAL);
912 
913 	if (vfsp->vfs_flag & VFS_RDONLY)
914 		return (EROFS);
915 
916 	/*
917 	 * This is a _local_ access check so that only the owner of
918 	 * this mount can set attributes.  With ACLs enabled, the
919 	 * file owner can be different from the mount owner, and we
920 	 * need to check the _mount_ owner here.  See _access_rwx
921 	 */
922 	bzero(&oldva, sizeof (oldva));
923 	oldva.va_mask = AT_TYPE | AT_MODE;
924 	error = smbfsgetattr(vp, &oldva, cr);
925 	if (error)
926 		return (error);
927 	oldva.va_mask |= AT_UID | AT_GID;
928 	oldva.va_uid = smi->smi_uid;
929 	oldva.va_gid = smi->smi_gid;
930 
931 	error = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags,
932 	    smbfs_accessx, vp);
933 	if (error)
934 		return (error);
935 
936 	if (mask & (AT_UID | AT_GID)) {
937 		if (smi->smi_flags & SMI_ACL)
938 			error = smbfs_acl_setids(vp, vap, cr);
939 		else
940 			error = ENOSYS;
941 		if (error != 0) {
942 			SMBVDEBUG("error %d seting UID/GID on %s",
943 			    error, VTOSMB(vp)->n_rpath);
944 			/*
945 			 * It might be more correct to return the
946 			 * error here, but that causes complaints
947 			 * when root extracts a cpio archive, etc.
948 			 * So ignore this error, and go ahead with
949 			 * the rest of the setattr work.
950 			 */
951 		}
952 	}
953 
954 	return (smbfssetattr(vp, vap, flags, cr));
955 }
956 
957 /*
958  * Mostly from Darwin smbfs_setattr()
959  * but then modified a lot.
960  */
961 /* ARGSUSED */
962 static int
963 smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr)
964 {
965 	int		error = 0;
966 	smbnode_t	*np = VTOSMB(vp);
967 	uint_t		mask = vap->va_mask;
968 	struct timespec	*mtime, *atime;
969 	struct smb_cred	scred;
970 	int		cerror, modified = 0;
971 	unsigned short	fid;
972 	int have_fid = 0;
973 	uint32_t rights = 0;
974 	uint32_t dosattr = 0;
975 
976 	ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone);
977 
978 	/*
979 	 * There are no settable attributes on the XATTR dir,
980 	 * so just silently ignore these.  On XATTR files,
981 	 * you can set the size but nothing else.
982 	 */
983 	if (vp->v_flag & V_XATTRDIR)
984 		return (0);
985 	if (np->n_flag & N_XATTR) {
986 		if (mask & AT_TIMES)
987 			SMBVDEBUG("ignore set time on xattr\n");
988 		mask &= AT_SIZE;
989 	}
990 
991 	/*
992 	 * If our caller is trying to set multiple attributes, they
993 	 * can make no assumption about what order they are done in.
994 	 * Here we try to do them in order of decreasing likelihood
995 	 * of failure, just to minimize the chance we'll wind up
996 	 * with a partially complete request.
997 	 */
998 
999 	/* Shared lock for (possible) n_fid use. */
1000 	if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
1001 		return (EINTR);
1002 	smb_credinit(&scred, cr);
1003 
1004 	/*
1005 	 * If the caller has provided extensible attributes,
1006 	 * map those into DOS attributes supported by SMB.
1007 	 * Note: zero means "no change".
1008 	 */
1009 	if (mask & AT_XVATTR)
1010 		dosattr = xvattr_to_dosattr(np, vap);
1011 
1012 	/*
1013 	 * Will we need an open handle for this setattr?
1014 	 * If so, what rights will we need?
1015 	 */
1016 	if (dosattr || (mask & (AT_ATIME | AT_MTIME))) {
1017 		rights |=
1018 		    SA_RIGHT_FILE_WRITE_ATTRIBUTES;
1019 	}
1020 	if (mask & AT_SIZE) {
1021 		rights |=
1022 		    SA_RIGHT_FILE_WRITE_DATA |
1023 		    SA_RIGHT_FILE_APPEND_DATA;
1024 	}
1025 
1026 	/*
1027 	 * Only SIZE really requires a handle, but it's
1028 	 * simpler and more reliable to set via a handle.
1029 	 * Some servers like NT4 won't set times by path.
1030 	 * Also, we're usually setting everything anyway.
1031 	 */
1032 	if (rights != 0) {
1033 		error = smbfs_smb_tmpopen(np, rights, &scred, &fid);
1034 		if (error) {
1035 			SMBVDEBUG("error %d opening %s\n",
1036 			    error, np->n_rpath);
1037 			goto out;
1038 		}
1039 		have_fid = 1;
1040 	}
1041 
1042 	/*
1043 	 * If the server supports the UNIX extensions, right here is where
1044 	 * we'd support changes to uid, gid, mode, and possibly va_flags.
1045 	 * For now we claim to have made any such changes.
1046 	 */
1047 
1048 	if (mask & AT_SIZE) {
1049 		/*
1050 		 * If the new file size is less than what the client sees as
1051 		 * the file size, then just change the size and invalidate
1052 		 * the pages.
1053 		 * I am commenting this code at present because the function
1054 		 * smbfs_putapage() is not yet implemented.
1055 		 */
1056 
1057 		/*
1058 		 * Set the file size to vap->va_size.
1059 		 */
1060 		ASSERT(have_fid);
1061 		error = smbfs_smb_setfsize(np, fid, vap->va_size, &scred);
1062 		if (error) {
1063 			SMBVDEBUG("setsize error %d file %s\n",
1064 			    error, np->n_rpath);
1065 		} else {
1066 			/*
1067 			 * Darwin had code here to zero-extend.
1068 			 * Tests indicate the server will zero-fill,
1069 			 * so looks like we don't need to do this.
1070 			 * Good thing, as this could take forever.
1071 			 *
1072 			 * XXX: Reportedly, writing one byte of zero
1073 			 * at the end offset avoids problems here.
1074 			 */
1075 			mutex_enter(&np->r_statelock);
1076 			np->r_size = vap->va_size;
1077 			mutex_exit(&np->r_statelock);
1078 			modified = 1;
1079 		}
1080 	}
1081 
1082 	/*
1083 	 * XXX: When Solaris has create_time, set that too.
1084 	 * Note: create_time is different from ctime.
1085 	 */
1086 	mtime = ((mask & AT_MTIME) ? &vap->va_mtime : 0);
1087 	atime = ((mask & AT_ATIME) ? &vap->va_atime : 0);
1088 
1089 	if (dosattr || mtime || atime) {
1090 		/*
1091 		 * Always use the handle-based set attr call now.
1092 		 */
1093 		ASSERT(have_fid);
1094 		error = smbfs_smb_setfattr(np, fid,
1095 		    dosattr, mtime, atime, &scred);
1096 		if (error) {
1097 			SMBVDEBUG("set times error %d file %s\n",
1098 			    error, np->n_rpath);
1099 		} else {
1100 			modified = 1;
1101 		}
1102 	}
1103 
1104 out:
1105 	if (modified) {
1106 		/*
1107 		 * Invalidate attribute cache in case the server
1108 		 * doesn't set exactly the attributes we asked.
1109 		 */
1110 		smbfs_attrcache_remove(np);
1111 	}
1112 
1113 	if (have_fid) {
1114 		cerror = smbfs_smb_tmpclose(np, fid, &scred);
1115 		if (cerror)
1116 			SMBVDEBUG("error %d closing %s\n",
1117 			    cerror, np->n_rpath);
1118 	}
1119 
1120 	smb_credrele(&scred);
1121 	smbfs_rw_exit(&np->r_lkserlock);
1122 
1123 	return (error);
1124 }
1125 
1126 /*
1127  * Helper function for extensible system attributes (PSARC 2007/315)
1128  * Compute the DOS attribute word to pass to _setfattr (see above).
1129  * This returns zero IFF no change is being made to attributes.
1130  * Otherwise return the new attributes or SMB_EFA_NORMAL.
1131  */
1132 static uint32_t
1133 xvattr_to_dosattr(smbnode_t *np, struct vattr *vap)
1134 {
1135 	xvattr_t *xvap = (xvattr_t *)vap;
1136 	xoptattr_t *xoap = NULL;
1137 	uint32_t attr = np->r_attr.fa_attr;
1138 	boolean_t anyset = B_FALSE;
1139 
1140 	if ((xoap = xva_getxoptattr(xvap)) == NULL)
1141 		return (0);
1142 
1143 	if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) {
1144 		if (xoap->xoa_archive)
1145 			attr |= SMB_FA_ARCHIVE;
1146 		else
1147 			attr &= ~SMB_FA_ARCHIVE;
1148 		XVA_SET_RTN(xvap, XAT_ARCHIVE);
1149 		anyset = B_TRUE;
1150 	}
1151 	if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
1152 		if (xoap->xoa_system)
1153 			attr |= SMB_FA_SYSTEM;
1154 		else
1155 			attr &= ~SMB_FA_SYSTEM;
1156 		XVA_SET_RTN(xvap, XAT_SYSTEM);
1157 		anyset = B_TRUE;
1158 	}
1159 	if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
1160 		if (xoap->xoa_readonly)
1161 			attr |= SMB_FA_RDONLY;
1162 		else
1163 			attr &= ~SMB_FA_RDONLY;
1164 		XVA_SET_RTN(xvap, XAT_READONLY);
1165 		anyset = B_TRUE;
1166 	}
1167 	if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
1168 		if (xoap->xoa_hidden)
1169 			attr |= SMB_FA_HIDDEN;
1170 		else
1171 			attr &= ~SMB_FA_HIDDEN;
1172 		XVA_SET_RTN(xvap, XAT_HIDDEN);
1173 		anyset = B_TRUE;
1174 	}
1175 
1176 	if (anyset == B_FALSE)
1177 		return (0);	/* no change */
1178 	if (attr == 0)
1179 		attr = SMB_EFA_NORMAL;
1180 
1181 	return (attr);
1182 }
1183 
1184 /*
1185  * smbfs_access_rwx()
1186  * Common function for smbfs_access, etc.
1187  *
1188  * The security model implemented by the FS is unusual
1189  * due to the current "single user mounts" restriction:
1190  * All access under a given mount point uses the CIFS
1191  * credentials established by the owner of the mount.
1192  *
1193  * Most access checking is handled by the CIFS server,
1194  * but we need sufficient Unix access checks here to
1195  * prevent other local Unix users from having access
1196  * to objects under this mount that the uid/gid/mode
1197  * settings in the mount would not allow.
1198  *
1199  * With this model, there is a case where we need the
1200  * ability to do an access check before we have the
1201  * vnode for an object.  This function takes advantage
1202  * of the fact that the uid/gid/mode is per mount, and
1203  * avoids the need for a vnode.
1204  *
1205  * We still (sort of) need a vnode when we call
1206  * secpolicy_vnode_access, but that only uses
1207  * the vtype field, so we can use a pair of fake
1208  * vnodes that have only v_type filled in.
1209  *
1210  * XXX: Later, add a new secpolicy_vtype_access()
1211  * that takes the vtype instead of a vnode, and
1212  * get rid of the tmpl_vxxx fake vnodes below.
1213  */
1214 static int
1215 smbfs_access_rwx(vfs_t *vfsp, int vtype, int mode, cred_t *cr)
1216 {
1217 	/* See the secpolicy call below. */
1218 	static const vnode_t tmpl_vdir = { .v_type = VDIR };
1219 	static const vnode_t tmpl_vreg = { .v_type = VREG };
1220 	vattr_t		va;
1221 	vnode_t		*tvp;
1222 	struct smbmntinfo *smi = VFTOSMI(vfsp);
1223 	int shift = 0;
1224 
1225 	/*
1226 	 * Build our (fabricated) vnode attributes.
1227 	 * XXX: Could make these templates in the
1228 	 * per-mount struct and use them here.
1229 	 */
1230 	bzero(&va, sizeof (va));
1231 	va.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
1232 	va.va_type = vtype;
1233 	va.va_mode = (vtype == VDIR) ?
1234 	    smi->smi_dmode : smi->smi_fmode;
1235 	va.va_uid = smi->smi_uid;
1236 	va.va_gid = smi->smi_gid;
1237 
1238 	/*
1239 	 * Disallow write attempts on read-only file systems,
1240 	 * unless the file is a device or fifo node.  Note:
1241 	 * Inline vn_is_readonly and IS_DEVVP here because
1242 	 * we may not have a vnode ptr.  Original expr. was:
1243 	 * (mode & VWRITE) && vn_is_readonly(vp) && !IS_DEVVP(vp))
1244 	 */
1245 	if ((mode & VWRITE) &&
1246 	    (vfsp->vfs_flag & VFS_RDONLY) &&
1247 	    !(vtype == VCHR || vtype == VBLK || vtype == VFIFO))
1248 		return (EROFS);
1249 
1250 	/*
1251 	 * Disallow attempts to access mandatory lock files.
1252 	 * Similarly, expand MANDLOCK here.
1253 	 * XXX: not sure we need this.
1254 	 */
1255 	if ((mode & (VWRITE | VREAD | VEXEC)) &&
1256 	    va.va_type == VREG && MANDMODE(va.va_mode))
1257 		return (EACCES);
1258 
1259 	/*
1260 	 * Access check is based on only
1261 	 * one of owner, group, public.
1262 	 * If not owner, then check group.
1263 	 * If not a member of the group,
1264 	 * then check public access.
1265 	 */
1266 	if (crgetuid(cr) != va.va_uid) {
1267 		shift += 3;
1268 		if (!groupmember(va.va_gid, cr))
1269 			shift += 3;
1270 	}
1271 
1272 	/*
1273 	 * We need a vnode for secpolicy_vnode_access,
1274 	 * but the only thing it looks at is v_type,
1275 	 * so pass one of the templates above.
1276 	 */
1277 	tvp = (va.va_type == VDIR) ?
1278 	    (vnode_t *)&tmpl_vdir :
1279 	    (vnode_t *)&tmpl_vreg;
1280 
1281 	return (secpolicy_vnode_access2(cr, tvp, va.va_uid,
1282 	    va.va_mode << shift, mode));
1283 }
1284 
1285 /*
1286  * See smbfs_setattr
1287  */
1288 static int
1289 smbfs_accessx(void *arg, int mode, cred_t *cr)
1290 {
1291 	vnode_t *vp = arg;
1292 	/*
1293 	 * Note: The caller has checked the current zone,
1294 	 * the SMI_DEAD and VFS_UNMOUNTED flags, etc.
1295 	 */
1296 	return (smbfs_access_rwx(vp->v_vfsp, vp->v_type, mode, cr));
1297 }
1298 
1299 /*
1300  * XXX
1301  * This op should support PSARC 2007/403, Modified Access Checks for CIFS
1302  */
1303 /* ARGSUSED */
1304 static int
1305 smbfs_access(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
1306 {
1307 	vfs_t		*vfsp;
1308 	smbmntinfo_t	*smi;
1309 
1310 	vfsp = vp->v_vfsp;
1311 	smi = VFTOSMI(vfsp);
1312 
1313 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1314 		return (EIO);
1315 
1316 	if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
1317 		return (EIO);
1318 
1319 	return (smbfs_access_rwx(vfsp, vp->v_type, mode, cr));
1320 }
1321 
1322 
1323 /*
1324  * Flush local dirty pages to stable storage on the server.
1325  *
1326  * If FNODSYNC is specified, then there is nothing to do because
1327  * metadata changes are not cached on the client before being
1328  * sent to the server.
1329  */
1330 /* ARGSUSED */
1331 static int
1332 smbfs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
1333 {
1334 	int		error = 0;
1335 	smbmntinfo_t	*smi;
1336 	smbnode_t 	*np;
1337 	struct smb_cred scred;
1338 
1339 	np = VTOSMB(vp);
1340 	smi = VTOSMI(vp);
1341 
1342 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1343 		return (EIO);
1344 
1345 	if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
1346 		return (EIO);
1347 
1348 	if ((syncflag & FNODSYNC) || IS_SWAPVP(vp))
1349 		return (0);
1350 
1351 	if ((syncflag & (FSYNC|FDSYNC)) == 0)
1352 		return (0);
1353 
1354 	/* Shared lock for n_fid use in _flush */
1355 	if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
1356 		return (EINTR);
1357 	smb_credinit(&scred, cr);
1358 
1359 	error = smbfs_smb_flush(np, &scred);
1360 
1361 	smb_credrele(&scred);
1362 	smbfs_rw_exit(&np->r_lkserlock);
1363 
1364 	return (error);
1365 }
1366 
1367 /*
1368  * Last reference to vnode went away.
1369  */
1370 /* ARGSUSED */
1371 static void
1372 smbfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
1373 {
1374 	smbnode_t	*np;
1375 	struct smb_cred scred;
1376 
1377 	/*
1378 	 * Don't "bail out" for VFS_UNMOUNTED here,
1379 	 * as we want to do cleanup, etc.
1380 	 * See also pcfs_inactive
1381 	 */
1382 
1383 	np = VTOSMB(vp);
1384 
1385 	/*
1386 	 * If this is coming from the wrong zone, we let someone in the right
1387 	 * zone take care of it asynchronously.  We can get here due to
1388 	 * VN_RELE() being called from pageout() or fsflush().  This call may
1389 	 * potentially turn into an expensive no-op if, for instance, v_count
1390 	 * gets incremented in the meantime, but it's still correct.
1391 	 */
1392 
1393 	/*
1394 	 * Defend against the possibility that higher-level callers
1395 	 * might not correctly balance open and close calls.  If we
1396 	 * get here with open references remaining, it means there
1397 	 * was a missing VOP_CLOSE somewhere.  If that happens, do
1398 	 * the close here so we don't "leak" FIDs on the server.
1399 	 *
1400 	 * Exclusive lock for modifying n_fid stuff.
1401 	 * Don't want this one ever interruptible.
1402 	 */
1403 	(void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
1404 	smb_credinit(&scred, cr);
1405 
1406 	switch (np->n_ovtype) {
1407 	case VNON:
1408 		/* not open (OK) */
1409 		break;
1410 
1411 	case VDIR:
1412 		if (np->n_dirrefs == 0)
1413 			break;
1414 		SMBVDEBUG("open dir: refs %d path %s\n",
1415 		    np->n_dirrefs, np->n_rpath);
1416 		/* Force last close. */
1417 		np->n_dirrefs = 1;
1418 		smbfs_rele_fid(np, &scred);
1419 		break;
1420 
1421 	case VREG:
1422 		if (np->n_fidrefs == 0)
1423 			break;
1424 		SMBVDEBUG("open file: refs %d id 0x%x path %s\n",
1425 		    np->n_fidrefs, np->n_fid, np->n_rpath);
1426 		/* Force last close. */
1427 		np->n_fidrefs = 1;
1428 		smbfs_rele_fid(np, &scred);
1429 		break;
1430 
1431 	default:
1432 		SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype);
1433 		np->n_ovtype = VNON;
1434 		break;
1435 	}
1436 
1437 	smb_credrele(&scred);
1438 	smbfs_rw_exit(&np->r_lkserlock);
1439 
1440 	smbfs_addfree(np);
1441 }
1442 
1443 /*
1444  * Remote file system operations having to do with directory manipulation.
1445  */
1446 /* ARGSUSED */
1447 static int
1448 smbfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
1449 	int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
1450 	int *direntflags, pathname_t *realpnp)
1451 {
1452 	vfs_t		*vfs;
1453 	smbmntinfo_t	*smi;
1454 	smbnode_t	*dnp;
1455 	int		error;
1456 
1457 	vfs = dvp->v_vfsp;
1458 	smi = VFTOSMI(vfs);
1459 
1460 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1461 		return (EPERM);
1462 
1463 	if (smi->smi_flags & SMI_DEAD || vfs->vfs_flag & VFS_UNMOUNTED)
1464 		return (EIO);
1465 
1466 	dnp = VTOSMB(dvp);
1467 
1468 	/*
1469 	 * Are we looking up extended attributes?  If so, "dvp" is
1470 	 * the file or directory for which we want attributes, and
1471 	 * we need a lookup of the (faked up) attribute directory
1472 	 * before we lookup the rest of the path.
1473 	 */
1474 	if (flags & LOOKUP_XATTR) {
1475 		/*
1476 		 * Require the xattr mount option.
1477 		 */
1478 		if ((vfs->vfs_flag & VFS_XATTR) == 0)
1479 			return (EINVAL);
1480 
1481 		error = smbfs_get_xattrdir(dvp, vpp, cr, flags);
1482 		return (error);
1483 	}
1484 
1485 	if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_READER, SMBINTR(dvp)))
1486 		return (EINTR);
1487 
1488 	error = smbfslookup(dvp, nm, vpp, cr, 1, ct);
1489 
1490 	smbfs_rw_exit(&dnp->r_rwlock);
1491 
1492 	return (error);
1493 }
1494 
1495 /* ARGSUSED */
1496 static int
1497 smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr,
1498 	int cache_ok, caller_context_t *ct)
1499 {
1500 	int		error;
1501 	int		supplen; /* supported length */
1502 	vnode_t		*vp;
1503 	smbnode_t	*np;
1504 	smbnode_t	*dnp;
1505 	smbmntinfo_t	*smi;
1506 	/* struct smb_vc	*vcp; */
1507 	const char	*ill;
1508 	const char	*name = (const char *)nm;
1509 	int 		nmlen = strlen(nm);
1510 	int 		rplen;
1511 	struct smb_cred scred;
1512 	struct smbfattr fa;
1513 
1514 	smi = VTOSMI(dvp);
1515 	dnp = VTOSMB(dvp);
1516 
1517 	ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone);
1518 
1519 #ifdef NOT_YET
1520 	vcp = SSTOVC(smi->smi_share);
1521 
1522 	/* XXX: Should compute this once and store it in smbmntinfo_t */
1523 	supplen = (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) ? 255 : 12;
1524 #else
1525 	supplen = 255;
1526 #endif
1527 
1528 	/*
1529 	 * RWlock must be held, either reader or writer.
1530 	 * XXX: Can we check without looking directly
1531 	 * inside the struct smbfs_rwlock_t?
1532 	 */
1533 	ASSERT(dnp->r_rwlock.count != 0);
1534 
1535 	/*
1536 	 * If lookup is for "", just return dvp.
1537 	 * No need to perform any access checks.
1538 	 */
1539 	if (nmlen == 0) {
1540 		VN_HOLD(dvp);
1541 		*vpp = dvp;
1542 		return (0);
1543 	}
1544 
1545 	/*
1546 	 * Can't do lookups in non-directories.
1547 	 */
1548 	if (dvp->v_type != VDIR)
1549 		return (ENOTDIR);
1550 
1551 	/*
1552 	 * Need search permission in the directory.
1553 	 */
1554 	error = smbfs_access(dvp, VEXEC, 0, cr, ct);
1555 	if (error)
1556 		return (error);
1557 
1558 	/*
1559 	 * If lookup is for ".", just return dvp.
1560 	 * Access check was done above.
1561 	 */
1562 	if (nmlen == 1 && name[0] == '.') {
1563 		VN_HOLD(dvp);
1564 		*vpp = dvp;
1565 		return (0);
1566 	}
1567 
1568 	/*
1569 	 * Now some sanity checks on the name.
1570 	 * First check the length.
1571 	 */
1572 	if (nmlen > supplen)
1573 		return (ENAMETOOLONG);
1574 
1575 	/*
1576 	 * Avoid surprises with characters that are
1577 	 * illegal in Windows file names.
1578 	 * Todo: CATIA mappings  XXX
1579 	 */
1580 	ill = illegal_chars;
1581 	if (dnp->n_flag & N_XATTR)
1582 		ill++; /* allow colon */
1583 	if (strpbrk(nm, ill))
1584 		return (EINVAL);
1585 
1586 	/*
1587 	 * Special handling for lookup of ".."
1588 	 *
1589 	 * We keep full pathnames (as seen on the server)
1590 	 * so we can just trim off the last component to
1591 	 * get the full pathname of the parent.  Note:
1592 	 * We don't actually copy and modify, but just
1593 	 * compute the trimmed length and pass that with
1594 	 * the current dir path (not null terminated).
1595 	 *
1596 	 * We don't go over-the-wire to get attributes
1597 	 * for ".." because we know it's a directory,
1598 	 * and we can just leave the rest "stale"
1599 	 * until someone does a getattr.
1600 	 */
1601 	if (nmlen == 2 && name[0] == '.' && name[1] == '.') {
1602 		if (dvp->v_flag & VROOT) {
1603 			/*
1604 			 * Already at the root.  This can happen
1605 			 * with directory listings at the root,
1606 			 * which lookup "." and ".." to get the
1607 			 * inode numbers.  Let ".." be the same
1608 			 * as "." in the FS root.
1609 			 */
1610 			VN_HOLD(dvp);
1611 			*vpp = dvp;
1612 			return (0);
1613 		}
1614 
1615 		/*
1616 		 * Special case for XATTR directory
1617 		 */
1618 		if (dvp->v_flag & V_XATTRDIR) {
1619 			error = smbfs_xa_parent(dvp, vpp);
1620 			return (error);
1621 		}
1622 
1623 		/*
1624 		 * Find the parent path length.
1625 		 */
1626 		rplen = dnp->n_rplen;
1627 		ASSERT(rplen > 0);
1628 		while (--rplen >= 0) {
1629 			if (dnp->n_rpath[rplen] == '\\')
1630 				break;
1631 		}
1632 		if (rplen <= 0) {
1633 			/* Found our way to the root. */
1634 			vp = SMBTOV(smi->smi_root);
1635 			VN_HOLD(vp);
1636 			*vpp = vp;
1637 			return (0);
1638 		}
1639 		np = smbfs_node_findcreate(smi,
1640 		    dnp->n_rpath, rplen, NULL, 0, 0,
1641 		    &smbfs_fattr0); /* force create */
1642 		ASSERT(np != NULL);
1643 		vp = SMBTOV(np);
1644 		vp->v_type = VDIR;
1645 
1646 		/* Success! */
1647 		*vpp = vp;
1648 		return (0);
1649 	}
1650 
1651 	/*
1652 	 * Normal lookup of a name under this directory.
1653 	 * Note we handled "", ".", ".." above.
1654 	 */
1655 	if (cache_ok) {
1656 		/*
1657 		 * The caller indicated that it's OK to use a
1658 		 * cached result for this lookup, so try to
1659 		 * reclaim a node from the smbfs node cache.
1660 		 */
1661 		error = smbfslookup_cache(dvp, nm, nmlen, &vp, cr);
1662 		if (error)
1663 			return (error);
1664 		if (vp != NULL) {
1665 			/* hold taken in lookup_cache */
1666 			*vpp = vp;
1667 			return (0);
1668 		}
1669 	}
1670 
1671 	/*
1672 	 * OK, go over-the-wire to get the attributes,
1673 	 * then create the node.
1674 	 */
1675 	smb_credinit(&scred, cr);
1676 	/* Note: this can allocate a new "name" */
1677 	error = smbfs_smb_lookup(dnp, &name, &nmlen, &fa, &scred);
1678 	smb_credrele(&scred);
1679 	if (error == ENOTDIR) {
1680 		/*
1681 		 * Lookup failed because this directory was
1682 		 * removed or renamed by another client.
1683 		 * Remove any cached attributes under it.
1684 		 */
1685 		smbfs_attrcache_remove(dnp);
1686 		smbfs_attrcache_prune(dnp);
1687 	}
1688 	if (error)
1689 		goto out;
1690 
1691 	error = smbfs_nget(dvp, name, nmlen, &fa, &vp);
1692 	if (error)
1693 		goto out;
1694 
1695 	/* Success! */
1696 	*vpp = vp;
1697 
1698 out:
1699 	/* smbfs_smb_lookup may have allocated name. */
1700 	if (name != nm)
1701 		smbfs_name_free(name, nmlen);
1702 
1703 	return (error);
1704 }
1705 
1706 /*
1707  * smbfslookup_cache
1708  *
1709  * Try to reclaim a node from the smbfs node cache.
1710  * Some statistics for DEBUG.
1711  *
1712  * This mechanism lets us avoid many of the five (or more)
1713  * OtW lookup calls per file seen with "ls -l" if we search
1714  * the smbfs node cache for recently inactive(ated) nodes.
1715  */
1716 #ifdef DEBUG
1717 int smbfs_lookup_cache_calls = 0;
1718 int smbfs_lookup_cache_error = 0;
1719 int smbfs_lookup_cache_miss = 0;
1720 int smbfs_lookup_cache_stale = 0;
1721 int smbfs_lookup_cache_hits = 0;
1722 #endif /* DEBUG */
1723 
1724 /* ARGSUSED */
1725 static int
1726 smbfslookup_cache(vnode_t *dvp, char *nm, int nmlen,
1727 	vnode_t **vpp, cred_t *cr)
1728 {
1729 	struct vattr va;
1730 	smbnode_t *dnp;
1731 	smbnode_t *np;
1732 	vnode_t *vp;
1733 	int error;
1734 	char sep;
1735 
1736 	dnp = VTOSMB(dvp);
1737 	*vpp = NULL;
1738 
1739 #ifdef DEBUG
1740 	smbfs_lookup_cache_calls++;
1741 #endif
1742 
1743 	/*
1744 	 * First make sure we can get attributes for the
1745 	 * directory.  Cached attributes are OK here.
1746 	 * If we removed or renamed the directory, this
1747 	 * will return ENOENT.  If someone else removed
1748 	 * this directory or file, we'll find out when we
1749 	 * try to open or get attributes.
1750 	 */
1751 	va.va_mask = AT_TYPE | AT_MODE;
1752 	error = smbfsgetattr(dvp, &va, cr);
1753 	if (error) {
1754 #ifdef DEBUG
1755 		smbfs_lookup_cache_error++;
1756 #endif
1757 		return (error);
1758 	}
1759 
1760 	/*
1761 	 * Passing NULL smbfattr here so we will
1762 	 * just look, not create.
1763 	 */
1764 	sep = SMBFS_DNP_SEP(dnp);
1765 	np = smbfs_node_findcreate(dnp->n_mount,
1766 	    dnp->n_rpath, dnp->n_rplen,
1767 	    nm, nmlen, sep, NULL);
1768 	if (np == NULL) {
1769 #ifdef DEBUG
1770 		smbfs_lookup_cache_miss++;
1771 #endif
1772 		return (0);
1773 	}
1774 
1775 	/*
1776 	 * Found it.  Attributes still valid?
1777 	 */
1778 	vp = SMBTOV(np);
1779 	if (np->r_attrtime <= gethrtime()) {
1780 		/* stale */
1781 #ifdef DEBUG
1782 		smbfs_lookup_cache_stale++;
1783 #endif
1784 		VN_RELE(vp);
1785 		return (0);
1786 	}
1787 
1788 	/*
1789 	 * Success!
1790 	 * Caller gets hold from smbfs_node_findcreate
1791 	 */
1792 #ifdef DEBUG
1793 	smbfs_lookup_cache_hits++;
1794 #endif
1795 	*vpp = vp;
1796 	return (0);
1797 }
1798 
1799 /*
1800  * XXX
1801  * vsecattr_t is new to build 77, and we need to eventually support
1802  * it in order to create an ACL when an object is created.
1803  *
1804  * This op should support the new FIGNORECASE flag for case-insensitive
1805  * lookups, per PSARC 2007/244.
1806  */
1807 /* ARGSUSED */
1808 static int
1809 smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive,
1810 	int mode, vnode_t **vpp, cred_t *cr, int lfaware, caller_context_t *ct,
1811 	vsecattr_t *vsecp)
1812 {
1813 	int		error;
1814 	int		cerror;
1815 	vfs_t		*vfsp;
1816 	vnode_t		*vp;
1817 #ifdef NOT_YET
1818 	smbnode_t	*np;
1819 #endif
1820 	smbnode_t	*dnp;
1821 	smbmntinfo_t	*smi;
1822 	struct vattr	vattr;
1823 	struct smbfattr	fattr;
1824 	struct smb_cred	scred;
1825 	const char *name = (const char *)nm;
1826 	int		nmlen = strlen(nm);
1827 	uint32_t	disp;
1828 	uint16_t	fid;
1829 	int		xattr;
1830 
1831 	vfsp = dvp->v_vfsp;
1832 	smi = VFTOSMI(vfsp);
1833 	dnp = VTOSMB(dvp);
1834 	vp = NULL;
1835 
1836 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
1837 		return (EPERM);
1838 
1839 	if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
1840 		return (EIO);
1841 
1842 	/*
1843 	 * Note: this may break mknod(2) calls to create a directory,
1844 	 * but that's obscure use.  Some other filesystems do this.
1845 	 * XXX: Later, redirect VDIR type here to _mkdir.
1846 	 */
1847 	if (va->va_type != VREG)
1848 		return (EINVAL);
1849 
1850 	/*
1851 	 * If the pathname is "", just use dvp, no checks.
1852 	 * Do this outside of the rwlock (like zfs).
1853 	 */
1854 	if (nmlen == 0) {
1855 		VN_HOLD(dvp);
1856 		*vpp = dvp;
1857 		return (0);
1858 	}
1859 
1860 	/* Don't allow "." or ".." through here. */
1861 	if ((nmlen == 1 && name[0] == '.') ||
1862 	    (nmlen == 2 && name[0] == '.' && name[1] == '.'))
1863 		return (EISDIR);
1864 
1865 	/*
1866 	 * We make a copy of the attributes because the caller does not
1867 	 * expect us to change what va points to.
1868 	 */
1869 	vattr = *va;
1870 
1871 	if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
1872 		return (EINTR);
1873 	smb_credinit(&scred, cr);
1874 
1875 	/*
1876 	 * XXX: Do we need r_lkserlock too?
1877 	 * No use of any shared fid or fctx...
1878 	 */
1879 
1880 	/*
1881 	 * NFS needs to go over the wire, just to be sure whether the
1882 	 * file exists or not.  Using a cached result is dangerous in
1883 	 * this case when making a decision regarding existence.
1884 	 *
1885 	 * The SMB protocol does NOT really need to go OTW here
1886 	 * thanks to the expressive NTCREATE disposition values.
1887 	 * Unfortunately, to do Unix access checks correctly,
1888 	 * we need to know if the object already exists.
1889 	 * When the object does not exist, we need VWRITE on
1890 	 * the directory.  Note: smbfslookup() checks VEXEC.
1891 	 */
1892 	error = smbfslookup(dvp, nm, &vp, cr, 0, ct);
1893 	if (error == 0) {
1894 		/*
1895 		 * The file already exists.  Error?
1896 		 * NB: have a hold from smbfslookup
1897 		 */
1898 		if (exclusive == EXCL) {
1899 			error = EEXIST;
1900 			VN_RELE(vp);
1901 			goto out;
1902 		}
1903 		/*
1904 		 * Verify requested access.
1905 		 */
1906 		error = smbfs_access(vp, mode, 0, cr, ct);
1907 		if (error) {
1908 			VN_RELE(vp);
1909 			goto out;
1910 		}
1911 
1912 		/*
1913 		 * Truncate (if requested).
1914 		 */
1915 		if ((vattr.va_mask & AT_SIZE) && vattr.va_size == 0) {
1916 			vattr.va_mask = AT_SIZE;
1917 			error = smbfssetattr(vp, &vattr, 0, cr);
1918 			if (error) {
1919 				VN_RELE(vp);
1920 				goto out;
1921 			}
1922 		}
1923 		/* Success! */
1924 #ifdef NOT_YET
1925 		vnevent_create(vp, ct);
1926 #endif
1927 		*vpp = vp;
1928 		goto out;
1929 	}
1930 
1931 	/*
1932 	 * The file did not exist.  Need VWRITE in the directory.
1933 	 */
1934 	error = smbfs_access(dvp, VWRITE, 0, cr, ct);
1935 	if (error)
1936 		goto out;
1937 
1938 	/*
1939 	 * Now things get tricky.  We also need to check the
1940 	 * requested open mode against the file we may create.
1941 	 * See comments at smbfs_access_rwx
1942 	 */
1943 	error = smbfs_access_rwx(vfsp, VREG, mode, cr);
1944 	if (error)
1945 		goto out;
1946 
1947 	/*
1948 	 * Now the code derived from Darwin,
1949 	 * but with greater use of NT_CREATE
1950 	 * disposition options.  Much changed.
1951 	 *
1952 	 * Create (or open) a new child node.
1953 	 * Note we handled "." and ".." above.
1954 	 */
1955 
1956 	if (exclusive == EXCL)
1957 		disp = NTCREATEX_DISP_CREATE;
1958 	else {
1959 		/* Truncate regular files if requested. */
1960 		if ((va->va_type == VREG) &&
1961 		    (va->va_mask & AT_SIZE) &&
1962 		    (va->va_size == 0))
1963 			disp = NTCREATEX_DISP_OVERWRITE_IF;
1964 		else
1965 			disp = NTCREATEX_DISP_OPEN_IF;
1966 	}
1967 	xattr = (dnp->n_flag & N_XATTR) ? 1 : 0;
1968 	error = smbfs_smb_create(dnp,
1969 	    name, nmlen, xattr,
1970 	    disp, &scred, &fid);
1971 	if (error)
1972 		goto out;
1973 
1974 	/*
1975 	 * XXX: Missing some code here to deal with
1976 	 * the case where we opened an existing file,
1977 	 * it's size is larger than 32-bits, and we're
1978 	 * setting the size from a process that's not
1979 	 * aware of large file offsets.  i.e.
1980 	 * from the NFS3 code:
1981 	 */
1982 #if NOT_YET /* XXX */
1983 	if ((vattr.va_mask & AT_SIZE) &&
1984 	    vp->v_type == VREG) {
1985 		np = VTOSMB(vp);
1986 		/*
1987 		 * Check here for large file handled
1988 		 * by LF-unaware process (as
1989 		 * ufs_create() does)
1990 		 */
1991 		if (!(lfaware & FOFFMAX)) {
1992 			mutex_enter(&np->r_statelock);
1993 			if (np->r_size > MAXOFF32_T)
1994 				error = EOVERFLOW;
1995 			mutex_exit(&np->r_statelock);
1996 		}
1997 		if (!error) {
1998 			vattr.va_mask = AT_SIZE;
1999 			error = smbfssetattr(vp,
2000 			    &vattr, 0, cr);
2001 		}
2002 	}
2003 #endif /* XXX */
2004 	/*
2005 	 * Should use the fid to get/set the size
2006 	 * while we have it opened here.  See above.
2007 	 */
2008 
2009 	cerror = smbfs_smb_close(smi->smi_share, fid, NULL, &scred);
2010 	if (cerror)
2011 		SMBVDEBUG("error %d closing %s\\%s\n",
2012 		    cerror, dnp->n_rpath, name);
2013 
2014 	/*
2015 	 * In the open case, the name may differ a little
2016 	 * from what we passed to create (case, etc.)
2017 	 * so call lookup to get the (opened) name.
2018 	 *
2019 	 * XXX: Could avoid this extra lookup if the
2020 	 * "createact" result from NT_CREATE says we
2021 	 * created the object.
2022 	 */
2023 	error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred);
2024 	if (error)
2025 		goto out;
2026 
2027 	/* update attr and directory cache */
2028 	smbfs_attr_touchdir(dnp);
2029 
2030 	error = smbfs_nget(dvp, name, nmlen, &fattr, &vp);
2031 	if (error)
2032 		goto out;
2033 
2034 	/* XXX invalidate pages if we truncated? */
2035 
2036 	/* Success! */
2037 	*vpp = vp;
2038 	error = 0;
2039 
2040 out:
2041 	smb_credrele(&scred);
2042 	smbfs_rw_exit(&dnp->r_rwlock);
2043 	if (name != nm)
2044 		smbfs_name_free(name, nmlen);
2045 	return (error);
2046 }
2047 
2048 /*
2049  * XXX
2050  * This op should support the new FIGNORECASE flag for case-insensitive
2051  * lookups, per PSARC 2007/244.
2052  */
2053 /* ARGSUSED */
2054 static int
2055 smbfs_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct,
2056 	int flags)
2057 {
2058 	int		error;
2059 	vnode_t		*vp;
2060 	smbnode_t	*np;
2061 	smbnode_t	*dnp;
2062 	struct smb_cred	scred;
2063 	/* enum smbfsstat status; */
2064 	smbmntinfo_t	*smi;
2065 
2066 	smi = VTOSMI(dvp);
2067 
2068 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2069 		return (EPERM);
2070 
2071 	if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2072 		return (EIO);
2073 
2074 	dnp = VTOSMB(dvp);
2075 	if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2076 		return (EINTR);
2077 	smb_credinit(&scred, cr);
2078 
2079 	/*
2080 	 * Verify access to the dirctory.
2081 	 */
2082 	error = smbfs_access(dvp, VWRITE|VEXEC, 0, cr, ct);
2083 	if (error)
2084 		goto out;
2085 
2086 	/*
2087 	 * NOTE:  the darwin code gets the "vp" passed in so it looks
2088 	 * like the "vp" has probably been "lookup"ed by the VFS layer.
2089 	 * It looks like we will need to lookup the vp to check the
2090 	 * caches and check if the object being deleted is a directory.
2091 	 */
2092 	error = smbfslookup(dvp, nm, &vp, cr, 0, ct);
2093 	if (error)
2094 		goto out;
2095 
2096 	/* Never allow link/unlink directories on CIFS. */
2097 	if (vp->v_type == VDIR) {
2098 		VN_RELE(vp);
2099 		error = EPERM;
2100 		goto out;
2101 	}
2102 
2103 	/*
2104 	 * Now we have the real reference count on the vnode
2105 	 * Do we have the file open?
2106 	 */
2107 	np = VTOSMB(vp);
2108 	mutex_enter(&np->r_statelock);
2109 	if ((vp->v_count > 1) && (np->n_fidrefs > 0)) {
2110 		/*
2111 		 * NFS does a rename on remove here.
2112 		 * Probably not applicable for SMB.
2113 		 * Like Darwin, just return EBUSY.
2114 		 *
2115 		 * XXX: Todo - Use Trans2rename, and
2116 		 * if that fails, ask the server to
2117 		 * set the delete-on-close flag.
2118 		 */
2119 		mutex_exit(&np->r_statelock);
2120 		error = EBUSY;
2121 	} else {
2122 		smbfs_attrcache_rm_locked(np);
2123 		mutex_exit(&np->r_statelock);
2124 
2125 		error = smbfs_smb_delete(np, &scred, NULL, 0, 0);
2126 
2127 		/*
2128 		 * If the file should no longer exist, discard
2129 		 * any cached attributes under this node.
2130 		 */
2131 		switch (error) {
2132 		case 0:
2133 		case ENOENT:
2134 		case ENOTDIR:
2135 			smbfs_attrcache_prune(np);
2136 			break;
2137 		}
2138 	}
2139 
2140 	VN_RELE(vp);
2141 
2142 out:
2143 	smb_credrele(&scred);
2144 	smbfs_rw_exit(&dnp->r_rwlock);
2145 
2146 	return (error);
2147 }
2148 
2149 
2150 /*
2151  * XXX
2152  * This op should support the new FIGNORECASE flag for case-insensitive
2153  * lookups, per PSARC 2007/244.
2154  */
2155 /* ARGSUSED */
2156 static int
2157 smbfs_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
2158 	caller_context_t *ct, int flags)
2159 {
2160 	/* vnode_t		*realvp; */
2161 
2162 	if (curproc->p_zone != VTOSMI(odvp)->smi_zone_ref.zref_zone ||
2163 	    curproc->p_zone != VTOSMI(ndvp)->smi_zone_ref.zref_zone)
2164 		return (EPERM);
2165 
2166 	if (VTOSMI(odvp)->smi_flags & SMI_DEAD ||
2167 	    VTOSMI(ndvp)->smi_flags & SMI_DEAD ||
2168 	    odvp->v_vfsp->vfs_flag & VFS_UNMOUNTED ||
2169 	    ndvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2170 		return (EIO);
2171 
2172 	return (smbfsrename(odvp, onm, ndvp, nnm, cr, ct));
2173 }
2174 
2175 /*
2176  * smbfsrename does the real work of renaming in SMBFS
2177  */
2178 /* ARGSUSED */
2179 static int
2180 smbfsrename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr,
2181 	caller_context_t *ct)
2182 {
2183 	int		error;
2184 	int		nvp_locked = 0;
2185 	vnode_t		*nvp = NULL;
2186 	vnode_t		*ovp = NULL;
2187 	smbnode_t	*onp;
2188 	smbnode_t	*nnp;
2189 	smbnode_t	*odnp;
2190 	smbnode_t	*ndnp;
2191 	struct smb_cred	scred;
2192 	/* enum smbfsstat	status; */
2193 
2194 	ASSERT(curproc->p_zone == VTOSMI(odvp)->smi_zone_ref.zref_zone);
2195 
2196 	if (strcmp(onm, ".") == 0 || strcmp(onm, "..") == 0 ||
2197 	    strcmp(nnm, ".") == 0 || strcmp(nnm, "..") == 0)
2198 		return (EINVAL);
2199 
2200 	/*
2201 	 * Check that everything is on the same filesystem.
2202 	 * vn_rename checks the fsid's, but in case we don't
2203 	 * fill those in correctly, check here too.
2204 	 */
2205 	if (odvp->v_vfsp != ndvp->v_vfsp)
2206 		return (EXDEV);
2207 
2208 	odnp = VTOSMB(odvp);
2209 	ndnp = VTOSMB(ndvp);
2210 
2211 	/*
2212 	 * Avoid deadlock here on old vs new directory nodes
2213 	 * by always taking the locks in order of address.
2214 	 * The order is arbitrary, but must be consistent.
2215 	 */
2216 	if (odnp < ndnp) {
2217 		if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER,
2218 		    SMBINTR(odvp)))
2219 			return (EINTR);
2220 		if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER,
2221 		    SMBINTR(ndvp))) {
2222 			smbfs_rw_exit(&odnp->r_rwlock);
2223 			return (EINTR);
2224 		}
2225 	} else {
2226 		if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER,
2227 		    SMBINTR(ndvp)))
2228 			return (EINTR);
2229 		if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER,
2230 		    SMBINTR(odvp))) {
2231 			smbfs_rw_exit(&ndnp->r_rwlock);
2232 			return (EINTR);
2233 		}
2234 	}
2235 	smb_credinit(&scred, cr);
2236 	/*
2237 	 * No returns after this point (goto out)
2238 	 */
2239 
2240 	/*
2241 	 * Need write access on source and target.
2242 	 * Server takes care of most checks.
2243 	 */
2244 	error = smbfs_access(odvp, VWRITE|VEXEC, 0, cr, ct);
2245 	if (error)
2246 		goto out;
2247 	if (odvp != ndvp) {
2248 		error = smbfs_access(ndvp, VWRITE, 0, cr, ct);
2249 		if (error)
2250 			goto out;
2251 	}
2252 
2253 	/*
2254 	 * Lookup the source name.  Must already exist.
2255 	 */
2256 	error = smbfslookup(odvp, onm, &ovp, cr, 0, ct);
2257 	if (error)
2258 		goto out;
2259 
2260 	/*
2261 	 * Lookup the target file.  If it exists, it needs to be
2262 	 * checked to see whether it is a mount point and whether
2263 	 * it is active (open).
2264 	 */
2265 	error = smbfslookup(ndvp, nnm, &nvp, cr, 0, ct);
2266 	if (!error) {
2267 		/*
2268 		 * Target (nvp) already exists.  Check that it
2269 		 * has the same type as the source.  The server
2270 		 * will check this also, (and more reliably) but
2271 		 * this lets us return the correct error codes.
2272 		 */
2273 		if (ovp->v_type == VDIR) {
2274 			if (nvp->v_type != VDIR) {
2275 				error = ENOTDIR;
2276 				goto out;
2277 			}
2278 		} else {
2279 			if (nvp->v_type == VDIR) {
2280 				error = EISDIR;
2281 				goto out;
2282 			}
2283 		}
2284 
2285 		/*
2286 		 * POSIX dictates that when the source and target
2287 		 * entries refer to the same file object, rename
2288 		 * must do nothing and exit without error.
2289 		 */
2290 		if (ovp == nvp) {
2291 			error = 0;
2292 			goto out;
2293 		}
2294 
2295 		/*
2296 		 * Also must ensure the target is not a mount point,
2297 		 * and keep mount/umount away until we're done.
2298 		 */
2299 		if (vn_vfsrlock(nvp)) {
2300 			error = EBUSY;
2301 			goto out;
2302 		}
2303 		nvp_locked = 1;
2304 		if (vn_mountedvfs(nvp) != NULL) {
2305 			error = EBUSY;
2306 			goto out;
2307 		}
2308 
2309 		/*
2310 		 * CIFS gives a SHARING_VIOLATION error when
2311 		 * trying to rename onto an exising object,
2312 		 * so try to remove the target first.
2313 		 * (Only for files, not directories.)
2314 		 */
2315 		if (nvp->v_type == VDIR) {
2316 			error = EEXIST;
2317 			goto out;
2318 		}
2319 
2320 		/*
2321 		 * Nodes that are "not active" here have v_count=2
2322 		 * because vn_renameat (our caller) did a lookup on
2323 		 * both the source and target before this call.
2324 		 * Otherwise this similar to smbfs_remove.
2325 		 */
2326 		nnp = VTOSMB(nvp);
2327 		mutex_enter(&nnp->r_statelock);
2328 		if ((nvp->v_count > 2) && (nnp->n_fidrefs > 0)) {
2329 			/*
2330 			 * The target file exists, is not the same as
2331 			 * the source file, and is active.  Other FS
2332 			 * implementations unlink the target here.
2333 			 * For SMB, we don't assume we can remove an
2334 			 * open file.  Return an error instead.
2335 			 */
2336 			mutex_exit(&nnp->r_statelock);
2337 			error = EBUSY;
2338 			goto out;
2339 		}
2340 
2341 		/*
2342 		 * Target file is not active. Try to remove it.
2343 		 */
2344 		smbfs_attrcache_rm_locked(nnp);
2345 		mutex_exit(&nnp->r_statelock);
2346 
2347 		error = smbfs_smb_delete(nnp, &scred, NULL, 0, 0);
2348 
2349 		/*
2350 		 * Similar to smbfs_remove
2351 		 */
2352 		switch (error) {
2353 		case 0:
2354 		case ENOENT:
2355 		case ENOTDIR:
2356 			smbfs_attrcache_prune(nnp);
2357 			break;
2358 		}
2359 
2360 		if (error)
2361 			goto out;
2362 		/*
2363 		 * OK, removed the target file.  Continue as if
2364 		 * lookup target had failed (nvp == NULL).
2365 		 */
2366 		vn_vfsunlock(nvp);
2367 		nvp_locked = 0;
2368 		VN_RELE(nvp);
2369 		nvp = NULL;
2370 	} /* nvp */
2371 
2372 	onp = VTOSMB(ovp);
2373 	smbfs_attrcache_remove(onp);
2374 
2375 	error = smbfs_smb_rename(onp, ndnp, nnm, strlen(nnm), &scred);
2376 
2377 	/*
2378 	 * If the old name should no longer exist,
2379 	 * discard any cached attributes under it.
2380 	 */
2381 	if (error == 0)
2382 		smbfs_attrcache_prune(onp);
2383 
2384 out:
2385 	if (nvp) {
2386 		if (nvp_locked)
2387 			vn_vfsunlock(nvp);
2388 		VN_RELE(nvp);
2389 	}
2390 	if (ovp)
2391 		VN_RELE(ovp);
2392 
2393 	smb_credrele(&scred);
2394 	smbfs_rw_exit(&odnp->r_rwlock);
2395 	smbfs_rw_exit(&ndnp->r_rwlock);
2396 
2397 	return (error);
2398 }
2399 
2400 /*
2401  * XXX
2402  * vsecattr_t is new to build 77, and we need to eventually support
2403  * it in order to create an ACL when an object is created.
2404  *
2405  * This op should support the new FIGNORECASE flag for case-insensitive
2406  * lookups, per PSARC 2007/244.
2407  */
2408 /* ARGSUSED */
2409 static int
2410 smbfs_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp,
2411 	cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp)
2412 {
2413 	vnode_t		*vp;
2414 	struct smbnode	*dnp = VTOSMB(dvp);
2415 	struct smbmntinfo *smi = VTOSMI(dvp);
2416 	struct smb_cred	scred;
2417 	struct smbfattr	fattr;
2418 	const char		*name = (const char *) nm;
2419 	int		nmlen = strlen(name);
2420 	int		error, hiderr;
2421 
2422 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2423 		return (EPERM);
2424 
2425 	if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2426 		return (EIO);
2427 
2428 	if ((nmlen == 1 && name[0] == '.') ||
2429 	    (nmlen == 2 && name[0] == '.' && name[1] == '.'))
2430 		return (EEXIST);
2431 
2432 	/* Only plain files are allowed in V_XATTRDIR. */
2433 	if (dvp->v_flag & V_XATTRDIR)
2434 		return (EINVAL);
2435 
2436 	if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2437 		return (EINTR);
2438 	smb_credinit(&scred, cr);
2439 
2440 	/*
2441 	 * XXX: Do we need r_lkserlock too?
2442 	 * No use of any shared fid or fctx...
2443 	 */
2444 
2445 	/*
2446 	 * Require write access in the containing directory.
2447 	 */
2448 	error = smbfs_access(dvp, VWRITE, 0, cr, ct);
2449 	if (error)
2450 		goto out;
2451 
2452 	error = smbfs_smb_mkdir(dnp, name, nmlen, &scred);
2453 	if (error)
2454 		goto out;
2455 
2456 	error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred);
2457 	if (error)
2458 		goto out;
2459 
2460 	smbfs_attr_touchdir(dnp);
2461 
2462 	error = smbfs_nget(dvp, name, nmlen, &fattr, &vp);
2463 	if (error)
2464 		goto out;
2465 
2466 	if (name[0] == '.')
2467 		if ((hiderr = smbfs_smb_hideit(VTOSMB(vp), NULL, 0, &scred)))
2468 			SMBVDEBUG("hide failure %d\n", hiderr);
2469 
2470 	/* Success! */
2471 	*vpp = vp;
2472 	error = 0;
2473 out:
2474 	smb_credrele(&scred);
2475 	smbfs_rw_exit(&dnp->r_rwlock);
2476 
2477 	if (name != nm)
2478 		smbfs_name_free(name, nmlen);
2479 
2480 	return (error);
2481 }
2482 
2483 /*
2484  * XXX
2485  * This op should support the new FIGNORECASE flag for case-insensitive
2486  * lookups, per PSARC 2007/244.
2487  */
2488 /* ARGSUSED */
2489 static int
2490 smbfs_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr,
2491 	caller_context_t *ct, int flags)
2492 {
2493 	vnode_t		*vp = NULL;
2494 	int		vp_locked = 0;
2495 	struct smbmntinfo *smi = VTOSMI(dvp);
2496 	struct smbnode	*dnp = VTOSMB(dvp);
2497 	struct smbnode	*np;
2498 	struct smb_cred	scred;
2499 	int		error;
2500 
2501 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2502 		return (EPERM);
2503 
2504 	if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2505 		return (EIO);
2506 
2507 	if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp)))
2508 		return (EINTR);
2509 	smb_credinit(&scred, cr);
2510 
2511 	/*
2512 	 * Require w/x access in the containing directory.
2513 	 * Server handles all other access checks.
2514 	 */
2515 	error = smbfs_access(dvp, VEXEC|VWRITE, 0, cr, ct);
2516 	if (error)
2517 		goto out;
2518 
2519 	/*
2520 	 * First lookup the entry to be removed.
2521 	 */
2522 	error = smbfslookup(dvp, nm, &vp, cr, 0, ct);
2523 	if (error)
2524 		goto out;
2525 	np = VTOSMB(vp);
2526 
2527 	/*
2528 	 * Disallow rmdir of "." or current dir, or the FS root.
2529 	 * Also make sure it's a directory, not a mount point,
2530 	 * and lock to keep mount/umount away until we're done.
2531 	 */
2532 	if ((vp == dvp) || (vp == cdir) || (vp->v_flag & VROOT)) {
2533 		error = EINVAL;
2534 		goto out;
2535 	}
2536 	if (vp->v_type != VDIR) {
2537 		error = ENOTDIR;
2538 		goto out;
2539 	}
2540 	if (vn_vfsrlock(vp)) {
2541 		error = EBUSY;
2542 		goto out;
2543 	}
2544 	vp_locked = 1;
2545 	if (vn_mountedvfs(vp) != NULL) {
2546 		error = EBUSY;
2547 		goto out;
2548 	}
2549 
2550 	smbfs_attrcache_remove(np);
2551 	error = smbfs_smb_rmdir(np, &scred);
2552 
2553 	/*
2554 	 * Similar to smbfs_remove
2555 	 */
2556 	switch (error) {
2557 	case 0:
2558 	case ENOENT:
2559 	case ENOTDIR:
2560 		smbfs_attrcache_prune(np);
2561 		break;
2562 	}
2563 
2564 	if (error)
2565 		goto out;
2566 
2567 	mutex_enter(&np->r_statelock);
2568 	dnp->n_flag |= NMODIFIED;
2569 	mutex_exit(&np->r_statelock);
2570 	smbfs_attr_touchdir(dnp);
2571 	smbfs_rmhash(np);
2572 
2573 out:
2574 	if (vp) {
2575 		if (vp_locked)
2576 			vn_vfsunlock(vp);
2577 		VN_RELE(vp);
2578 	}
2579 	smb_credrele(&scred);
2580 	smbfs_rw_exit(&dnp->r_rwlock);
2581 
2582 	return (error);
2583 }
2584 
2585 
2586 /* ARGSUSED */
2587 static int
2588 smbfs_readdir(vnode_t *vp, struct uio *uiop, cred_t *cr, int *eofp,
2589 	caller_context_t *ct, int flags)
2590 {
2591 	struct smbnode	*np = VTOSMB(vp);
2592 	int		error = 0;
2593 	smbmntinfo_t	*smi;
2594 
2595 	smi = VTOSMI(vp);
2596 
2597 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2598 		return (EIO);
2599 
2600 	if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2601 		return (EIO);
2602 
2603 	/*
2604 	 * Require read access in the directory.
2605 	 */
2606 	error = smbfs_access(vp, VREAD, 0, cr, ct);
2607 	if (error)
2608 		return (error);
2609 
2610 	ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER));
2611 
2612 	/*
2613 	 * XXX: Todo readdir cache here
2614 	 * Note: NFS code is just below this.
2615 	 *
2616 	 * I am serializing the entire readdir opreation
2617 	 * now since we have not yet implemented readdir
2618 	 * cache. This fix needs to be revisited once
2619 	 * we implement readdir cache.
2620 	 */
2621 	if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp)))
2622 		return (EINTR);
2623 
2624 	error = smbfs_readvdir(vp, uiop, cr, eofp, ct);
2625 
2626 	smbfs_rw_exit(&np->r_lkserlock);
2627 
2628 	return (error);
2629 }
2630 
2631 /* ARGSUSED */
2632 static int
2633 smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
2634 	caller_context_t *ct)
2635 {
2636 	/*
2637 	 * Note: "limit" tells the SMB-level FindFirst/FindNext
2638 	 * functions how many directory entries to request in
2639 	 * each OtW call.  It needs to be large enough so that
2640 	 * we don't make lots of tiny OtW requests, but there's
2641 	 * no point making it larger than the maximum number of
2642 	 * OtW entries that would fit in a maximum sized trans2
2643 	 * response (64k / 48).  Beyond that, it's just tuning.
2644 	 * WinNT used 512, Win2k used 1366.  We use 1000.
2645 	 */
2646 	static const int limit = 1000;
2647 	/* Largest possible dirent size. */
2648 	static const size_t dbufsiz = DIRENT64_RECLEN(SMB_MAXFNAMELEN);
2649 	struct smb_cred scred;
2650 	vnode_t		*newvp;
2651 	struct smbnode	*np = VTOSMB(vp);
2652 	struct smbfs_fctx *ctx;
2653 	struct dirent64 *dp;
2654 	ssize_t		save_resid;
2655 	offset_t	save_offset; /* 64 bits */
2656 	int		offset; /* yes, 32 bits */
2657 	int		nmlen, error;
2658 	ushort_t	reclen;
2659 
2660 	ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone);
2661 
2662 	/* Make sure we serialize for n_dirseq use. */
2663 	ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER));
2664 
2665 	/*
2666 	 * Make sure smbfs_open filled in n_dirseq
2667 	 */
2668 	if (np->n_dirseq == NULL)
2669 		return (EBADF);
2670 
2671 	/* Check for overflow of (32-bit) directory offset. */
2672 	if (uio->uio_loffset < 0 || uio->uio_loffset > INT32_MAX ||
2673 	    (uio->uio_loffset + uio->uio_resid) > INT32_MAX)
2674 		return (EINVAL);
2675 
2676 	/* Require space for at least one dirent. */
2677 	if (uio->uio_resid < dbufsiz)
2678 		return (EINVAL);
2679 
2680 	SMBVDEBUG("dirname='%s'\n", np->n_rpath);
2681 	smb_credinit(&scred, cr);
2682 	dp = kmem_alloc(dbufsiz, KM_SLEEP);
2683 
2684 	save_resid = uio->uio_resid;
2685 	save_offset = uio->uio_loffset;
2686 	offset = uio->uio_offset;
2687 	SMBVDEBUG("in: offset=%d, resid=%d\n",
2688 	    (int)uio->uio_offset, (int)uio->uio_resid);
2689 	error = 0;
2690 
2691 	/*
2692 	 * Generate the "." and ".." entries here so we can
2693 	 * (1) make sure they appear (but only once), and
2694 	 * (2) deal with getting their I numbers which the
2695 	 * findnext below does only for normal names.
2696 	 */
2697 	while (offset < FIRST_DIROFS) {
2698 		/*
2699 		 * Tricky bit filling in the first two:
2700 		 * offset 0 is ".", offset 1 is ".."
2701 		 * so strlen of these is offset+1.
2702 		 */
2703 		reclen = DIRENT64_RECLEN(offset + 1);
2704 		if (uio->uio_resid < reclen)
2705 			goto out;
2706 		bzero(dp, reclen);
2707 		dp->d_reclen = reclen;
2708 		dp->d_name[0] = '.';
2709 		dp->d_name[1] = '.';
2710 		dp->d_name[offset + 1] = '\0';
2711 		/*
2712 		 * Want the real I-numbers for the "." and ".."
2713 		 * entries.  For these two names, we know that
2714 		 * smbfslookup can get the nodes efficiently.
2715 		 */
2716 		error = smbfslookup(vp, dp->d_name, &newvp, cr, 1, ct);
2717 		if (error) {
2718 			dp->d_ino = np->n_ino + offset; /* fiction */
2719 		} else {
2720 			dp->d_ino = VTOSMB(newvp)->n_ino;
2721 			VN_RELE(newvp);
2722 		}
2723 		/*
2724 		 * Note: d_off is the offset that a user-level program
2725 		 * should seek to for reading the NEXT directory entry.
2726 		 * See libc: readdir, telldir, seekdir
2727 		 */
2728 		dp->d_off = offset + 1;
2729 		error = uiomove(dp, reclen, UIO_READ, uio);
2730 		if (error)
2731 			goto out;
2732 		/*
2733 		 * Note: uiomove updates uio->uio_offset,
2734 		 * but we want it to be our "cookie" value,
2735 		 * which just counts dirents ignoring size.
2736 		 */
2737 		uio->uio_offset = ++offset;
2738 	}
2739 
2740 	/*
2741 	 * If there was a backward seek, we have to reopen.
2742 	 */
2743 	if (offset < np->n_dirofs) {
2744 		SMBVDEBUG("Reopening search %d:%d\n",
2745 		    offset, np->n_dirofs);
2746 		error = smbfs_smb_findopen(np, "*", 1,
2747 		    SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR,
2748 		    &scred, &ctx);
2749 		if (error) {
2750 			SMBVDEBUG("can not open search, error = %d", error);
2751 			goto out;
2752 		}
2753 		/* free the old one */
2754 		(void) smbfs_smb_findclose(np->n_dirseq, &scred);
2755 		/* save the new one */
2756 		np->n_dirseq = ctx;
2757 		np->n_dirofs = FIRST_DIROFS;
2758 	} else {
2759 		ctx = np->n_dirseq;
2760 	}
2761 
2762 	/*
2763 	 * Skip entries before the requested offset.
2764 	 */
2765 	while (np->n_dirofs < offset) {
2766 		error = smbfs_smb_findnext(ctx, limit, &scred);
2767 		if (error != 0)
2768 			goto out;
2769 		np->n_dirofs++;
2770 	}
2771 
2772 	/*
2773 	 * While there's room in the caller's buffer:
2774 	 *	get a directory entry from SMB,
2775 	 *	convert to a dirent, copyout.
2776 	 * We stop when there is no longer room for a
2777 	 * maximum sized dirent because we must decide
2778 	 * before we know anything about the next entry.
2779 	 */
2780 	while (uio->uio_resid >= dbufsiz) {
2781 		error = smbfs_smb_findnext(ctx, limit, &scred);
2782 		if (error != 0)
2783 			goto out;
2784 		np->n_dirofs++;
2785 
2786 		/* Sanity check the name length. */
2787 		nmlen = ctx->f_nmlen;
2788 		if (nmlen > SMB_MAXFNAMELEN) {
2789 			nmlen = SMB_MAXFNAMELEN;
2790 			SMBVDEBUG("Truncating name: %s\n", ctx->f_name);
2791 		}
2792 		if (smbfs_fastlookup) {
2793 			/* See comment at smbfs_fastlookup above. */
2794 			if (smbfs_nget(vp, ctx->f_name, nmlen,
2795 			    &ctx->f_attr, &newvp) == 0)
2796 				VN_RELE(newvp);
2797 		}
2798 
2799 		reclen = DIRENT64_RECLEN(nmlen);
2800 		bzero(dp, reclen);
2801 		dp->d_reclen = reclen;
2802 		bcopy(ctx->f_name, dp->d_name, nmlen);
2803 		dp->d_name[nmlen] = '\0';
2804 		dp->d_ino = ctx->f_inum;
2805 		dp->d_off = offset + 1;	/* See d_off comment above */
2806 		error = uiomove(dp, reclen, UIO_READ, uio);
2807 		if (error)
2808 			goto out;
2809 		/* See comment re. uio_offset above. */
2810 		uio->uio_offset = ++offset;
2811 	}
2812 
2813 out:
2814 	/*
2815 	 * When we come to the end of a directory, the
2816 	 * SMB-level functions return ENOENT, but the
2817 	 * caller is not expecting an error return.
2818 	 *
2819 	 * Also note that we must delay the call to
2820 	 * smbfs_smb_findclose(np->n_dirseq, ...)
2821 	 * until smbfs_close so that all reads at the
2822 	 * end of the directory will return no data.
2823 	 */
2824 	if (error == ENOENT) {
2825 		error = 0;
2826 		if (eofp)
2827 			*eofp = 1;
2828 	}
2829 	/*
2830 	 * If we encountered an error (i.e. "access denied")
2831 	 * from the FindFirst call, we will have copied out
2832 	 * the "." and ".." entries leaving offset == 2.
2833 	 * In that case, restore the original offset/resid
2834 	 * so the caller gets no data with the error.
2835 	 */
2836 	if (error != 0 && offset == FIRST_DIROFS) {
2837 		uio->uio_loffset = save_offset;
2838 		uio->uio_resid = save_resid;
2839 	}
2840 	SMBVDEBUG("out: offset=%d, resid=%d\n",
2841 	    (int)uio->uio_offset, (int)uio->uio_resid);
2842 
2843 	kmem_free(dp, dbufsiz);
2844 	smb_credrele(&scred);
2845 	return (error);
2846 }
2847 
2848 
2849 /*
2850  * The pair of functions VOP_RWLOCK, VOP_RWUNLOCK
2851  * are optional functions that are called by:
2852  *    getdents, before/after VOP_READDIR
2853  *    pread, before/after ... VOP_READ
2854  *    pwrite, before/after ... VOP_WRITE
2855  *    (other places)
2856  *
2857  * Careful here: None of the above check for any
2858  * error returns from VOP_RWLOCK / VOP_RWUNLOCK!
2859  * In fact, the return value from _rwlock is NOT
2860  * an error code, but V_WRITELOCK_TRUE / _FALSE.
2861  *
2862  * Therefore, it's up to _this_ code to make sure
2863  * the lock state remains balanced, which means
2864  * we can't "bail out" on interrupts, etc.
2865  */
2866 
2867 /* ARGSUSED2 */
2868 static int
2869 smbfs_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
2870 {
2871 	smbnode_t	*np = VTOSMB(vp);
2872 
2873 	if (!write_lock) {
2874 		(void) smbfs_rw_enter_sig(&np->r_rwlock, RW_READER, FALSE);
2875 		return (V_WRITELOCK_FALSE);
2876 	}
2877 
2878 
2879 	(void) smbfs_rw_enter_sig(&np->r_rwlock, RW_WRITER, FALSE);
2880 	return (V_WRITELOCK_TRUE);
2881 }
2882 
2883 /* ARGSUSED */
2884 static void
2885 smbfs_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
2886 {
2887 	smbnode_t	*np = VTOSMB(vp);
2888 
2889 	smbfs_rw_exit(&np->r_rwlock);
2890 }
2891 
2892 
2893 /* ARGSUSED */
2894 static int
2895 smbfs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
2896 {
2897 	smbmntinfo_t	*smi;
2898 
2899 	smi = VTOSMI(vp);
2900 
2901 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2902 		return (EPERM);
2903 
2904 	if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2905 		return (EIO);
2906 
2907 	/*
2908 	 * Because we stuff the readdir cookie into the offset field
2909 	 * someone may attempt to do an lseek with the cookie which
2910 	 * we want to succeed.
2911 	 */
2912 	if (vp->v_type == VDIR)
2913 		return (0);
2914 
2915 	/* Like NFS3, just check for 63-bit overflow. */
2916 	if (*noffp < 0)
2917 		return (EINVAL);
2918 
2919 	return (0);
2920 }
2921 
2922 
2923 /*
2924  * XXX
2925  * This op may need to support PSARC 2007/440, nbmand changes for CIFS Service.
2926  */
2927 static int
2928 smbfs_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
2929 	offset_t offset, struct flk_callback *flk_cbp, cred_t *cr,
2930 	caller_context_t *ct)
2931 {
2932 	if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
2933 		return (EIO);
2934 
2935 	if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
2936 		return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ct));
2937 	else
2938 		return (ENOSYS);
2939 }
2940 
2941 /*
2942  * Free storage space associated with the specified vnode.  The portion
2943  * to be freed is specified by bfp->l_start and bfp->l_len (already
2944  * normalized to a "whence" of 0).
2945  *
2946  * Called by fcntl(fd, F_FREESP, lkp) for libc:ftruncate, etc.
2947  */
2948 /* ARGSUSED */
2949 static int
2950 smbfs_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
2951 	offset_t offset, cred_t *cr, caller_context_t *ct)
2952 {
2953 	int		error;
2954 	smbmntinfo_t	*smi;
2955 
2956 	smi = VTOSMI(vp);
2957 
2958 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
2959 		return (EIO);
2960 
2961 	if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
2962 		return (EIO);
2963 
2964 	/* Caller (fcntl) has checked v_type */
2965 	ASSERT(vp->v_type == VREG);
2966 	if (cmd != F_FREESP)
2967 		return (EINVAL);
2968 
2969 	/*
2970 	 * Like NFS3, no 32-bit offset checks here.
2971 	 * Our SMB layer takes care to return EFBIG
2972 	 * when it has to fallback to a 32-bit call.
2973 	 */
2974 
2975 	error = convoff(vp, bfp, 0, offset);
2976 	if (!error) {
2977 		ASSERT(bfp->l_start >= 0);
2978 		if (bfp->l_len == 0) {
2979 			struct vattr va;
2980 
2981 			/*
2982 			 * ftruncate should not change the ctime and
2983 			 * mtime if we truncate the file to its
2984 			 * previous size.
2985 			 */
2986 			va.va_mask = AT_SIZE;
2987 			error = smbfsgetattr(vp, &va, cr);
2988 			if (error || va.va_size == bfp->l_start)
2989 				return (error);
2990 			va.va_mask = AT_SIZE;
2991 			va.va_size = bfp->l_start;
2992 			error = smbfssetattr(vp, &va, 0, cr);
2993 		} else
2994 			error = EINVAL;
2995 	}
2996 
2997 	return (error);
2998 }
2999 
3000 /* ARGSUSED */
3001 static int
3002 smbfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
3003 	caller_context_t *ct)
3004 {
3005 	vfs_t *vfs;
3006 	smbmntinfo_t *smi;
3007 	struct smb_share *ssp;
3008 
3009 	vfs = vp->v_vfsp;
3010 	smi = VFTOSMI(vfs);
3011 
3012 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3013 		return (EIO);
3014 
3015 	if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED)
3016 		return (EIO);
3017 
3018 	switch (cmd) {
3019 	case _PC_FILESIZEBITS:
3020 		ssp = smi->smi_share;
3021 		if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)
3022 			*valp = 64;
3023 		else
3024 			*valp = 32;
3025 		break;
3026 
3027 	case _PC_LINK_MAX:
3028 		/* We only ever report one link to an object */
3029 		*valp = 1;
3030 		break;
3031 
3032 	case _PC_ACL_ENABLED:
3033 		/*
3034 		 * Always indicate that ACLs are enabled and
3035 		 * that we support ACE_T format, otherwise
3036 		 * libsec will ask for ACLENT_T format data
3037 		 * which we don't support.
3038 		 */
3039 		*valp = _ACL_ACE_ENABLED;
3040 		break;
3041 
3042 	case _PC_SYMLINK_MAX:	/* No symlinks until we do Unix extensions */
3043 		*valp = 0;
3044 		break;
3045 
3046 	case _PC_XATTR_EXISTS:
3047 		if (vfs->vfs_flag & VFS_XATTR) {
3048 			*valp = smbfs_xa_exists(vp, cr);
3049 			break;
3050 		}
3051 		return (EINVAL);
3052 
3053 	case _PC_SATTR_ENABLED:
3054 	case _PC_SATTR_EXISTS:
3055 		*valp = 1;
3056 		break;
3057 
3058 	case _PC_TIMESTAMP_RESOLUTION:
3059 		/*
3060 		 * Windows times are tenths of microseconds
3061 		 * (multiples of 100 nanoseconds).
3062 		 */
3063 		*valp = 100L;
3064 		break;
3065 
3066 	default:
3067 		return (fs_pathconf(vp, cmd, valp, cr, ct));
3068 	}
3069 	return (0);
3070 }
3071 
3072 /* ARGSUSED */
3073 static int
3074 smbfs_getsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr,
3075 	caller_context_t *ct)
3076 {
3077 	vfs_t *vfsp;
3078 	smbmntinfo_t *smi;
3079 	int	error;
3080 	uint_t	mask;
3081 
3082 	vfsp = vp->v_vfsp;
3083 	smi = VFTOSMI(vfsp);
3084 
3085 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3086 		return (EIO);
3087 
3088 	if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
3089 		return (EIO);
3090 
3091 	/*
3092 	 * Our _pathconf indicates _ACL_ACE_ENABLED,
3093 	 * so we should only see VSA_ACE, etc here.
3094 	 * Note: vn_create asks for VSA_DFACLCNT,
3095 	 * and it expects ENOSYS and empty data.
3096 	 */
3097 	mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT |
3098 	    VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES);
3099 	if (mask == 0)
3100 		return (ENOSYS);
3101 
3102 	if (smi->smi_flags & SMI_ACL)
3103 		error = smbfs_acl_getvsa(vp, vsa, flag, cr);
3104 	else
3105 		error = ENOSYS;
3106 
3107 	if (error == ENOSYS)
3108 		error = fs_fab_acl(vp, vsa, flag, cr, ct);
3109 
3110 	return (error);
3111 }
3112 
3113 /* ARGSUSED */
3114 static int
3115 smbfs_setsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr,
3116 	caller_context_t *ct)
3117 {
3118 	vfs_t *vfsp;
3119 	smbmntinfo_t *smi;
3120 	int	error;
3121 	uint_t	mask;
3122 
3123 	vfsp = vp->v_vfsp;
3124 	smi = VFTOSMI(vfsp);
3125 
3126 	if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
3127 		return (EIO);
3128 
3129 	if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
3130 		return (EIO);
3131 
3132 	/*
3133 	 * Our _pathconf indicates _ACL_ACE_ENABLED,
3134 	 * so we should only see VSA_ACE, etc here.
3135 	 */
3136 	mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT);
3137 	if (mask == 0)
3138 		return (ENOSYS);
3139 
3140 	if (vfsp->vfs_flag & VFS_RDONLY)
3141 		return (EROFS);
3142 
3143 	/*
3144 	 * Allow only the mount owner to do this.
3145 	 * See comments at smbfs_access_rwx.
3146 	 */
3147 	error = secpolicy_vnode_setdac(cr, smi->smi_uid);
3148 	if (error != 0)
3149 		return (error);
3150 
3151 	if (smi->smi_flags & SMI_ACL)
3152 		error = smbfs_acl_setvsa(vp, vsa, flag, cr);
3153 	else
3154 		error = ENOSYS;
3155 
3156 	return (error);
3157 }
3158 
3159 
3160 /*
3161  * XXX
3162  * This op should eventually support PSARC 2007/268.
3163  */
3164 static int
3165 smbfs_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr,
3166 	caller_context_t *ct)
3167 {
3168 	if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone)
3169 		return (EIO);
3170 
3171 	if (VTOSMI(vp)->smi_flags & SMI_LLOCK)
3172 		return (fs_shrlock(vp, cmd, shr, flag, cr, ct));
3173 	else
3174 		return (ENOSYS);
3175 }
3176