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