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 /*
22148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23*b819cea2SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
24da6c28aaSamw */
25da6c28aaSamw
26da6c28aaSamw #include <sys/vfs.h>
27c8ec8eeaSjose borrego #include <smbsrv/smb_ktypes.h>
28c8ec8eeaSjose borrego #include <smbsrv/smb_kproto.h>
29da6c28aaSamw
30148c5f43SAlan Wright static smb_vfs_t *smb_vfs_find(smb_export_t *, vfs_t *);
318622ec45SGordon Ross static void smb_vfs_destroy(smb_vfs_t *);
32da6c28aaSamw
33da6c28aaSamw /*
34148c5f43SAlan Wright * If a hold on the specified VFS has already been taken
35148c5f43SAlan Wright * then only increment the reference count of the corresponding
36148c5f43SAlan Wright * smb_vfs_t structure. If no smb_vfs_t structure has been created
37148c5f43SAlan Wright * yet for the specified VFS then create one and take a hold on
38148c5f43SAlan Wright * the VFS.
39da6c28aaSamw */
40148c5f43SAlan Wright int
smb_vfs_hold(smb_export_t * se,vfs_t * vfsp)41148c5f43SAlan Wright smb_vfs_hold(smb_export_t *se, vfs_t *vfsp)
42da6c28aaSamw {
43da6c28aaSamw smb_vfs_t *smb_vfs;
44da6c28aaSamw vnode_t *rootvp;
45148c5f43SAlan Wright int rc;
46da6c28aaSamw
47148c5f43SAlan Wright if (se == NULL || vfsp == NULL)
48148c5f43SAlan Wright return (EINVAL);
49da6c28aaSamw
50148c5f43SAlan Wright smb_llist_enter(&se->e_vfs_list, RW_WRITER);
51148c5f43SAlan Wright
52148c5f43SAlan Wright if ((smb_vfs = smb_vfs_find(se, vfsp)) != NULL) {
53148c5f43SAlan Wright smb_vfs->sv_refcnt++;
54da6c28aaSamw DTRACE_PROBE1(smb_vfs_hold_hit, smb_vfs_t *, smb_vfs);
55148c5f43SAlan Wright smb_llist_exit(&se->e_vfs_list);
56148c5f43SAlan Wright return (0);
57da6c28aaSamw }
58148c5f43SAlan Wright
59148c5f43SAlan Wright if ((rc = VFS_ROOT(vfsp, &rootvp)) != 0) {
60148c5f43SAlan Wright smb_llist_exit(&se->e_vfs_list);
61148c5f43SAlan Wright return (rc);
62148c5f43SAlan Wright }
63148c5f43SAlan Wright
648622ec45SGordon Ross smb_vfs = kmem_cache_alloc(smb_kshare_cache_vfs, KM_SLEEP);
65da6c28aaSamw
66da6c28aaSamw bzero(smb_vfs, sizeof (smb_vfs_t));
67da6c28aaSamw
68da6c28aaSamw smb_vfs->sv_magic = SMB_VFS_MAGIC;
69da6c28aaSamw smb_vfs->sv_refcnt = 1;
70da6c28aaSamw smb_vfs->sv_vfsp = vfsp;
71da6c28aaSamw /*
72da6c28aaSamw * We have a hold on the root vnode of the file system
73da6c28aaSamw * from the VFS_ROOT call above.
74da6c28aaSamw */
75da6c28aaSamw smb_vfs->sv_rootvp = rootvp;
76148c5f43SAlan Wright
77148c5f43SAlan Wright smb_llist_insert_head(&se->e_vfs_list, smb_vfs);
78da6c28aaSamw DTRACE_PROBE1(smb_vfs_hold_miss, smb_vfs_t *, smb_vfs);
79148c5f43SAlan Wright smb_llist_exit(&se->e_vfs_list);
80148c5f43SAlan Wright
81148c5f43SAlan Wright return (0);
82da6c28aaSamw }
83da6c28aaSamw
84da6c28aaSamw /*
85da6c28aaSamw * smb_vfs_rele
86da6c28aaSamw *
87da6c28aaSamw * Decrements the reference count of the fs passed in. If the reference count
88da6c28aaSamw * drops to zero the smb_vfs_t structure associated with the fs is freed.
89da6c28aaSamw */
90da6c28aaSamw void
smb_vfs_rele(smb_export_t * se,vfs_t * vfsp)91148c5f43SAlan Wright smb_vfs_rele(smb_export_t *se, vfs_t *vfsp)
92da6c28aaSamw {
93da6c28aaSamw smb_vfs_t *smb_vfs;
94da6c28aaSamw
95da6c28aaSamw ASSERT(vfsp);
96da6c28aaSamw
97148c5f43SAlan Wright smb_llist_enter(&se->e_vfs_list, RW_WRITER);
98148c5f43SAlan Wright smb_vfs = smb_vfs_find(se, vfsp);
99*b819cea2SGordon Ross DTRACE_PROBE1(smb_vfs_release, smb_vfs_t *, smb_vfs);
100da6c28aaSamw if (smb_vfs) {
101da6c28aaSamw ASSERT(smb_vfs->sv_refcnt);
102da6c28aaSamw if (--smb_vfs->sv_refcnt == 0) {
103148c5f43SAlan Wright smb_llist_remove(&se->e_vfs_list, smb_vfs);
104148c5f43SAlan Wright smb_llist_exit(&se->e_vfs_list);
1058622ec45SGordon Ross smb_vfs_destroy(smb_vfs);
106da6c28aaSamw return;
107da6c28aaSamw }
108da6c28aaSamw }
109148c5f43SAlan Wright smb_llist_exit(&se->e_vfs_list);
110da6c28aaSamw }
111da6c28aaSamw
112da6c28aaSamw /*
113da6c28aaSamw * smb_vfs_rele_all()
114da6c28aaSamw *
115da6c28aaSamw * Release all holds on root vnodes of file systems which were taken
116da6c28aaSamw * due to the existence of at least one enabled share on the file system.
117da6c28aaSamw * Called at driver close time.
118da6c28aaSamw */
119da6c28aaSamw void
smb_vfs_rele_all(smb_export_t * se)120148c5f43SAlan Wright smb_vfs_rele_all(smb_export_t *se)
121da6c28aaSamw {
122da6c28aaSamw smb_vfs_t *smb_vfs;
123da6c28aaSamw
124148c5f43SAlan Wright smb_llist_enter(&se->e_vfs_list, RW_WRITER);
125148c5f43SAlan Wright while ((smb_vfs = smb_llist_head(&se->e_vfs_list)) != NULL) {
126da6c28aaSamw
127da6c28aaSamw ASSERT(smb_vfs->sv_magic == SMB_VFS_MAGIC);
128da6c28aaSamw DTRACE_PROBE1(smb_vfs_rele_all_hit, smb_vfs_t *, smb_vfs);
129148c5f43SAlan Wright smb_llist_remove(&se->e_vfs_list, smb_vfs);
1308622ec45SGordon Ross smb_vfs_destroy(smb_vfs);
131da6c28aaSamw }
132148c5f43SAlan Wright smb_llist_exit(&se->e_vfs_list);
133da6c28aaSamw }
134da6c28aaSamw
135da6c28aaSamw /*
136da6c28aaSamw * Goes through the list of smb_vfs_t structure and returns the one matching
137da6c28aaSamw * the vnode passed in. If no match is found a NULL pointer is returned.
138da6c28aaSamw *
139da6c28aaSamw * The list of smb_vfs_t structures has to have been entered prior calling
140da6c28aaSamw * this function.
141da6c28aaSamw */
142da6c28aaSamw static smb_vfs_t *
smb_vfs_find(smb_export_t * se,vfs_t * vfsp)143148c5f43SAlan Wright smb_vfs_find(smb_export_t *se, vfs_t *vfsp)
144da6c28aaSamw {
145da6c28aaSamw smb_vfs_t *smb_vfs;
146da6c28aaSamw
147148c5f43SAlan Wright smb_vfs = smb_llist_head(&se->e_vfs_list);
148da6c28aaSamw while (smb_vfs) {
149da6c28aaSamw ASSERT(smb_vfs->sv_magic == SMB_VFS_MAGIC);
150148c5f43SAlan Wright if (smb_vfs->sv_vfsp == vfsp)
151da6c28aaSamw return (smb_vfs);
152148c5f43SAlan Wright smb_vfs = smb_llist_next(&se->e_vfs_list, smb_vfs);
153da6c28aaSamw }
154148c5f43SAlan Wright
155da6c28aaSamw return (NULL);
156da6c28aaSamw }
157c8ec8eeaSjose borrego
158148c5f43SAlan Wright static void
smb_vfs_destroy(smb_vfs_t * smb_vfs)1598622ec45SGordon Ross smb_vfs_destroy(smb_vfs_t *smb_vfs)
160c8ec8eeaSjose borrego {
161148c5f43SAlan Wright VN_RELE(smb_vfs->sv_rootvp);
162148c5f43SAlan Wright smb_vfs->sv_magic = (uint32_t)~SMB_VFS_MAGIC;
1638622ec45SGordon Ross kmem_cache_free(smb_kshare_cache_vfs, smb_vfs);
164c8ec8eeaSjose borrego }
165