xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_vfs.c (revision 7348:73b61202d5d6)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
226139Sjb150015  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
26*7348SJose.Borrego@Sun.COM #pragma ident	"@(#)smb_vfs.c	1.3	08/08/07 SMI"
275331Samw 
28*7348SJose.Borrego@Sun.COM #include <sys/types.h>
29*7348SJose.Borrego@Sun.COM #include <sys/fsid.h>
305331Samw #include <sys/vfs.h>
31*7348SJose.Borrego@Sun.COM #include <sys/stat.h>
32*7348SJose.Borrego@Sun.COM #include <smbsrv/smb_ktypes.h>
33*7348SJose.Borrego@Sun.COM #include <smbsrv/smb_kproto.h>
34*7348SJose.Borrego@Sun.COM #include <smbsrv/string.h>
355331Samw 
366139Sjb150015 static smb_vfs_t *smb_vfs_lookup(smb_server_t *, vnode_t *);
375331Samw 
385331Samw /*
395331Samw  * smb_vfs_hold
405331Samw  *
415331Samw  * Increments the reference count of the fs passed in. If no smb_vfs_t structure
425331Samw  * has been created yet for the fs passed in it is created.
435331Samw  */
445331Samw boolean_t
456139Sjb150015 smb_vfs_hold(smb_server_t *sv, vfs_t *vfsp)
465331Samw {
475331Samw 	smb_vfs_t	*smb_vfs;
485331Samw 	vnode_t 	*rootvp;
495331Samw 
505331Samw 	if ((vfsp == NULL) || VFS_ROOT(vfsp, &rootvp))
515331Samw 		return (B_FALSE);
525331Samw 
536139Sjb150015 	smb_llist_enter(&sv->sv_vfs_list, RW_WRITER);
546139Sjb150015 	smb_vfs = smb_vfs_lookup(sv, rootvp);
555331Samw 	if (smb_vfs) {
565331Samw 		DTRACE_PROBE1(smb_vfs_hold_hit, smb_vfs_t *, smb_vfs);
576139Sjb150015 		smb_llist_exit(&sv->sv_vfs_list);
585331Samw 		VN_RELE(rootvp);
595331Samw 		return (B_TRUE);
605331Samw 	}
616139Sjb150015 	smb_vfs = kmem_cache_alloc(sv->si_cache_vfs, KM_SLEEP);
625331Samw 
635331Samw 	bzero(smb_vfs, sizeof (smb_vfs_t));
645331Samw 
655331Samw 	smb_vfs->sv_magic = SMB_VFS_MAGIC;
665331Samw 	smb_vfs->sv_refcnt = 1;
675331Samw 	smb_vfs->sv_vfsp = vfsp;
685331Samw 	/*
695331Samw 	 * We have a hold on the root vnode of the file system
705331Samw 	 * from the VFS_ROOT call above.
715331Samw 	 */
725331Samw 	smb_vfs->sv_rootvp = rootvp;
736139Sjb150015 	smb_llist_insert_head(&sv->sv_vfs_list, smb_vfs);
745331Samw 	DTRACE_PROBE1(smb_vfs_hold_miss, smb_vfs_t *, smb_vfs);
756139Sjb150015 	smb_llist_exit(&sv->sv_vfs_list);
765331Samw 	return (B_TRUE);
775331Samw }
785331Samw 
795331Samw /*
805331Samw  * smb_vfs_rele
815331Samw  *
825331Samw  * Decrements the reference count of the fs passed in. If the reference count
835331Samw  * drops to zero the smb_vfs_t structure associated with the fs is freed.
845331Samw  */
855331Samw void
866139Sjb150015 smb_vfs_rele(smb_server_t *sv, vfs_t *vfsp)
875331Samw {
885331Samw 	smb_vfs_t	*smb_vfs;
895331Samw 	vnode_t		*rootvp;
905331Samw 
915331Samw 	ASSERT(vfsp);
925331Samw 
935331Samw 	if (VFS_ROOT(vfsp, &rootvp))
945331Samw 		return;
955331Samw 
966139Sjb150015 	smb_llist_enter(&sv->sv_vfs_list, RW_WRITER);
976139Sjb150015 	smb_vfs = smb_vfs_lookup(sv, rootvp);
985331Samw 	DTRACE_PROBE2(smb_vfs_release, smb_vfs_t *, smb_vfs, vnode_t *, rootvp);
995331Samw 	VN_RELE(rootvp);
1005331Samw 	if (smb_vfs) {
1015331Samw 		--smb_vfs->sv_refcnt;
1025331Samw 		ASSERT(smb_vfs->sv_refcnt);
1035331Samw 		if (--smb_vfs->sv_refcnt == 0) {
1046139Sjb150015 			smb_llist_remove(&sv->sv_vfs_list, smb_vfs);
1056139Sjb150015 			smb_llist_exit(&sv->sv_vfs_list);
1065331Samw 			ASSERT(rootvp == smb_vfs->sv_rootvp);
1075331Samw 			VN_RELE(smb_vfs->sv_rootvp);
1085331Samw 			smb_vfs->sv_magic = (uint32_t)~SMB_VFS_MAGIC;
1096139Sjb150015 			kmem_cache_free(sv->si_cache_vfs, smb_vfs);
1105331Samw 			return;
1115331Samw 		}
1125331Samw 	}
1136139Sjb150015 	smb_llist_exit(&sv->sv_vfs_list);
1145331Samw }
1155331Samw 
1165331Samw /*
1175331Samw  * smb_vfs_rele_all()
1185331Samw  *
1195331Samw  * Release all holds on root vnodes of file systems which were taken
1205331Samw  * due to the existence of at least one enabled share on the file system.
1215331Samw  * Called at driver close time.
1225331Samw  */
1235331Samw void
1246139Sjb150015 smb_vfs_rele_all(smb_server_t *sv)
1255331Samw {
1265331Samw 	smb_vfs_t	*smb_vfs;
1275331Samw 
1286139Sjb150015 	smb_llist_enter(&sv->sv_vfs_list, RW_WRITER);
1296139Sjb150015 	while ((smb_vfs = smb_llist_head(&sv->sv_vfs_list)) != NULL) {
1305331Samw 
1315331Samw 		ASSERT(smb_vfs->sv_magic == SMB_VFS_MAGIC);
1325331Samw 		DTRACE_PROBE1(smb_vfs_rele_all_hit, smb_vfs_t *, smb_vfs);
1336139Sjb150015 		smb_llist_remove(&sv->sv_vfs_list, smb_vfs);
1345331Samw 		VN_RELE(smb_vfs->sv_rootvp);
1356139Sjb150015 		kmem_cache_free(sv->si_cache_vfs, smb_vfs);
1365331Samw 	}
1376139Sjb150015 	smb_llist_exit(&sv->sv_vfs_list);
1385331Samw }
1395331Samw 
1405331Samw /*
1415331Samw  * smb_vfs_lookup
1425331Samw  *
1435331Samw  * Goes through the list of smb_vfs_t structure and returns the one matching
1445331Samw  * the vnode passed in. If no match is found a NULL pointer is returned.
1455331Samw  *
1465331Samw  * The list of smb_vfs_t structures has to have been entered prior calling
1475331Samw  * this function.
1485331Samw  */
1495331Samw static smb_vfs_t *
1506139Sjb150015 smb_vfs_lookup(smb_server_t *sv, vnode_t *rootvp)
1515331Samw {
1525331Samw 	smb_vfs_t	*smb_vfs;
1535331Samw 
1546139Sjb150015 	smb_vfs = smb_llist_head(&sv->sv_vfs_list);
1555331Samw 	while (smb_vfs) {
1565331Samw 		ASSERT(smb_vfs->sv_magic == SMB_VFS_MAGIC);
1575331Samw 		if (smb_vfs->sv_rootvp == rootvp) {
1585331Samw 			smb_vfs->sv_refcnt++;
1595331Samw 			ASSERT(smb_vfs->sv_refcnt);
1605331Samw 			return (smb_vfs);
1615331Samw 		}
1626139Sjb150015 		smb_vfs = smb_llist_next(&sv->sv_vfs_list, smb_vfs);
1635331Samw 	}
1645331Samw 	return (NULL);
1655331Samw }
166*7348SJose.Borrego@Sun.COM 
167*7348SJose.Borrego@Sun.COM /*
168*7348SJose.Borrego@Sun.COM  * Returns true if both VFS pointers represent the same mounted
169*7348SJose.Borrego@Sun.COM  * file system.  Otherwise returns false.
170*7348SJose.Borrego@Sun.COM  */
171*7348SJose.Borrego@Sun.COM boolean_t
172*7348SJose.Borrego@Sun.COM smb_vfs_cmp(vfs_t *vfsp1, vfs_t *vfsp2)
173*7348SJose.Borrego@Sun.COM {
174*7348SJose.Borrego@Sun.COM 	fsid_t *fsid1 = &vfsp1->vfs_fsid;
175*7348SJose.Borrego@Sun.COM 	fsid_t *fsid2 = &vfsp2->vfs_fsid;
176*7348SJose.Borrego@Sun.COM 	boolean_t result = B_FALSE;
177*7348SJose.Borrego@Sun.COM 
178*7348SJose.Borrego@Sun.COM 	if ((vfsp1 = getvfs(fsid1)) == NULL)
179*7348SJose.Borrego@Sun.COM 		return (B_FALSE);
180*7348SJose.Borrego@Sun.COM 
181*7348SJose.Borrego@Sun.COM 	if ((vfsp2 = getvfs(fsid2)) == NULL) {
182*7348SJose.Borrego@Sun.COM 		VFS_RELE(vfsp1);
183*7348SJose.Borrego@Sun.COM 		return (B_FALSE);
184*7348SJose.Borrego@Sun.COM 	}
185*7348SJose.Borrego@Sun.COM 
186*7348SJose.Borrego@Sun.COM 	if ((fsid1->val[0] == fsid2->val[0]) &&
187*7348SJose.Borrego@Sun.COM 	    (fsid1->val[1] == fsid2->val[1])) {
188*7348SJose.Borrego@Sun.COM 		result = B_TRUE;
189*7348SJose.Borrego@Sun.COM 	}
190*7348SJose.Borrego@Sun.COM 
191*7348SJose.Borrego@Sun.COM 	VFS_RELE(vfsp2);
192*7348SJose.Borrego@Sun.COM 	VFS_RELE(vfsp1);
193*7348SJose.Borrego@Sun.COM 	return (result);
194*7348SJose.Borrego@Sun.COM }
195*7348SJose.Borrego@Sun.COM 
196*7348SJose.Borrego@Sun.COM /*
197*7348SJose.Borrego@Sun.COM  * Check whether or not a file system is readonly.
198*7348SJose.Borrego@Sun.COM  */
199*7348SJose.Borrego@Sun.COM boolean_t
200*7348SJose.Borrego@Sun.COM smb_vfs_is_readonly(vfs_t *vfsp)
201*7348SJose.Borrego@Sun.COM {
202*7348SJose.Borrego@Sun.COM 	boolean_t result;
203*7348SJose.Borrego@Sun.COM 
204*7348SJose.Borrego@Sun.COM 	if (getvfs(&vfsp->vfs_fsid) == NULL)
205*7348SJose.Borrego@Sun.COM 		return (B_FALSE);
206*7348SJose.Borrego@Sun.COM 
207*7348SJose.Borrego@Sun.COM 	result = (vfsp->vfs_flag & VFS_RDONLY);
208*7348SJose.Borrego@Sun.COM 	VFS_RELE(vfsp);
209*7348SJose.Borrego@Sun.COM 	return (result);
210*7348SJose.Borrego@Sun.COM }
211