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