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