1*4bff34e3Sthurlow /* 2*4bff34e3Sthurlow * CDDL HEADER START 3*4bff34e3Sthurlow * 4*4bff34e3Sthurlow * The contents of this file are subject to the terms of the 5*4bff34e3Sthurlow * Common Development and Distribution License (the "License"). 6*4bff34e3Sthurlow * You may not use this file except in compliance with the License. 7*4bff34e3Sthurlow * 8*4bff34e3Sthurlow * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*4bff34e3Sthurlow * or http://www.opensolaris.org/os/licensing. 10*4bff34e3Sthurlow * See the License for the specific language governing permissions 11*4bff34e3Sthurlow * and limitations under the License. 12*4bff34e3Sthurlow * 13*4bff34e3Sthurlow * When distributing Covered Code, include this CDDL HEADER in each 14*4bff34e3Sthurlow * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*4bff34e3Sthurlow * If applicable, add the following below this CDDL HEADER, with the 16*4bff34e3Sthurlow * fields enclosed by brackets "[]" replaced with your own identifying 17*4bff34e3Sthurlow * information: Portions Copyright [yyyy] [name of copyright owner] 18*4bff34e3Sthurlow * 19*4bff34e3Sthurlow * CDDL HEADER END 20*4bff34e3Sthurlow */ 21*4bff34e3Sthurlow /* 22*4bff34e3Sthurlow * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*4bff34e3Sthurlow * Use is subject to license terms. 24*4bff34e3Sthurlow * 25*4bff34e3Sthurlow * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. 26*4bff34e3Sthurlow * All rights reserved. 27*4bff34e3Sthurlow */ 28*4bff34e3Sthurlow 29*4bff34e3Sthurlow #pragma ident "%Z%%M% %I% %E% SMI" 30*4bff34e3Sthurlow 31*4bff34e3Sthurlow #include <sys/param.h> 32*4bff34e3Sthurlow #include <sys/systm.h> 33*4bff34e3Sthurlow #include <sys/thread.h> 34*4bff34e3Sthurlow #include <sys/t_lock.h> 35*4bff34e3Sthurlow #include <sys/time.h> 36*4bff34e3Sthurlow #include <sys/vnode.h> 37*4bff34e3Sthurlow #include <sys/vfs.h> 38*4bff34e3Sthurlow #include <sys/errno.h> 39*4bff34e3Sthurlow #include <sys/buf.h> 40*4bff34e3Sthurlow #include <sys/stat.h> 41*4bff34e3Sthurlow #include <sys/cred.h> 42*4bff34e3Sthurlow #include <sys/kmem.h> 43*4bff34e3Sthurlow #include <sys/debug.h> 44*4bff34e3Sthurlow #include <sys/dnlc.h> 45*4bff34e3Sthurlow #include <sys/vmsystm.h> 46*4bff34e3Sthurlow #include <sys/flock.h> 47*4bff34e3Sthurlow #include <sys/share.h> 48*4bff34e3Sthurlow #include <sys/cmn_err.h> 49*4bff34e3Sthurlow #include <sys/tiuser.h> 50*4bff34e3Sthurlow #include <sys/sysmacros.h> 51*4bff34e3Sthurlow #include <sys/callb.h> 52*4bff34e3Sthurlow #include <sys/acl.h> 53*4bff34e3Sthurlow #include <sys/kstat.h> 54*4bff34e3Sthurlow #include <sys/signal.h> 55*4bff34e3Sthurlow #include <sys/list.h> 56*4bff34e3Sthurlow #include <sys/zone.h> 57*4bff34e3Sthurlow 58*4bff34e3Sthurlow #include <netsmb/smb_conn.h> 59*4bff34e3Sthurlow 60*4bff34e3Sthurlow #include <smbfs/smbfs.h> 61*4bff34e3Sthurlow #include <smbfs/smbfs_node.h> 62*4bff34e3Sthurlow #include <smbfs/smbfs_subr.h> 63*4bff34e3Sthurlow 64*4bff34e3Sthurlow #include <vm/hat.h> 65*4bff34e3Sthurlow #include <vm/as.h> 66*4bff34e3Sthurlow #include <vm/page.h> 67*4bff34e3Sthurlow #include <vm/pvn.h> 68*4bff34e3Sthurlow #include <vm/seg.h> 69*4bff34e3Sthurlow #include <vm/seg_map.h> 70*4bff34e3Sthurlow #include <vm/seg_vn.h> 71*4bff34e3Sthurlow 72*4bff34e3Sthurlow /* 73*4bff34e3Sthurlow * The following code provide zone support in order to perform an action 74*4bff34e3Sthurlow * for each smbfs mount in a zone. This is also where we would add 75*4bff34e3Sthurlow * per-zone globals and kernel threads for the smbfs module (since 76*4bff34e3Sthurlow * they must be terminated by the shutdown callback). 77*4bff34e3Sthurlow */ 78*4bff34e3Sthurlow 79*4bff34e3Sthurlow struct smi_globals { 80*4bff34e3Sthurlow kmutex_t smg_lock; /* lock protecting smg_list */ 81*4bff34e3Sthurlow list_t smg_list; /* list of SMBFS mounts in zone */ 82*4bff34e3Sthurlow boolean_t smg_destructor_called; 83*4bff34e3Sthurlow }; 84*4bff34e3Sthurlow typedef struct smi_globals smi_globals_t; 85*4bff34e3Sthurlow 86*4bff34e3Sthurlow static zone_key_t smi_list_key; 87*4bff34e3Sthurlow 88*4bff34e3Sthurlow /* ARGSUSED */ 89*4bff34e3Sthurlow static void * 90*4bff34e3Sthurlow smbfs_zone_init(zoneid_t zoneid) 91*4bff34e3Sthurlow { 92*4bff34e3Sthurlow smi_globals_t *smg; 93*4bff34e3Sthurlow 94*4bff34e3Sthurlow smg = kmem_alloc(sizeof (*smg), KM_SLEEP); 95*4bff34e3Sthurlow mutex_init(&smg->smg_lock, NULL, MUTEX_DEFAULT, NULL); 96*4bff34e3Sthurlow list_create(&smg->smg_list, sizeof (smbmntinfo_t), 97*4bff34e3Sthurlow offsetof(smbmntinfo_t, smi_zone_node)); 98*4bff34e3Sthurlow smg->smg_destructor_called = B_FALSE; 99*4bff34e3Sthurlow return (smg); 100*4bff34e3Sthurlow } 101*4bff34e3Sthurlow 102*4bff34e3Sthurlow /* 103*4bff34e3Sthurlow * Callback routine to tell all SMBFS mounts in the zone to stop creating new 104*4bff34e3Sthurlow * threads. Existing threads should exit. 105*4bff34e3Sthurlow */ 106*4bff34e3Sthurlow /* ARGSUSED */ 107*4bff34e3Sthurlow static void 108*4bff34e3Sthurlow smbfs_zone_shutdown(zoneid_t zoneid, void *data) 109*4bff34e3Sthurlow { 110*4bff34e3Sthurlow smi_globals_t *smg = data; 111*4bff34e3Sthurlow smbmntinfo_t *smi; 112*4bff34e3Sthurlow 113*4bff34e3Sthurlow ASSERT(smg != NULL); 114*4bff34e3Sthurlow again: 115*4bff34e3Sthurlow mutex_enter(&smg->smg_lock); 116*4bff34e3Sthurlow for (smi = list_head(&smg->smg_list); smi != NULL; 117*4bff34e3Sthurlow smi = list_next(&smg->smg_list, smi)) { 118*4bff34e3Sthurlow 119*4bff34e3Sthurlow /* 120*4bff34e3Sthurlow * If we've done the shutdown work for this FS, skip. 121*4bff34e3Sthurlow * Once we go off the end of the list, we're done. 122*4bff34e3Sthurlow */ 123*4bff34e3Sthurlow if (smi->smi_flags & SMI_DEAD) 124*4bff34e3Sthurlow continue; 125*4bff34e3Sthurlow 126*4bff34e3Sthurlow /* 127*4bff34e3Sthurlow * We will do work, so not done. Get a hold on the FS. 128*4bff34e3Sthurlow */ 129*4bff34e3Sthurlow VFS_HOLD(smi->smi_vfsp); 130*4bff34e3Sthurlow 131*4bff34e3Sthurlow /* 132*4bff34e3Sthurlow * purge the DNLC for this filesystem 133*4bff34e3Sthurlow */ 134*4bff34e3Sthurlow (void) dnlc_purge_vfsp(smi->smi_vfsp, 0); 135*4bff34e3Sthurlow 136*4bff34e3Sthurlow mutex_enter(&smi->smi_lock); 137*4bff34e3Sthurlow smi->smi_flags |= SMI_DEAD; 138*4bff34e3Sthurlow mutex_exit(&smi->smi_lock); 139*4bff34e3Sthurlow 140*4bff34e3Sthurlow /* 141*4bff34e3Sthurlow * Drop lock and release FS, which may change list, then repeat. 142*4bff34e3Sthurlow * We're done when every mi has been done or the list is empty. 143*4bff34e3Sthurlow */ 144*4bff34e3Sthurlow mutex_exit(&smg->smg_lock); 145*4bff34e3Sthurlow VFS_RELE(smi->smi_vfsp); 146*4bff34e3Sthurlow goto again; 147*4bff34e3Sthurlow } 148*4bff34e3Sthurlow mutex_exit(&smg->smg_lock); 149*4bff34e3Sthurlow } 150*4bff34e3Sthurlow 151*4bff34e3Sthurlow static void 152*4bff34e3Sthurlow smbfs_zone_free_globals(smi_globals_t *smg) 153*4bff34e3Sthurlow { 154*4bff34e3Sthurlow list_destroy(&smg->smg_list); /* makes sure the list is empty */ 155*4bff34e3Sthurlow mutex_destroy(&smg->smg_lock); 156*4bff34e3Sthurlow kmem_free(smg, sizeof (*smg)); 157*4bff34e3Sthurlow 158*4bff34e3Sthurlow } 159*4bff34e3Sthurlow 160*4bff34e3Sthurlow /* ARGSUSED */ 161*4bff34e3Sthurlow static void 162*4bff34e3Sthurlow smbfs_zone_destroy(zoneid_t zoneid, void *data) 163*4bff34e3Sthurlow { 164*4bff34e3Sthurlow smi_globals_t *smg = data; 165*4bff34e3Sthurlow 166*4bff34e3Sthurlow ASSERT(smg != NULL); 167*4bff34e3Sthurlow mutex_enter(&smg->smg_lock); 168*4bff34e3Sthurlow if (list_head(&smg->smg_list) != NULL) { 169*4bff34e3Sthurlow /* Still waiting for VFS_FREEVFS() */ 170*4bff34e3Sthurlow smg->smg_destructor_called = B_TRUE; 171*4bff34e3Sthurlow mutex_exit(&smg->smg_lock); 172*4bff34e3Sthurlow return; 173*4bff34e3Sthurlow } 174*4bff34e3Sthurlow smbfs_zone_free_globals(smg); 175*4bff34e3Sthurlow } 176*4bff34e3Sthurlow 177*4bff34e3Sthurlow /* 178*4bff34e3Sthurlow * Add an SMBFS mount to the per-zone list of SMBFS mounts. 179*4bff34e3Sthurlow */ 180*4bff34e3Sthurlow void 181*4bff34e3Sthurlow smbfs_zonelist_add(smbmntinfo_t *smi) 182*4bff34e3Sthurlow { 183*4bff34e3Sthurlow smi_globals_t *smg; 184*4bff34e3Sthurlow 185*4bff34e3Sthurlow smg = zone_getspecific(smi_list_key, smi->smi_zone); 186*4bff34e3Sthurlow mutex_enter(&smg->smg_lock); 187*4bff34e3Sthurlow list_insert_head(&smg->smg_list, smi); 188*4bff34e3Sthurlow mutex_exit(&smg->smg_lock); 189*4bff34e3Sthurlow } 190*4bff34e3Sthurlow 191*4bff34e3Sthurlow /* 192*4bff34e3Sthurlow * Remove an SMBFS mount from the per-zone list of SMBFS mounts. 193*4bff34e3Sthurlow */ 194*4bff34e3Sthurlow void 195*4bff34e3Sthurlow smbfs_zonelist_remove(smbmntinfo_t *smi) 196*4bff34e3Sthurlow { 197*4bff34e3Sthurlow smi_globals_t *smg; 198*4bff34e3Sthurlow 199*4bff34e3Sthurlow smg = zone_getspecific(smi_list_key, smi->smi_zone); 200*4bff34e3Sthurlow mutex_enter(&smg->smg_lock); 201*4bff34e3Sthurlow list_remove(&smg->smg_list, smi); 202*4bff34e3Sthurlow /* 203*4bff34e3Sthurlow * We can be called asynchronously by VFS_FREEVFS() after the zone 204*4bff34e3Sthurlow * shutdown/destroy callbacks have executed; if so, clean up the zone's 205*4bff34e3Sthurlow * smi_globals. 206*4bff34e3Sthurlow */ 207*4bff34e3Sthurlow if (list_head(&smg->smg_list) == NULL && 208*4bff34e3Sthurlow smg->smg_destructor_called == B_TRUE) { 209*4bff34e3Sthurlow smbfs_zone_free_globals(smg); 210*4bff34e3Sthurlow return; 211*4bff34e3Sthurlow } 212*4bff34e3Sthurlow mutex_exit(&smg->smg_lock); 213*4bff34e3Sthurlow } 214*4bff34e3Sthurlow 215*4bff34e3Sthurlow 216*4bff34e3Sthurlow #ifdef NEED_SMBFS_CALLBACKS 217*4bff34e3Sthurlow /* 218*4bff34e3Sthurlow * Call-back hooks for netsmb, in case we want them. 219*4bff34e3Sthurlow * Apple's VFS wants them. We may not need them. 220*4bff34e3Sthurlow * 221*4bff34e3Sthurlow * I thought I could use the "dead" callback from netsmb 222*4bff34e3Sthurlow * to set the SMI_DEAD flag, but that looks like it will 223*4bff34e3Sthurlow * interfere with the zone shutdown mechanisms. 224*4bff34e3Sthurlow */ 225*4bff34e3Sthurlow static void smbfs_dead(smb_share_t *ssp) 226*4bff34e3Sthurlow { 227*4bff34e3Sthurlow #if 0 /* see above */ 228*4bff34e3Sthurlow smbmntinfo_t *smi = ssp->ss_mount; 229*4bff34e3Sthurlow if (smi) { 230*4bff34e3Sthurlow mutex_enter(&smi->smi_lock); 231*4bff34e3Sthurlow smi->smi_flags |= SMI_DEAD; 232*4bff34e3Sthurlow mutex_exit(&smi->smi_lock); 233*4bff34e3Sthurlow } 234*4bff34e3Sthurlow #endif 235*4bff34e3Sthurlow } 236*4bff34e3Sthurlow 237*4bff34e3Sthurlow static void smbfs_down(smb_share_t *ss) 238*4bff34e3Sthurlow { 239*4bff34e3Sthurlow /* no-op */ 240*4bff34e3Sthurlow } 241*4bff34e3Sthurlow 242*4bff34e3Sthurlow static void smbfs_up(smb_share_t *ss) 243*4bff34e3Sthurlow { 244*4bff34e3Sthurlow /* no-op */ 245*4bff34e3Sthurlow } 246*4bff34e3Sthurlow 247*4bff34e3Sthurlow smb_fscb_t smbfs_cb = { 248*4bff34e3Sthurlow .fscb_dead = smbfs_dead, 249*4bff34e3Sthurlow .fscb_down = smbfs_down, 250*4bff34e3Sthurlow .fscb_up = smbfs_up }; 251*4bff34e3Sthurlow 252*4bff34e3Sthurlow #endif /* NEED_SMBFS_CALLBACKS */ 253*4bff34e3Sthurlow 254*4bff34e3Sthurlow /* 255*4bff34e3Sthurlow * SMBFS Client initialization routine. This routine should only be called 256*4bff34e3Sthurlow * once. It performs the following tasks: 257*4bff34e3Sthurlow * - Initalize all global locks 258*4bff34e3Sthurlow * - Call sub-initialization routines (localize access to variables) 259*4bff34e3Sthurlow */ 260*4bff34e3Sthurlow int 261*4bff34e3Sthurlow smbfs_clntinit(void) 262*4bff34e3Sthurlow { 263*4bff34e3Sthurlow int error; 264*4bff34e3Sthurlow 265*4bff34e3Sthurlow error = smbfs_subrinit(); 266*4bff34e3Sthurlow if (error) 267*4bff34e3Sthurlow return (error); 268*4bff34e3Sthurlow zone_key_create(&smi_list_key, smbfs_zone_init, smbfs_zone_shutdown, 269*4bff34e3Sthurlow smbfs_zone_destroy); 270*4bff34e3Sthurlow #ifdef NEED_SMBFS_CALLBACKS 271*4bff34e3Sthurlow smb_fscb_set(&smbfs_cb); 272*4bff34e3Sthurlow #endif /* NEED_SMBFS_CALLBACKS */ 273*4bff34e3Sthurlow return (0); 274*4bff34e3Sthurlow } 275*4bff34e3Sthurlow 276*4bff34e3Sthurlow /* 277*4bff34e3Sthurlow * This routine is called when the modunload is called. This will cleanup 278*4bff34e3Sthurlow * the previously allocated/initialized nodes. 279*4bff34e3Sthurlow */ 280*4bff34e3Sthurlow void 281*4bff34e3Sthurlow smbfs_clntfini(void) 282*4bff34e3Sthurlow { 283*4bff34e3Sthurlow #ifdef NEED_SMBFS_CALLBACKS 284*4bff34e3Sthurlow smb_fscb_set(NULL); 285*4bff34e3Sthurlow #endif /* NEED_SMBFS_CALLBACKS */ 286*4bff34e3Sthurlow (void) zone_key_delete(smi_list_key); 287*4bff34e3Sthurlow smbfs_subrfini(); 288*4bff34e3Sthurlow } 289