xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_node.c (revision 0897f7fbb62326e60e858c62a1654b2ca3e2667e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
24  */
25 /*
26  * SMB Node State Machine
27  * ----------------------
28  *
29  *
30  *		    +----------- Creation/Allocation
31  *		    |
32  *		    | T0
33  *		    |
34  *		    v
35  *    +----------------------------+
36  *    |  SMB_NODE_STATE_AVAILABLE  |
37  *    +----------------------------+
38  *		    |
39  *		    | T1
40  *		    |
41  *		    v
42  *    +-----------------------------+
43  *    |  SMB_NODE_STATE_DESTROYING  |
44  *    +-----------------------------+
45  *		    |
46  *		    |
47  *		    | T2
48  *		    |
49  *		    +----------> Deletion/Free
50  *
51  * Transition T0
52  *
53  *    This transition occurs in smb_node_lookup(). If the node looked for is
54  *    not found in the has table a new node is created. The reference count is
55  *    initialized to 1 and the state initialized to SMB_NODE_STATE_AVAILABLE.
56  *
57  * Transition T1
58  *
59  *    This transition occurs in smb_node_release(). If the reference count
60  *    drops to zero the state is moved to SMB_NODE_STATE_DESTROYING and no more
61  *    reference count will be given out for that node.
62  *
63  * Transition T2
64  *
65  *    This transition occurs in smb_node_release(). The structure is deleted.
66  *
67  * Comments
68  * --------
69  *
70  *    The reason the smb node has 2 states is the following synchronization
71  *    rule:
72  *
73  *    There's a mutex embedded in the node used to protect its fields and
74  *    there's a lock embedded in the bucket of the hash table the node belongs
75  *    to. To increment or to decrement the reference count the mutex must be
76  *    entered. To insert the node into the bucket and to remove it from the
77  *    bucket the lock must be entered in RW_WRITER mode. When both (mutex and
78  *    lock) have to be entered, the lock has always to be entered first then
79  *    the mutex. This prevents a deadlock between smb_node_lookup() and
80  *    smb_node_release() from occurring. However, in smb_node_release() when the
81  *    reference count drops to zero and triggers the deletion of the node, the
82  *    mutex has to be released before entering the lock of the bucket (to
83  *    remove the node). This creates a window during which the node that is
84  *    about to be freed could be given out by smb_node_lookup(). To close that
85  *    window the node is moved to the state SMB_NODE_STATE_DESTROYING before
86  *    releasing the mutex. That way, even if smb_node_lookup() finds it, the
87  *    state will indicate that the node should be treated as non existent (of
88  *    course the state of the node should be tested/updated under the
89  *    protection of the mutex).
90  */
91 #include <smbsrv/smb_kproto.h>
92 #include <smbsrv/smb_fsops.h>
93 #include <smbsrv/smb_kstat.h>
94 #include <sys/ddi.h>
95 #include <sys/extdirent.h>
96 #include <sys/pathname.h>
97 #include <sys/sdt.h>
98 #include <sys/nbmlock.h>
99 #include <fs/fs_reparse.h>
100 
101 uint32_t smb_is_executable(char *);
102 static void smb_node_delete_on_close(smb_node_t *);
103 static void smb_node_create_audit_buf(smb_node_t *, int);
104 static void smb_node_destroy_audit_buf(smb_node_t *);
105 static void smb_node_audit(smb_node_t *);
106 static smb_node_t *smb_node_alloc(char *, vnode_t *, smb_llist_t *, uint32_t);
107 static void smb_node_free(smb_node_t *);
108 static int smb_node_constructor(void *, void *, int);
109 static void smb_node_destructor(void *, void *);
110 static smb_llist_t *smb_node_get_hash(fsid_t *, smb_attr_t *, uint32_t *);
111 
112 static void smb_node_init_reparse(smb_node_t *, smb_attr_t *);
113 static void smb_node_init_system(smb_node_t *);
114 
115 #define	VALIDATE_DIR_NODE(_dir_, _node_) \
116     ASSERT((_dir_)->n_magic == SMB_NODE_MAGIC); \
117     ASSERT(((_dir_)->vp->v_xattrdir) || ((_dir_)->vp->v_type == VDIR)); \
118     ASSERT((_dir_)->n_dnode != (_node_));
119 
120 /* round sz to DEV_BSIZE block */
121 #define	SMB_ALLOCSZ(sz)	(((sz) + DEV_BSIZE-1) & ~(DEV_BSIZE-1))
122 
123 static kmem_cache_t	*smb_node_cache = NULL;
124 static smb_llist_t	smb_node_hash_table[SMBND_HASH_MASK+1];
125 static smb_node_t	*smb_root_node;
126 
127 /*
128  * smb_node_init
129  *
130  * Initialization of the SMB node layer.
131  *
132  * This function is not multi-thread safe. The caller must make sure only one
133  * thread makes the call.
134  */
135 void
136 smb_node_init(void)
137 {
138 	smb_attr_t	attr;
139 	smb_llist_t	*node_hdr;
140 	smb_node_t	*node;
141 	uint32_t	hashkey;
142 	int		i;
143 
144 	if (smb_node_cache != NULL)
145 		return;
146 
147 	smb_node_cache = kmem_cache_create(SMBSRV_KSTAT_NODE_CACHE,
148 	    sizeof (smb_node_t), 8, smb_node_constructor, smb_node_destructor,
149 	    NULL, NULL, NULL, 0);
150 
151 	for (i = 0; i <= SMBND_HASH_MASK; i++) {
152 		smb_llist_constructor(&smb_node_hash_table[i],
153 		    sizeof (smb_node_t), offsetof(smb_node_t, n_lnd));
154 	}
155 
156 	/*
157 	 * The node cache is shared by all zones, so the smb_root_node
158 	 * must represent the real (global zone) rootdir.
159 	 * Note intentional use of kcred here.
160 	 */
161 	attr.sa_mask = SMB_AT_ALL;
162 	VERIFY0(smb_vop_getattr(rootdir, NULL, &attr, 0, kcred));
163 	node_hdr = smb_node_get_hash(&rootdir->v_vfsp->vfs_fsid, &attr,
164 	    &hashkey);
165 	node = smb_node_alloc("/", rootdir, node_hdr, hashkey);
166 	smb_llist_enter(node_hdr, RW_WRITER);
167 	smb_llist_insert_head(node_hdr, node);
168 	smb_llist_exit(node_hdr);
169 	smb_root_node = node;	/* smb_node_release in smb_node_fini */
170 }
171 
172 /*
173  * smb_node_fini
174  *
175  * This function is not multi-thread safe. The caller must make sure only one
176  * thread makes the call.
177  */
178 void
179 smb_node_fini(void)
180 {
181 	int	i;
182 
183 	if (smb_root_node != NULL) {
184 		smb_node_release(smb_root_node);
185 		smb_root_node = NULL;
186 	}
187 
188 	if (smb_node_cache == NULL)
189 		return;
190 
191 #ifdef DEBUG
192 	for (i = 0; i <= SMBND_HASH_MASK; i++) {
193 		smb_node_t	*node;
194 
195 		/*
196 		 * The following sequence is just intended for sanity check.
197 		 * This will have to be modified when the code goes into
198 		 * production.
199 		 *
200 		 * The SMB node hash table should be emtpy at this point. If the
201 		 * hash table is not empty a panic will be triggered.
202 		 *
203 		 * The reason why SMB nodes are still remaining in the hash
204 		 * table is problably due to a mismatch between calls to
205 		 * smb_node_lookup() and smb_node_release(). You must track that
206 		 * down.
207 		 */
208 		node = smb_llist_head(&smb_node_hash_table[i]);
209 		ASSERT(node == NULL);
210 	}
211 #endif
212 
213 	for (i = 0; i <= SMBND_HASH_MASK; i++) {
214 		smb_llist_destructor(&smb_node_hash_table[i]);
215 	}
216 	kmem_cache_destroy(smb_node_cache);
217 	smb_node_cache = NULL;
218 }
219 
220 /*
221  * smb_node_lookup()
222  *
223  * NOTE: This routine should only be called by the file system interface layer,
224  * and not by SMB.
225  *
226  * smb_node_lookup() is called upon successful lookup, mkdir, and create
227  * (for both non-streams and streams).  In each of these cases, a held vnode is
228  * passed into this routine.  If a new smb_node is created it will take its
229  * own hold on the vnode.  The caller's hold therefore still belongs to, and
230  * should be released by, the caller.
231  *
232  * A reference is taken on the smb_node whether found in the hash table
233  * or newly created.
234  *
235  * If an smb_node needs to be created, a reference is also taken on the
236  * dnode (if passed in).
237  *
238  * See smb_node_release() for details on the release of these references.
239  */
240 
241 /*ARGSUSED*/
242 smb_node_t *
243 smb_node_lookup(
244     struct smb_request	*sr,
245     struct open_param	*op,
246     cred_t		*cred,
247     vnode_t		*vp,
248     char		*od_name,
249     smb_node_t		*dnode,
250     smb_node_t		*unode)
251 {
252 	smb_llist_t		*node_hdr;
253 	smb_node_t		*node;
254 	smb_attr_t		attr;
255 	uint32_t		hashkey = 0;
256 	fsid_t			fsid;
257 	int			error;
258 	krw_t			lock_mode;
259 	vnode_t			*unnamed_vp = NULL;
260 
261 	/*
262 	 * smb_vop_getattr() is called here instead of smb_fsop_getattr(),
263 	 * because the node may not yet exist.  We also do not want to call
264 	 * it with the list lock held.
265 	 */
266 
267 	if (unode)
268 		unnamed_vp = unode->vp;
269 
270 	/*
271 	 * This getattr is performed on behalf of the server
272 	 * that's why kcred is used not the user's cred
273 	 */
274 	attr.sa_mask = SMB_AT_ALL;
275 	error = smb_vop_getattr(vp, unnamed_vp, &attr, 0, zone_kcred());
276 	if (error)
277 		return (NULL);
278 
279 	if (sr && sr->tid_tree) {
280 		/*
281 		 * The fsid for a file is that of the tree, even
282 		 * if the file resides in a different mountpoint
283 		 * under the share.
284 		 */
285 		fsid = SMB_TREE_FSID(sr->tid_tree);
286 	} else {
287 		/*
288 		 * This should be getting executed only for the
289 		 * tree root smb_node.
290 		 */
291 		fsid = vp->v_vfsp->vfs_fsid;
292 	}
293 
294 	node_hdr = smb_node_get_hash(&fsid, &attr, &hashkey);
295 	lock_mode = RW_READER;
296 
297 	smb_llist_enter(node_hdr, lock_mode);
298 	for (;;) {
299 		node = list_head(&node_hdr->ll_list);
300 		while (node) {
301 			ASSERT(node->n_magic == SMB_NODE_MAGIC);
302 			ASSERT(node->n_hash_bucket == node_hdr);
303 			if ((node->n_hashkey == hashkey) && (node->vp == vp)) {
304 				mutex_enter(&node->n_mutex);
305 				DTRACE_PROBE1(smb_node_lookup_hit,
306 				    smb_node_t *, node);
307 				switch (node->n_state) {
308 				case SMB_NODE_STATE_AVAILABLE:
309 					/* The node was found. */
310 					node->n_refcnt++;
311 					if ((node->n_dnode == NULL) &&
312 					    (dnode != NULL) &&
313 					    (node != dnode) &&
314 					    (strcmp(od_name, "..") != 0) &&
315 					    (strcmp(od_name, ".") != 0)) {
316 						VALIDATE_DIR_NODE(dnode, node);
317 						node->n_dnode = dnode;
318 						smb_node_ref(dnode);
319 					}
320 
321 					smb_node_audit(node);
322 					mutex_exit(&node->n_mutex);
323 					smb_llist_exit(node_hdr);
324 					return (node);
325 
326 				case SMB_NODE_STATE_DESTROYING:
327 					/*
328 					 * Although the node exists it is about
329 					 * to be destroyed. We act as it hasn't
330 					 * been found.
331 					 */
332 					mutex_exit(&node->n_mutex);
333 					break;
334 				default:
335 					/*
336 					 * Although the node exists it is in an
337 					 * unknown state. We act as it hasn't
338 					 * been found.
339 					 */
340 					ASSERT(0);
341 					mutex_exit(&node->n_mutex);
342 					break;
343 				}
344 			}
345 			node = smb_llist_next(node_hdr, node);
346 		}
347 		if ((lock_mode == RW_READER) && smb_llist_upgrade(node_hdr)) {
348 			lock_mode = RW_WRITER;
349 			continue;
350 		}
351 		break;
352 	}
353 	node = smb_node_alloc(od_name, vp, node_hdr, hashkey);
354 	smb_node_init_reparse(node, &attr);
355 
356 	if (op)
357 		node->flags |= smb_is_executable(op->fqi.fq_last_comp);
358 
359 	if (dnode) {
360 		smb_node_ref(dnode);
361 		node->n_dnode = dnode;
362 		ASSERT(dnode->n_dnode != node);
363 		ASSERT((dnode->vp->v_xattrdir) ||
364 		    (dnode->vp->v_type == VDIR));
365 	}
366 
367 	if (unode) {
368 		smb_node_ref(unode);
369 		node->n_unode = unode;
370 	}
371 
372 	smb_node_init_system(node);
373 
374 	DTRACE_PROBE1(smb_node_lookup_miss, smb_node_t *, node);
375 	smb_node_audit(node);
376 	smb_llist_insert_head(node_hdr, node);
377 	smb_llist_exit(node_hdr);
378 	return (node);
379 }
380 
381 /*
382  * smb_stream_node_lookup()
383  *
384  * Note: stream_name (the name that will be stored in the "od_name" field
385  * of a stream's smb_node) is the same as the on-disk name for the stream
386  * except that it does not have SMB_STREAM_PREFIX prepended.
387  */
388 
389 smb_node_t *
390 smb_stream_node_lookup(smb_request_t *sr, cred_t *cr, smb_node_t *fnode,
391     vnode_t *xattrdirvp, vnode_t *vp, char *stream_name)
392 {
393 	smb_node_t	*xattrdir_node;
394 	smb_node_t	*snode;
395 
396 	xattrdir_node = smb_node_lookup(sr, NULL, cr, xattrdirvp, XATTR_DIR,
397 	    fnode, NULL);
398 
399 	if (xattrdir_node == NULL)
400 		return (NULL);
401 
402 	snode = smb_node_lookup(sr, NULL, cr, vp, stream_name, xattrdir_node,
403 	    fnode);
404 
405 	(void) smb_node_release(xattrdir_node);
406 	return (snode);
407 }
408 
409 
410 /*
411  * This function should be called whenever a reference is needed on an
412  * smb_node pointer.  The copy of an smb_node pointer from one non-local
413  * data structure to another requires a reference to be taken on the smb_node
414  * (unless the usage is localized).  Each data structure deallocation routine
415  * will call smb_node_release() on its smb_node pointers.
416  *
417  * In general, an smb_node pointer residing in a structure should never be
418  * stale.  A node pointer may be NULL, however, and care should be taken
419  * prior to calling smb_node_ref(), which ASSERTs that the pointer is valid.
420  * Care also needs to be taken with respect to racing deallocations of a
421  * structure.
422  */
423 void
424 smb_node_ref(smb_node_t *node)
425 {
426 	SMB_NODE_VALID(node);
427 
428 	mutex_enter(&node->n_mutex);
429 	switch (node->n_state) {
430 	case SMB_NODE_STATE_AVAILABLE:
431 		node->n_refcnt++;
432 		ASSERT(node->n_refcnt);
433 		DTRACE_PROBE1(smb_node_ref_exit, smb_node_t *, node);
434 		smb_node_audit(node);
435 		break;
436 	default:
437 		SMB_PANIC();
438 	}
439 	mutex_exit(&node->n_mutex);
440 }
441 
442 /*
443  * smb_node_lookup() takes a hold on an smb_node, whether found in the
444  * hash table or newly created.  This hold is expected to be released
445  * in the following manner.
446  *
447  * smb_node_lookup() takes an address of an smb_node pointer.  This should
448  * be getting passed down via a lookup (whether path name or component), mkdir,
449  * create.  If the original smb_node pointer resides in a data structure, then
450  * the deallocation routine for the data structure is responsible for calling
451  * smb_node_release() on the smb_node pointer.  Alternatively,
452  * smb_node_release() can be called as soon as the smb_node pointer is no longer
453  * needed.  In this case, callers are responsible for setting an embedded
454  * pointer to NULL if it is known that the last reference is being released.
455  *
456  * If the passed-in address of the smb_node pointer belongs to a local variable,
457  * then the caller with the local variable should call smb_node_release()
458  * directly.
459  *
460  * smb_node_release() itself will call smb_node_release() on a node's n_dnode,
461  * as smb_node_lookup() takes a hold on dnode.
462  */
463 void
464 smb_node_release(smb_node_t *node)
465 {
466 	SMB_NODE_VALID(node);
467 
468 	mutex_enter(&node->n_mutex);
469 	ASSERT(node->n_refcnt);
470 	DTRACE_PROBE1(smb_node_release, smb_node_t *, node);
471 	if (--node->n_refcnt == 0) {
472 		switch (node->n_state) {
473 
474 		case SMB_NODE_STATE_AVAILABLE:
475 			node->n_state = SMB_NODE_STATE_DESTROYING;
476 			mutex_exit(&node->n_mutex);
477 
478 			smb_llist_enter(node->n_hash_bucket, RW_WRITER);
479 			smb_llist_remove(node->n_hash_bucket, node);
480 			smb_llist_exit(node->n_hash_bucket);
481 
482 			/*
483 			 * Check if the file was deleted
484 			 */
485 			smb_node_delete_on_close(node);
486 
487 			if (node->n_dnode) {
488 				ASSERT(node->n_dnode->n_magic ==
489 				    SMB_NODE_MAGIC);
490 				smb_node_release(node->n_dnode);
491 			}
492 
493 			if (node->n_unode) {
494 				ASSERT(node->n_unode->n_magic ==
495 				    SMB_NODE_MAGIC);
496 				smb_node_release(node->n_unode);
497 			}
498 
499 			smb_node_free(node);
500 			return;
501 
502 		default:
503 			SMB_PANIC();
504 		}
505 	}
506 	smb_node_audit(node);
507 	mutex_exit(&node->n_mutex);
508 }
509 
510 static void
511 smb_node_delete_on_close(smb_node_t *node)
512 {
513 	smb_node_t	*d_snode;
514 	int		rc = 0;
515 	uint32_t	flags = 0;
516 
517 	d_snode = node->n_dnode;
518 	if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
519 		node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE;
520 		flags = node->n_delete_on_close_flags;
521 		ASSERT(node->od_name != NULL);
522 
523 		if (smb_node_is_dir(node))
524 			rc = smb_fsop_rmdir(0, node->delete_on_close_cred,
525 			    d_snode, node->od_name, flags);
526 		else
527 			rc = smb_fsop_remove(0, node->delete_on_close_cred,
528 			    d_snode, node->od_name, flags);
529 		crfree(node->delete_on_close_cred);
530 	}
531 	if (rc != 0)
532 		cmn_err(CE_WARN, "File %s could not be removed, rc=%d\n",
533 		    node->od_name, rc);
534 	DTRACE_PROBE2(smb_node_delete_on_close, int, rc, smb_node_t *, node);
535 }
536 
537 /*
538  * smb_node_rename()
539  *
540  */
541 void
542 smb_node_rename(
543     smb_node_t	*from_dnode,
544     smb_node_t	*ret_node,
545     smb_node_t	*to_dnode,
546     char	*to_name)
547 {
548 	SMB_NODE_VALID(from_dnode);
549 	SMB_NODE_VALID(to_dnode);
550 	SMB_NODE_VALID(ret_node);
551 
552 	smb_node_ref(to_dnode);
553 	mutex_enter(&ret_node->n_mutex);
554 	switch (ret_node->n_state) {
555 	case SMB_NODE_STATE_AVAILABLE:
556 		ret_node->n_dnode = to_dnode;
557 		mutex_exit(&ret_node->n_mutex);
558 		ASSERT(to_dnode->n_dnode != ret_node);
559 		ASSERT((to_dnode->vp->v_xattrdir) ||
560 		    (to_dnode->vp->v_type == VDIR));
561 		smb_node_release(from_dnode);
562 		(void) strcpy(ret_node->od_name, to_name);
563 		/*
564 		 * XXX Need to update attributes?
565 		 */
566 		break;
567 	default:
568 		SMB_PANIC();
569 	}
570 }
571 
572 /*
573  * Find/create an SMB node for the root of this zone and store it
574  * in *svrootp.  Also create nodes leading to this directory.
575  */
576 int
577 smb_node_root_init(smb_server_t *sv, smb_node_t **svrootp)
578 {
579 	zone_t		*zone = curzone;
580 	int		error;
581 
582 	ASSERT(zone->zone_id == sv->sv_zid);
583 	if (smb_root_node == NULL)
584 		return (ENOENT);
585 
586 	/*
587 	 * We're getting smb nodes below the zone root here,
588 	 * so need to use kcred, not zone_kcred().
589 	 */
590 	error = smb_pathname(NULL, zone->zone_rootpath, 0,
591 	    smb_root_node, smb_root_node, NULL, svrootp, kcred);
592 
593 	return (error);
594 }
595 
596 /*
597  * Helper function for smb_node_set_delete_on_close(). Assumes node is a dir.
598  * Return 0 if this is an empty dir. Otherwise return a NT_STATUS code.
599  * We distinguish between readdir failure and non-empty dir by returning
600  * different values.
601  */
602 static uint32_t
603 smb_rmdir_possible(smb_node_t *n, uint32_t flags)
604 {
605 	ASSERT(n->vp->v_type == VDIR);
606 	char buf[512]; /* Only large enough to see if the dir is empty. */
607 	int eof, bsize = sizeof (buf), reclen = 0;
608 	char *name;
609 	boolean_t edp = vfs_has_feature(n->vp->v_vfsp, VFSFT_DIRENTFLAGS);
610 
611 	union {
612 		char		*u_bufptr;
613 		struct edirent	*u_edp;
614 		struct dirent64	*u_dp;
615 	} u;
616 #define	bufptr	u.u_bufptr
617 #define	extdp	u.u_edp
618 #define	dp	u.u_dp
619 
620 	if (smb_vop_readdir(n->vp, 0, buf, &bsize, &eof, flags, zone_kcred()))
621 		return (NT_STATUS_CANNOT_DELETE);
622 	if (bsize == 0)
623 		return (NT_STATUS_CANNOT_DELETE);
624 	bufptr = buf;
625 	while ((bufptr += reclen) < buf + bsize) {
626 		if (edp) {
627 			reclen = extdp->ed_reclen;
628 			name = extdp->ed_name;
629 		} else {
630 			reclen = dp->d_reclen;
631 			name = dp->d_name;
632 		}
633 		if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0)
634 			return (NT_STATUS_DIRECTORY_NOT_EMPTY);
635 	}
636 	return (0);
637 }
638 
639 /*
640  * When DeleteOnClose is set on an smb_node, the common open code will
641  * reject subsequent open requests for the file. Observation of Windows
642  * 2000 indicates that subsequent opens should be allowed (assuming
643  * there would be no sharing violation) until the file is closed using
644  * the fid on which the DeleteOnClose was requested.
645  *
646  * If there are multiple opens with delete-on-close create options,
647  * whichever the first file handle is closed will trigger the node to be
648  * marked as delete-on-close. The credentials of that ofile will be used
649  * as the delete-on-close credentials of the node.
650  */
651 uint32_t
652 smb_node_set_delete_on_close(smb_node_t *node, cred_t *cr, uint32_t flags)
653 {
654 	int rc = 0;
655 	uint32_t status;
656 	smb_attr_t attr;
657 
658 	if (node->n_pending_dosattr & FILE_ATTRIBUTE_READONLY)
659 		return (NT_STATUS_CANNOT_DELETE);
660 
661 	bzero(&attr, sizeof (smb_attr_t));
662 	attr.sa_mask = SMB_AT_DOSATTR;
663 	rc = smb_fsop_getattr(NULL, zone_kcred(), node, &attr);
664 	if ((rc != 0) || (attr.sa_dosattr & FILE_ATTRIBUTE_READONLY)) {
665 		return (NT_STATUS_CANNOT_DELETE);
666 	}
667 
668 	/*
669 	 * If the directory is not empty we should fail setting del-on-close
670 	 * with STATUS_DIRECTORY_NOT_EMPTY. see MS's
671 	 * "File System Behavior Overview" doc section 4.3.2
672 	 */
673 	if (smb_node_is_dir(node)) {
674 		status = smb_rmdir_possible(node, flags);
675 		if (status != 0) {
676 			return (status);
677 		}
678 	}
679 
680 	mutex_enter(&node->n_mutex);
681 	if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
682 		mutex_exit(&node->n_mutex);
683 		return (NT_STATUS_CANNOT_DELETE);
684 	}
685 
686 	crhold(cr);
687 	node->delete_on_close_cred = cr;
688 	node->n_delete_on_close_flags = flags;
689 	node->flags |= NODE_FLAGS_DELETE_ON_CLOSE;
690 	mutex_exit(&node->n_mutex);
691 
692 	/*
693 	 * Tell any change notify calls to close their handles
694 	 * and get out of the way.  FILE_ACTION_DELETE_PENDING
695 	 * is a special, internal-only action for this purpose.
696 	 */
697 	smb_node_notify_change(node, FILE_ACTION_DELETE_PENDING, NULL);
698 
699 	return (NT_STATUS_SUCCESS);
700 }
701 
702 void
703 smb_node_reset_delete_on_close(smb_node_t *node)
704 {
705 	mutex_enter(&node->n_mutex);
706 	if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
707 		node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE;
708 		crfree(node->delete_on_close_cred);
709 		node->delete_on_close_cred = NULL;
710 		node->n_delete_on_close_flags = 0;
711 	}
712 	mutex_exit(&node->n_mutex);
713 }
714 
715 /*
716  * smb_node_open_check
717  *
718  * check file sharing rules for current open request
719  * against all existing opens for a file.
720  *
721  * Returns NT_STATUS_SHARING_VIOLATION if there is any
722  * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
723  */
724 uint32_t
725 smb_node_open_check(smb_node_t *node, uint32_t desired_access,
726     uint32_t share_access)
727 {
728 	smb_ofile_t *of;
729 	uint32_t status;
730 
731 	SMB_NODE_VALID(node);
732 
733 	smb_llist_enter(&node->n_ofile_list, RW_READER);
734 	of = smb_llist_head(&node->n_ofile_list);
735 	while (of) {
736 		status = smb_ofile_open_check(of, desired_access, share_access);
737 
738 		switch (status) {
739 		case NT_STATUS_INVALID_HANDLE:
740 		case NT_STATUS_SUCCESS:
741 			of = smb_llist_next(&node->n_ofile_list, of);
742 			break;
743 		default:
744 			ASSERT(status == NT_STATUS_SHARING_VIOLATION);
745 			smb_llist_exit(&node->n_ofile_list);
746 			return (status);
747 		}
748 	}
749 
750 	smb_llist_exit(&node->n_ofile_list);
751 	return (NT_STATUS_SUCCESS);
752 }
753 
754 uint32_t
755 smb_node_rename_check(smb_node_t *node)
756 {
757 	smb_ofile_t	*of;
758 	uint32_t	status;
759 
760 	SMB_NODE_VALID(node);
761 
762 	/*
763 	 * Intra-CIFS check
764 	 */
765 	smb_llist_enter(&node->n_ofile_list, RW_READER);
766 	of = smb_llist_head(&node->n_ofile_list);
767 	while (of) {
768 		status = smb_ofile_rename_check(of);
769 
770 		switch (status) {
771 		case NT_STATUS_INVALID_HANDLE:
772 		case NT_STATUS_SUCCESS:
773 			of = smb_llist_next(&node->n_ofile_list, of);
774 			break;
775 		default:
776 			ASSERT(status == NT_STATUS_SHARING_VIOLATION);
777 			smb_llist_exit(&node->n_ofile_list);
778 			return (status);
779 		}
780 	}
781 	smb_llist_exit(&node->n_ofile_list);
782 	return (NT_STATUS_SUCCESS);
783 }
784 
785 uint32_t
786 smb_node_delete_check(smb_node_t *node)
787 {
788 	smb_ofile_t	*of;
789 	uint32_t	status;
790 
791 	SMB_NODE_VALID(node);
792 
793 	if (smb_node_is_dir(node))
794 		return (NT_STATUS_SUCCESS);
795 
796 	if (smb_node_is_reparse(node))
797 		return (NT_STATUS_ACCESS_DENIED);
798 
799 	/*
800 	 * intra-CIFS check
801 	 */
802 	smb_llist_enter(&node->n_ofile_list, RW_READER);
803 	of = smb_llist_head(&node->n_ofile_list);
804 	while (of) {
805 		status = smb_ofile_delete_check(of);
806 
807 		switch (status) {
808 		case NT_STATUS_INVALID_HANDLE:
809 		case NT_STATUS_SUCCESS:
810 			of = smb_llist_next(&node->n_ofile_list, of);
811 			break;
812 		default:
813 			ASSERT(status == NT_STATUS_SHARING_VIOLATION);
814 			smb_llist_exit(&node->n_ofile_list);
815 			return (status);
816 		}
817 	}
818 	smb_llist_exit(&node->n_ofile_list);
819 	return (NT_STATUS_SUCCESS);
820 }
821 
822 /*
823  * smb_node_share_check
824  *
825  * Returns: TRUE    - ofiles have non-zero share access
826  *          B_FALSE - ofile with share access NONE.
827  */
828 boolean_t
829 smb_node_share_check(smb_node_t *node)
830 {
831 	smb_ofile_t	*of;
832 	boolean_t	status = B_TRUE;
833 
834 	SMB_NODE_VALID(node);
835 
836 	smb_llist_enter(&node->n_ofile_list, RW_READER);
837 	of = smb_llist_head(&node->n_ofile_list);
838 	if (of)
839 		status = smb_ofile_share_check(of);
840 	smb_llist_exit(&node->n_ofile_list);
841 
842 	return (status);
843 }
844 
845 /*
846  * SMB Change Notification
847  */
848 
849 void
850 smb_node_fcn_subscribe(smb_node_t *node)
851 {
852 
853 	mutex_enter(&node->n_mutex);
854 	if (node->n_fcn_count == 0)
855 		(void) smb_fem_fcn_install(node);
856 	node->n_fcn_count++;
857 	mutex_exit(&node->n_mutex);
858 }
859 
860 void
861 smb_node_fcn_unsubscribe(smb_node_t *node)
862 {
863 
864 	mutex_enter(&node->n_mutex);
865 	node->n_fcn_count--;
866 	if (node->n_fcn_count == 0)
867 		smb_fem_fcn_uninstall(node);
868 	mutex_exit(&node->n_mutex);
869 }
870 
871 void
872 smb_node_notify_change(smb_node_t *node, uint_t action, const char *name)
873 {
874 	smb_ofile_t	*of;
875 
876 	SMB_NODE_VALID(node);
877 
878 	smb_llist_enter(&node->n_ofile_list, RW_READER);
879 	of = smb_llist_head(&node->n_ofile_list);
880 	while (of) {
881 		/*
882 		 * We'd rather deliver events only to ofiles that have
883 		 * subscribed.  There's no explicit synchronization with
884 		 * where this flag is set, but other actions cause this
885 		 * value to reach visibility soon enough for events to
886 		 * start arriving by the time we need them to start.
887 		 * Once nc_subscribed is set, it stays set for the
888 		 * life of the ofile.
889 		 */
890 		if (of->f_notify.nc_subscribed)
891 			smb_notify_ofile(of, action, name);
892 		of = smb_llist_next(&node->n_ofile_list, of);
893 	}
894 	smb_llist_exit(&node->n_ofile_list);
895 
896 	/*
897 	 * After changes that add or remove a name,
898 	 * we know the directory attributes changed,
899 	 * and we can tell the immediate parent.
900 	 */
901 	switch (action) {
902 	case FILE_ACTION_ADDED:
903 	case FILE_ACTION_REMOVED:
904 	case FILE_ACTION_RENAMED_NEW_NAME:
905 		/*
906 		 * Note: FILE_ACTION_RENAMED_OLD_NAME is intentionally
907 		 * omitted, because it's always followed by another
908 		 * event with FILE_ACTION_RENAMED_NEW_NAME posted to
909 		 * the same directory, and we only need/want one.
910 		 */
911 		if (node->n_dnode != NULL) {
912 			smb_node_notify_change(node->n_dnode,
913 			    FILE_ACTION_MODIFIED, node->od_name);
914 		}
915 		break;
916 	}
917 
918 	/*
919 	 * If we wanted to support recursive notify events
920 	 * (where a notify call on some directory receives
921 	 * events from all objects below that directory),
922 	 * we might deliver _SUBDIR_CHANGED to all our
923 	 * parents, grandparents etc, here.  However, we
924 	 * don't currently subscribe to changes on all the
925 	 * child (and grandchild) objects that would be
926 	 * needed to make that work. It's prohibitively
927 	 * expensive to do that, and support for recursive
928 	 * notify is optional anyway, so don't bother.
929 	 */
930 }
931 
932 /*
933  * smb_node_start_crit()
934  *
935  * Enter critical region for share reservations.
936  * See comments above smb_fsop_shrlock().
937  */
938 void
939 smb_node_start_crit(smb_node_t *node, krw_t mode)
940 {
941 	rw_enter(&node->n_lock, mode);
942 	nbl_start_crit(node->vp, mode);
943 }
944 
945 /*
946  * smb_node_end_crit()
947  *
948  * Exit critical region for share reservations.
949  */
950 void
951 smb_node_end_crit(smb_node_t *node)
952 {
953 	nbl_end_crit(node->vp);
954 	rw_exit(&node->n_lock);
955 }
956 
957 int
958 smb_node_in_crit(smb_node_t *node)
959 {
960 	return (nbl_in_crit(node->vp) && RW_LOCK_HELD(&node->n_lock));
961 }
962 
963 void
964 smb_node_rdlock(smb_node_t *node)
965 {
966 	rw_enter(&node->n_lock, RW_READER);
967 }
968 
969 void
970 smb_node_wrlock(smb_node_t *node)
971 {
972 	rw_enter(&node->n_lock, RW_WRITER);
973 }
974 
975 void
976 smb_node_unlock(smb_node_t *node)
977 {
978 	rw_exit(&node->n_lock);
979 }
980 
981 void
982 smb_node_add_ofile(smb_node_t *node, smb_ofile_t *of)
983 {
984 	SMB_NODE_VALID(node);
985 
986 	smb_llist_enter(&node->n_ofile_list, RW_WRITER);
987 	smb_llist_insert_tail(&node->n_ofile_list, of);
988 	smb_llist_exit(&node->n_ofile_list);
989 }
990 
991 void
992 smb_node_rem_ofile(smb_node_t *node, smb_ofile_t *of)
993 {
994 	SMB_NODE_VALID(node);
995 
996 	smb_llist_enter(&node->n_ofile_list, RW_WRITER);
997 	smb_llist_remove(&node->n_ofile_list, of);
998 	smb_llist_exit(&node->n_ofile_list);
999 }
1000 
1001 /*
1002  * smb_node_inc_open_ofiles
1003  */
1004 void
1005 smb_node_inc_open_ofiles(smb_node_t *node)
1006 {
1007 	SMB_NODE_VALID(node);
1008 	atomic_inc_32(&node->n_open_count);
1009 }
1010 
1011 /*
1012  * smb_node_dec_open_ofiles
1013  * returns new value
1014  */
1015 uint32_t
1016 smb_node_dec_open_ofiles(smb_node_t *node)
1017 {
1018 	SMB_NODE_VALID(node);
1019 	return (atomic_dec_32_nv(&node->n_open_count));
1020 }
1021 
1022 /*
1023  * smb_node_inc_opening_count
1024  */
1025 void
1026 smb_node_inc_opening_count(smb_node_t *node)
1027 {
1028 	SMB_NODE_VALID(node);
1029 	atomic_inc_32(&node->n_opening_count);
1030 }
1031 
1032 /*
1033  * smb_node_dec_opening_count
1034  */
1035 void
1036 smb_node_dec_opening_count(smb_node_t *node)
1037 {
1038 	SMB_NODE_VALID(node);
1039 	atomic_dec_32(&node->n_opening_count);
1040 }
1041 
1042 /*
1043  * smb_node_getmntpath
1044  */
1045 int
1046 smb_node_getmntpath(smb_node_t *node, char *buf, uint32_t buflen)
1047 {
1048 	vnode_t *vp, *root_vp;
1049 	vfs_t *vfsp;
1050 	int err;
1051 
1052 	ASSERT(node);
1053 	ASSERT(node->vp);
1054 	ASSERT(node->vp->v_vfsp);
1055 
1056 	vp = node->vp;
1057 	vfsp = vp->v_vfsp;
1058 
1059 	if (VFS_ROOT(vfsp, &root_vp))
1060 		return (ENOENT);
1061 
1062 	VN_HOLD(vp);
1063 
1064 	/* NULL is passed in as we want to start at "/" */
1065 	err = vnodetopath(NULL, root_vp, buf, buflen, zone_kcred());
1066 
1067 	VN_RELE(vp);
1068 	VN_RELE(root_vp);
1069 	return (err);
1070 }
1071 
1072 /*
1073  * smb_node_getshrpath
1074  *
1075  * Determine the absolute pathname of 'node' within the share (tree).
1076  * For example if the node represents file "test1.txt" in directory
1077  * "dir1" the pathname would be: \dir1\test1.txt
1078  */
1079 int
1080 smb_node_getshrpath(smb_node_t *node, smb_tree_t *tree,
1081     char *buf, uint32_t buflen)
1082 {
1083 	int rc;
1084 
1085 	ASSERT(node);
1086 	ASSERT(tree);
1087 	ASSERT(tree->t_snode);
1088 
1089 	rc = smb_node_getpath(node, tree->t_snode->vp, buf, buflen);
1090 	(void) strsubst(buf, '/', '\\');
1091 	return (rc);
1092 }
1093 
1094 /*
1095  * smb_node_getpath
1096  *
1097  * Determine the absolute pathname of 'node' from 'rootvp'.
1098  *
1099  * Using vnodetopath is only reliable for directory nodes (due to
1100  * its reliance on the DNLC for non-directory nodes). Thus, if node
1101  * represents a file, construct the pathname for the parent dnode
1102  * and append filename.
1103  * If node represents a named stream, construct the pathname for the
1104  * associated unnamed stream and append the stream name.
1105  *
1106  * The pathname returned in buf will be '/' separated.
1107  */
1108 int
1109 smb_node_getpath(smb_node_t *node, vnode_t *rootvp, char *buf, uint32_t buflen)
1110 {
1111 	int rc;
1112 	vnode_t *vp;
1113 	smb_node_t *unode, *dnode;
1114 	cred_t *kcr = zone_kcred();
1115 
1116 	unode = (SMB_IS_STREAM(node)) ? node->n_unode : node;
1117 	dnode = (smb_node_is_dir(unode)) ? unode : unode->n_dnode;
1118 
1119 	/* find path to directory node */
1120 	vp = dnode->vp;
1121 	VN_HOLD(vp);
1122 	if (rootvp) {
1123 		VN_HOLD(rootvp);
1124 		rc = vnodetopath(rootvp, vp, buf, buflen, kcr);
1125 		VN_RELE(rootvp);
1126 	} else {
1127 		rc = vnodetopath(NULL, vp, buf, buflen, kcr);
1128 	}
1129 	VN_RELE(vp);
1130 
1131 	if (rc != 0)
1132 		return (rc);
1133 
1134 	/* append filename if necessary */
1135 	if (!smb_node_is_dir(unode)) {
1136 		if (buf[strlen(buf) - 1] != '/')
1137 			(void) strlcat(buf, "/", buflen);
1138 		(void) strlcat(buf, unode->od_name, buflen);
1139 	}
1140 
1141 	/* append named stream name if necessary */
1142 	if (SMB_IS_STREAM(node))
1143 		(void) strlcat(buf, node->od_name, buflen);
1144 
1145 	return (rc);
1146 }
1147 
1148 /*
1149  * smb_node_alloc
1150  */
1151 static smb_node_t *
1152 smb_node_alloc(
1153     char	*od_name,
1154     vnode_t	*vp,
1155     smb_llist_t	*bucket,
1156     uint32_t	hashkey)
1157 {
1158 	smb_node_t	*node;
1159 	vnode_t		*root_vp;
1160 
1161 	node = kmem_cache_alloc(smb_node_cache, KM_SLEEP);
1162 
1163 	if (node->n_audit_buf != NULL)
1164 		node->n_audit_buf->anb_index = 0;
1165 
1166 	node->flags = 0;
1167 	VN_HOLD(vp);
1168 	node->vp = vp;
1169 	node->n_refcnt = 1;
1170 	node->n_hash_bucket = bucket;
1171 	node->n_hashkey = hashkey;
1172 	node->n_pending_dosattr = 0;
1173 	node->n_open_count = 0;
1174 	node->n_allocsz = 0;
1175 	node->n_dnode = NULL;
1176 	node->n_unode = NULL;
1177 	node->delete_on_close_cred = NULL;
1178 	node->n_delete_on_close_flags = 0;
1179 	node->n_oplock.ol_fem = B_FALSE;
1180 	node->n_oplock.ol_xthread = NULL;
1181 	node->n_oplock.ol_count = 0;
1182 	node->n_oplock.ol_break = SMB_OPLOCK_NO_BREAK;
1183 
1184 	(void) strlcpy(node->od_name, od_name, sizeof (node->od_name));
1185 	if (strcmp(od_name, XATTR_DIR) == 0)
1186 		node->flags |= NODE_XATTR_DIR;
1187 
1188 	if (VFS_ROOT(vp->v_vfsp, &root_vp) == 0) {
1189 		if (vp == root_vp)
1190 			node->flags |= NODE_FLAGS_VFSROOT;
1191 		VN_RELE(root_vp);
1192 	}
1193 
1194 	node->n_state = SMB_NODE_STATE_AVAILABLE;
1195 	node->n_magic = SMB_NODE_MAGIC;
1196 
1197 	return (node);
1198 }
1199 
1200 /*
1201  * smb_node_free
1202  */
1203 static void
1204 smb_node_free(smb_node_t *node)
1205 {
1206 	SMB_NODE_VALID(node);
1207 
1208 	node->n_magic = 0;
1209 	VERIFY(!list_link_active(&node->n_lnd));
1210 	VERIFY(node->n_lock_list.ll_count == 0);
1211 	VERIFY(node->n_wlock_list.ll_count == 0);
1212 	VERIFY(node->n_ofile_list.ll_count == 0);
1213 	VERIFY(node->n_oplock.ol_count == 0);
1214 	VERIFY(node->n_oplock.ol_xthread == NULL);
1215 	VERIFY(node->n_oplock.ol_fem == B_FALSE);
1216 	VERIFY(MUTEX_NOT_HELD(&node->n_mutex));
1217 	VERIFY(!RW_LOCK_HELD(&node->n_lock));
1218 	VN_RELE(node->vp);
1219 	kmem_cache_free(smb_node_cache, node);
1220 }
1221 
1222 /*
1223  * smb_node_constructor
1224  */
1225 static int
1226 smb_node_constructor(void *buf, void *un, int kmflags)
1227 {
1228 	_NOTE(ARGUNUSED(kmflags, un))
1229 
1230 	smb_node_t	*node = (smb_node_t *)buf;
1231 
1232 	bzero(node, sizeof (smb_node_t));
1233 
1234 	smb_llist_constructor(&node->n_ofile_list, sizeof (smb_ofile_t),
1235 	    offsetof(smb_ofile_t, f_nnd));
1236 	smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t),
1237 	    offsetof(smb_lock_t, l_lnd));
1238 	smb_llist_constructor(&node->n_wlock_list, sizeof (smb_lock_t),
1239 	    offsetof(smb_lock_t, l_lnd));
1240 	cv_init(&node->n_oplock.ol_cv, NULL, CV_DEFAULT, NULL);
1241 	mutex_init(&node->n_oplock.ol_mutex, NULL, MUTEX_DEFAULT, NULL);
1242 	list_create(&node->n_oplock.ol_grants, sizeof (smb_oplock_grant_t),
1243 	    offsetof(smb_oplock_grant_t, og_lnd));
1244 	rw_init(&node->n_lock, NULL, RW_DEFAULT, NULL);
1245 	mutex_init(&node->n_mutex, NULL, MUTEX_DEFAULT, NULL);
1246 	smb_node_create_audit_buf(node, kmflags);
1247 	return (0);
1248 }
1249 
1250 /*
1251  * smb_node_destructor
1252  */
1253 static void
1254 smb_node_destructor(void *buf, void *un)
1255 {
1256 	_NOTE(ARGUNUSED(un))
1257 
1258 	smb_node_t	*node = (smb_node_t *)buf;
1259 
1260 	smb_node_destroy_audit_buf(node);
1261 	mutex_destroy(&node->n_mutex);
1262 	rw_destroy(&node->n_lock);
1263 	cv_destroy(&node->n_oplock.ol_cv);
1264 	mutex_destroy(&node->n_oplock.ol_mutex);
1265 	smb_llist_destructor(&node->n_lock_list);
1266 	smb_llist_destructor(&node->n_wlock_list);
1267 	smb_llist_destructor(&node->n_ofile_list);
1268 	list_destroy(&node->n_oplock.ol_grants);
1269 }
1270 
1271 /*
1272  * smb_node_create_audit_buf
1273  */
1274 static void
1275 smb_node_create_audit_buf(smb_node_t *node, int kmflags)
1276 {
1277 	smb_audit_buf_node_t	*abn;
1278 
1279 	if (smb_audit_flags & SMB_AUDIT_NODE) {
1280 		abn = kmem_zalloc(sizeof (smb_audit_buf_node_t), kmflags);
1281 		abn->anb_max_index = SMB_AUDIT_BUF_MAX_REC - 1;
1282 		node->n_audit_buf = abn;
1283 	}
1284 }
1285 
1286 /*
1287  * smb_node_destroy_audit_buf
1288  */
1289 static void
1290 smb_node_destroy_audit_buf(smb_node_t *node)
1291 {
1292 	if (node->n_audit_buf != NULL) {
1293 		kmem_free(node->n_audit_buf, sizeof (smb_audit_buf_node_t));
1294 		node->n_audit_buf = NULL;
1295 	}
1296 }
1297 
1298 /*
1299  * smb_node_audit
1300  *
1301  * This function saves the calling stack in the audit buffer of the node passed
1302  * in.
1303  */
1304 static void
1305 smb_node_audit(smb_node_t *node)
1306 {
1307 #ifdef	_KERNEL
1308 	smb_audit_buf_node_t	*abn;
1309 	smb_audit_record_node_t	*anr;
1310 
1311 	if (node->n_audit_buf) {
1312 		abn = node->n_audit_buf;
1313 		anr = abn->anb_records;
1314 		anr += abn->anb_index;
1315 		abn->anb_index++;
1316 		abn->anb_index &= abn->anb_max_index;
1317 		anr->anr_refcnt = node->n_refcnt;
1318 		anr->anr_depth = getpcstack(anr->anr_stack,
1319 		    SMB_AUDIT_STACK_DEPTH);
1320 	}
1321 #else	/* _KERNEL */
1322 	_NOTE(ARGUNUSED(node))
1323 #endif	/* _KERNEL */
1324 }
1325 
1326 static smb_llist_t *
1327 smb_node_get_hash(fsid_t *fsid, smb_attr_t *attr, uint32_t *phashkey)
1328 {
1329 	uint32_t	hashkey;
1330 
1331 	hashkey = fsid->val[0] + attr->sa_vattr.va_nodeid;
1332 	hashkey += (hashkey >> 24) + (hashkey >> 16) + (hashkey >> 8);
1333 	*phashkey = hashkey;
1334 	return (&smb_node_hash_table[(hashkey & SMBND_HASH_MASK)]);
1335 }
1336 
1337 boolean_t
1338 smb_node_is_file(smb_node_t *node)
1339 {
1340 	SMB_NODE_VALID(node);
1341 	return (node->vp->v_type == VREG);
1342 }
1343 
1344 boolean_t
1345 smb_node_is_dir(smb_node_t *node)
1346 {
1347 	SMB_NODE_VALID(node);
1348 	return ((node->vp->v_type == VDIR) ||
1349 	    (node->flags & NODE_FLAGS_DFSLINK));
1350 }
1351 
1352 boolean_t
1353 smb_node_is_symlink(smb_node_t *node)
1354 {
1355 	SMB_NODE_VALID(node);
1356 	return ((node->vp->v_type == VLNK) &&
1357 	    ((node->flags & NODE_FLAGS_REPARSE) == 0));
1358 }
1359 
1360 boolean_t
1361 smb_node_is_dfslink(smb_node_t *node)
1362 {
1363 	SMB_NODE_VALID(node);
1364 	return ((node->vp->v_type == VLNK) &&
1365 	    (node->flags & NODE_FLAGS_DFSLINK));
1366 }
1367 
1368 boolean_t
1369 smb_node_is_reparse(smb_node_t *node)
1370 {
1371 	SMB_NODE_VALID(node);
1372 	return ((node->vp->v_type == VLNK) &&
1373 	    (node->flags & NODE_FLAGS_REPARSE));
1374 }
1375 
1376 boolean_t
1377 smb_node_is_vfsroot(smb_node_t *node)
1378 {
1379 	SMB_NODE_VALID(node);
1380 	return ((node->flags & NODE_FLAGS_VFSROOT) == NODE_FLAGS_VFSROOT);
1381 }
1382 
1383 boolean_t
1384 smb_node_is_system(smb_node_t *node)
1385 {
1386 	SMB_NODE_VALID(node);
1387 	return ((node->flags & NODE_FLAGS_SYSTEM) == NODE_FLAGS_SYSTEM);
1388 }
1389 
1390 /*
1391  * smb_node_file_is_readonly
1392  *
1393  * Checks if the file (which node represents) is marked readonly
1394  * in the filesystem. No account is taken of any pending readonly
1395  * in the node, which must be handled by the callers.
1396  * (See SMB_OFILE_IS_READONLY and SMB_PATHFILE_IS_READONLY)
1397  */
1398 boolean_t
1399 smb_node_file_is_readonly(smb_node_t *node)
1400 {
1401 	smb_attr_t attr;
1402 
1403 	if (node == NULL)
1404 		return (B_FALSE);	/* pipes */
1405 
1406 	if (node->n_pending_dosattr & FILE_ATTRIBUTE_READONLY)
1407 		return (B_TRUE);
1408 
1409 	bzero(&attr, sizeof (smb_attr_t));
1410 	attr.sa_mask = SMB_AT_DOSATTR;
1411 	(void) smb_fsop_getattr(NULL, zone_kcred(), node, &attr);
1412 	return ((attr.sa_dosattr & FILE_ATTRIBUTE_READONLY) != 0);
1413 }
1414 
1415 /*
1416  * smb_node_setattr
1417  *
1418  * The sr may be NULL, for example when closing an ofile.
1419  * The ofile may be NULL, for example when a client request
1420  * specifies the file by pathname.
1421  *
1422  * Returns: errno
1423  *
1424  * Timestamps
1425  *
1426  * Windows and Unix have different models for timestamp updates.
1427  * [MS-FSA 2.1.5.14 Server Requests Setting of File Information]
1428  *
1429  * An open "handle" in Windows can control whether and when
1430  * any timestamp updates happen for that handle.  For example,
1431  * timestamps set via some handle are no longer updated by I/O
1432  * operations on that handle.  In Unix we don't really have any
1433  * way to avoid the timestamp updates that the file system does.
1434  * Therefore, we need to make some compromises, and simulate the
1435  * more important parts of the Windows file system semantics.
1436  *
1437  * For example, when an SMB client sets file times, set those
1438  * times in the file system (so the change will be visible to
1439  * other clients, at least until they change again) but we also
1440  * make those times "sticky" in our open handle, and reapply
1441  * those times when the handle is closed.  That reapply on close
1442  * simulates the Windows behavior where the timestamp updates
1443  * would be discontinued after they were set.  These "sticky"
1444  * attributes are returned in any query on the handle where
1445  * they are stored.
1446  *
1447  * Other than the above, the file system layer takes care of the
1448  * normal time stamp updates, such as updating the mtime after a
1449  * write, and ctime after an attribute change.
1450  *
1451  * Dos Attributes are stored persistently, but with a twist:
1452  * In Windows, when you set the "read-only" bit on some file,
1453  * existing writable handles to that file continue to have
1454  * write access.  (because access check happens at open)
1455  * If we were to set the read-only bit directly, we would
1456  * cause errors in subsequent writes on any of our open
1457  * (and writable) file handles.  So here too, we have to
1458  * simulate the Windows behavior.  We keep the read-only
1459  * bit "pending" in the smb_node (so it will be visible in
1460  * any new opens of the file) and apply it on close.
1461  *
1462  * File allocation size is also simulated, and not persistent.
1463  * When the file allocation size is set it is first rounded up
1464  * to block size. If the file size is smaller than the allocation
1465  * size the file is truncated by setting the filesize to allocsz.
1466  */
1467 int
1468 smb_node_setattr(smb_request_t *sr, smb_node_t *node,
1469     cred_t *cr, smb_ofile_t *of, smb_attr_t *attr)
1470 {
1471 	int rc;
1472 	uint_t times_mask;
1473 	smb_attr_t tmp_attr;
1474 
1475 	SMB_NODE_VALID(node);
1476 
1477 	/* set attributes specified in attr */
1478 	if (attr->sa_mask == 0)
1479 		return (0);  /* nothing to do (caller bug?) */
1480 
1481 	/*
1482 	 * Allocation size and EOF position interact.
1483 	 * We don't persistently store the allocation size
1484 	 * but make it look like we do while there are opens.
1485 	 * Note: We update the caller's attr in the cases
1486 	 * where they're setting only one of allocsz|size.
1487 	 */
1488 	switch (attr->sa_mask & (SMB_AT_ALLOCSZ | SMB_AT_SIZE)) {
1489 
1490 	case SMB_AT_ALLOCSZ:
1491 		/*
1492 		 * Setting the allocation size but not EOF position.
1493 		 * Get the current EOF in tmp_attr and (if necessary)
1494 		 * truncate to the (rounded up) allocation size.
1495 		 * Using kcred here because if we don't have access,
1496 		 * we want to fail at setattr below and not here.
1497 		 */
1498 		bzero(&tmp_attr, sizeof (smb_attr_t));
1499 		tmp_attr.sa_mask = SMB_AT_SIZE;
1500 		rc = smb_fsop_getattr(NULL, zone_kcred(), node, &tmp_attr);
1501 		if (rc != 0)
1502 			return (rc);
1503 		attr->sa_allocsz = SMB_ALLOCSZ(attr->sa_allocsz);
1504 		if (tmp_attr.sa_vattr.va_size > attr->sa_allocsz) {
1505 			/* truncate the file to allocsz */
1506 			attr->sa_vattr.va_size = attr->sa_allocsz;
1507 			attr->sa_mask |= SMB_AT_SIZE;
1508 		}
1509 		break;
1510 
1511 	case SMB_AT_SIZE:
1512 		/*
1513 		 * Setting the EOF position but not allocation size.
1514 		 * If the new EOF position would be greater than
1515 		 * the allocation size, increase the latter.
1516 		 */
1517 		if (node->n_allocsz < attr->sa_vattr.va_size) {
1518 			attr->sa_mask |= SMB_AT_ALLOCSZ;
1519 			attr->sa_allocsz =
1520 			    SMB_ALLOCSZ(attr->sa_vattr.va_size);
1521 		}
1522 		break;
1523 
1524 	case SMB_AT_ALLOCSZ | SMB_AT_SIZE:
1525 		/*
1526 		 * Setting both.  Increase alloc size if needed.
1527 		 */
1528 		if (attr->sa_allocsz < attr->sa_vattr.va_size)
1529 			attr->sa_allocsz =
1530 			    SMB_ALLOCSZ(attr->sa_vattr.va_size);
1531 		break;
1532 
1533 	default:
1534 		break;
1535 	}
1536 
1537 	/*
1538 	 * If we have an open file, and we set the size,
1539 	 * then set the "written" flag so that at close,
1540 	 * we can force an mtime update.
1541 	 */
1542 	if (of != NULL && (attr->sa_mask & SMB_AT_SIZE) != 0)
1543 		of->f_written = B_TRUE;
1544 
1545 	/*
1546 	 * When operating on an open file, some settable attributes
1547 	 * become "sticky" in the open file object until close.
1548 	 * (see above re. timestamps)
1549 	 */
1550 	times_mask = attr->sa_mask & SMB_AT_TIMES;
1551 	if (of != NULL && times_mask != 0) {
1552 		smb_attr_t *pa;
1553 
1554 		SMB_OFILE_VALID(of);
1555 		mutex_enter(&of->f_mutex);
1556 		pa = &of->f_pending_attr;
1557 
1558 		pa->sa_mask |= times_mask;
1559 
1560 		if (times_mask & SMB_AT_ATIME)
1561 			pa->sa_vattr.va_atime =
1562 			    attr->sa_vattr.va_atime;
1563 		if (times_mask & SMB_AT_MTIME)
1564 			pa->sa_vattr.va_mtime =
1565 			    attr->sa_vattr.va_mtime;
1566 		if (times_mask & SMB_AT_CTIME)
1567 			pa->sa_vattr.va_ctime =
1568 			    attr->sa_vattr.va_ctime;
1569 		if (times_mask & SMB_AT_CRTIME)
1570 			pa->sa_crtime =
1571 			    attr->sa_crtime;
1572 
1573 		mutex_exit(&of->f_mutex);
1574 		/*
1575 		 * The f_pending_attr times are reapplied in
1576 		 * smb_ofile_close().
1577 		 */
1578 	}
1579 
1580 	/*
1581 	 * After this point, tmp_attr is what we will actually
1582 	 * store in the file system _now_, which may differ
1583 	 * from the callers attr and f_pending_attr w.r.t.
1584 	 * the DOS readonly flag etc.
1585 	 */
1586 	bcopy(attr, &tmp_attr, sizeof (tmp_attr));
1587 	if (attr->sa_mask & (SMB_AT_DOSATTR | SMB_AT_ALLOCSZ)) {
1588 		mutex_enter(&node->n_mutex);
1589 		if ((attr->sa_mask & SMB_AT_DOSATTR) != 0) {
1590 			tmp_attr.sa_dosattr &= smb_vop_dosattr_settable;
1591 			if (((tmp_attr.sa_dosattr &
1592 			    FILE_ATTRIBUTE_READONLY) != 0) &&
1593 			    (node->n_open_count != 0)) {
1594 				/* Delay setting readonly */
1595 				node->n_pending_dosattr =
1596 				    tmp_attr.sa_dosattr;
1597 				tmp_attr.sa_dosattr &=
1598 				    ~FILE_ATTRIBUTE_READONLY;
1599 			} else {
1600 				node->n_pending_dosattr = 0;
1601 			}
1602 		}
1603 		/*
1604 		 * Simulate n_allocsz persistence only while
1605 		 * there are opens.  See smb_node_getattr
1606 		 */
1607 		if ((attr->sa_mask & SMB_AT_ALLOCSZ) != 0 &&
1608 		    node->n_open_count != 0)
1609 			node->n_allocsz = attr->sa_allocsz;
1610 		mutex_exit(&node->n_mutex);
1611 	}
1612 
1613 	rc = smb_fsop_setattr(sr, cr, node, &tmp_attr);
1614 	if (rc != 0)
1615 		return (rc);
1616 
1617 	if (node->n_dnode != NULL) {
1618 		smb_node_notify_change(node->n_dnode,
1619 		    FILE_ACTION_MODIFIED, node->od_name);
1620 	}
1621 
1622 	return (0);
1623 }
1624 
1625 /*
1626  * smb_node_getattr
1627  *
1628  * Get attributes from the file system and apply any smb-specific
1629  * overrides for size, dos attributes and timestamps
1630  *
1631  * When node->n_pending_readonly is set on a node, pretend that
1632  * we've already set this node readonly at the filesystem level.
1633  * We can't actually do that until all writable handles are closed
1634  * or those writable handles would suddenly loose their access.
1635  *
1636  * Returns: errno
1637  */
1638 int
1639 smb_node_getattr(smb_request_t *sr, smb_node_t *node, cred_t *cr,
1640     smb_ofile_t *of, smb_attr_t *attr)
1641 {
1642 	int rc;
1643 	uint_t want_mask, pend_mask;
1644 	boolean_t isdir;
1645 
1646 	SMB_NODE_VALID(node);
1647 
1648 	/* Deal with some interdependencies */
1649 	if (attr->sa_mask & SMB_AT_ALLOCSZ)
1650 		attr->sa_mask |= SMB_AT_SIZE;
1651 	if (attr->sa_mask & SMB_AT_DOSATTR)
1652 		attr->sa_mask |= SMB_AT_TYPE;
1653 
1654 	rc = smb_fsop_getattr(sr, cr, node, attr);
1655 	if (rc != 0)
1656 		return (rc);
1657 
1658 	isdir = smb_node_is_dir(node);
1659 
1660 	mutex_enter(&node->n_mutex);
1661 
1662 	/*
1663 	 * When there are open handles, and one of them has
1664 	 * set the DOS readonly flag (in n_pending_dosattr),
1665 	 * it will not have been stored in the file system.
1666 	 * In this case use n_pending_dosattr. Note that
1667 	 * n_pending_dosattr has only the settable bits,
1668 	 * (setattr masks it with smb_vop_dosattr_settable)
1669 	 * so we need to keep any non-settable bits we got
1670 	 * from the file-system above.
1671 	 */
1672 	if (attr->sa_mask & SMB_AT_DOSATTR) {
1673 		if (node->n_pending_dosattr) {
1674 			attr->sa_dosattr &= ~smb_vop_dosattr_settable;
1675 			attr->sa_dosattr |= node->n_pending_dosattr;
1676 		}
1677 		if (attr->sa_dosattr == 0) {
1678 			attr->sa_dosattr = (isdir) ?
1679 			    FILE_ATTRIBUTE_DIRECTORY:
1680 			    FILE_ATTRIBUTE_NORMAL;
1681 		}
1682 	}
1683 
1684 	/*
1685 	 * Also fix-up sa_allocsz, which is not persistent.
1686 	 * When there are no open files, allocsz is faked.
1687 	 * While there are open files, we pretend we have a
1688 	 * persistent allocation size in n_allocsz, and
1689 	 * keep that up-to-date here, increasing it when
1690 	 * we see the file size grow past it.
1691 	 */
1692 	if (attr->sa_mask & SMB_AT_ALLOCSZ) {
1693 		if (isdir) {
1694 			attr->sa_allocsz = 0;
1695 		} else if (node->n_open_count == 0) {
1696 			attr->sa_allocsz =
1697 			    SMB_ALLOCSZ(attr->sa_vattr.va_size);
1698 		} else {
1699 			if (node->n_allocsz < attr->sa_vattr.va_size)
1700 				node->n_allocsz =
1701 				    SMB_ALLOCSZ(attr->sa_vattr.va_size);
1702 			attr->sa_allocsz = node->n_allocsz;
1703 		}
1704 	}
1705 
1706 	mutex_exit(&node->n_mutex);
1707 
1708 	if (isdir) {
1709 		attr->sa_vattr.va_size = 0;
1710 		attr->sa_vattr.va_nlink = 1;
1711 	}
1712 
1713 	/*
1714 	 * getattr with an ofile gets any "pending" times that
1715 	 * might have been previously set via this ofile.
1716 	 * This is what makes these times "sticky".
1717 	 */
1718 	want_mask = attr->sa_mask & SMB_AT_TIMES;
1719 	if (of != NULL && want_mask != 0) {
1720 		smb_attr_t *pa;
1721 
1722 		SMB_OFILE_VALID(of);
1723 		mutex_enter(&of->f_mutex);
1724 		pa = &of->f_pending_attr;
1725 
1726 		pend_mask = pa->sa_mask;
1727 
1728 		if (want_mask & pend_mask & SMB_AT_ATIME)
1729 			attr->sa_vattr.va_atime =
1730 			    pa->sa_vattr.va_atime;
1731 		if (want_mask & pend_mask & SMB_AT_MTIME)
1732 			attr->sa_vattr.va_mtime =
1733 			    pa->sa_vattr.va_mtime;
1734 		if (want_mask & pend_mask & SMB_AT_CTIME)
1735 			attr->sa_vattr.va_ctime =
1736 			    pa->sa_vattr.va_ctime;
1737 		if (want_mask & pend_mask & SMB_AT_CRTIME)
1738 			attr->sa_crtime =
1739 			    pa->sa_crtime;
1740 
1741 		mutex_exit(&of->f_mutex);
1742 	}
1743 
1744 
1745 	return (0);
1746 }
1747 
1748 
1749 #ifndef	_KERNEL
1750 extern int reparse_vnode_parse(vnode_t *vp, nvlist_t *nvl);
1751 #endif	/* _KERNEL */
1752 
1753 /*
1754  * Check to see if the node represents a reparse point.
1755  * If yes, whether the reparse point contains a DFS link.
1756  */
1757 static void
1758 smb_node_init_reparse(smb_node_t *node, smb_attr_t *attr)
1759 {
1760 	nvlist_t *nvl;
1761 	nvpair_t *rec;
1762 	char *rec_type;
1763 
1764 	if ((attr->sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
1765 		return;
1766 
1767 	if ((nvl = reparse_init()) == NULL)
1768 		return;
1769 
1770 	if (reparse_vnode_parse(node->vp, nvl) != 0) {
1771 		reparse_free(nvl);
1772 		return;
1773 	}
1774 
1775 	node->flags |= NODE_FLAGS_REPARSE;
1776 
1777 	rec = nvlist_next_nvpair(nvl, NULL);
1778 	while (rec != NULL) {
1779 		rec_type = nvpair_name(rec);
1780 		if ((rec_type != NULL) &&
1781 		    (strcasecmp(rec_type, DFS_REPARSE_SVCTYPE) == 0)) {
1782 			node->flags |= NODE_FLAGS_DFSLINK;
1783 			break;
1784 		}
1785 		rec = nvlist_next_nvpair(nvl, rec);
1786 	}
1787 
1788 	reparse_free(nvl);
1789 }
1790 
1791 /*
1792  * smb_node_init_system
1793  *
1794  * If the node represents a special system file set NODE_FLAG_SYSTEM.
1795  * System files:
1796  * - any node whose parent dnode has NODE_FLAG_SYSTEM set
1797  * - any node whose associated unnamed stream node (unode) has
1798  *   NODE_FLAG_SYSTEM set
1799  * - .$EXTEND at root of share (quota management)
1800  */
1801 static void
1802 smb_node_init_system(smb_node_t *node)
1803 {
1804 	smb_node_t *dnode = node->n_dnode;
1805 	smb_node_t *unode = node->n_unode;
1806 
1807 	if ((dnode) && (dnode->flags & NODE_FLAGS_SYSTEM)) {
1808 		node->flags |= NODE_FLAGS_SYSTEM;
1809 		return;
1810 	}
1811 
1812 	if ((unode) && (unode->flags & NODE_FLAGS_SYSTEM)) {
1813 		node->flags |= NODE_FLAGS_SYSTEM;
1814 		return;
1815 	}
1816 
1817 	if ((dnode) && (smb_node_is_vfsroot(node->n_dnode) &&
1818 	    (strcasecmp(node->od_name, ".$EXTEND") == 0))) {
1819 		node->flags |= NODE_FLAGS_SYSTEM;
1820 	}
1821 }
1822