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