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