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