xref: /titanic_44/usr/src/uts/common/fs/smbsrv/smb_vfs.c (revision b819cea2f73f98c5662230cc9affc8cc84f77fcf)
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