1da6c28aaSamw /*
2da6c28aaSamw * CDDL HEADER START
3da6c28aaSamw *
4da6c28aaSamw * The contents of this file are subject to the terms of the
5da6c28aaSamw * Common Development and Distribution License (the "License").
6da6c28aaSamw * You may not use this file except in compliance with the License.
7da6c28aaSamw *
8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw * See the License for the specific language governing permissions
11da6c28aaSamw * and limitations under the License.
12da6c28aaSamw *
13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw *
19da6c28aaSamw * CDDL HEADER END
20da6c28aaSamw */
21da6c28aaSamw /*
22c5866007SKeyur Desai * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23d6e098b6SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
24da6c28aaSamw */
25da6c28aaSamw /*
26da6c28aaSamw * SMB Node State Machine
27da6c28aaSamw * ----------------------
28da6c28aaSamw *
29fc724630SAlan Wright *
30fc724630SAlan Wright * +----------- Creation/Allocation
31da6c28aaSamw * |
32fc724630SAlan Wright * | T0
33da6c28aaSamw * |
34da6c28aaSamw * v
35cb174861Sjoyce mcintosh * +----------------------------+
36cb174861Sjoyce mcintosh * | SMB_NODE_STATE_AVAILABLE |
37cb174861Sjoyce mcintosh * +----------------------------+
38cb174861Sjoyce mcintosh * |
39cb174861Sjoyce mcintosh * | T1
40fc724630SAlan Wright * |
41fc724630SAlan Wright * v
42da6c28aaSamw * +-----------------------------+
43fc724630SAlan Wright * | SMB_NODE_STATE_DESTROYING |
44fc724630SAlan Wright * +-----------------------------+
45fc724630SAlan Wright * |
46fc724630SAlan Wright * |
47cb174861Sjoyce mcintosh * | T2
48fc724630SAlan Wright * |
49fc724630SAlan Wright * +----------> Deletion/Free
50da6c28aaSamw *
51da6c28aaSamw * Transition T0
52da6c28aaSamw *
53da6c28aaSamw * This transition occurs in smb_node_lookup(). If the node looked for is
54da6c28aaSamw * not found in the has table a new node is created. The reference count is
55da6c28aaSamw * initialized to 1 and the state initialized to SMB_NODE_STATE_AVAILABLE.
56da6c28aaSamw *
57da6c28aaSamw * Transition T1
58da6c28aaSamw *
59da6c28aaSamw * This transition occurs in smb_node_release(). If the reference count
60da6c28aaSamw * drops to zero the state is moved to SMB_NODE_STATE_DESTROYING and no more
61da6c28aaSamw * reference count will be given out for that node.
62da6c28aaSamw *
63cb174861Sjoyce mcintosh * Transition T2
64da6c28aaSamw *
65da6c28aaSamw * This transition occurs in smb_node_release(). The structure is deleted.
66da6c28aaSamw *
67da6c28aaSamw * Comments
68da6c28aaSamw * --------
69da6c28aaSamw *
70da6c28aaSamw * The reason the smb node has 2 states is the following synchronization
71da6c28aaSamw * rule:
72da6c28aaSamw *
73da6c28aaSamw * There's a mutex embedded in the node used to protect its fields and
74da6c28aaSamw * there's a lock embedded in the bucket of the hash table the node belongs
75da6c28aaSamw * to. To increment or to decrement the reference count the mutex must be
76da6c28aaSamw * entered. To insert the node into the bucket and to remove it from the
77da6c28aaSamw * bucket the lock must be entered in RW_WRITER mode. When both (mutex and
78da6c28aaSamw * lock) have to be entered, the lock has always to be entered first then
79da6c28aaSamw * the mutex. This prevents a deadlock between smb_node_lookup() and
80da6c28aaSamw * smb_node_release() from occurring. However, in smb_node_release() when the
81da6c28aaSamw * reference count drops to zero and triggers the deletion of the node, the
82da6c28aaSamw * mutex has to be released before entering the lock of the bucket (to
83da6c28aaSamw * remove the node). This creates a window during which the node that is
84da6c28aaSamw * about to be freed could be given out by smb_node_lookup(). To close that
85da6c28aaSamw * window the node is moved to the state SMB_NODE_STATE_DESTROYING before
86da6c28aaSamw * releasing the mutex. That way, even if smb_node_lookup() finds it, the
87da6c28aaSamw * state will indicate that the node should be treated as non existent (of
88da6c28aaSamw * course the state of the node should be tested/updated under the
89da6c28aaSamw * protection of the mutex).
90da6c28aaSamw */
91bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
92da6c28aaSamw #include <smbsrv/smb_fsops.h>
932c2961f8Sjose borrego #include <smbsrv/smb_kstat.h>
9445c1cdfcSAlek Pinchuk #include <sys/ddi.h>
9545c1cdfcSAlek Pinchuk #include <sys/extdirent.h>
96da6c28aaSamw #include <sys/pathname.h>
97da6c28aaSamw #include <sys/sdt.h>
98dc20a302Sas200622 #include <sys/nbmlock.h>
999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #include <fs/fs_reparse.h>
100da6c28aaSamw
1012c2961f8Sjose borrego uint32_t smb_is_executable(char *);
1022c2961f8Sjose borrego static void smb_node_delete_on_close(smb_node_t *);
1032c2961f8Sjose borrego static void smb_node_create_audit_buf(smb_node_t *, int);
1042c2961f8Sjose borrego static void smb_node_destroy_audit_buf(smb_node_t *);
1052c2961f8Sjose borrego static void smb_node_audit(smb_node_t *);
106037cac00Sjoyce mcintosh static smb_node_t *smb_node_alloc(char *, vnode_t *, smb_llist_t *, uint32_t);
1072c2961f8Sjose borrego static void smb_node_free(smb_node_t *);
1082c2961f8Sjose borrego static int smb_node_constructor(void *, void *, int);
1092c2961f8Sjose borrego static void smb_node_destructor(void *, void *);
1102c2961f8Sjose borrego static smb_llist_t *smb_node_get_hash(fsid_t *, smb_attr_t *, uint32_t *);
111e3f2c991SKeyur Desai
1129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_node_init_reparse(smb_node_t *, smb_attr_t *);
1139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void smb_node_init_system(smb_node_t *);
114e3f2c991SKeyur Desai
115da6c28aaSamw #define VALIDATE_DIR_NODE(_dir_, _node_) \
116da6c28aaSamw ASSERT((_dir_)->n_magic == SMB_NODE_MAGIC); \
117da6c28aaSamw ASSERT(((_dir_)->vp->v_xattrdir) || ((_dir_)->vp->v_type == VDIR)); \
1181fcced4cSJordan Brown ASSERT((_dir_)->n_dnode != (_node_));
119da6c28aaSamw
120e3f2c991SKeyur Desai /* round sz to DEV_BSIZE block */
121e3f2c991SKeyur Desai #define SMB_ALLOCSZ(sz) (((sz) + DEV_BSIZE-1) & ~(DEV_BSIZE-1))
122e3f2c991SKeyur Desai
1232c2961f8Sjose borrego static kmem_cache_t *smb_node_cache = NULL;
124faa1795aSjb150015 static smb_llist_t smb_node_hash_table[SMBND_HASH_MASK+1];
125ae240eb8SGordon Ross static smb_node_t *smb_root_node;
126faa1795aSjb150015
127faa1795aSjb150015 /*
128faa1795aSjb150015 * smb_node_init
129faa1795aSjb150015 *
130faa1795aSjb150015 * Initialization of the SMB node layer.
131faa1795aSjb150015 *
132faa1795aSjb150015 * This function is not multi-thread safe. The caller must make sure only one
133faa1795aSjb150015 * thread makes the call.
134faa1795aSjb150015 */
135ae240eb8SGordon Ross void
smb_node_init(void)136faa1795aSjb150015 smb_node_init(void)
137faa1795aSjb150015 {
138ae240eb8SGordon Ross smb_attr_t attr;
139ae240eb8SGordon Ross smb_llist_t *node_hdr;
140ae240eb8SGordon Ross smb_node_t *node;
141ae240eb8SGordon Ross uint32_t hashkey;
142faa1795aSjb150015 int i;
143faa1795aSjb150015
144ae240eb8SGordon Ross if (smb_node_cache != NULL)
145ae240eb8SGordon Ross return;
146ae240eb8SGordon Ross
1472c2961f8Sjose borrego smb_node_cache = kmem_cache_create(SMBSRV_KSTAT_NODE_CACHE,
1482c2961f8Sjose borrego sizeof (smb_node_t), 8, smb_node_constructor, smb_node_destructor,
1492c2961f8Sjose borrego NULL, NULL, NULL, 0);
150faa1795aSjb150015
151faa1795aSjb150015 for (i = 0; i <= SMBND_HASH_MASK; i++) {
152faa1795aSjb150015 smb_llist_constructor(&smb_node_hash_table[i],
153faa1795aSjb150015 sizeof (smb_node_t), offsetof(smb_node_t, n_lnd));
154faa1795aSjb150015 }
155ae240eb8SGordon Ross
156ae240eb8SGordon Ross /*
157ae240eb8SGordon Ross * The node cache is shared by all zones, so the smb_root_node
158ae240eb8SGordon Ross * must represent the real (global zone) rootdir.
159ae240eb8SGordon Ross * Note intentional use of kcred here.
160ae240eb8SGordon Ross */
161ae240eb8SGordon Ross attr.sa_mask = SMB_AT_ALL;
162ae240eb8SGordon Ross VERIFY0(smb_vop_getattr(rootdir, NULL, &attr, 0, kcred));
163ae240eb8SGordon Ross node_hdr = smb_node_get_hash(&rootdir->v_vfsp->vfs_fsid, &attr,
164ae240eb8SGordon Ross &hashkey);
165ae240eb8SGordon Ross node = smb_node_alloc("/", rootdir, node_hdr, hashkey);
166ae240eb8SGordon Ross smb_llist_enter(node_hdr, RW_WRITER);
167ae240eb8SGordon Ross smb_llist_insert_head(node_hdr, node);
168ae240eb8SGordon Ross smb_llist_exit(node_hdr);
169ae240eb8SGordon Ross smb_root_node = node; /* smb_node_release in smb_node_fini */
170faa1795aSjb150015 }
171faa1795aSjb150015
172faa1795aSjb150015 /*
173faa1795aSjb150015 * smb_node_fini
174faa1795aSjb150015 *
175faa1795aSjb150015 * This function is not multi-thread safe. The caller must make sure only one
176faa1795aSjb150015 * thread makes the call.
177faa1795aSjb150015 */
178faa1795aSjb150015 void
smb_node_fini(void)179faa1795aSjb150015 smb_node_fini(void)
180faa1795aSjb150015 {
181faa1795aSjb150015 int i;
182faa1795aSjb150015
183ae240eb8SGordon Ross if (smb_root_node != NULL) {
184ae240eb8SGordon Ross smb_node_release(smb_root_node);
185ae240eb8SGordon Ross smb_root_node = NULL;
186ae240eb8SGordon Ross }
187ae240eb8SGordon Ross
188ae240eb8SGordon Ross if (smb_node_cache == NULL)
189faa1795aSjb150015 return;
190faa1795aSjb150015
191faa1795aSjb150015 #ifdef DEBUG
192faa1795aSjb150015 for (i = 0; i <= SMBND_HASH_MASK; i++) {
193faa1795aSjb150015 smb_node_t *node;
194faa1795aSjb150015
195faa1795aSjb150015 /*
196faa1795aSjb150015 * The following sequence is just intended for sanity check.
197faa1795aSjb150015 * This will have to be modified when the code goes into
198faa1795aSjb150015 * production.
199faa1795aSjb150015 *
200faa1795aSjb150015 * The SMB node hash table should be emtpy at this point. If the
201faa1795aSjb150015 * hash table is not empty a panic will be triggered.
202faa1795aSjb150015 *
203faa1795aSjb150015 * The reason why SMB nodes are still remaining in the hash
204faa1795aSjb150015 * table is problably due to a mismatch between calls to
205faa1795aSjb150015 * smb_node_lookup() and smb_node_release(). You must track that
206faa1795aSjb150015 * down.
207faa1795aSjb150015 */
208faa1795aSjb150015 node = smb_llist_head(&smb_node_hash_table[i]);
209faa1795aSjb150015 ASSERT(node == NULL);
210faa1795aSjb150015 }
211faa1795aSjb150015 #endif
212faa1795aSjb150015
213faa1795aSjb150015 for (i = 0; i <= SMBND_HASH_MASK; i++) {
214faa1795aSjb150015 smb_llist_destructor(&smb_node_hash_table[i]);
215faa1795aSjb150015 }
2162c2961f8Sjose borrego kmem_cache_destroy(smb_node_cache);
2172c2961f8Sjose borrego smb_node_cache = NULL;
218faa1795aSjb150015 }
219faa1795aSjb150015
220da6c28aaSamw /*
221da6c28aaSamw * smb_node_lookup()
222da6c28aaSamw *
223da6c28aaSamw * NOTE: This routine should only be called by the file system interface layer,
224da6c28aaSamw * and not by SMB.
225da6c28aaSamw *
226da6c28aaSamw * smb_node_lookup() is called upon successful lookup, mkdir, and create
227da6c28aaSamw * (for both non-streams and streams). In each of these cases, a held vnode is
2287f667e74Sjose borrego * passed into this routine. If a new smb_node is created it will take its
2297f667e74Sjose borrego * own hold on the vnode. The caller's hold therefore still belongs to, and
2307f667e74Sjose borrego * should be released by, the caller.
231da6c28aaSamw *
232da6c28aaSamw * A reference is taken on the smb_node whether found in the hash table
233da6c28aaSamw * or newly created.
234da6c28aaSamw *
235da6c28aaSamw * If an smb_node needs to be created, a reference is also taken on the
2361fcced4cSJordan Brown * dnode (if passed in).
237da6c28aaSamw *
238da6c28aaSamw * See smb_node_release() for details on the release of these references.
239da6c28aaSamw */
240da6c28aaSamw
241da6c28aaSamw /*ARGSUSED*/
242da6c28aaSamw smb_node_t *
smb_node_lookup(struct smb_request * sr,struct open_param * op,cred_t * cred,vnode_t * vp,char * od_name,smb_node_t * dnode,smb_node_t * unode)243da6c28aaSamw smb_node_lookup(
244da6c28aaSamw struct smb_request *sr,
245da6c28aaSamw struct open_param *op,
246da6c28aaSamw cred_t *cred,
247da6c28aaSamw vnode_t *vp,
248da6c28aaSamw char *od_name,
2491fcced4cSJordan Brown smb_node_t *dnode,
2501fcced4cSJordan Brown smb_node_t *unode)
251da6c28aaSamw {
252da6c28aaSamw smb_llist_t *node_hdr;
253da6c28aaSamw smb_node_t *node;
254037cac00Sjoyce mcintosh smb_attr_t attr;
255da6c28aaSamw uint32_t hashkey = 0;
256c8ec8eeaSjose borrego fsid_t fsid;
257da6c28aaSamw int error;
258da6c28aaSamw krw_t lock_mode;
259da6c28aaSamw vnode_t *unnamed_vp = NULL;
260da6c28aaSamw
261da6c28aaSamw /*
262da6c28aaSamw * smb_vop_getattr() is called here instead of smb_fsop_getattr(),
263da6c28aaSamw * because the node may not yet exist. We also do not want to call
264da6c28aaSamw * it with the list lock held.
265da6c28aaSamw */
266da6c28aaSamw
2671fcced4cSJordan Brown if (unode)
2681fcced4cSJordan Brown unnamed_vp = unode->vp;
269da6c28aaSamw
270da6c28aaSamw /*
271da6c28aaSamw * This getattr is performed on behalf of the server
272da6c28aaSamw * that's why kcred is used not the user's cred
273da6c28aaSamw */
274037cac00Sjoyce mcintosh attr.sa_mask = SMB_AT_ALL;
275ae240eb8SGordon Ross error = smb_vop_getattr(vp, unnamed_vp, &attr, 0, zone_kcred());
276da6c28aaSamw if (error)
277da6c28aaSamw return (NULL);
278da6c28aaSamw
279c8ec8eeaSjose borrego if (sr && sr->tid_tree) {
280da6c28aaSamw /*
281c8ec8eeaSjose borrego * The fsid for a file is that of the tree, even
282da6c28aaSamw * if the file resides in a different mountpoint
283da6c28aaSamw * under the share.
284da6c28aaSamw */
285c8ec8eeaSjose borrego fsid = SMB_TREE_FSID(sr->tid_tree);
286da6c28aaSamw } else {
287da6c28aaSamw /*
288da6c28aaSamw * This should be getting executed only for the
289c8ec8eeaSjose borrego * tree root smb_node.
290da6c28aaSamw */
291c8ec8eeaSjose borrego fsid = vp->v_vfsp->vfs_fsid;
292da6c28aaSamw }
293da6c28aaSamw
294037cac00Sjoyce mcintosh node_hdr = smb_node_get_hash(&fsid, &attr, &hashkey);
295da6c28aaSamw lock_mode = RW_READER;
296da6c28aaSamw
297da6c28aaSamw smb_llist_enter(node_hdr, lock_mode);
298da6c28aaSamw for (;;) {
299da6c28aaSamw node = list_head(&node_hdr->ll_list);
300da6c28aaSamw while (node) {
301da6c28aaSamw ASSERT(node->n_magic == SMB_NODE_MAGIC);
302da6c28aaSamw ASSERT(node->n_hash_bucket == node_hdr);
303da6c28aaSamw if ((node->n_hashkey == hashkey) && (node->vp == vp)) {
3042c2961f8Sjose borrego mutex_enter(&node->n_mutex);
305da6c28aaSamw DTRACE_PROBE1(smb_node_lookup_hit,
306da6c28aaSamw smb_node_t *, node);
307da6c28aaSamw switch (node->n_state) {
308da6c28aaSamw case SMB_NODE_STATE_AVAILABLE:
309da6c28aaSamw /* The node was found. */
310da6c28aaSamw node->n_refcnt++;
3111fcced4cSJordan Brown if ((node->n_dnode == NULL) &&
3121fcced4cSJordan Brown (dnode != NULL) &&
31396a62adaSjoyce mcintosh (node != dnode) &&
314da6c28aaSamw (strcmp(od_name, "..") != 0) &&
315da6c28aaSamw (strcmp(od_name, ".") != 0)) {
3161fcced4cSJordan Brown VALIDATE_DIR_NODE(dnode, node);
3171fcced4cSJordan Brown node->n_dnode = dnode;
3181fcced4cSJordan Brown smb_node_ref(dnode);
319da6c28aaSamw }
320da6c28aaSamw
3212c2961f8Sjose borrego smb_node_audit(node);
3222c2961f8Sjose borrego mutex_exit(&node->n_mutex);
323da6c28aaSamw smb_llist_exit(node_hdr);
324da6c28aaSamw return (node);
325da6c28aaSamw
326da6c28aaSamw case SMB_NODE_STATE_DESTROYING:
327da6c28aaSamw /*
328da6c28aaSamw * Although the node exists it is about
329da6c28aaSamw * to be destroyed. We act as it hasn't
330da6c28aaSamw * been found.
331da6c28aaSamw */
3322c2961f8Sjose borrego mutex_exit(&node->n_mutex);
333da6c28aaSamw break;
334da6c28aaSamw default:
335da6c28aaSamw /*
336da6c28aaSamw * Although the node exists it is in an
337da6c28aaSamw * unknown state. We act as it hasn't
338da6c28aaSamw * been found.
339da6c28aaSamw */
340da6c28aaSamw ASSERT(0);
3412c2961f8Sjose borrego mutex_exit(&node->n_mutex);
342da6c28aaSamw break;
343da6c28aaSamw }
344da6c28aaSamw }
345da6c28aaSamw node = smb_llist_next(node_hdr, node);
346da6c28aaSamw }
347da6c28aaSamw if ((lock_mode == RW_READER) && smb_llist_upgrade(node_hdr)) {
348da6c28aaSamw lock_mode = RW_WRITER;
349da6c28aaSamw continue;
350da6c28aaSamw }
351da6c28aaSamw break;
352da6c28aaSamw }
353037cac00Sjoyce mcintosh node = smb_node_alloc(od_name, vp, node_hdr, hashkey);
3549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_init_reparse(node, &attr);
355da6c28aaSamw
356da6c28aaSamw if (op)
357eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States node->flags |= smb_is_executable(op->fqi.fq_last_comp);
358da6c28aaSamw
3591fcced4cSJordan Brown if (dnode) {
3601fcced4cSJordan Brown smb_node_ref(dnode);
3611fcced4cSJordan Brown node->n_dnode = dnode;
3621fcced4cSJordan Brown ASSERT(dnode->n_dnode != node);
3631fcced4cSJordan Brown ASSERT((dnode->vp->v_xattrdir) ||
3641fcced4cSJordan Brown (dnode->vp->v_type == VDIR));
365da6c28aaSamw }
366da6c28aaSamw
3671fcced4cSJordan Brown if (unode) {
3681fcced4cSJordan Brown smb_node_ref(unode);
3691fcced4cSJordan Brown node->n_unode = unode;
370da6c28aaSamw }
371da6c28aaSamw
3729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_init_system(node);
3739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
374da6c28aaSamw DTRACE_PROBE1(smb_node_lookup_miss, smb_node_t *, node);
3752c2961f8Sjose borrego smb_node_audit(node);
376da6c28aaSamw smb_llist_insert_head(node_hdr, node);
377da6c28aaSamw smb_llist_exit(node_hdr);
378da6c28aaSamw return (node);
379da6c28aaSamw }
380da6c28aaSamw
381da6c28aaSamw /*
382da6c28aaSamw * smb_stream_node_lookup()
383da6c28aaSamw *
384da6c28aaSamw * Note: stream_name (the name that will be stored in the "od_name" field
385da6c28aaSamw * of a stream's smb_node) is the same as the on-disk name for the stream
386da6c28aaSamw * except that it does not have SMB_STREAM_PREFIX prepended.
387da6c28aaSamw */
388da6c28aaSamw
389da6c28aaSamw smb_node_t *
smb_stream_node_lookup(smb_request_t * sr,cred_t * cr,smb_node_t * fnode,vnode_t * xattrdirvp,vnode_t * vp,char * stream_name)3902c2961f8Sjose borrego smb_stream_node_lookup(smb_request_t *sr, cred_t *cr, smb_node_t *fnode,
391037cac00Sjoyce mcintosh vnode_t *xattrdirvp, vnode_t *vp, char *stream_name)
392da6c28aaSamw {
393da6c28aaSamw smb_node_t *xattrdir_node;
394da6c28aaSamw smb_node_t *snode;
395da6c28aaSamw
396da6c28aaSamw xattrdir_node = smb_node_lookup(sr, NULL, cr, xattrdirvp, XATTR_DIR,
397037cac00Sjoyce mcintosh fnode, NULL);
398da6c28aaSamw
399da6c28aaSamw if (xattrdir_node == NULL)
400da6c28aaSamw return (NULL);
401da6c28aaSamw
402da6c28aaSamw snode = smb_node_lookup(sr, NULL, cr, vp, stream_name, xattrdir_node,
403037cac00Sjoyce mcintosh fnode);
404da6c28aaSamw
405da6c28aaSamw (void) smb_node_release(xattrdir_node);
406da6c28aaSamw return (snode);
407da6c28aaSamw }
408da6c28aaSamw
409da6c28aaSamw
410da6c28aaSamw /*
411da6c28aaSamw * This function should be called whenever a reference is needed on an
412da6c28aaSamw * smb_node pointer. The copy of an smb_node pointer from one non-local
413da6c28aaSamw * data structure to another requires a reference to be taken on the smb_node
414da6c28aaSamw * (unless the usage is localized). Each data structure deallocation routine
415da6c28aaSamw * will call smb_node_release() on its smb_node pointers.
416da6c28aaSamw *
417da6c28aaSamw * In general, an smb_node pointer residing in a structure should never be
418da6c28aaSamw * stale. A node pointer may be NULL, however, and care should be taken
419da6c28aaSamw * prior to calling smb_node_ref(), which ASSERTs that the pointer is valid.
420da6c28aaSamw * Care also needs to be taken with respect to racing deallocations of a
421da6c28aaSamw * structure.
422da6c28aaSamw */
423da6c28aaSamw void
smb_node_ref(smb_node_t * node)424da6c28aaSamw smb_node_ref(smb_node_t *node)
425da6c28aaSamw {
4262c2961f8Sjose borrego SMB_NODE_VALID(node);
427da6c28aaSamw
4282c2961f8Sjose borrego mutex_enter(&node->n_mutex);
4292c2961f8Sjose borrego switch (node->n_state) {
4302c2961f8Sjose borrego case SMB_NODE_STATE_AVAILABLE:
431da6c28aaSamw node->n_refcnt++;
432da6c28aaSamw ASSERT(node->n_refcnt);
433da6c28aaSamw DTRACE_PROBE1(smb_node_ref_exit, smb_node_t *, node);
4342c2961f8Sjose borrego smb_node_audit(node);
4352c2961f8Sjose borrego break;
4362c2961f8Sjose borrego default:
4372c2961f8Sjose borrego SMB_PANIC();
4382c2961f8Sjose borrego }
4392c2961f8Sjose borrego mutex_exit(&node->n_mutex);
440da6c28aaSamw }
441da6c28aaSamw
442da6c28aaSamw /*
443da6c28aaSamw * smb_node_lookup() takes a hold on an smb_node, whether found in the
444da6c28aaSamw * hash table or newly created. This hold is expected to be released
445da6c28aaSamw * in the following manner.
446da6c28aaSamw *
447da6c28aaSamw * smb_node_lookup() takes an address of an smb_node pointer. This should
448da6c28aaSamw * be getting passed down via a lookup (whether path name or component), mkdir,
449da6c28aaSamw * create. If the original smb_node pointer resides in a data structure, then
450da6c28aaSamw * the deallocation routine for the data structure is responsible for calling
451da6c28aaSamw * smb_node_release() on the smb_node pointer. Alternatively,
452da6c28aaSamw * smb_node_release() can be called as soon as the smb_node pointer is no longer
453da6c28aaSamw * needed. In this case, callers are responsible for setting an embedded
454da6c28aaSamw * pointer to NULL if it is known that the last reference is being released.
455da6c28aaSamw *
456da6c28aaSamw * If the passed-in address of the smb_node pointer belongs to a local variable,
457da6c28aaSamw * then the caller with the local variable should call smb_node_release()
458da6c28aaSamw * directly.
459da6c28aaSamw *
4601fcced4cSJordan Brown * smb_node_release() itself will call smb_node_release() on a node's n_dnode,
4611fcced4cSJordan Brown * as smb_node_lookup() takes a hold on dnode.
462da6c28aaSamw */
463da6c28aaSamw void
smb_node_release(smb_node_t * node)464da6c28aaSamw smb_node_release(smb_node_t *node)
465da6c28aaSamw {
4662c2961f8Sjose borrego SMB_NODE_VALID(node);
467da6c28aaSamw
4682c2961f8Sjose borrego mutex_enter(&node->n_mutex);
469da6c28aaSamw ASSERT(node->n_refcnt);
470da6c28aaSamw DTRACE_PROBE1(smb_node_release, smb_node_t *, node);
471da6c28aaSamw if (--node->n_refcnt == 0) {
472da6c28aaSamw switch (node->n_state) {
473da6c28aaSamw
474da6c28aaSamw case SMB_NODE_STATE_AVAILABLE:
475da6c28aaSamw node->n_state = SMB_NODE_STATE_DESTROYING;
4762c2961f8Sjose borrego mutex_exit(&node->n_mutex);
477da6c28aaSamw
478da6c28aaSamw smb_llist_enter(node->n_hash_bucket, RW_WRITER);
479da6c28aaSamw smb_llist_remove(node->n_hash_bucket, node);
480da6c28aaSamw smb_llist_exit(node->n_hash_bucket);
481da6c28aaSamw
482da6c28aaSamw /*
483da6c28aaSamw * Check if the file was deleted
484da6c28aaSamw */
485da6c28aaSamw smb_node_delete_on_close(node);
486da6c28aaSamw
4871fcced4cSJordan Brown if (node->n_dnode) {
4881fcced4cSJordan Brown ASSERT(node->n_dnode->n_magic ==
489da6c28aaSamw SMB_NODE_MAGIC);
4901fcced4cSJordan Brown smb_node_release(node->n_dnode);
491da6c28aaSamw }
492da6c28aaSamw
4931fcced4cSJordan Brown if (node->n_unode) {
4941fcced4cSJordan Brown ASSERT(node->n_unode->n_magic ==
495da6c28aaSamw SMB_NODE_MAGIC);
4961fcced4cSJordan Brown smb_node_release(node->n_unode);
497da6c28aaSamw }
498da6c28aaSamw
4992c2961f8Sjose borrego smb_node_free(node);
500da6c28aaSamw return;
501da6c28aaSamw
502da6c28aaSamw default:
5032c2961f8Sjose borrego SMB_PANIC();
504da6c28aaSamw }
505da6c28aaSamw }
5062c2961f8Sjose borrego smb_node_audit(node);
5072c2961f8Sjose borrego mutex_exit(&node->n_mutex);
508da6c28aaSamw }
509da6c28aaSamw
510da6c28aaSamw static void
smb_node_delete_on_close(smb_node_t * node)511da6c28aaSamw smb_node_delete_on_close(smb_node_t *node)
512da6c28aaSamw {
513da6c28aaSamw smb_node_t *d_snode;
514da6c28aaSamw int rc = 0;
5158b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States uint32_t flags = 0;
516da6c28aaSamw
5171fcced4cSJordan Brown d_snode = node->n_dnode;
518da6c28aaSamw if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
519da6c28aaSamw node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE;
5208b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States flags = node->n_delete_on_close_flags;
521da6c28aaSamw ASSERT(node->od_name != NULL);
5228b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States
5239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_node_is_dir(node))
524da6c28aaSamw rc = smb_fsop_rmdir(0, node->delete_on_close_cred,
5258b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States d_snode, node->od_name, flags);
526da6c28aaSamw else
527da6c28aaSamw rc = smb_fsop_remove(0, node->delete_on_close_cred,
5288b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States d_snode, node->od_name, flags);
529148c5f43SAlan Wright crfree(node->delete_on_close_cred);
530da6c28aaSamw }
531da6c28aaSamw if (rc != 0)
532da6c28aaSamw cmn_err(CE_WARN, "File %s could not be removed, rc=%d\n",
533da6c28aaSamw node->od_name, rc);
534da6c28aaSamw DTRACE_PROBE2(smb_node_delete_on_close, int, rc, smb_node_t *, node);
535da6c28aaSamw }
536da6c28aaSamw
537da6c28aaSamw /*
538da6c28aaSamw * smb_node_rename()
539da6c28aaSamw *
540da6c28aaSamw */
5412c2961f8Sjose borrego void
smb_node_rename(smb_node_t * from_dnode,smb_node_t * ret_node,smb_node_t * to_dnode,char * to_name)542da6c28aaSamw smb_node_rename(
5432c2961f8Sjose borrego smb_node_t *from_dnode,
5442c2961f8Sjose borrego smb_node_t *ret_node,
5452c2961f8Sjose borrego smb_node_t *to_dnode,
546da6c28aaSamw char *to_name)
547da6c28aaSamw {
5482c2961f8Sjose borrego SMB_NODE_VALID(from_dnode);
5492c2961f8Sjose borrego SMB_NODE_VALID(to_dnode);
5502c2961f8Sjose borrego SMB_NODE_VALID(ret_node);
551da6c28aaSamw
5522c2961f8Sjose borrego smb_node_ref(to_dnode);
5532c2961f8Sjose borrego mutex_enter(&ret_node->n_mutex);
5542c2961f8Sjose borrego switch (ret_node->n_state) {
5552c2961f8Sjose borrego case SMB_NODE_STATE_AVAILABLE:
5561fcced4cSJordan Brown ret_node->n_dnode = to_dnode;
5572c2961f8Sjose borrego mutex_exit(&ret_node->n_mutex);
5581fcced4cSJordan Brown ASSERT(to_dnode->n_dnode != ret_node);
5592c2961f8Sjose borrego ASSERT((to_dnode->vp->v_xattrdir) ||
5602c2961f8Sjose borrego (to_dnode->vp->v_type == VDIR));
5612c2961f8Sjose borrego smb_node_release(from_dnode);
5622c2961f8Sjose borrego (void) strcpy(ret_node->od_name, to_name);
563da6c28aaSamw /*
564da6c28aaSamw * XXX Need to update attributes?
565da6c28aaSamw */
5662c2961f8Sjose borrego break;
5672c2961f8Sjose borrego default:
5682c2961f8Sjose borrego SMB_PANIC();
5692c2961f8Sjose borrego }
570da6c28aaSamw }
571da6c28aaSamw
572ae240eb8SGordon Ross /*
573ae240eb8SGordon Ross * Find/create an SMB node for the root of this zone and store it
574ae240eb8SGordon Ross * in *svrootp. Also create nodes leading to this directory.
575ae240eb8SGordon Ross */
576da6c28aaSamw int
smb_node_root_init(smb_server_t * sv,smb_node_t ** svrootp)577ae240eb8SGordon Ross smb_node_root_init(smb_server_t *sv, smb_node_t **svrootp)
578da6c28aaSamw {
579ae240eb8SGordon Ross zone_t *zone = curzone;
580faa1795aSjb150015 int error;
581da6c28aaSamw
582ae240eb8SGordon Ross ASSERT(zone->zone_id == sv->sv_zid);
583ae240eb8SGordon Ross if (smb_root_node == NULL)
584ae240eb8SGordon Ross return (ENOENT);
585ae240eb8SGordon Ross
586ae240eb8SGordon Ross /*
587ae240eb8SGordon Ross * We're getting smb nodes below the zone root here,
588ae240eb8SGordon Ross * so need to use kcred, not zone_kcred().
589ae240eb8SGordon Ross */
590ae240eb8SGordon Ross error = smb_pathname(NULL, zone->zone_rootpath, 0,
591ae240eb8SGordon Ross smb_root_node, smb_root_node, NULL, svrootp, kcred);
592ae240eb8SGordon Ross
593faa1795aSjb150015 return (error);
594faa1795aSjb150015 }
59545c1cdfcSAlek Pinchuk /*
59645c1cdfcSAlek Pinchuk * Helper function for smb_node_set_delete_on_close(). Assumes node is a dir.
59745c1cdfcSAlek Pinchuk * Return 0 if this is an empty dir. Otherwise return a NT_STATUS code.
59845c1cdfcSAlek Pinchuk * We distinguish between readdir failure and non-empty dir by returning
59945c1cdfcSAlek Pinchuk * different values.
60045c1cdfcSAlek Pinchuk */
60145c1cdfcSAlek Pinchuk static uint32_t
smb_rmdir_possible(smb_node_t * n,uint32_t flags)60245c1cdfcSAlek Pinchuk smb_rmdir_possible(smb_node_t *n, uint32_t flags)
60345c1cdfcSAlek Pinchuk {
60445c1cdfcSAlek Pinchuk ASSERT(n->vp->v_type == VDIR);
60545c1cdfcSAlek Pinchuk char buf[512]; /* Only large enough to see if the dir is empty. */
60645c1cdfcSAlek Pinchuk int eof, bsize = sizeof (buf), reclen = 0;
60745c1cdfcSAlek Pinchuk char *name;
60845c1cdfcSAlek Pinchuk boolean_t edp = vfs_has_feature(n->vp->v_vfsp, VFSFT_DIRENTFLAGS);
60945c1cdfcSAlek Pinchuk
61045c1cdfcSAlek Pinchuk union {
61145c1cdfcSAlek Pinchuk char *u_bufptr;
61245c1cdfcSAlek Pinchuk struct edirent *u_edp;
61345c1cdfcSAlek Pinchuk struct dirent64 *u_dp;
61445c1cdfcSAlek Pinchuk } u;
61545c1cdfcSAlek Pinchuk #define bufptr u.u_bufptr
61645c1cdfcSAlek Pinchuk #define extdp u.u_edp
61745c1cdfcSAlek Pinchuk #define dp u.u_dp
61845c1cdfcSAlek Pinchuk
61945c1cdfcSAlek Pinchuk if (smb_vop_readdir(n->vp, 0, buf, &bsize, &eof, flags, zone_kcred()))
62045c1cdfcSAlek Pinchuk return (NT_STATUS_CANNOT_DELETE);
62145c1cdfcSAlek Pinchuk if (bsize == 0)
62245c1cdfcSAlek Pinchuk return (NT_STATUS_CANNOT_DELETE);
62345c1cdfcSAlek Pinchuk bufptr = buf;
62445c1cdfcSAlek Pinchuk while ((bufptr += reclen) < buf + bsize) {
62545c1cdfcSAlek Pinchuk if (edp) {
62645c1cdfcSAlek Pinchuk reclen = extdp->ed_reclen;
62745c1cdfcSAlek Pinchuk name = extdp->ed_name;
62845c1cdfcSAlek Pinchuk } else {
62945c1cdfcSAlek Pinchuk reclen = dp->d_reclen;
63045c1cdfcSAlek Pinchuk name = dp->d_name;
63145c1cdfcSAlek Pinchuk }
63245c1cdfcSAlek Pinchuk if (strcmp(name, ".") != 0 && strcmp(name, "..") != 0)
63345c1cdfcSAlek Pinchuk return (NT_STATUS_DIRECTORY_NOT_EMPTY);
63445c1cdfcSAlek Pinchuk }
63545c1cdfcSAlek Pinchuk return (0);
63645c1cdfcSAlek Pinchuk }
637da6c28aaSamw
638da6c28aaSamw /*
6398b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * When DeleteOnClose is set on an smb_node, the common open code will
6408b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * reject subsequent open requests for the file. Observation of Windows
6418b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * 2000 indicates that subsequent opens should be allowed (assuming
6428b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * there would be no sharing violation) until the file is closed using
6438b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * the fid on which the DeleteOnClose was requested.
6448b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States *
6458b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * If there are multiple opens with delete-on-close create options,
6468b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * whichever the first file handle is closed will trigger the node to be
6478b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * marked as delete-on-close. The credentials of that ofile will be used
6488b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States * as the delete-on-close credentials of the node.
6498b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States */
65045c1cdfcSAlek Pinchuk uint32_t
smb_node_set_delete_on_close(smb_node_t * node,cred_t * cr,uint32_t flags)6518b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_node_set_delete_on_close(smb_node_t *node, cred_t *cr, uint32_t flags)
652da6c28aaSamw {
653a0aa776eSAlan Wright int rc = 0;
65445c1cdfcSAlek Pinchuk uint32_t status;
655037cac00Sjoyce mcintosh smb_attr_t attr;
656da6c28aaSamw
657d6e098b6SGordon Ross if (node->n_pending_dosattr & FILE_ATTRIBUTE_READONLY)
65845c1cdfcSAlek Pinchuk return (NT_STATUS_CANNOT_DELETE);
659037cac00Sjoyce mcintosh
660037cac00Sjoyce mcintosh bzero(&attr, sizeof (smb_attr_t));
661037cac00Sjoyce mcintosh attr.sa_mask = SMB_AT_DOSATTR;
662ae240eb8SGordon Ross rc = smb_fsop_getattr(NULL, zone_kcred(), node, &attr);
663037cac00Sjoyce mcintosh if ((rc != 0) || (attr.sa_dosattr & FILE_ATTRIBUTE_READONLY)) {
66445c1cdfcSAlek Pinchuk return (NT_STATUS_CANNOT_DELETE);
66545c1cdfcSAlek Pinchuk }
66645c1cdfcSAlek Pinchuk
66745c1cdfcSAlek Pinchuk /*
66845c1cdfcSAlek Pinchuk * If the directory is not empty we should fail setting del-on-close
66945c1cdfcSAlek Pinchuk * with STATUS_DIRECTORY_NOT_EMPTY. see MS's
67045c1cdfcSAlek Pinchuk * "File System Behavior Overview" doc section 4.3.2
67145c1cdfcSAlek Pinchuk */
67245c1cdfcSAlek Pinchuk if (smb_node_is_dir(node)) {
67345c1cdfcSAlek Pinchuk status = smb_rmdir_possible(node, flags);
67445c1cdfcSAlek Pinchuk if (status != 0) {
67545c1cdfcSAlek Pinchuk return (status);
67645c1cdfcSAlek Pinchuk }
677037cac00Sjoyce mcintosh }
678037cac00Sjoyce mcintosh
679a0aa776eSAlan Wright mutex_enter(&node->n_mutex);
680a0aa776eSAlan Wright if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
68145c1cdfcSAlek Pinchuk mutex_exit(&node->n_mutex);
68245c1cdfcSAlek Pinchuk return (NT_STATUS_CANNOT_DELETE);
68345c1cdfcSAlek Pinchuk }
68445c1cdfcSAlek Pinchuk
685da6c28aaSamw crhold(cr);
686da6c28aaSamw node->delete_on_close_cred = cr;
6878b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States node->n_delete_on_close_flags = flags;
688da6c28aaSamw node->flags |= NODE_FLAGS_DELETE_ON_CLOSE;
6892c2961f8Sjose borrego mutex_exit(&node->n_mutex);
69045c1cdfcSAlek Pinchuk
69145c1cdfcSAlek Pinchuk return (NT_STATUS_SUCCESS);
692da6c28aaSamw }
693da6c28aaSamw
694da6c28aaSamw void
smb_node_reset_delete_on_close(smb_node_t * node)695da6c28aaSamw smb_node_reset_delete_on_close(smb_node_t *node)
696da6c28aaSamw {
6972c2961f8Sjose borrego mutex_enter(&node->n_mutex);
698da6c28aaSamw if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
699da6c28aaSamw node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE;
700da6c28aaSamw crfree(node->delete_on_close_cred);
701da6c28aaSamw node->delete_on_close_cred = NULL;
7028b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States node->n_delete_on_close_flags = 0;
703da6c28aaSamw }
7042c2961f8Sjose borrego mutex_exit(&node->n_mutex);
705da6c28aaSamw }
706dc20a302Sas200622
707dc20a302Sas200622 /*
7083ad684d6Sjb150015 * smb_node_open_check
709dc20a302Sas200622 *
710dc20a302Sas200622 * check file sharing rules for current open request
711dc20a302Sas200622 * against all existing opens for a file.
712dc20a302Sas200622 *
713dc20a302Sas200622 * Returns NT_STATUS_SHARING_VIOLATION if there is any
714dc20a302Sas200622 * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
715dc20a302Sas200622 */
716dc20a302Sas200622 uint32_t
smb_node_open_check(smb_node_t * node,uint32_t desired_access,uint32_t share_access)7179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_open_check(smb_node_t *node, uint32_t desired_access,
7182c2961f8Sjose borrego uint32_t share_access)
719dc20a302Sas200622 {
720dc20a302Sas200622 smb_ofile_t *of;
721dc20a302Sas200622 uint32_t status;
722dc20a302Sas200622
7232c2961f8Sjose borrego SMB_NODE_VALID(node);
724dc20a302Sas200622
725dc20a302Sas200622 smb_llist_enter(&node->n_ofile_list, RW_READER);
726dc20a302Sas200622 of = smb_llist_head(&node->n_ofile_list);
727dc20a302Sas200622 while (of) {
7289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States status = smb_ofile_open_check(of, desired_access, share_access);
7293ad684d6Sjb150015
7303ad684d6Sjb150015 switch (status) {
7313ad684d6Sjb150015 case NT_STATUS_INVALID_HANDLE:
7323ad684d6Sjb150015 case NT_STATUS_SUCCESS:
7333ad684d6Sjb150015 of = smb_llist_next(&node->n_ofile_list, of);
7343ad684d6Sjb150015 break;
7353ad684d6Sjb150015 default:
7363ad684d6Sjb150015 ASSERT(status == NT_STATUS_SHARING_VIOLATION);
737dc20a302Sas200622 smb_llist_exit(&node->n_ofile_list);
738dc20a302Sas200622 return (status);
739dc20a302Sas200622 }
740dc20a302Sas200622 }
7413ad684d6Sjb150015
742dc20a302Sas200622 smb_llist_exit(&node->n_ofile_list);
743dc20a302Sas200622 return (NT_STATUS_SUCCESS);
744dc20a302Sas200622 }
745dc20a302Sas200622
746dc20a302Sas200622 uint32_t
smb_node_rename_check(smb_node_t * node)7472c2961f8Sjose borrego smb_node_rename_check(smb_node_t *node)
748dc20a302Sas200622 {
7492c2961f8Sjose borrego smb_ofile_t *of;
7503ad684d6Sjb150015 uint32_t status;
751dc20a302Sas200622
7522c2961f8Sjose borrego SMB_NODE_VALID(node);
753dc20a302Sas200622
754dc20a302Sas200622 /*
755dc20a302Sas200622 * Intra-CIFS check
756dc20a302Sas200622 */
757dc20a302Sas200622 smb_llist_enter(&node->n_ofile_list, RW_READER);
7583ad684d6Sjb150015 of = smb_llist_head(&node->n_ofile_list);
7593ad684d6Sjb150015 while (of) {
7603ad684d6Sjb150015 status = smb_ofile_rename_check(of);
761dc20a302Sas200622
7623ad684d6Sjb150015 switch (status) {
7633ad684d6Sjb150015 case NT_STATUS_INVALID_HANDLE:
7643ad684d6Sjb150015 case NT_STATUS_SUCCESS:
7653ad684d6Sjb150015 of = smb_llist_next(&node->n_ofile_list, of);
7663ad684d6Sjb150015 break;
7673ad684d6Sjb150015 default:
7683ad684d6Sjb150015 ASSERT(status == NT_STATUS_SHARING_VIOLATION);
769dc20a302Sas200622 smb_llist_exit(&node->n_ofile_list);
7703ad684d6Sjb150015 return (status);
771dc20a302Sas200622 }
772dc20a302Sas200622 }
773dc20a302Sas200622 smb_llist_exit(&node->n_ofile_list);
774dc20a302Sas200622 return (NT_STATUS_SUCCESS);
775dc20a302Sas200622 }
776dc20a302Sas200622
7773ad684d6Sjb150015 uint32_t
smb_node_delete_check(smb_node_t * node)778dc20a302Sas200622 smb_node_delete_check(smb_node_t *node)
779dc20a302Sas200622 {
7803ad684d6Sjb150015 smb_ofile_t *of;
7813ad684d6Sjb150015 uint32_t status;
782dc20a302Sas200622
7832c2961f8Sjose borrego SMB_NODE_VALID(node);
784dc20a302Sas200622
7859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_node_is_dir(node))
786dc20a302Sas200622 return (NT_STATUS_SUCCESS);
787dc20a302Sas200622
7889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_node_is_reparse(node))
7899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (NT_STATUS_ACCESS_DENIED);
7909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
791dc20a302Sas200622 /*
792dc20a302Sas200622 * intra-CIFS check
793dc20a302Sas200622 */
794dc20a302Sas200622 smb_llist_enter(&node->n_ofile_list, RW_READER);
7953ad684d6Sjb150015 of = smb_llist_head(&node->n_ofile_list);
7963ad684d6Sjb150015 while (of) {
7973ad684d6Sjb150015 status = smb_ofile_delete_check(of);
7983ad684d6Sjb150015
7993ad684d6Sjb150015 switch (status) {
8003ad684d6Sjb150015 case NT_STATUS_INVALID_HANDLE:
8013ad684d6Sjb150015 case NT_STATUS_SUCCESS:
8023ad684d6Sjb150015 of = smb_llist_next(&node->n_ofile_list, of);
8033ad684d6Sjb150015 break;
8043ad684d6Sjb150015 default:
8053ad684d6Sjb150015 ASSERT(status == NT_STATUS_SHARING_VIOLATION);
806dc20a302Sas200622 smb_llist_exit(&node->n_ofile_list);
8073ad684d6Sjb150015 return (status);
808dc20a302Sas200622 }
809dc20a302Sas200622 }
810dc20a302Sas200622 smb_llist_exit(&node->n_ofile_list);
811dc20a302Sas200622 return (NT_STATUS_SUCCESS);
812dc20a302Sas200622 }
813dc20a302Sas200622
814cb174861Sjoyce mcintosh /*
815cb174861Sjoyce mcintosh * smb_node_share_check
816cb174861Sjoyce mcintosh *
817cb174861Sjoyce mcintosh * Returns: TRUE - ofiles have non-zero share access
818cb174861Sjoyce mcintosh * B_FALSE - ofile with share access NONE.
819cb174861Sjoyce mcintosh */
820cb174861Sjoyce mcintosh boolean_t
smb_node_share_check(smb_node_t * node)821cb174861Sjoyce mcintosh smb_node_share_check(smb_node_t *node)
822cb174861Sjoyce mcintosh {
823cb174861Sjoyce mcintosh smb_ofile_t *of;
824cb174861Sjoyce mcintosh boolean_t status = B_TRUE;
825cb174861Sjoyce mcintosh
826cb174861Sjoyce mcintosh SMB_NODE_VALID(node);
827cb174861Sjoyce mcintosh
828cb174861Sjoyce mcintosh smb_llist_enter(&node->n_ofile_list, RW_READER);
829cb174861Sjoyce mcintosh of = smb_llist_head(&node->n_ofile_list);
830cb174861Sjoyce mcintosh if (of)
831cb174861Sjoyce mcintosh status = smb_ofile_share_check(of);
832cb174861Sjoyce mcintosh smb_llist_exit(&node->n_ofile_list);
833cb174861Sjoyce mcintosh
834cb174861Sjoyce mcintosh return (status);
835cb174861Sjoyce mcintosh }
836cb174861Sjoyce mcintosh
837ccc71be5SGordon Ross /*
838ccc71be5SGordon Ross * SMB Change Notification
839ccc71be5SGordon Ross */
840ccc71be5SGordon Ross
841b1352070SAlan Wright void
smb_node_fcn_subscribe(smb_node_t * node,smb_request_t * sr)842ccc71be5SGordon Ross smb_node_fcn_subscribe(smb_node_t *node, smb_request_t *sr)
843ccc71be5SGordon Ross {
844ccc71be5SGordon Ross smb_node_fcn_t *fcn = &node->n_fcn;
845ccc71be5SGordon Ross
846ccc71be5SGordon Ross mutex_enter(&fcn->fcn_mutex);
847ccc71be5SGordon Ross if (fcn->fcn_count == 0)
848ae240eb8SGordon Ross (void) smb_fem_fcn_install(node);
849ccc71be5SGordon Ross fcn->fcn_count++;
850ccc71be5SGordon Ross list_insert_tail(&fcn->fcn_watchers, sr);
851ccc71be5SGordon Ross mutex_exit(&fcn->fcn_mutex);
852ccc71be5SGordon Ross }
853ccc71be5SGordon Ross
854ccc71be5SGordon Ross void
smb_node_fcn_unsubscribe(smb_node_t * node,smb_request_t * sr)855ccc71be5SGordon Ross smb_node_fcn_unsubscribe(smb_node_t *node, smb_request_t *sr)
856ccc71be5SGordon Ross {
857ccc71be5SGordon Ross smb_node_fcn_t *fcn = &node->n_fcn;
858ccc71be5SGordon Ross
859ccc71be5SGordon Ross mutex_enter(&fcn->fcn_mutex);
860ccc71be5SGordon Ross list_remove(&fcn->fcn_watchers, sr);
861ccc71be5SGordon Ross fcn->fcn_count--;
862ccc71be5SGordon Ross if (fcn->fcn_count == 0)
863ccc71be5SGordon Ross smb_fem_fcn_uninstall(node);
864ccc71be5SGordon Ross mutex_exit(&fcn->fcn_mutex);
865ccc71be5SGordon Ross }
866ccc71be5SGordon Ross
867ccc71be5SGordon Ross void
smb_node_notify_change(smb_node_t * node,uint_t action,const char * name)868ccc71be5SGordon Ross smb_node_notify_change(smb_node_t *node, uint_t action, const char *name)
869b1352070SAlan Wright {
870b1352070SAlan Wright SMB_NODE_VALID(node);
871b1352070SAlan Wright
872ccc71be5SGordon Ross smb_notify_event(node, action, name);
873ccc71be5SGordon Ross
874ccc71be5SGordon Ross /*
875ccc71be5SGordon Ross * These two events come as a pair:
876ccc71be5SGordon Ross * FILE_ACTION_RENAMED_OLD_NAME
877ccc71be5SGordon Ross * FILE_ACTION_RENAMED_NEW_NAME
878ccc71be5SGordon Ross * Only do the parent notify for "new".
879ccc71be5SGordon Ross */
880ccc71be5SGordon Ross if (action == FILE_ACTION_RENAMED_OLD_NAME)
881ccc71be5SGordon Ross return;
8829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
8839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_notify_parents(node);
884b1352070SAlan Wright }
885b1352070SAlan Wright
8869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
8879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * smb_node_notify_parents
8889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States *
8899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Iterate up the directory tree notifying any parent
8909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * directories that are being watched for changes in
8919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * their sub directories.
8929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Stop at the root node, which has a NULL parent node.
8939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */
8949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void
smb_node_notify_parents(smb_node_t * dnode)8959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_notify_parents(smb_node_t *dnode)
896fe1c642dSBill Krier {
897ccc71be5SGordon Ross smb_node_t *pnode; /* parent */
898fe1c642dSBill Krier
8999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_NODE_VALID(dnode);
900ccc71be5SGordon Ross pnode = dnode->n_dnode;
9019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
902ccc71be5SGordon Ross while (pnode != NULL) {
9039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_NODE_VALID(pnode);
904ccc71be5SGordon Ross smb_notify_event(pnode, 0, dnode->od_name);
905ccc71be5SGordon Ross /* cd .. */
906ccc71be5SGordon Ross dnode = pnode;
907ccc71be5SGordon Ross pnode = dnode->n_dnode;
9089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
909fe1c642dSBill Krier }
910fe1c642dSBill Krier
911dc20a302Sas200622 /*
912dc20a302Sas200622 * smb_node_start_crit()
913dc20a302Sas200622 *
914dc20a302Sas200622 * Enter critical region for share reservations.
915dc20a302Sas200622 * See comments above smb_fsop_shrlock().
916dc20a302Sas200622 */
917dc20a302Sas200622 void
smb_node_start_crit(smb_node_t * node,krw_t mode)918dc20a302Sas200622 smb_node_start_crit(smb_node_t *node, krw_t mode)
919dc20a302Sas200622 {
9202c2961f8Sjose borrego rw_enter(&node->n_lock, mode);
921dc20a302Sas200622 nbl_start_crit(node->vp, mode);
922dc20a302Sas200622 }
923dc20a302Sas200622
924dc20a302Sas200622 /*
925dc20a302Sas200622 * smb_node_end_crit()
926dc20a302Sas200622 *
927dc20a302Sas200622 * Exit critical region for share reservations.
928dc20a302Sas200622 */
929dc20a302Sas200622 void
smb_node_end_crit(smb_node_t * node)930dc20a302Sas200622 smb_node_end_crit(smb_node_t *node)
931dc20a302Sas200622 {
932dc20a302Sas200622 nbl_end_crit(node->vp);
9332c2961f8Sjose borrego rw_exit(&node->n_lock);
934dc20a302Sas200622 }
935dc20a302Sas200622
936dc20a302Sas200622 int
smb_node_in_crit(smb_node_t * node)937dc20a302Sas200622 smb_node_in_crit(smb_node_t *node)
938dc20a302Sas200622 {
9392c2961f8Sjose borrego return (nbl_in_crit(node->vp) && RW_LOCK_HELD(&node->n_lock));
9402c2961f8Sjose borrego }
9412c2961f8Sjose borrego
9422c2961f8Sjose borrego void
smb_node_rdlock(smb_node_t * node)9432c2961f8Sjose borrego smb_node_rdlock(smb_node_t *node)
9442c2961f8Sjose borrego {
9452c2961f8Sjose borrego rw_enter(&node->n_lock, RW_READER);
9462c2961f8Sjose borrego }
9472c2961f8Sjose borrego
9482c2961f8Sjose borrego void
smb_node_wrlock(smb_node_t * node)9492c2961f8Sjose borrego smb_node_wrlock(smb_node_t *node)
9502c2961f8Sjose borrego {
9512c2961f8Sjose borrego rw_enter(&node->n_lock, RW_WRITER);
9522c2961f8Sjose borrego }
9532c2961f8Sjose borrego
9542c2961f8Sjose borrego void
smb_node_unlock(smb_node_t * node)9552c2961f8Sjose borrego smb_node_unlock(smb_node_t *node)
9562c2961f8Sjose borrego {
9572c2961f8Sjose borrego rw_exit(&node->n_lock);
9582c2961f8Sjose borrego }
9592c2961f8Sjose borrego
9602c2961f8Sjose borrego void
smb_node_add_ofile(smb_node_t * node,smb_ofile_t * of)9612c2961f8Sjose borrego smb_node_add_ofile(smb_node_t *node, smb_ofile_t *of)
9622c2961f8Sjose borrego {
9632c2961f8Sjose borrego SMB_NODE_VALID(node);
9642c2961f8Sjose borrego
9652c2961f8Sjose borrego smb_llist_enter(&node->n_ofile_list, RW_WRITER);
9662c2961f8Sjose borrego smb_llist_insert_tail(&node->n_ofile_list, of);
9672c2961f8Sjose borrego smb_llist_exit(&node->n_ofile_list);
9682c2961f8Sjose borrego }
9692c2961f8Sjose borrego
9702c2961f8Sjose borrego void
smb_node_rem_ofile(smb_node_t * node,smb_ofile_t * of)9712c2961f8Sjose borrego smb_node_rem_ofile(smb_node_t *node, smb_ofile_t *of)
9722c2961f8Sjose borrego {
9732c2961f8Sjose borrego SMB_NODE_VALID(node);
9742c2961f8Sjose borrego
9752c2961f8Sjose borrego smb_llist_enter(&node->n_ofile_list, RW_WRITER);
9762c2961f8Sjose borrego smb_llist_remove(&node->n_ofile_list, of);
9772c2961f8Sjose borrego smb_llist_exit(&node->n_ofile_list);
9782c2961f8Sjose borrego }
9792c2961f8Sjose borrego
980037cac00Sjoyce mcintosh /*
981037cac00Sjoyce mcintosh * smb_node_inc_open_ofiles
982037cac00Sjoyce mcintosh */
9832c2961f8Sjose borrego void
smb_node_inc_open_ofiles(smb_node_t * node)9842c2961f8Sjose borrego smb_node_inc_open_ofiles(smb_node_t *node)
9852c2961f8Sjose borrego {
9862c2961f8Sjose borrego SMB_NODE_VALID(node);
987d6e098b6SGordon Ross atomic_inc_32(&node->n_open_count);
9882c2961f8Sjose borrego }
9892c2961f8Sjose borrego
990037cac00Sjoyce mcintosh /*
991037cac00Sjoyce mcintosh * smb_node_dec_open_ofiles
992d6e098b6SGordon Ross * returns new value
993037cac00Sjoyce mcintosh */
994d6e098b6SGordon Ross uint32_t
smb_node_dec_open_ofiles(smb_node_t * node)9952c2961f8Sjose borrego smb_node_dec_open_ofiles(smb_node_t *node)
9962c2961f8Sjose borrego {
9972c2961f8Sjose borrego SMB_NODE_VALID(node);
998d6e098b6SGordon Ross return (atomic_dec_32_nv(&node->n_open_count));
9992c2961f8Sjose borrego }
10002c2961f8Sjose borrego
1001cb174861Sjoyce mcintosh /*
1002cb174861Sjoyce mcintosh * smb_node_inc_opening_count
1003cb174861Sjoyce mcintosh */
1004cb174861Sjoyce mcintosh void
smb_node_inc_opening_count(smb_node_t * node)1005cb174861Sjoyce mcintosh smb_node_inc_opening_count(smb_node_t *node)
10062c2961f8Sjose borrego {
10072c2961f8Sjose borrego SMB_NODE_VALID(node);
1008d6e098b6SGordon Ross atomic_inc_32(&node->n_opening_count);
1009cb174861Sjoyce mcintosh }
1010cb174861Sjoyce mcintosh
1011cb174861Sjoyce mcintosh /*
1012cb174861Sjoyce mcintosh * smb_node_dec_opening_count
1013cb174861Sjoyce mcintosh */
1014cb174861Sjoyce mcintosh void
smb_node_dec_opening_count(smb_node_t * node)1015cb174861Sjoyce mcintosh smb_node_dec_opening_count(smb_node_t *node)
1016cb174861Sjoyce mcintosh {
1017cb174861Sjoyce mcintosh SMB_NODE_VALID(node);
1018d6e098b6SGordon Ross atomic_dec_32(&node->n_opening_count);
10192c2961f8Sjose borrego }
10202c2961f8Sjose borrego
10212c2961f8Sjose borrego /*
10229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * smb_node_getmntpath
10239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */
10249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
smb_node_getmntpath(smb_node_t * node,char * buf,uint32_t buflen)10259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_getmntpath(smb_node_t *node, char *buf, uint32_t buflen)
10269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
10279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States vnode_t *vp, *root_vp;
10289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States vfs_t *vfsp;
10299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int err;
10309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
10319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(node);
10329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(node->vp);
10339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ASSERT(node->vp->v_vfsp);
10349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
10359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States vp = node->vp;
10369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States vfsp = vp->v_vfsp;
10379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
10389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (VFS_ROOT(vfsp, &root_vp))
10399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (ENOENT);
10409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
10419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States VN_HOLD(vp);
10429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
10439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /* NULL is passed in as we want to start at "/" */
1044ae240eb8SGordon Ross err = vnodetopath(NULL, root_vp, buf, buflen, zone_kcred());
10459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
10469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States VN_RELE(vp);
10479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States VN_RELE(root_vp);
10489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (err);
10499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
10509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
10519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
10529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * smb_node_getshrpath
10539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States *
10549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Determine the absolute pathname of 'node' within the share (tree).
10559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * For example if the node represents file "test1.txt" in directory
10569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * "dir1" the pathname would be: \dir1\test1.txt
10579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */
10589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
smb_node_getshrpath(smb_node_t * node,smb_tree_t * tree,char * buf,uint32_t buflen)10599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_getshrpath(smb_node_t *node, smb_tree_t *tree,
10609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States char *buf, uint32_t buflen)
10619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
10629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int rc;
10639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
1064c5866007SKeyur Desai ASSERT(node);
1065c5866007SKeyur Desai ASSERT(tree);
1066c5866007SKeyur Desai ASSERT(tree->t_snode);
10679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
1068c5866007SKeyur Desai rc = smb_node_getpath(node, tree->t_snode->vp, buf, buflen);
10699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) strsubst(buf, '/', '\\');
1070c5866007SKeyur Desai return (rc);
1071c5866007SKeyur Desai }
10729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
1073c5866007SKeyur Desai /*
1074c5866007SKeyur Desai * smb_node_getpath
1075c5866007SKeyur Desai *
1076c5866007SKeyur Desai * Determine the absolute pathname of 'node' from 'rootvp'.
1077c5866007SKeyur Desai *
1078c5866007SKeyur Desai * Using vnodetopath is only reliable for directory nodes (due to
1079c5866007SKeyur Desai * its reliance on the DNLC for non-directory nodes). Thus, if node
1080c5866007SKeyur Desai * represents a file, construct the pathname for the parent dnode
1081c5866007SKeyur Desai * and append filename.
1082c5866007SKeyur Desai * If node represents a named stream, construct the pathname for the
1083c5866007SKeyur Desai * associated unnamed stream and append the stream name.
1084c5866007SKeyur Desai *
1085c5866007SKeyur Desai * The pathname returned in buf will be '/' separated.
1086c5866007SKeyur Desai */
1087c5866007SKeyur Desai int
smb_node_getpath(smb_node_t * node,vnode_t * rootvp,char * buf,uint32_t buflen)1088c5866007SKeyur Desai smb_node_getpath(smb_node_t *node, vnode_t *rootvp, char *buf, uint32_t buflen)
1089c5866007SKeyur Desai {
1090c5866007SKeyur Desai int rc;
1091c5866007SKeyur Desai vnode_t *vp;
1092c5866007SKeyur Desai smb_node_t *unode, *dnode;
1093ae240eb8SGordon Ross cred_t *kcr = zone_kcred();
1094c5866007SKeyur Desai
1095c5866007SKeyur Desai unode = (SMB_IS_STREAM(node)) ? node->n_unode : node;
1096c5866007SKeyur Desai dnode = (smb_node_is_dir(unode)) ? unode : unode->n_dnode;
1097c5866007SKeyur Desai
1098c5866007SKeyur Desai /* find path to directory node */
1099c5866007SKeyur Desai vp = dnode->vp;
1100c5866007SKeyur Desai VN_HOLD(vp);
1101c5866007SKeyur Desai if (rootvp) {
1102c5866007SKeyur Desai VN_HOLD(rootvp);
1103ae240eb8SGordon Ross rc = vnodetopath(rootvp, vp, buf, buflen, kcr);
1104c5866007SKeyur Desai VN_RELE(rootvp);
1105c5866007SKeyur Desai } else {
1106ae240eb8SGordon Ross rc = vnodetopath(NULL, vp, buf, buflen, kcr);
1107c5866007SKeyur Desai }
1108c5866007SKeyur Desai VN_RELE(vp);
1109c5866007SKeyur Desai
1110c5866007SKeyur Desai if (rc != 0)
1111c5866007SKeyur Desai return (rc);
1112c5866007SKeyur Desai
1113c5866007SKeyur Desai /* append filename if necessary */
1114c5866007SKeyur Desai if (!smb_node_is_dir(unode)) {
1115c5866007SKeyur Desai if (buf[strlen(buf) - 1] != '/')
1116c5866007SKeyur Desai (void) strlcat(buf, "/", buflen);
1117c5866007SKeyur Desai (void) strlcat(buf, unode->od_name, buflen);
1118c5866007SKeyur Desai }
1119c5866007SKeyur Desai
1120c5866007SKeyur Desai /* append named stream name if necessary */
11219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (SMB_IS_STREAM(node))
11229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) strlcat(buf, node->od_name, buflen);
11239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
11249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (rc);
11259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
11269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
11279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
11282c2961f8Sjose borrego * smb_node_alloc
11292c2961f8Sjose borrego */
11302c2961f8Sjose borrego static smb_node_t *
smb_node_alloc(char * od_name,vnode_t * vp,smb_llist_t * bucket,uint32_t hashkey)11312c2961f8Sjose borrego smb_node_alloc(
11322c2961f8Sjose borrego char *od_name,
11332c2961f8Sjose borrego vnode_t *vp,
11342c2961f8Sjose borrego smb_llist_t *bucket,
11352c2961f8Sjose borrego uint32_t hashkey)
11362c2961f8Sjose borrego {
11372c2961f8Sjose borrego smb_node_t *node;
11389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States vnode_t *root_vp;
11392c2961f8Sjose borrego
11402c2961f8Sjose borrego node = kmem_cache_alloc(smb_node_cache, KM_SLEEP);
11412c2961f8Sjose borrego
11422c2961f8Sjose borrego if (node->n_audit_buf != NULL)
11432c2961f8Sjose borrego node->n_audit_buf->anb_index = 0;
11442c2961f8Sjose borrego
1145037cac00Sjoyce mcintosh node->flags = 0;
11462c2961f8Sjose borrego VN_HOLD(vp);
11472c2961f8Sjose borrego node->vp = vp;
11482c2961f8Sjose borrego node->n_refcnt = 1;
11492c2961f8Sjose borrego node->n_hash_bucket = bucket;
11502c2961f8Sjose borrego node->n_hashkey = hashkey;
1151d6e098b6SGordon Ross node->n_pending_dosattr = 0;
11522c2961f8Sjose borrego node->n_open_count = 0;
1153d6e098b6SGordon Ross node->n_allocsz = 0;
11541fcced4cSJordan Brown node->n_dnode = NULL;
11551fcced4cSJordan Brown node->n_unode = NULL;
11562c2961f8Sjose borrego node->delete_on_close_cred = NULL;
11578b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States node->n_delete_on_close_flags = 0;
1158cb174861Sjoyce mcintosh node->n_oplock.ol_fem = B_FALSE;
1159cb174861Sjoyce mcintosh node->n_oplock.ol_xthread = NULL;
1160cb174861Sjoyce mcintosh node->n_oplock.ol_count = 0;
1161cb174861Sjoyce mcintosh node->n_oplock.ol_break = SMB_OPLOCK_NO_BREAK;
11622c2961f8Sjose borrego
11632c2961f8Sjose borrego (void) strlcpy(node->od_name, od_name, sizeof (node->od_name));
11642c2961f8Sjose borrego if (strcmp(od_name, XATTR_DIR) == 0)
11652c2961f8Sjose borrego node->flags |= NODE_XATTR_DIR;
11662c2961f8Sjose borrego
11679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (VFS_ROOT(vp->v_vfsp, &root_vp) == 0) {
11689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (vp == root_vp)
11699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States node->flags |= NODE_FLAGS_VFSROOT;
11709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States VN_RELE(root_vp);
11719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
11729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
11732c2961f8Sjose borrego node->n_state = SMB_NODE_STATE_AVAILABLE;
11742c2961f8Sjose borrego node->n_magic = SMB_NODE_MAGIC;
11759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
11762c2961f8Sjose borrego return (node);
11772c2961f8Sjose borrego }
11782c2961f8Sjose borrego
11792c2961f8Sjose borrego /*
11802c2961f8Sjose borrego * smb_node_free
11812c2961f8Sjose borrego */
11822c2961f8Sjose borrego static void
smb_node_free(smb_node_t * node)11832c2961f8Sjose borrego smb_node_free(smb_node_t *node)
11842c2961f8Sjose borrego {
11852c2961f8Sjose borrego SMB_NODE_VALID(node);
11862c2961f8Sjose borrego
11872c2961f8Sjose borrego node->n_magic = 0;
11882c2961f8Sjose borrego VERIFY(!list_link_active(&node->n_lnd));
11892c2961f8Sjose borrego VERIFY(node->n_lock_list.ll_count == 0);
11902c2961f8Sjose borrego VERIFY(node->n_ofile_list.ll_count == 0);
1191cb174861Sjoyce mcintosh VERIFY(node->n_oplock.ol_count == 0);
11922c2961f8Sjose borrego VERIFY(node->n_oplock.ol_xthread == NULL);
1193cb174861Sjoyce mcintosh VERIFY(node->n_oplock.ol_fem == B_FALSE);
1194*7206bf49SGordon Ross VERIFY(MUTEX_NOT_HELD(&node->n_mutex));
1195fc724630SAlan Wright VERIFY(!RW_LOCK_HELD(&node->n_lock));
11962c2961f8Sjose borrego VN_RELE(node->vp);
11972c2961f8Sjose borrego kmem_cache_free(smb_node_cache, node);
11982c2961f8Sjose borrego }
11992c2961f8Sjose borrego
12002c2961f8Sjose borrego /*
12012c2961f8Sjose borrego * smb_node_constructor
12022c2961f8Sjose borrego */
12032c2961f8Sjose borrego static int
smb_node_constructor(void * buf,void * un,int kmflags)12042c2961f8Sjose borrego smb_node_constructor(void *buf, void *un, int kmflags)
12052c2961f8Sjose borrego {
12062c2961f8Sjose borrego _NOTE(ARGUNUSED(kmflags, un))
12072c2961f8Sjose borrego
12082c2961f8Sjose borrego smb_node_t *node = (smb_node_t *)buf;
12092c2961f8Sjose borrego
12102c2961f8Sjose borrego bzero(node, sizeof (smb_node_t));
12112c2961f8Sjose borrego
12122c2961f8Sjose borrego smb_llist_constructor(&node->n_ofile_list, sizeof (smb_ofile_t),
12132c2961f8Sjose borrego offsetof(smb_ofile_t, f_nnd));
12142c2961f8Sjose borrego smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t),
12152c2961f8Sjose borrego offsetof(smb_lock_t, l_lnd));
1216ccc71be5SGordon Ross mutex_init(&node->n_fcn.fcn_mutex, NULL, MUTEX_DEFAULT, NULL);
1217ccc71be5SGordon Ross list_create(&node->n_fcn.fcn_watchers, sizeof (smb_request_t),
1218ccc71be5SGordon Ross offsetof(smb_request_t, sr_ncr.nc_lnd));
12192c2961f8Sjose borrego cv_init(&node->n_oplock.ol_cv, NULL, CV_DEFAULT, NULL);
1220cb174861Sjoyce mcintosh mutex_init(&node->n_oplock.ol_mutex, NULL, MUTEX_DEFAULT, NULL);
1221cb174861Sjoyce mcintosh list_create(&node->n_oplock.ol_grants, sizeof (smb_oplock_grant_t),
1222cb174861Sjoyce mcintosh offsetof(smb_oplock_grant_t, og_lnd));
12232c2961f8Sjose borrego rw_init(&node->n_lock, NULL, RW_DEFAULT, NULL);
12242c2961f8Sjose borrego mutex_init(&node->n_mutex, NULL, MUTEX_DEFAULT, NULL);
12252c2961f8Sjose borrego smb_node_create_audit_buf(node, kmflags);
12262c2961f8Sjose borrego return (0);
12272c2961f8Sjose borrego }
12282c2961f8Sjose borrego
12292c2961f8Sjose borrego /*
12302c2961f8Sjose borrego * smb_node_destructor
12312c2961f8Sjose borrego */
12322c2961f8Sjose borrego static void
smb_node_destructor(void * buf,void * un)12332c2961f8Sjose borrego smb_node_destructor(void *buf, void *un)
12342c2961f8Sjose borrego {
12352c2961f8Sjose borrego _NOTE(ARGUNUSED(un))
12362c2961f8Sjose borrego
12372c2961f8Sjose borrego smb_node_t *node = (smb_node_t *)buf;
12382c2961f8Sjose borrego
12392c2961f8Sjose borrego smb_node_destroy_audit_buf(node);
12402c2961f8Sjose borrego mutex_destroy(&node->n_mutex);
12412c2961f8Sjose borrego rw_destroy(&node->n_lock);
12422c2961f8Sjose borrego cv_destroy(&node->n_oplock.ol_cv);
1243cb174861Sjoyce mcintosh mutex_destroy(&node->n_oplock.ol_mutex);
1244ccc71be5SGordon Ross list_destroy(&node->n_fcn.fcn_watchers);
1245ccc71be5SGordon Ross mutex_destroy(&node->n_fcn.fcn_mutex);
12462c2961f8Sjose borrego smb_llist_destructor(&node->n_lock_list);
12472c2961f8Sjose borrego smb_llist_destructor(&node->n_ofile_list);
1248cb174861Sjoyce mcintosh list_destroy(&node->n_oplock.ol_grants);
12492c2961f8Sjose borrego }
12502c2961f8Sjose borrego
12512c2961f8Sjose borrego /*
12522c2961f8Sjose borrego * smb_node_create_audit_buf
12532c2961f8Sjose borrego */
12542c2961f8Sjose borrego static void
smb_node_create_audit_buf(smb_node_t * node,int kmflags)12552c2961f8Sjose borrego smb_node_create_audit_buf(smb_node_t *node, int kmflags)
12562c2961f8Sjose borrego {
12572c2961f8Sjose borrego smb_audit_buf_node_t *abn;
12582c2961f8Sjose borrego
12592c2961f8Sjose borrego if (smb_audit_flags & SMB_AUDIT_NODE) {
12602c2961f8Sjose borrego abn = kmem_zalloc(sizeof (smb_audit_buf_node_t), kmflags);
12612c2961f8Sjose borrego abn->anb_max_index = SMB_AUDIT_BUF_MAX_REC - 1;
12622c2961f8Sjose borrego node->n_audit_buf = abn;
12632c2961f8Sjose borrego }
12642c2961f8Sjose borrego }
12652c2961f8Sjose borrego
12662c2961f8Sjose borrego /*
12672c2961f8Sjose borrego * smb_node_destroy_audit_buf
12682c2961f8Sjose borrego */
12692c2961f8Sjose borrego static void
smb_node_destroy_audit_buf(smb_node_t * node)12702c2961f8Sjose borrego smb_node_destroy_audit_buf(smb_node_t *node)
12712c2961f8Sjose borrego {
12722c2961f8Sjose borrego if (node->n_audit_buf != NULL) {
12732c2961f8Sjose borrego kmem_free(node->n_audit_buf, sizeof (smb_audit_buf_node_t));
12742c2961f8Sjose borrego node->n_audit_buf = NULL;
12752c2961f8Sjose borrego }
12762c2961f8Sjose borrego }
12772c2961f8Sjose borrego
12782c2961f8Sjose borrego /*
12792c2961f8Sjose borrego * smb_node_audit
12802c2961f8Sjose borrego *
12812c2961f8Sjose borrego * This function saves the calling stack in the audit buffer of the node passed
12822c2961f8Sjose borrego * in.
12832c2961f8Sjose borrego */
12842c2961f8Sjose borrego static void
smb_node_audit(smb_node_t * node)12852c2961f8Sjose borrego smb_node_audit(smb_node_t *node)
12862c2961f8Sjose borrego {
1287*7206bf49SGordon Ross #ifdef _KERNEL
12882c2961f8Sjose borrego smb_audit_buf_node_t *abn;
12892c2961f8Sjose borrego smb_audit_record_node_t *anr;
12902c2961f8Sjose borrego
12912c2961f8Sjose borrego if (node->n_audit_buf) {
12922c2961f8Sjose borrego abn = node->n_audit_buf;
12932c2961f8Sjose borrego anr = abn->anb_records;
12942c2961f8Sjose borrego anr += abn->anb_index;
12952c2961f8Sjose borrego abn->anb_index++;
12962c2961f8Sjose borrego abn->anb_index &= abn->anb_max_index;
12972c2961f8Sjose borrego anr->anr_refcnt = node->n_refcnt;
12982c2961f8Sjose borrego anr->anr_depth = getpcstack(anr->anr_stack,
12992c2961f8Sjose borrego SMB_AUDIT_STACK_DEPTH);
13002c2961f8Sjose borrego }
1301*7206bf49SGordon Ross #else /* _KERNEL */
1302*7206bf49SGordon Ross _NOTE(ARGUNUSED(node))
1303*7206bf49SGordon Ross #endif /* _KERNEL */
13042c2961f8Sjose borrego }
13052c2961f8Sjose borrego
13062c2961f8Sjose borrego static smb_llist_t *
smb_node_get_hash(fsid_t * fsid,smb_attr_t * attr,uint32_t * phashkey)13072c2961f8Sjose borrego smb_node_get_hash(fsid_t *fsid, smb_attr_t *attr, uint32_t *phashkey)
13082c2961f8Sjose borrego {
13092c2961f8Sjose borrego uint32_t hashkey;
13102c2961f8Sjose borrego
13112c2961f8Sjose borrego hashkey = fsid->val[0] + attr->sa_vattr.va_nodeid;
13122c2961f8Sjose borrego hashkey += (hashkey >> 24) + (hashkey >> 16) + (hashkey >> 8);
13132c2961f8Sjose borrego *phashkey = hashkey;
13142c2961f8Sjose borrego return (&smb_node_hash_table[(hashkey & SMBND_HASH_MASK)]);
1315dc20a302Sas200622 }
1316037cac00Sjoyce mcintosh
1317037cac00Sjoyce mcintosh boolean_t
smb_node_is_file(smb_node_t * node)13189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_is_file(smb_node_t *node)
1319037cac00Sjoyce mcintosh {
1320037cac00Sjoyce mcintosh SMB_NODE_VALID(node);
13219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return (node->vp->v_type == VREG);
1322037cac00Sjoyce mcintosh }
1323037cac00Sjoyce mcintosh
1324037cac00Sjoyce mcintosh boolean_t
smb_node_is_dir(smb_node_t * node)13259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_is_dir(smb_node_t *node)
1326037cac00Sjoyce mcintosh {
1327037cac00Sjoyce mcintosh SMB_NODE_VALID(node);
13289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return ((node->vp->v_type == VDIR) ||
13299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (node->flags & NODE_FLAGS_DFSLINK));
13309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
13319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
13329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States boolean_t
smb_node_is_symlink(smb_node_t * node)13339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_is_symlink(smb_node_t *node)
13349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
13359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_NODE_VALID(node);
13369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return ((node->vp->v_type == VLNK) &&
13379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ((node->flags & NODE_FLAGS_REPARSE) == 0));
13389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
13399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
13409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States boolean_t
smb_node_is_dfslink(smb_node_t * node)13419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_is_dfslink(smb_node_t *node)
13429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
13439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_NODE_VALID(node);
13449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return ((node->vp->v_type == VLNK) &&
13459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (node->flags & NODE_FLAGS_DFSLINK));
13469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
13479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
13489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States boolean_t
smb_node_is_reparse(smb_node_t * node)13499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_is_reparse(smb_node_t *node)
13509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
13519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_NODE_VALID(node);
13529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return ((node->vp->v_type == VLNK) &&
13539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (node->flags & NODE_FLAGS_REPARSE));
13549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
13559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
13569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States boolean_t
smb_node_is_vfsroot(smb_node_t * node)13579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_is_vfsroot(smb_node_t *node)
13589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
13599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_NODE_VALID(node);
13609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return ((node->flags & NODE_FLAGS_VFSROOT) == NODE_FLAGS_VFSROOT);
13619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
13629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
13639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States boolean_t
smb_node_is_system(smb_node_t * node)13649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_is_system(smb_node_t *node)
13659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
13669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_NODE_VALID(node);
13679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return ((node->flags & NODE_FLAGS_SYSTEM) == NODE_FLAGS_SYSTEM);
1368037cac00Sjoyce mcintosh }
1369037cac00Sjoyce mcintosh
1370037cac00Sjoyce mcintosh /*
1371037cac00Sjoyce mcintosh * smb_node_file_is_readonly
1372037cac00Sjoyce mcintosh *
1373037cac00Sjoyce mcintosh * Checks if the file (which node represents) is marked readonly
1374037cac00Sjoyce mcintosh * in the filesystem. No account is taken of any pending readonly
1375037cac00Sjoyce mcintosh * in the node, which must be handled by the callers.
1376037cac00Sjoyce mcintosh * (See SMB_OFILE_IS_READONLY and SMB_PATHFILE_IS_READONLY)
1377037cac00Sjoyce mcintosh */
1378037cac00Sjoyce mcintosh boolean_t
smb_node_file_is_readonly(smb_node_t * node)1379037cac00Sjoyce mcintosh smb_node_file_is_readonly(smb_node_t *node)
1380037cac00Sjoyce mcintosh {
1381037cac00Sjoyce mcintosh smb_attr_t attr;
1382037cac00Sjoyce mcintosh
1383037cac00Sjoyce mcintosh if (node == NULL)
1384d6e098b6SGordon Ross return (B_FALSE); /* pipes */
1385d6e098b6SGordon Ross
1386d6e098b6SGordon Ross if (node->n_pending_dosattr & FILE_ATTRIBUTE_READONLY)
1387d6e098b6SGordon Ross return (B_TRUE);
1388037cac00Sjoyce mcintosh
1389037cac00Sjoyce mcintosh bzero(&attr, sizeof (smb_attr_t));
1390037cac00Sjoyce mcintosh attr.sa_mask = SMB_AT_DOSATTR;
1391ae240eb8SGordon Ross (void) smb_fsop_getattr(NULL, zone_kcred(), node, &attr);
1392037cac00Sjoyce mcintosh return ((attr.sa_dosattr & FILE_ATTRIBUTE_READONLY) != 0);
1393037cac00Sjoyce mcintosh }
1394037cac00Sjoyce mcintosh
1395037cac00Sjoyce mcintosh /*
1396037cac00Sjoyce mcintosh * smb_node_setattr
1397037cac00Sjoyce mcintosh *
1398037cac00Sjoyce mcintosh * The sr may be NULL, for example when closing an ofile.
1399037cac00Sjoyce mcintosh * The ofile may be NULL, for example when a client request
1400037cac00Sjoyce mcintosh * specifies the file by pathname.
1401037cac00Sjoyce mcintosh *
1402d6e098b6SGordon Ross * Returns: errno
1403d6e098b6SGordon Ross *
1404e3f2c991SKeyur Desai * Timestamps
1405037cac00Sjoyce mcintosh *
1406d6e098b6SGordon Ross * Windows and Unix have different models for timestamp updates.
1407d6e098b6SGordon Ross * [MS-FSA 2.1.5.14 Server Requests Setting of File Information]
1408037cac00Sjoyce mcintosh *
1409d6e098b6SGordon Ross * An open "handle" in Windows can control whether and when
1410d6e098b6SGordon Ross * any timestamp updates happen for that handle. For example,
1411d6e098b6SGordon Ross * timestamps set via some handle are no longer updated by I/O
1412d6e098b6SGordon Ross * operations on that handle. In Unix we don't really have any
1413d6e098b6SGordon Ross * way to avoid the timestamp updates that the file system does.
1414d6e098b6SGordon Ross * Therefore, we need to make some compromises, and simulate the
1415d6e098b6SGordon Ross * more important parts of the Windows file system semantics.
1416037cac00Sjoyce mcintosh *
1417d6e098b6SGordon Ross * For example, when an SMB client sets file times, set those
1418d6e098b6SGordon Ross * times in the file system (so the change will be visible to
1419d6e098b6SGordon Ross * other clients, at least until they change again) but we also
1420d6e098b6SGordon Ross * make those times "sticky" in our open handle, and reapply
1421d6e098b6SGordon Ross * those times when the handle is closed. That reapply on close
1422d6e098b6SGordon Ross * simulates the Windows behavior where the timestamp updates
1423d6e098b6SGordon Ross * would be discontinued after they were set. These "sticky"
1424d6e098b6SGordon Ross * attributes are returned in any query on the handle where
1425d6e098b6SGordon Ross * they are stored.
1426d6e098b6SGordon Ross *
1427d6e098b6SGordon Ross * Other than the above, the file system layer takes care of the
1428d6e098b6SGordon Ross * normal time stamp updates, such as updating the mtime after a
1429d6e098b6SGordon Ross * write, and ctime after an attribute change.
1430d6e098b6SGordon Ross *
1431d6e098b6SGordon Ross * Dos Attributes are stored persistently, but with a twist:
1432d6e098b6SGordon Ross * In Windows, when you set the "read-only" bit on some file,
1433d6e098b6SGordon Ross * existing writable handles to that file continue to have
1434d6e098b6SGordon Ross * write access. (because access check happens at open)
1435d6e098b6SGordon Ross * If we were to set the read-only bit directly, we would
1436d6e098b6SGordon Ross * cause errors in subsequent writes on any of our open
1437d6e098b6SGordon Ross * (and writable) file handles. So here too, we have to
1438d6e098b6SGordon Ross * simulate the Windows behavior. We keep the read-only
1439d6e098b6SGordon Ross * bit "pending" in the smb_node (so it will be visible in
1440d6e098b6SGordon Ross * any new opens of the file) and apply it on close.
1441d6e098b6SGordon Ross *
1442d6e098b6SGordon Ross * File allocation size is also simulated, and not persistent.
1443e3f2c991SKeyur Desai * When the file allocation size is set it is first rounded up
1444e3f2c991SKeyur Desai * to block size. If the file size is smaller than the allocation
1445e3f2c991SKeyur Desai * size the file is truncated by setting the filesize to allocsz.
1446037cac00Sjoyce mcintosh */
1447037cac00Sjoyce mcintosh int
smb_node_setattr(smb_request_t * sr,smb_node_t * node,cred_t * cr,smb_ofile_t * of,smb_attr_t * attr)1448037cac00Sjoyce mcintosh smb_node_setattr(smb_request_t *sr, smb_node_t *node,
1449037cac00Sjoyce mcintosh cred_t *cr, smb_ofile_t *of, smb_attr_t *attr)
1450037cac00Sjoyce mcintosh {
1451037cac00Sjoyce mcintosh int rc;
1452d6e098b6SGordon Ross uint_t times_mask;
1453e3f2c991SKeyur Desai smb_attr_t tmp_attr;
1454037cac00Sjoyce mcintosh
1455037cac00Sjoyce mcintosh SMB_NODE_VALID(node);
1456037cac00Sjoyce mcintosh
1457e3f2c991SKeyur Desai /* set attributes specified in attr */
1458d6e098b6SGordon Ross if (attr->sa_mask == 0)
1459d6e098b6SGordon Ross return (0); /* nothing to do (caller bug?) */
1460037cac00Sjoyce mcintosh
1461d6e098b6SGordon Ross /*
1462d6e098b6SGordon Ross * Allocation size and EOF position interact.
1463d6e098b6SGordon Ross * We don't persistently store the allocation size
1464d6e098b6SGordon Ross * but make it look like we do while there are opens.
1465d6e098b6SGordon Ross * Note: We update the caller's attr in the cases
1466d6e098b6SGordon Ross * where they're setting only one of allocsz|size.
1467d6e098b6SGordon Ross */
1468d6e098b6SGordon Ross switch (attr->sa_mask & (SMB_AT_ALLOCSZ | SMB_AT_SIZE)) {
1469d6e098b6SGordon Ross
1470d6e098b6SGordon Ross case SMB_AT_ALLOCSZ:
1471d6e098b6SGordon Ross /*
1472d6e098b6SGordon Ross * Setting the allocation size but not EOF position.
1473d6e098b6SGordon Ross * Get the current EOF in tmp_attr and (if necessary)
1474d6e098b6SGordon Ross * truncate to the (rounded up) allocation size.
1475ae240eb8SGordon Ross * Using kcred here because if we don't have access,
1476ae240eb8SGordon Ross * we want to fail at setattr below and not here.
1477d6e098b6SGordon Ross */
1478e3f2c991SKeyur Desai bzero(&tmp_attr, sizeof (smb_attr_t));
1479e3f2c991SKeyur Desai tmp_attr.sa_mask = SMB_AT_SIZE;
1480ae240eb8SGordon Ross rc = smb_fsop_getattr(NULL, zone_kcred(), node, &tmp_attr);
1481d6e098b6SGordon Ross if (rc != 0)
1482d6e098b6SGordon Ross return (rc);
1483d6e098b6SGordon Ross attr->sa_allocsz = SMB_ALLOCSZ(attr->sa_allocsz);
1484e3f2c991SKeyur Desai if (tmp_attr.sa_vattr.va_size > attr->sa_allocsz) {
1485d6e098b6SGordon Ross /* truncate the file to allocsz */
1486e3f2c991SKeyur Desai attr->sa_vattr.va_size = attr->sa_allocsz;
1487e3f2c991SKeyur Desai attr->sa_mask |= SMB_AT_SIZE;
1488037cac00Sjoyce mcintosh }
1489d6e098b6SGordon Ross break;
1490037cac00Sjoyce mcintosh
1491d6e098b6SGordon Ross case SMB_AT_SIZE:
1492d6e098b6SGordon Ross /*
1493d6e098b6SGordon Ross * Setting the EOF position but not allocation size.
1494d6e098b6SGordon Ross * If the new EOF position would be greater than
1495d6e098b6SGordon Ross * the allocation size, increase the latter.
1496d6e098b6SGordon Ross */
1497d6e098b6SGordon Ross if (node->n_allocsz < attr->sa_vattr.va_size) {
1498d6e098b6SGordon Ross attr->sa_mask |= SMB_AT_ALLOCSZ;
1499d6e098b6SGordon Ross attr->sa_allocsz =
1500d6e098b6SGordon Ross SMB_ALLOCSZ(attr->sa_vattr.va_size);
1501e3f2c991SKeyur Desai }
1502d6e098b6SGordon Ross break;
1503d6e098b6SGordon Ross
1504d6e098b6SGordon Ross case SMB_AT_ALLOCSZ | SMB_AT_SIZE:
1505d6e098b6SGordon Ross /*
1506d6e098b6SGordon Ross * Setting both. Increase alloc size if needed.
1507d6e098b6SGordon Ross */
1508d6e098b6SGordon Ross if (attr->sa_allocsz < attr->sa_vattr.va_size)
1509d6e098b6SGordon Ross attr->sa_allocsz =
1510d6e098b6SGordon Ross SMB_ALLOCSZ(attr->sa_vattr.va_size);
1511d6e098b6SGordon Ross break;
1512d6e098b6SGordon Ross
1513d6e098b6SGordon Ross default:
1514d6e098b6SGordon Ross break;
1515e3f2c991SKeyur Desai }
1516037cac00Sjoyce mcintosh
1517e3f2c991SKeyur Desai /*
1518d6e098b6SGordon Ross * If we have an open file, and we set the size,
1519d6e098b6SGordon Ross * then set the "written" flag so that at close,
1520d6e098b6SGordon Ross * we can force an mtime update.
1521e3f2c991SKeyur Desai */
1522d6e098b6SGordon Ross if (of != NULL && (attr->sa_mask & SMB_AT_SIZE) != 0)
1523d6e098b6SGordon Ross of->f_written = B_TRUE;
1524e3f2c991SKeyur Desai
1525d6e098b6SGordon Ross /*
1526d6e098b6SGordon Ross * When operating on an open file, some settable attributes
1527d6e098b6SGordon Ross * become "sticky" in the open file object until close.
1528d6e098b6SGordon Ross * (see above re. timestamps)
1529d6e098b6SGordon Ross */
1530d6e098b6SGordon Ross times_mask = attr->sa_mask & SMB_AT_TIMES;
1531d6e098b6SGordon Ross if (of != NULL && times_mask != 0) {
1532d6e098b6SGordon Ross smb_attr_t *pa;
1533e3f2c991SKeyur Desai
1534d6e098b6SGordon Ross SMB_OFILE_VALID(of);
1535d6e098b6SGordon Ross mutex_enter(&of->f_mutex);
1536d6e098b6SGordon Ross pa = &of->f_pending_attr;
1537d6e098b6SGordon Ross
1538d6e098b6SGordon Ross pa->sa_mask |= times_mask;
1539d6e098b6SGordon Ross
1540d6e098b6SGordon Ross if (times_mask & SMB_AT_ATIME)
1541d6e098b6SGordon Ross pa->sa_vattr.va_atime =
1542d6e098b6SGordon Ross attr->sa_vattr.va_atime;
1543d6e098b6SGordon Ross if (times_mask & SMB_AT_MTIME)
1544d6e098b6SGordon Ross pa->sa_vattr.va_mtime =
1545d6e098b6SGordon Ross attr->sa_vattr.va_mtime;
1546d6e098b6SGordon Ross if (times_mask & SMB_AT_CTIME)
1547d6e098b6SGordon Ross pa->sa_vattr.va_ctime =
1548d6e098b6SGordon Ross attr->sa_vattr.va_ctime;
1549d6e098b6SGordon Ross if (times_mask & SMB_AT_CRTIME)
1550d6e098b6SGordon Ross pa->sa_crtime =
1551d6e098b6SGordon Ross attr->sa_crtime;
1552d6e098b6SGordon Ross
1553d6e098b6SGordon Ross mutex_exit(&of->f_mutex);
1554d6e098b6SGordon Ross /*
1555d6e098b6SGordon Ross * The f_pending_attr times are reapplied in
1556d6e098b6SGordon Ross * smb_ofile_close().
1557d6e098b6SGordon Ross */
1558e3f2c991SKeyur Desai }
1559e3f2c991SKeyur Desai
1560d6e098b6SGordon Ross /*
1561d6e098b6SGordon Ross * After this point, tmp_attr is what we will actually
1562d6e098b6SGordon Ross * store in the file system _now_, which may differ
1563d6e098b6SGordon Ross * from the callers attr and f_pending_attr w.r.t.
1564d6e098b6SGordon Ross * the DOS readonly flag etc.
1565d6e098b6SGordon Ross */
1566d6e098b6SGordon Ross bcopy(attr, &tmp_attr, sizeof (tmp_attr));
1567d6e098b6SGordon Ross if (attr->sa_mask & (SMB_AT_DOSATTR | SMB_AT_ALLOCSZ)) {
1568d6e098b6SGordon Ross mutex_enter(&node->n_mutex);
1569d6e098b6SGordon Ross if ((attr->sa_mask & SMB_AT_DOSATTR) != 0) {
1570d6e098b6SGordon Ross tmp_attr.sa_dosattr &= smb_vop_dosattr_settable;
1571d6e098b6SGordon Ross if (((tmp_attr.sa_dosattr &
1572d6e098b6SGordon Ross FILE_ATTRIBUTE_READONLY) != 0) &&
1573d6e098b6SGordon Ross (node->n_open_count != 0)) {
1574d6e098b6SGordon Ross /* Delay setting readonly */
1575d6e098b6SGordon Ross node->n_pending_dosattr =
1576d6e098b6SGordon Ross tmp_attr.sa_dosattr;
1577d6e098b6SGordon Ross tmp_attr.sa_dosattr &=
1578d6e098b6SGordon Ross ~FILE_ATTRIBUTE_READONLY;
1579d6e098b6SGordon Ross } else {
1580d6e098b6SGordon Ross node->n_pending_dosattr = 0;
1581d6e098b6SGordon Ross }
1582d6e098b6SGordon Ross }
1583d6e098b6SGordon Ross /*
1584d6e098b6SGordon Ross * Simulate n_allocsz persistence only while
1585d6e098b6SGordon Ross * there are opens. See smb_node_getattr
1586d6e098b6SGordon Ross */
1587d6e098b6SGordon Ross if ((attr->sa_mask & SMB_AT_ALLOCSZ) != 0 &&
1588d6e098b6SGordon Ross node->n_open_count != 0)
1589d6e098b6SGordon Ross node->n_allocsz = attr->sa_allocsz;
1590d6e098b6SGordon Ross mutex_exit(&node->n_mutex);
1591d6e098b6SGordon Ross }
1592e3f2c991SKeyur Desai
1593d6e098b6SGordon Ross rc = smb_fsop_setattr(sr, cr, node, &tmp_attr);
1594d6e098b6SGordon Ross if (rc != 0)
1595d6e098b6SGordon Ross return (rc);
1596037cac00Sjoyce mcintosh
1597ccc71be5SGordon Ross if (node->n_dnode != NULL) {
1598ccc71be5SGordon Ross smb_node_notify_change(node->n_dnode,
1599ccc71be5SGordon Ross FILE_ACTION_MODIFIED, node->od_name);
1600ccc71be5SGordon Ross }
1601fe1c642dSBill Krier
1602037cac00Sjoyce mcintosh return (0);
1603037cac00Sjoyce mcintosh }
1604037cac00Sjoyce mcintosh
1605037cac00Sjoyce mcintosh /*
1606037cac00Sjoyce mcintosh * smb_node_getattr
1607037cac00Sjoyce mcintosh *
1608037cac00Sjoyce mcintosh * Get attributes from the file system and apply any smb-specific
1609037cac00Sjoyce mcintosh * overrides for size, dos attributes and timestamps
1610037cac00Sjoyce mcintosh *
1611d6e098b6SGordon Ross * When node->n_pending_readonly is set on a node, pretend that
1612d6e098b6SGordon Ross * we've already set this node readonly at the filesystem level.
1613d6e098b6SGordon Ross * We can't actually do that until all writable handles are closed
1614d6e098b6SGordon Ross * or those writable handles would suddenly loose their access.
1615037cac00Sjoyce mcintosh *
1616037cac00Sjoyce mcintosh * Returns: errno
1617037cac00Sjoyce mcintosh */
1618037cac00Sjoyce mcintosh int
smb_node_getattr(smb_request_t * sr,smb_node_t * node,cred_t * cr,smb_ofile_t * of,smb_attr_t * attr)1619d6e098b6SGordon Ross smb_node_getattr(smb_request_t *sr, smb_node_t *node, cred_t *cr,
1620d6e098b6SGordon Ross smb_ofile_t *of, smb_attr_t *attr)
1621037cac00Sjoyce mcintosh {
1622037cac00Sjoyce mcintosh int rc;
1623d6e098b6SGordon Ross uint_t want_mask, pend_mask;
1624d6e098b6SGordon Ross boolean_t isdir;
1625037cac00Sjoyce mcintosh
1626037cac00Sjoyce mcintosh SMB_NODE_VALID(node);
1627037cac00Sjoyce mcintosh
1628d6e098b6SGordon Ross /* Deal with some interdependencies */
1629d6e098b6SGordon Ross if (attr->sa_mask & SMB_AT_ALLOCSZ)
1630d6e098b6SGordon Ross attr->sa_mask |= SMB_AT_SIZE;
1631d6e098b6SGordon Ross if (attr->sa_mask & SMB_AT_DOSATTR)
1632d6e098b6SGordon Ross attr->sa_mask |= SMB_AT_TYPE;
1633d6e098b6SGordon Ross
1634d6e098b6SGordon Ross rc = smb_fsop_getattr(sr, cr, node, attr);
1635037cac00Sjoyce mcintosh if (rc != 0)
1636037cac00Sjoyce mcintosh return (rc);
1637037cac00Sjoyce mcintosh
1638d6e098b6SGordon Ross isdir = smb_node_is_dir(node);
1639d6e098b6SGordon Ross
1640037cac00Sjoyce mcintosh mutex_enter(&node->n_mutex);
1641037cac00Sjoyce mcintosh
1642d6e098b6SGordon Ross /*
1643d6e098b6SGordon Ross * When there are open handles, and one of them has
1644d6e098b6SGordon Ross * set the DOS readonly flag (in n_pending_dosattr),
1645d6e098b6SGordon Ross * it will not have been stored in the file system.
1646d6e098b6SGordon Ross * In this case use n_pending_dosattr. Note that
1647d6e098b6SGordon Ross * n_pending_dosattr has only the settable bits,
1648d6e098b6SGordon Ross * (setattr masks it with smb_vop_dosattr_settable)
1649d6e098b6SGordon Ross * so we need to keep any non-settable bits we got
1650d6e098b6SGordon Ross * from the file-system above.
1651d6e098b6SGordon Ross */
1652d6e098b6SGordon Ross if (attr->sa_mask & SMB_AT_DOSATTR) {
1653d6e098b6SGordon Ross if (node->n_pending_dosattr) {
1654d6e098b6SGordon Ross attr->sa_dosattr &= ~smb_vop_dosattr_settable;
1655d6e098b6SGordon Ross attr->sa_dosattr |= node->n_pending_dosattr;
1656d6e098b6SGordon Ross }
1657d6e098b6SGordon Ross if (attr->sa_dosattr == 0) {
1658d6e098b6SGordon Ross attr->sa_dosattr = (isdir) ?
1659d6e098b6SGordon Ross FILE_ATTRIBUTE_DIRECTORY:
1660d6e098b6SGordon Ross FILE_ATTRIBUTE_NORMAL;
1661d6e098b6SGordon Ross }
1662e3f2c991SKeyur Desai }
1663037cac00Sjoyce mcintosh
1664d6e098b6SGordon Ross /*
1665d6e098b6SGordon Ross * Also fix-up sa_allocsz, which is not persistent.
1666d6e098b6SGordon Ross * When there are no open files, allocsz is faked.
1667d6e098b6SGordon Ross * While there are open files, we pretend we have a
1668d6e098b6SGordon Ross * persistent allocation size in n_allocsz, and
1669d6e098b6SGordon Ross * keep that up-to-date here, increasing it when
1670d6e098b6SGordon Ross * we see the file size grow past it.
1671d6e098b6SGordon Ross */
1672d6e098b6SGordon Ross if (attr->sa_mask & SMB_AT_ALLOCSZ) {
1673d6e098b6SGordon Ross if (isdir) {
1674d6e098b6SGordon Ross attr->sa_allocsz = 0;
1675d6e098b6SGordon Ross } else if (node->n_open_count == 0) {
1676d6e098b6SGordon Ross attr->sa_allocsz =
1677d6e098b6SGordon Ross SMB_ALLOCSZ(attr->sa_vattr.va_size);
1678d6e098b6SGordon Ross } else {
1679d6e098b6SGordon Ross if (node->n_allocsz < attr->sa_vattr.va_size)
1680d6e098b6SGordon Ross node->n_allocsz =
1681d6e098b6SGordon Ross SMB_ALLOCSZ(attr->sa_vattr.va_size);
1682d6e098b6SGordon Ross attr->sa_allocsz = node->n_allocsz;
1683d6e098b6SGordon Ross }
1684d6e098b6SGordon Ross }
1685e3f2c991SKeyur Desai
1686037cac00Sjoyce mcintosh mutex_exit(&node->n_mutex);
1687037cac00Sjoyce mcintosh
1688d6e098b6SGordon Ross if (isdir) {
1689d6e098b6SGordon Ross attr->sa_vattr.va_size = 0;
1690d6e098b6SGordon Ross attr->sa_vattr.va_nlink = 1;
1691d6e098b6SGordon Ross }
1692d6e098b6SGordon Ross
1693d6e098b6SGordon Ross /*
1694d6e098b6SGordon Ross * getattr with an ofile gets any "pending" times that
1695d6e098b6SGordon Ross * might have been previously set via this ofile.
1696d6e098b6SGordon Ross * This is what makes these times "sticky".
1697d6e098b6SGordon Ross */
1698d6e098b6SGordon Ross want_mask = attr->sa_mask & SMB_AT_TIMES;
1699d6e098b6SGordon Ross if (of != NULL && want_mask != 0) {
1700d6e098b6SGordon Ross smb_attr_t *pa;
1701d6e098b6SGordon Ross
1702d6e098b6SGordon Ross SMB_OFILE_VALID(of);
1703d6e098b6SGordon Ross mutex_enter(&of->f_mutex);
1704d6e098b6SGordon Ross pa = &of->f_pending_attr;
1705d6e098b6SGordon Ross
1706d6e098b6SGordon Ross pend_mask = pa->sa_mask;
1707d6e098b6SGordon Ross
1708d6e098b6SGordon Ross if (want_mask & pend_mask & SMB_AT_ATIME)
1709d6e098b6SGordon Ross attr->sa_vattr.va_atime =
1710d6e098b6SGordon Ross pa->sa_vattr.va_atime;
1711d6e098b6SGordon Ross if (want_mask & pend_mask & SMB_AT_MTIME)
1712d6e098b6SGordon Ross attr->sa_vattr.va_mtime =
1713d6e098b6SGordon Ross pa->sa_vattr.va_mtime;
1714d6e098b6SGordon Ross if (want_mask & pend_mask & SMB_AT_CTIME)
1715d6e098b6SGordon Ross attr->sa_vattr.va_ctime =
1716d6e098b6SGordon Ross pa->sa_vattr.va_ctime;
1717d6e098b6SGordon Ross if (want_mask & pend_mask & SMB_AT_CRTIME)
1718d6e098b6SGordon Ross attr->sa_crtime =
1719d6e098b6SGordon Ross pa->sa_crtime;
1720d6e098b6SGordon Ross
1721d6e098b6SGordon Ross mutex_exit(&of->f_mutex);
1722d6e098b6SGordon Ross }
1723d6e098b6SGordon Ross
1724e3f2c991SKeyur Desai
1725037cac00Sjoyce mcintosh return (0);
1726037cac00Sjoyce mcintosh }
1727037cac00Sjoyce mcintosh
17289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
1729*7206bf49SGordon Ross #ifndef _KERNEL
1730*7206bf49SGordon Ross extern int reparse_vnode_parse(vnode_t *vp, nvlist_t *nvl);
1731*7206bf49SGordon Ross #endif /* _KERNEL */
1732*7206bf49SGordon Ross
17339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
17349fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Check to see if the node represents a reparse point.
17359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * If yes, whether the reparse point contains a DFS link.
17369fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */
17379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
smb_node_init_reparse(smb_node_t * node,smb_attr_t * attr)17389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_init_reparse(smb_node_t *node, smb_attr_t *attr)
17399fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
17409fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States nvlist_t *nvl;
17419fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States nvpair_t *rec;
17429fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States char *rec_type;
17439fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
17449fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((attr->sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
17459fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return;
17469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
17479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((nvl = reparse_init()) == NULL)
17489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return;
17499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
17509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (reparse_vnode_parse(node->vp, nvl) != 0) {
17519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States reparse_free(nvl);
17529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return;
17539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
17549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
17559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States node->flags |= NODE_FLAGS_REPARSE;
17569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
17579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rec = nvlist_next_nvpair(nvl, NULL);
17589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States while (rec != NULL) {
17599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rec_type = nvpair_name(rec);
17609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((rec_type != NULL) &&
17619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (strcasecmp(rec_type, DFS_REPARSE_SVCTYPE) == 0)) {
17629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States node->flags |= NODE_FLAGS_DFSLINK;
17639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break;
17649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
17659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rec = nvlist_next_nvpair(nvl, rec);
17669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
17679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
17689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States reparse_free(nvl);
17699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
17709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
17719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
17729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * smb_node_init_system
17739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States *
17749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * If the node represents a special system file set NODE_FLAG_SYSTEM.
17759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * System files:
17769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * - any node whose parent dnode has NODE_FLAG_SYSTEM set
17779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * - any node whose associated unnamed stream node (unode) has
17789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * NODE_FLAG_SYSTEM set
17799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * - .$EXTEND at root of share (quota management)
17809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */
17819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void
smb_node_init_system(smb_node_t * node)17829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_init_system(smb_node_t *node)
17839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
17849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_t *dnode = node->n_dnode;
17859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_node_t *unode = node->n_unode;
17869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
17879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((dnode) && (dnode->flags & NODE_FLAGS_SYSTEM)) {
17889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States node->flags |= NODE_FLAGS_SYSTEM;
17899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return;
17909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
17919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
17929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((unode) && (unode->flags & NODE_FLAGS_SYSTEM)) {
17939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States node->flags |= NODE_FLAGS_SYSTEM;
17949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return;
17959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
17969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
17979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((dnode) && (smb_node_is_vfsroot(node->n_dnode) &&
17989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (strcasecmp(node->od_name, ".$EXTEND") == 0))) {
17999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States node->flags |= NODE_FLAGS_SYSTEM;
18009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
18019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
1802