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