xref: /titanic_52/usr/src/uts/common/fs/smbsrv/smb_node.c (revision 269552cd714f2f1e308fdde0fc69b18a7f1142b2)
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 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 /*
26  * SMB Node State Machine
27  * ----------------------
28  *
29  *    +----------------------------+	 T0
30  *    |  SMB_NODE_STATE_AVAILABLE  |<----------- Creation/Allocation
31  *    +----------------------------+
32  *		    |
33  *		    | T1
34  *		    |
35  *		    v
36  *    +-----------------------------+    T2
37  *    |  SMB_NODE_STATE_DESTROYING  |----------> Deletion/Free
38  *    +-----------------------------+
39  *
40  * Transition T0
41  *
42  *    This transition occurs in smb_node_lookup(). If the node looked for is
43  *    not found in the has table a new node is created. The reference count is
44  *    initialized to 1 and the state initialized to SMB_NODE_STATE_AVAILABLE.
45  *
46  * Transition T1
47  *
48  *    This transition occurs in smb_node_release(). If the reference count
49  *    drops to zero the state is moved to SMB_NODE_STATE_DESTROYING and no more
50  *    reference count will be given out for that node.
51  *
52  * Transition T2
53  *
54  *    This transition occurs in smb_node_release(). The structure is deleted.
55  *
56  * Comments
57  * --------
58  *
59  *    The reason the smb node has 2 states is the following synchronization
60  *    rule:
61  *
62  *    There's a mutex embedded in the node used to protect its fields and
63  *    there's a lock embedded in the bucket of the hash table the node belongs
64  *    to. To increment or to decrement the reference count the mutex must be
65  *    entered. To insert the node into the bucket and to remove it from the
66  *    bucket the lock must be entered in RW_WRITER mode. When both (mutex and
67  *    lock) have to be entered, the lock has always to be entered first then
68  *    the mutex. This prevents a deadlock between smb_node_lookup() and
69  *    smb_node_release() from occurring. However, in smb_node_release() when the
70  *    reference count drops to zero and triggers the deletion of the node, the
71  *    mutex has to be released before entering the lock of the bucket (to
72  *    remove the node). This creates a window during which the node that is
73  *    about to be freed could be given out by smb_node_lookup(). To close that
74  *    window the node is moved to the state SMB_NODE_STATE_DESTROYING before
75  *    releasing the mutex. That way, even if smb_node_lookup() finds it, the
76  *    state will indicate that the node should be treated as non existent (of
77  *    course the state of the node should be tested/updated under the
78  *    protection of the mutex).
79  */
80 #include <smbsrv/smb_incl.h>
81 #include <smbsrv/smb_fsops.h>
82 #include <smbsrv/smb_kstat.h>
83 #include <sys/pathname.h>
84 #include <sys/sdt.h>
85 #include <sys/nbmlock.h>
86 
87 uint32_t smb_is_executable(char *);
88 static void smb_node_delete_on_close(smb_node_t *);
89 static void smb_node_create_audit_buf(smb_node_t *, int);
90 static void smb_node_destroy_audit_buf(smb_node_t *);
91 static void smb_node_audit(smb_node_t *);
92 static smb_node_t *smb_node_alloc(char *, vnode_t *, smb_attr_t *,
93     smb_llist_t *bucket, uint32_t hashkey);
94 static void smb_node_free(smb_node_t *);
95 static int smb_node_constructor(void *, void *, int);
96 static void smb_node_destructor(void *, void *);
97 static smb_llist_t *smb_node_get_hash(fsid_t *, smb_attr_t *, uint32_t *);
98 
99 #define	VALIDATE_DIR_NODE(_dir_, _node_) \
100     ASSERT((_dir_)->n_magic == SMB_NODE_MAGIC); \
101     ASSERT(((_dir_)->vp->v_xattrdir) || ((_dir_)->vp->v_type == VDIR)); \
102     ASSERT((_dir_)->dir_snode != (_node_));
103 
104 static kmem_cache_t	*smb_node_cache = NULL;
105 static boolean_t	smb_node_initialized = B_FALSE;
106 static smb_llist_t	smb_node_hash_table[SMBND_HASH_MASK+1];
107 
108 /*
109  * smb_node_init
110  *
111  * Initialization of the SMB node layer.
112  *
113  * This function is not multi-thread safe. The caller must make sure only one
114  * thread makes the call.
115  */
116 int
117 smb_node_init(void)
118 {
119 	int	i;
120 
121 	if (smb_node_initialized)
122 		return (0);
123 	smb_node_cache = kmem_cache_create(SMBSRV_KSTAT_NODE_CACHE,
124 	    sizeof (smb_node_t), 8, smb_node_constructor, smb_node_destructor,
125 	    NULL, NULL, NULL, 0);
126 
127 	for (i = 0; i <= SMBND_HASH_MASK; i++) {
128 		smb_llist_constructor(&smb_node_hash_table[i],
129 		    sizeof (smb_node_t), offsetof(smb_node_t, n_lnd));
130 	}
131 	smb_node_initialized = B_TRUE;
132 	return (0);
133 }
134 
135 /*
136  * smb_node_fini
137  *
138  * This function is not multi-thread safe. The caller must make sure only one
139  * thread makes the call.
140  */
141 void
142 smb_node_fini(void)
143 {
144 	int	i;
145 
146 	if (!smb_node_initialized)
147 		return;
148 
149 #ifdef DEBUG
150 	for (i = 0; i <= SMBND_HASH_MASK; i++) {
151 		smb_node_t	*node;
152 
153 		/*
154 		 * The following sequence is just intended for sanity check.
155 		 * This will have to be modified when the code goes into
156 		 * production.
157 		 *
158 		 * The SMB node hash table should be emtpy at this point. If the
159 		 * hash table is not empty a panic will be triggered.
160 		 *
161 		 * The reason why SMB nodes are still remaining in the hash
162 		 * table is problably due to a mismatch between calls to
163 		 * smb_node_lookup() and smb_node_release(). You must track that
164 		 * down.
165 		 */
166 		node = smb_llist_head(&smb_node_hash_table[i]);
167 		ASSERT(node == NULL);
168 	}
169 #endif
170 
171 	for (i = 0; i <= SMBND_HASH_MASK; i++) {
172 		smb_llist_destructor(&smb_node_hash_table[i]);
173 	}
174 	kmem_cache_destroy(smb_node_cache);
175 	smb_node_cache = NULL;
176 	smb_node_initialized = B_FALSE;
177 }
178 
179 /*
180  * smb_node_lookup()
181  *
182  * NOTE: This routine should only be called by the file system interface layer,
183  * and not by SMB.
184  *
185  * smb_node_lookup() is called upon successful lookup, mkdir, and create
186  * (for both non-streams and streams).  In each of these cases, a held vnode is
187  * passed into this routine.  If a new smb_node is created it will take its
188  * own hold on the vnode.  The caller's hold therefore still belongs to, and
189  * should be released by, the caller.
190  *
191  * A reference is taken on the smb_node whether found in the hash table
192  * or newly created.
193  *
194  * If an smb_node needs to be created, a reference is also taken on the
195  * dir_snode (if passed in).
196  *
197  * See smb_node_release() for details on the release of these references.
198  */
199 
200 /*ARGSUSED*/
201 smb_node_t *
202 smb_node_lookup(
203     struct smb_request	*sr,
204     struct open_param	*op,
205     cred_t		*cred,
206     vnode_t		*vp,
207     char		*od_name,
208     smb_node_t		*dir_snode,
209     smb_node_t		*unnamed_node,
210     smb_attr_t		*attr)
211 {
212 	smb_llist_t		*node_hdr;
213 	smb_node_t		*node;
214 	uint32_t		hashkey = 0;
215 	fsid_t			fsid;
216 	int			error;
217 	krw_t			lock_mode;
218 	vnode_t			*unnamed_vp = NULL;
219 
220 	/*
221 	 * smb_vop_getattr() is called here instead of smb_fsop_getattr(),
222 	 * because the node may not yet exist.  We also do not want to call
223 	 * it with the list lock held.
224 	 */
225 
226 	if (unnamed_node)
227 		unnamed_vp = unnamed_node->vp;
228 
229 	/*
230 	 * This getattr is performed on behalf of the server
231 	 * that's why kcred is used not the user's cred
232 	 */
233 	attr->sa_mask = SMB_AT_ALL;
234 	error = smb_vop_getattr(vp, unnamed_vp, attr, 0, kcred);
235 	if (error)
236 		return (NULL);
237 
238 	if (sr && sr->tid_tree) {
239 		/*
240 		 * The fsid for a file is that of the tree, even
241 		 * if the file resides in a different mountpoint
242 		 * under the share.
243 		 */
244 		fsid = SMB_TREE_FSID(sr->tid_tree);
245 	} else {
246 		/*
247 		 * This should be getting executed only for the
248 		 * tree root smb_node.
249 		 */
250 		fsid = vp->v_vfsp->vfs_fsid;
251 	}
252 
253 	node_hdr = smb_node_get_hash(&fsid, attr, &hashkey);
254 	lock_mode = RW_READER;
255 
256 	smb_llist_enter(node_hdr, lock_mode);
257 	for (;;) {
258 		node = list_head(&node_hdr->ll_list);
259 		while (node) {
260 			ASSERT(node->n_magic == SMB_NODE_MAGIC);
261 			ASSERT(node->n_hash_bucket == node_hdr);
262 			if ((node->n_hashkey == hashkey) && (node->vp == vp)) {
263 				mutex_enter(&node->n_mutex);
264 				DTRACE_PROBE1(smb_node_lookup_hit,
265 				    smb_node_t *, node);
266 				switch (node->n_state) {
267 				case SMB_NODE_STATE_OPLOCK_GRANTED:
268 				case SMB_NODE_STATE_OPLOCK_BREAKING:
269 				case SMB_NODE_STATE_AVAILABLE:
270 					/* The node was found. */
271 					node->n_refcnt++;
272 					if ((node->dir_snode == NULL) &&
273 					    (dir_snode != NULL) &&
274 					    (strcmp(od_name, "..") != 0) &&
275 					    (strcmp(od_name, ".") != 0)) {
276 						VALIDATE_DIR_NODE(dir_snode,
277 						    node);
278 						node->dir_snode = dir_snode;
279 						smb_node_ref(dir_snode);
280 					}
281 					node->attr = *attr;
282 					node->n_size = attr->sa_vattr.va_size;
283 
284 					smb_node_audit(node);
285 					mutex_exit(&node->n_mutex);
286 					smb_llist_exit(node_hdr);
287 					return (node);
288 
289 				case SMB_NODE_STATE_DESTROYING:
290 					/*
291 					 * Although the node exists it is about
292 					 * to be destroyed. We act as it hasn't
293 					 * been found.
294 					 */
295 					mutex_exit(&node->n_mutex);
296 					break;
297 				default:
298 					/*
299 					 * Although the node exists it is in an
300 					 * unknown state. We act as it hasn't
301 					 * been found.
302 					 */
303 					ASSERT(0);
304 					mutex_exit(&node->n_mutex);
305 					break;
306 				}
307 			}
308 			node = smb_llist_next(node_hdr, node);
309 		}
310 		if ((lock_mode == RW_READER) && smb_llist_upgrade(node_hdr)) {
311 			lock_mode = RW_WRITER;
312 			continue;
313 		}
314 		break;
315 	}
316 	node = smb_node_alloc(od_name, vp, attr, node_hdr, hashkey);
317 	node->n_orig_uid = crgetuid(sr->user_cr);
318 
319 	if (op)
320 		node->flags |= smb_is_executable(op->fqi.last_comp);
321 
322 	if (dir_snode) {
323 		smb_node_ref(dir_snode);
324 		node->dir_snode = dir_snode;
325 		ASSERT(dir_snode->dir_snode != node);
326 		ASSERT((dir_snode->vp->v_xattrdir) ||
327 		    (dir_snode->vp->v_type == VDIR));
328 	}
329 
330 	if (unnamed_node) {
331 		smb_node_ref(unnamed_node);
332 		node->unnamed_stream_node = unnamed_node;
333 	}
334 
335 	DTRACE_PROBE1(smb_node_lookup_miss, smb_node_t *, node);
336 	smb_node_audit(node);
337 	smb_llist_insert_head(node_hdr, node);
338 	smb_llist_exit(node_hdr);
339 	return (node);
340 }
341 
342 /*
343  * smb_stream_node_lookup()
344  *
345  * Note: stream_name (the name that will be stored in the "od_name" field
346  * of a stream's smb_node) is the same as the on-disk name for the stream
347  * except that it does not have SMB_STREAM_PREFIX prepended.
348  */
349 
350 smb_node_t *
351 smb_stream_node_lookup(smb_request_t *sr, cred_t *cr, smb_node_t *fnode,
352     vnode_t *xattrdirvp, vnode_t *vp, char *stream_name, smb_attr_t *ret_attr)
353 {
354 	smb_node_t	*xattrdir_node;
355 	smb_node_t	*snode;
356 	smb_attr_t	tmp_attr;
357 
358 	xattrdir_node = smb_node_lookup(sr, NULL, cr, xattrdirvp, XATTR_DIR,
359 	    fnode, NULL, &tmp_attr);
360 
361 	if (xattrdir_node == NULL)
362 		return (NULL);
363 
364 	snode = smb_node_lookup(sr, NULL, cr, vp, stream_name, xattrdir_node,
365 	    fnode, ret_attr);
366 
367 	(void) smb_node_release(xattrdir_node);
368 	return (snode);
369 }
370 
371 
372 /*
373  * This function should be called whenever a reference is needed on an
374  * smb_node pointer.  The copy of an smb_node pointer from one non-local
375  * data structure to another requires a reference to be taken on the smb_node
376  * (unless the usage is localized).  Each data structure deallocation routine
377  * will call smb_node_release() on its smb_node pointers.
378  *
379  * In general, an smb_node pointer residing in a structure should never be
380  * stale.  A node pointer may be NULL, however, and care should be taken
381  * prior to calling smb_node_ref(), which ASSERTs that the pointer is valid.
382  * Care also needs to be taken with respect to racing deallocations of a
383  * structure.
384  */
385 void
386 smb_node_ref(smb_node_t *node)
387 {
388 	SMB_NODE_VALID(node);
389 
390 	mutex_enter(&node->n_mutex);
391 	switch (node->n_state) {
392 	case SMB_NODE_STATE_AVAILABLE:
393 	case SMB_NODE_STATE_OPLOCK_GRANTED:
394 	case SMB_NODE_STATE_OPLOCK_BREAKING:
395 		node->n_refcnt++;
396 		ASSERT(node->n_refcnt);
397 		DTRACE_PROBE1(smb_node_ref_exit, smb_node_t *, node);
398 		smb_node_audit(node);
399 		break;
400 	default:
401 		SMB_PANIC();
402 	}
403 	mutex_exit(&node->n_mutex);
404 }
405 
406 /*
407  * smb_node_lookup() takes a hold on an smb_node, whether found in the
408  * hash table or newly created.  This hold is expected to be released
409  * in the following manner.
410  *
411  * smb_node_lookup() takes an address of an smb_node pointer.  This should
412  * be getting passed down via a lookup (whether path name or component), mkdir,
413  * create.  If the original smb_node pointer resides in a data structure, then
414  * the deallocation routine for the data structure is responsible for calling
415  * smb_node_release() on the smb_node pointer.  Alternatively,
416  * smb_node_release() can be called as soon as the smb_node pointer is no longer
417  * needed.  In this case, callers are responsible for setting an embedded
418  * pointer to NULL if it is known that the last reference is being released.
419  *
420  * If the passed-in address of the smb_node pointer belongs to a local variable,
421  * then the caller with the local variable should call smb_node_release()
422  * directly.
423  *
424  * smb_node_release() itself will call smb_node_release() on a node's dir_snode,
425  * as smb_node_lookup() takes a hold on dir_snode.
426  */
427 void
428 smb_node_release(smb_node_t *node)
429 {
430 	SMB_NODE_VALID(node);
431 
432 	mutex_enter(&node->n_mutex);
433 	ASSERT(node->n_refcnt);
434 	DTRACE_PROBE1(smb_node_release, smb_node_t *, node);
435 	if (--node->n_refcnt == 0) {
436 		switch (node->n_state) {
437 
438 		case SMB_NODE_STATE_AVAILABLE:
439 			node->n_state = SMB_NODE_STATE_DESTROYING;
440 			mutex_exit(&node->n_mutex);
441 
442 			smb_llist_enter(node->n_hash_bucket, RW_WRITER);
443 			smb_llist_remove(node->n_hash_bucket, node);
444 			smb_llist_exit(node->n_hash_bucket);
445 
446 			/*
447 			 * Check if the file was deleted
448 			 */
449 			smb_node_delete_on_close(node);
450 
451 			if (node->dir_snode) {
452 				ASSERT(node->dir_snode->n_magic ==
453 				    SMB_NODE_MAGIC);
454 				smb_node_release(node->dir_snode);
455 			}
456 
457 			if (node->unnamed_stream_node) {
458 				ASSERT(node->unnamed_stream_node->n_magic ==
459 				    SMB_NODE_MAGIC);
460 				smb_node_release(node->unnamed_stream_node);
461 			}
462 
463 			smb_node_free(node);
464 			return;
465 
466 		default:
467 			SMB_PANIC();
468 		}
469 	}
470 	smb_node_audit(node);
471 	mutex_exit(&node->n_mutex);
472 }
473 
474 static void
475 smb_node_delete_on_close(smb_node_t *node)
476 {
477 	smb_node_t	*d_snode;
478 	int		rc = 0;
479 
480 	d_snode = node->dir_snode;
481 	if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
482 
483 		node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE;
484 		ASSERT(node->od_name != NULL);
485 		if (node->attr.sa_vattr.va_type == VDIR)
486 			rc = smb_fsop_rmdir(0, node->delete_on_close_cred,
487 			    d_snode, node->od_name, 1);
488 		else
489 			rc = smb_fsop_remove(0, node->delete_on_close_cred,
490 			    d_snode, node->od_name, 1);
491 		smb_cred_rele(node->delete_on_close_cred);
492 	}
493 	if (rc != 0)
494 		cmn_err(CE_WARN, "File %s could not be removed, rc=%d\n",
495 		    node->od_name, rc);
496 	DTRACE_PROBE2(smb_node_delete_on_close, int, rc, smb_node_t *, node);
497 }
498 
499 /*
500  * smb_node_rename()
501  *
502  */
503 void
504 smb_node_rename(
505     smb_node_t	*from_dnode,
506     smb_node_t	*ret_node,
507     smb_node_t	*to_dnode,
508     char	*to_name)
509 {
510 	SMB_NODE_VALID(from_dnode);
511 	SMB_NODE_VALID(to_dnode);
512 	SMB_NODE_VALID(ret_node);
513 
514 	smb_node_ref(to_dnode);
515 	mutex_enter(&ret_node->n_mutex);
516 	switch (ret_node->n_state) {
517 	case SMB_NODE_STATE_AVAILABLE:
518 	case SMB_NODE_STATE_OPLOCK_GRANTED:
519 	case SMB_NODE_STATE_OPLOCK_BREAKING:
520 		ret_node->dir_snode = to_dnode;
521 		mutex_exit(&ret_node->n_mutex);
522 		ASSERT(to_dnode->dir_snode != ret_node);
523 		ASSERT((to_dnode->vp->v_xattrdir) ||
524 		    (to_dnode->vp->v_type == VDIR));
525 		smb_node_release(from_dnode);
526 		(void) strcpy(ret_node->od_name, to_name);
527 		/*
528 		 * XXX Need to update attributes?
529 		 */
530 		break;
531 	default:
532 		SMB_PANIC();
533 	}
534 }
535 
536 int
537 smb_node_root_init(vnode_t *vp, smb_server_t *sv, smb_node_t **root)
538 {
539 	smb_attr_t	va;
540 	int		error;
541 	uint32_t	hashkey;
542 	smb_llist_t	*node_hdr;
543 	smb_node_t	*node;
544 
545 	va.sa_mask = SMB_AT_ALL;
546 	error = smb_vop_getattr(vp, NULL, &va, 0, kcred);
547 	if (error) {
548 		VN_RELE(vp);
549 		return (error);
550 	}
551 
552 	node_hdr = smb_node_get_hash(&vp->v_vfsp->vfs_fsid, &va, &hashkey);
553 
554 	node = smb_node_alloc(ROOTVOL, vp, &va, node_hdr, hashkey);
555 
556 	sv->si_root_smb_node = node;
557 	smb_node_audit(node);
558 	smb_llist_enter(node_hdr, RW_WRITER);
559 	smb_llist_insert_head(node_hdr, node);
560 	smb_llist_exit(node_hdr);
561 	*root = node;
562 	return (0);
563 }
564 
565 /*
566  * smb_node_get_size
567  */
568 u_offset_t
569 smb_node_get_size(smb_node_t *node, smb_attr_t *attr)
570 {
571 	u_offset_t size;
572 
573 	if (attr->sa_vattr.va_type == VDIR)
574 		return (0);
575 
576 	mutex_enter(&node->n_mutex);
577 	if (node && (node->flags & NODE_FLAGS_SET_SIZE))
578 		size = node->n_size;
579 	else
580 		size = attr->sa_vattr.va_size;
581 	mutex_exit(&node->n_mutex);
582 	return (size);
583 }
584 
585 static int
586 timeval_cmp(timestruc_t *a, timestruc_t *b)
587 {
588 	if (a->tv_sec < b->tv_sec)
589 		return (-1);
590 	if (a->tv_sec > b->tv_sec)
591 		return (1);
592 	/* Seconds are equal compare tv_nsec */
593 	if (a->tv_nsec < b->tv_nsec)
594 		return (-1);
595 	return (a->tv_nsec > b->tv_nsec);
596 }
597 
598 /*
599  * smb_node_set_time
600  *
601  * This function will update the time stored in the node and
602  * set the appropriate flags. If there is nothing to update,
603  * the function will return without any updates.  The update
604  * is only in the node level and the attribute in the file system
605  * will be updated when client close the file.
606  */
607 void
608 smb_node_set_time(
609     smb_node_t	*node,
610     timestruc_t	*crtime,
611     timestruc_t	*mtime,
612     timestruc_t	*atime,
613     timestruc_t	*ctime,
614     uint_t	what)
615 {
616 	if (what == 0)
617 		return;
618 
619 	if ((what & SMB_AT_CRTIME && crtime == 0) ||
620 	    (what & SMB_AT_MTIME && mtime == 0) ||
621 	    (what & SMB_AT_ATIME && atime == 0) ||
622 	    (what & SMB_AT_CTIME && ctime == 0))
623 		return;
624 
625 	mutex_enter(&node->n_mutex);
626 
627 	if ((what & SMB_AT_CRTIME) &&
628 	    timeval_cmp((timestruc_t *)&node->attr.sa_crtime,
629 	    crtime) != 0) {
630 		node->what |= SMB_AT_CRTIME;
631 		node->attr.sa_crtime = *((timestruc_t *)crtime);
632 	}
633 
634 	if ((what & SMB_AT_MTIME) &&
635 	    timeval_cmp((timestruc_t *)&node->attr.sa_vattr.va_mtime,
636 	    mtime) != 0) {
637 		node->what |= SMB_AT_MTIME;
638 		node->attr.sa_vattr.va_mtime = *((timestruc_t *)mtime);
639 	}
640 
641 	if ((what & SMB_AT_ATIME) &&
642 	    timeval_cmp((timestruc_t *)&node->attr.sa_vattr.va_atime,
643 	    atime) != 0) {
644 			node->what |= SMB_AT_ATIME;
645 			node->attr.sa_vattr.va_atime = *((timestruc_t *)atime);
646 	}
647 
648 	/*
649 	 * The ctime handling is trickier. It has three scenarios.
650 	 * 1. Only ctime need to be set and it is the same as the ctime
651 	 *    stored in the node. (update not necessary)
652 	 * 2. The ctime is the same as the ctime stored in the node but
653 	 *    is not the only time need to be set. (update required)
654 	 * 3. The ctime need to be set and is not the same as the ctime
655 	 *    stored in the node. (update required)
656 	 * Unlike other time setting, the ctime needs to be set even when
657 	 * it is the same as the ctime in the node if there are other time
658 	 * needs to be set (#2). This will ensure the ctime not being
659 	 * updated when other times are being updated in the file system.
660 	 *
661 	 * Retained file rules:
662 	 *
663 	 * 1. Don't add SMB_AT_CTIME to node->what by default because the
664 	 *    request will be rejected by filesystem
665 	 * 2. 'what' SMB_AT_CTIME shouldn't be set for retained files, i.e.
666 	 *    any request for changing ctime on these files should have
667 	 *    been already rejected
668 	 */
669 	node->what |= SMB_AT_CTIME;
670 	if (what & SMB_AT_CTIME) {
671 		if ((what == SMB_AT_CTIME) &&
672 		    timeval_cmp((timestruc_t *)&node->attr.sa_vattr.va_ctime,
673 		    ctime) == 0) {
674 			node->what &= ~SMB_AT_CTIME;
675 		} else {
676 			gethrestime(&node->attr.sa_vattr.va_ctime);
677 		}
678 	} else {
679 		gethrestime(&node->attr.sa_vattr.va_ctime);
680 	}
681 	mutex_exit(&node->n_mutex);
682 }
683 
684 
685 timestruc_t *
686 smb_node_get_crtime(smb_node_t *node)
687 {
688 	return ((timestruc_t *)&node->attr.sa_crtime);
689 }
690 
691 timestruc_t *
692 smb_node_get_atime(smb_node_t *node)
693 {
694 	return ((timestruc_t *)&node->attr.sa_vattr.va_atime);
695 }
696 
697 timestruc_t *
698 smb_node_get_ctime(smb_node_t *node)
699 {
700 	return ((timestruc_t *)&node->attr.sa_vattr.va_ctime);
701 }
702 
703 timestruc_t *
704 smb_node_get_mtime(smb_node_t *node)
705 {
706 	return ((timestruc_t *)&node->attr.sa_vattr.va_mtime);
707 }
708 
709 /*
710  * smb_node_set_dosattr
711  *
712  * Parse the specified DOS attributes and, if they have been modified,
713  * update the node cache. This call should be followed by a
714  * smb_sync_fsattr() call to write the attribute changes to filesystem.
715  */
716 void
717 smb_node_set_dosattr(smb_node_t *node, uint32_t dosattr)
718 {
719 	uint32_t mode = dosattr & (FILE_ATTRIBUTE_ARCHIVE |
720 	    FILE_ATTRIBUTE_READONLY |
721 	    FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
722 
723 	mutex_enter(&node->n_mutex);
724 	if (node->attr.sa_dosattr != mode) {
725 		node->attr.sa_dosattr = mode;
726 		node->what |= SMB_AT_DOSATTR;
727 	}
728 	mutex_exit(&node->n_mutex);
729 }
730 
731 /*
732  * smb_node_get_dosattr()
733  *
734  * This function is used to provide clients with information as to whether
735  * the readonly bit is set.  Hence both the node attribute cache (which
736  * reflects the on-disk attributes) and node->readonly_creator (which
737  * reflects whether a readonly set is pending from a readonly create) are
738  * checked.  In the latter case, the readonly attribute should be visible to
739  * all clients even though the readonly creator fid is immune to the readonly
740  * bit until close.
741  */
742 
743 uint32_t
744 smb_node_get_dosattr(smb_node_t *node)
745 {
746 	uint32_t dosattr = node->attr.sa_dosattr;
747 
748 	if (node->readonly_creator)
749 		dosattr |= FILE_ATTRIBUTE_READONLY;
750 
751 	if (!dosattr)
752 		dosattr = FILE_ATTRIBUTE_NORMAL;
753 
754 	return (dosattr);
755 }
756 
757 int
758 smb_node_set_delete_on_close(smb_node_t *node, cred_t *cr)
759 {
760 	int	rc = -1;
761 
762 	mutex_enter(&node->n_mutex);
763 	if (!(node->attr.sa_dosattr & FILE_ATTRIBUTE_READONLY) &&
764 	    !(node->flags & NODE_FLAGS_DELETE_ON_CLOSE)) {
765 		crhold(cr);
766 		node->delete_on_close_cred = cr;
767 		node->flags |= NODE_FLAGS_DELETE_ON_CLOSE;
768 		rc = 0;
769 	}
770 	mutex_exit(&node->n_mutex);
771 	return (rc);
772 }
773 
774 void
775 smb_node_reset_delete_on_close(smb_node_t *node)
776 {
777 	mutex_enter(&node->n_mutex);
778 	if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
779 		node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE;
780 		crfree(node->delete_on_close_cred);
781 		node->delete_on_close_cred = NULL;
782 	}
783 	mutex_exit(&node->n_mutex);
784 }
785 
786 /*
787  * smb_node_open_check
788  *
789  * check file sharing rules for current open request
790  * against all existing opens for a file.
791  *
792  * Returns NT_STATUS_SHARING_VIOLATION if there is any
793  * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
794  */
795 uint32_t
796 smb_node_open_check(
797     smb_node_t	*node,
798     cred_t	*cr,
799     uint32_t	desired_access,
800     uint32_t	share_access)
801 {
802 	smb_ofile_t *of;
803 	uint32_t status;
804 
805 	SMB_NODE_VALID(node);
806 
807 	smb_llist_enter(&node->n_ofile_list, RW_READER);
808 	of = smb_llist_head(&node->n_ofile_list);
809 	while (of) {
810 		status = smb_ofile_open_check(of, cr, desired_access,
811 		    share_access);
812 
813 		switch (status) {
814 		case NT_STATUS_INVALID_HANDLE:
815 		case NT_STATUS_SUCCESS:
816 			of = smb_llist_next(&node->n_ofile_list, of);
817 			break;
818 		default:
819 			ASSERT(status == NT_STATUS_SHARING_VIOLATION);
820 			smb_llist_exit(&node->n_ofile_list);
821 			return (status);
822 		}
823 	}
824 
825 	smb_llist_exit(&node->n_ofile_list);
826 	return (NT_STATUS_SUCCESS);
827 }
828 
829 uint32_t
830 smb_node_rename_check(smb_node_t *node)
831 {
832 	smb_ofile_t	*of;
833 	uint32_t	status;
834 
835 	SMB_NODE_VALID(node);
836 
837 	/*
838 	 * Intra-CIFS check
839 	 */
840 	smb_llist_enter(&node->n_ofile_list, RW_READER);
841 	of = smb_llist_head(&node->n_ofile_list);
842 	while (of) {
843 		status = smb_ofile_rename_check(of);
844 
845 		switch (status) {
846 		case NT_STATUS_INVALID_HANDLE:
847 		case NT_STATUS_SUCCESS:
848 			of = smb_llist_next(&node->n_ofile_list, of);
849 			break;
850 		default:
851 			ASSERT(status == NT_STATUS_SHARING_VIOLATION);
852 			smb_llist_exit(&node->n_ofile_list);
853 			return (status);
854 		}
855 	}
856 	smb_llist_exit(&node->n_ofile_list);
857 
858 	/*
859 	 * system-wide share check
860 	 */
861 	if (nbl_share_conflict(node->vp, NBL_RENAME, NULL))
862 		return (NT_STATUS_SHARING_VIOLATION);
863 	else
864 		return (NT_STATUS_SUCCESS);
865 }
866 
867 uint32_t
868 smb_node_delete_check(smb_node_t *node)
869 {
870 	smb_ofile_t	*of;
871 	uint32_t	status;
872 
873 	SMB_NODE_VALID(node);
874 
875 	if (node->attr.sa_vattr.va_type == VDIR)
876 		return (NT_STATUS_SUCCESS);
877 
878 	/*
879 	 * intra-CIFS check
880 	 */
881 	smb_llist_enter(&node->n_ofile_list, RW_READER);
882 	of = smb_llist_head(&node->n_ofile_list);
883 	while (of) {
884 		status = smb_ofile_delete_check(of);
885 
886 		switch (status) {
887 		case NT_STATUS_INVALID_HANDLE:
888 		case NT_STATUS_SUCCESS:
889 			of = smb_llist_next(&node->n_ofile_list, of);
890 			break;
891 		default:
892 			ASSERT(status == NT_STATUS_SHARING_VIOLATION);
893 			smb_llist_exit(&node->n_ofile_list);
894 			return (status);
895 		}
896 	}
897 	smb_llist_exit(&node->n_ofile_list);
898 
899 	/*
900 	 * system-wide share check
901 	 */
902 	if (nbl_share_conflict(node->vp, NBL_REMOVE, NULL))
903 		return (NT_STATUS_SHARING_VIOLATION);
904 	else
905 		return (NT_STATUS_SUCCESS);
906 }
907 
908 /*
909  * smb_node_start_crit()
910  *
911  * Enter critical region for share reservations.
912  * See comments above smb_fsop_shrlock().
913  */
914 
915 void
916 smb_node_start_crit(smb_node_t *node, krw_t mode)
917 {
918 	rw_enter(&node->n_lock, mode);
919 	nbl_start_crit(node->vp, mode);
920 }
921 
922 /*
923  * smb_node_end_crit()
924  *
925  * Exit critical region for share reservations.
926  */
927 
928 void
929 smb_node_end_crit(smb_node_t *node)
930 {
931 	nbl_end_crit(node->vp);
932 	rw_exit(&node->n_lock);
933 }
934 
935 int
936 smb_node_in_crit(smb_node_t *node)
937 {
938 	return (nbl_in_crit(node->vp) && RW_LOCK_HELD(&node->n_lock));
939 }
940 
941 void
942 smb_node_rdlock(smb_node_t *node)
943 {
944 	rw_enter(&node->n_lock, RW_READER);
945 }
946 
947 void
948 smb_node_wrlock(smb_node_t *node)
949 {
950 	rw_enter(&node->n_lock, RW_WRITER);
951 }
952 
953 void
954 smb_node_unlock(smb_node_t *node)
955 {
956 	rw_exit(&node->n_lock);
957 }
958 
959 uint32_t
960 smb_node_get_ofile_count(smb_node_t *node)
961 {
962 	uint32_t	cntr;
963 
964 	SMB_NODE_VALID(node);
965 
966 	smb_llist_enter(&node->n_ofile_list, RW_READER);
967 	cntr = smb_llist_get_count(&node->n_ofile_list);
968 	smb_llist_exit(&node->n_ofile_list);
969 	return (cntr);
970 }
971 
972 void
973 smb_node_add_ofile(smb_node_t *node, smb_ofile_t *of)
974 {
975 	SMB_NODE_VALID(node);
976 
977 	smb_llist_enter(&node->n_ofile_list, RW_WRITER);
978 	smb_llist_insert_tail(&node->n_ofile_list, of);
979 	smb_llist_exit(&node->n_ofile_list);
980 }
981 
982 void
983 smb_node_rem_ofile(smb_node_t *node, smb_ofile_t *of)
984 {
985 	SMB_NODE_VALID(node);
986 
987 	smb_llist_enter(&node->n_ofile_list, RW_WRITER);
988 	smb_llist_remove(&node->n_ofile_list, of);
989 	smb_llist_exit(&node->n_ofile_list);
990 }
991 
992 void
993 smb_node_inc_open_ofiles(smb_node_t *node)
994 {
995 	SMB_NODE_VALID(node);
996 
997 	mutex_enter(&node->n_mutex);
998 	node->n_open_count++;
999 	mutex_exit(&node->n_mutex);
1000 }
1001 
1002 void
1003 smb_node_dec_open_ofiles(smb_node_t *node)
1004 {
1005 	SMB_NODE_VALID(node);
1006 
1007 	mutex_enter(&node->n_mutex);
1008 	node->n_open_count--;
1009 	mutex_exit(&node->n_mutex);
1010 }
1011 
1012 uint32_t
1013 smb_node_get_open_ofiles(smb_node_t *node)
1014 {
1015 	uint32_t	cnt;
1016 
1017 	SMB_NODE_VALID(node);
1018 
1019 	mutex_enter(&node->n_mutex);
1020 	cnt = node->n_open_count;
1021 	mutex_exit(&node->n_mutex);
1022 	return (cnt);
1023 }
1024 
1025 /*
1026  * smb_node_alloc
1027  */
1028 static smb_node_t *
1029 smb_node_alloc(
1030     char	*od_name,
1031     vnode_t	*vp,
1032     smb_attr_t	*attr,
1033     smb_llist_t	*bucket,
1034     uint32_t	hashkey)
1035 {
1036 	smb_node_t	*node;
1037 
1038 	node = kmem_cache_alloc(smb_node_cache, KM_SLEEP);
1039 
1040 	if (node->n_audit_buf != NULL)
1041 		node->n_audit_buf->anb_index = 0;
1042 
1043 	node->attr = *attr;
1044 	node->flags = NODE_FLAGS_ATTR_VALID;
1045 	node->n_size = node->attr.sa_vattr.va_size;
1046 	VN_HOLD(vp);
1047 	node->vp = vp;
1048 	node->n_refcnt = 1;
1049 	node->n_hash_bucket = bucket;
1050 	node->n_hashkey = hashkey;
1051 	node->n_orig_uid = 0;
1052 	node->readonly_creator = NULL;
1053 	node->waiting_event = 0;
1054 	node->what = 0;
1055 	node->n_open_count = 0;
1056 	node->dir_snode = NULL;
1057 	node->unnamed_stream_node = NULL;
1058 	node->delete_on_close_cred = NULL;
1059 
1060 	(void) strlcpy(node->od_name, od_name, sizeof (node->od_name));
1061 	if (strcmp(od_name, XATTR_DIR) == 0)
1062 		node->flags |= NODE_XATTR_DIR;
1063 
1064 	node->n_state = SMB_NODE_STATE_AVAILABLE;
1065 	node->n_magic = SMB_NODE_MAGIC;
1066 	return (node);
1067 }
1068 
1069 /*
1070  * smb_node_free
1071  */
1072 static void
1073 smb_node_free(smb_node_t *node)
1074 {
1075 	SMB_NODE_VALID(node);
1076 
1077 	node->n_magic = 0;
1078 	VERIFY(!list_link_active(&node->n_lnd));
1079 	VERIFY(node->n_lock_list.ll_count == 0);
1080 	VERIFY(node->n_ofile_list.ll_count == 0);
1081 	VERIFY(node->n_oplock.ol_xthread == NULL);
1082 	VERIFY(node->n_oplock.ol_waiters_count == 0);
1083 	VN_RELE(node->vp);
1084 	kmem_cache_free(smb_node_cache, node);
1085 }
1086 
1087 /*
1088  * smb_node_constructor
1089  */
1090 static int
1091 smb_node_constructor(void *buf, void *un, int kmflags)
1092 {
1093 	_NOTE(ARGUNUSED(kmflags, un))
1094 
1095 	smb_node_t	*node = (smb_node_t *)buf;
1096 
1097 	bzero(node, sizeof (smb_node_t));
1098 
1099 	smb_llist_constructor(&node->n_ofile_list, sizeof (smb_ofile_t),
1100 	    offsetof(smb_ofile_t, f_nnd));
1101 	smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t),
1102 	    offsetof(smb_lock_t, l_lnd));
1103 	cv_init(&node->n_oplock.ol_cv, NULL, CV_DEFAULT, NULL);
1104 	rw_init(&node->n_lock, NULL, RW_DEFAULT, NULL);
1105 	mutex_init(&node->n_mutex, NULL, MUTEX_DEFAULT, NULL);
1106 	smb_node_create_audit_buf(node, kmflags);
1107 	return (0);
1108 }
1109 
1110 /*
1111  * smb_node_destructor
1112  */
1113 static void
1114 smb_node_destructor(void *buf, void *un)
1115 {
1116 	_NOTE(ARGUNUSED(un))
1117 
1118 	smb_node_t	*node = (smb_node_t *)buf;
1119 
1120 	smb_node_destroy_audit_buf(node);
1121 	mutex_destroy(&node->n_mutex);
1122 	rw_destroy(&node->n_lock);
1123 	cv_destroy(&node->n_oplock.ol_cv);
1124 	smb_llist_destructor(&node->n_lock_list);
1125 	smb_llist_destructor(&node->n_ofile_list);
1126 }
1127 
1128 /*
1129  * smb_node_create_audit_buf
1130  */
1131 static void
1132 smb_node_create_audit_buf(smb_node_t *node, int kmflags)
1133 {
1134 	smb_audit_buf_node_t	*abn;
1135 
1136 	if (smb_audit_flags & SMB_AUDIT_NODE) {
1137 		abn = kmem_zalloc(sizeof (smb_audit_buf_node_t), kmflags);
1138 		abn->anb_max_index = SMB_AUDIT_BUF_MAX_REC - 1;
1139 		node->n_audit_buf = abn;
1140 	}
1141 }
1142 
1143 /*
1144  * smb_node_destroy_audit_buf
1145  */
1146 static void
1147 smb_node_destroy_audit_buf(smb_node_t *node)
1148 {
1149 	if (node->n_audit_buf != NULL) {
1150 		kmem_free(node->n_audit_buf, sizeof (smb_audit_buf_node_t));
1151 		node->n_audit_buf = NULL;
1152 	}
1153 }
1154 
1155 /*
1156  * smb_node_audit
1157  *
1158  * This function saves the calling stack in the audit buffer of the node passed
1159  * in.
1160  */
1161 static void
1162 smb_node_audit(smb_node_t *node)
1163 {
1164 	smb_audit_buf_node_t	*abn;
1165 	smb_audit_record_node_t	*anr;
1166 
1167 	if (node->n_audit_buf) {
1168 		abn = node->n_audit_buf;
1169 		anr = abn->anb_records;
1170 		anr += abn->anb_index;
1171 		abn->anb_index++;
1172 		abn->anb_index &= abn->anb_max_index;
1173 		anr->anr_refcnt = node->n_refcnt;
1174 		anr->anr_depth = getpcstack(anr->anr_stack,
1175 		    SMB_AUDIT_STACK_DEPTH);
1176 	}
1177 }
1178 
1179 static smb_llist_t *
1180 smb_node_get_hash(fsid_t *fsid, smb_attr_t *attr, uint32_t *phashkey)
1181 {
1182 	uint32_t	hashkey;
1183 
1184 	hashkey = fsid->val[0] + attr->sa_vattr.va_nodeid;
1185 	hashkey += (hashkey >> 24) + (hashkey >> 16) + (hashkey >> 8);
1186 	*phashkey = hashkey;
1187 	return (&smb_node_hash_table[(hashkey & SMBND_HASH_MASK)]);
1188 }
1189