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