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