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