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