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