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
98uint32_t smb_is_executable(char *);
99static void smb_node_delete_on_close(smb_node_t *);
100static void smb_node_create_audit_buf(smb_node_t *, int);
101static void smb_node_destroy_audit_buf(smb_node_t *);
102static void smb_node_audit(smb_node_t *);
103static smb_node_t *smb_node_alloc(char *, vnode_t *, smb_llist_t *, uint32_t);
104static void smb_node_free(smb_node_t *);
105static int smb_node_constructor(void *, void *, int);
106static void smb_node_destructor(void *, void *);
107static smb_llist_t *smb_node_get_hash(fsid_t *, smb_attr_t *, uint32_t *);
108
109static void smb_node_init_cached_data(smb_node_t *);
110static void smb_node_clear_cached_data(smb_node_t *);
111
112static void smb_node_init_cached_timestamps(smb_node_t *, smb_attr_t *);
113static void smb_node_clear_cached_timestamps(smb_node_t *);
114static void smb_node_get_cached_timestamps(smb_node_t *, smb_attr_t *);
115static void smb_node_set_cached_timestamps(smb_node_t *, smb_attr_t *);
116
117static void smb_node_init_cached_allocsz(smb_node_t *, smb_attr_t *);
118static void smb_node_clear_cached_allocsz(smb_node_t *);
119static void smb_node_get_cached_allocsz(smb_node_t *, smb_attr_t *);
120static void smb_node_set_cached_allocsz(smb_node_t *, smb_attr_t *);
121static void smb_node_init_reparse(smb_node_t *, smb_attr_t *);
122static 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
132static kmem_cache_t	*smb_node_cache = NULL;
133static boolean_t	smb_node_initialized = B_FALSE;
134static 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 */
144int
145smb_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 */
169void
170smb_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*/
229smb_node_t *
230smb_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
376smb_node_t *
377smb_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 */
410void
411smb_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 */
450void
451smb_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
497static void
498smb_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 */
528void
529smb_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
559int
560smb_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 */
600int
601smb_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
630void
631smb_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 */
652uint32_t
653smb_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
682uint32_t
683smb_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
720uint32_t
721smb_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 */
770boolean_t
771smb_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
787void
788smb_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 */
808void
809smb_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 */
831void
832smb_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 */
843void
844smb_node_end_crit(smb_node_t *node)
845{
846	nbl_end_crit(node->vp);
847	rw_exit(&node->n_lock);
848}
849
850int
851smb_node_in_crit(smb_node_t *node)
852{
853	return (nbl_in_crit(node->vp) && RW_LOCK_HELD(&node->n_lock));
854}
855
856void
857smb_node_rdlock(smb_node_t *node)
858{
859	rw_enter(&node->n_lock, RW_READER);
860}
861
862void
863smb_node_wrlock(smb_node_t *node)
864{
865	rw_enter(&node->n_lock, RW_WRITER);
866}
867
868void
869smb_node_unlock(smb_node_t *node)
870{
871	rw_exit(&node->n_lock);
872}
873
874void
875smb_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
884void
885smb_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 */
897void
898smb_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 */
912void
913smb_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 */
927void
928smb_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 */
939void
940smb_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 */
952int
953smb_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 */
986int
987smb_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 */
1015int
1016smb_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 */
1057static smb_node_t *
1058smb_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 */
1109static void
1110smb_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 */
1130static int
1131smb_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 */
1156static void
1157smb_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 */
1176static void
1177smb_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 */
1191static void
1192smb_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 */
1206static void
1207smb_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
1224static smb_llist_t *
1225smb_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
1235boolean_t
1236smb_node_is_file(smb_node_t *node)
1237{
1238	SMB_NODE_VALID(node);
1239	return (node->vp->v_type == VREG);
1240}
1241
1242boolean_t
1243smb_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
1250boolean_t
1251smb_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
1258boolean_t
1259smb_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
1266boolean_t
1267smb_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
1274boolean_t
1275smb_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
1281boolean_t
1282smb_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 */
1296boolean_t
1297smb_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 */
1342int
1343smb_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 */
1440int
1441smb_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 */
1478static void
1479smb_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 */
1494static void
1495smb_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 */
1519static void
1520smb_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 */
1531static void
1532smb_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 */
1550static void
1551smb_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 */
1573static void
1574smb_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 */
1614static void
1615smb_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 */
1640static void
1641smb_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 */
1661static void
1662smb_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 */
1684static void
1685smb_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 */
1710static void
1711smb_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 */
1754static void
1755smb_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