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