1*433d6423SLionel Sambuc /* Virtual mount table related routines. 2*433d6423SLionel Sambuc * 3*433d6423SLionel Sambuc */ 4*433d6423SLionel Sambuc 5*433d6423SLionel Sambuc #include "fs.h" 6*433d6423SLionel Sambuc #include "vmnt.h" 7*433d6423SLionel Sambuc #include <assert.h> 8*433d6423SLionel Sambuc #include <string.h> 9*433d6423SLionel Sambuc 10*433d6423SLionel Sambuc static int is_vmnt_locked(struct vmnt *vmp); 11*433d6423SLionel Sambuc static void clear_vmnt(struct vmnt *vmp); 12*433d6423SLionel Sambuc 13*433d6423SLionel Sambuc /* Is vmp pointer reasonable? */ 14*433d6423SLionel Sambuc #define SANEVMP(v) ((((v) >= &vmnt[0] && (v) < &vmnt[NR_MNTS]))) 15*433d6423SLionel Sambuc #define BADVMP(v, f, l) printf("%s:%d: bad vmp %p\n", f, l, v) 16*433d6423SLionel Sambuc /* vp check that panics */ 17*433d6423SLionel Sambuc #define ASSERTVMP(v) if(!SANEVMP(v)) { \ 18*433d6423SLionel Sambuc BADVMP(v, __FILE__, __LINE__); panic("bad vmp"); } 19*433d6423SLionel Sambuc 20*433d6423SLionel Sambuc #if LOCK_DEBUG 21*433d6423SLionel Sambuc /*===========================================================================* 22*433d6423SLionel Sambuc * check_vmnt_locks_by_me * 23*433d6423SLionel Sambuc *===========================================================================*/ 24*433d6423SLionel Sambuc void check_vmnt_locks_by_me(struct fproc *rfp) 25*433d6423SLionel Sambuc { 26*433d6423SLionel Sambuc /* Check whether this thread still has locks held on vmnts */ 27*433d6423SLionel Sambuc struct vmnt *vmp; 28*433d6423SLionel Sambuc 29*433d6423SLionel Sambuc for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) { 30*433d6423SLionel Sambuc if (tll_locked_by_me(&vmp->m_lock)) 31*433d6423SLionel Sambuc panic("Thread %d still holds vmnt lock on vmp %p call_nr=%d\n", 32*433d6423SLionel Sambuc mthread_self(), vmp, job_call_nr); 33*433d6423SLionel Sambuc } 34*433d6423SLionel Sambuc 35*433d6423SLionel Sambuc if (rfp->fp_vmnt_rdlocks != 0) 36*433d6423SLionel Sambuc panic("Thread %d still holds read locks on a vmnt (%d) call_nr=%d\n", 37*433d6423SLionel Sambuc mthread_self(), rfp->fp_vmnt_rdlocks, job_call_nr); 38*433d6423SLionel Sambuc } 39*433d6423SLionel Sambuc #endif 40*433d6423SLionel Sambuc 41*433d6423SLionel Sambuc /*===========================================================================* 42*433d6423SLionel Sambuc * check_vmnt_locks * 43*433d6423SLionel Sambuc *===========================================================================*/ 44*433d6423SLionel Sambuc void check_vmnt_locks() 45*433d6423SLionel Sambuc { 46*433d6423SLionel Sambuc struct vmnt *vmp; 47*433d6423SLionel Sambuc int count = 0; 48*433d6423SLionel Sambuc 49*433d6423SLionel Sambuc for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) 50*433d6423SLionel Sambuc if (is_vmnt_locked(vmp)) { 51*433d6423SLionel Sambuc count++; 52*433d6423SLionel Sambuc printf("vmnt %p is %s, fs_e=%d dev=%llx\n", vmp, (tll_islocked(&vmp->m_lock) ? "locked":"pending locked"), vmp->m_fs_e, vmp->m_dev); 53*433d6423SLionel Sambuc } 54*433d6423SLionel Sambuc 55*433d6423SLionel Sambuc if (count) panic("%d locked vmnts\n", count); 56*433d6423SLionel Sambuc #if 0 57*433d6423SLionel Sambuc printf("check_vmnt_locks OK\n"); 58*433d6423SLionel Sambuc #endif 59*433d6423SLionel Sambuc } 60*433d6423SLionel Sambuc 61*433d6423SLionel Sambuc /*===========================================================================* 62*433d6423SLionel Sambuc * mark_vmnt_free * 63*433d6423SLionel Sambuc *===========================================================================*/ 64*433d6423SLionel Sambuc void mark_vmnt_free(struct vmnt *vmp) 65*433d6423SLionel Sambuc { 66*433d6423SLionel Sambuc ASSERTVMP(vmp); 67*433d6423SLionel Sambuc 68*433d6423SLionel Sambuc vmp->m_fs_e = NONE; 69*433d6423SLionel Sambuc vmp->m_dev = NO_DEV; 70*433d6423SLionel Sambuc } 71*433d6423SLionel Sambuc 72*433d6423SLionel Sambuc /*===========================================================================* 73*433d6423SLionel Sambuc * clear_vmnt * 74*433d6423SLionel Sambuc *===========================================================================*/ 75*433d6423SLionel Sambuc static void clear_vmnt(struct vmnt *vmp) 76*433d6423SLionel Sambuc { 77*433d6423SLionel Sambuc /* Reset vmp to initial parameters */ 78*433d6423SLionel Sambuc ASSERTVMP(vmp); 79*433d6423SLionel Sambuc 80*433d6423SLionel Sambuc vmp->m_fs_e = NONE; 81*433d6423SLionel Sambuc vmp->m_dev = NO_DEV; 82*433d6423SLionel Sambuc vmp->m_flags = 0; 83*433d6423SLionel Sambuc vmp->m_mounted_on = NULL; 84*433d6423SLionel Sambuc vmp->m_root_node = NULL; 85*433d6423SLionel Sambuc vmp->m_label[0] = '\0'; 86*433d6423SLionel Sambuc vmp->m_comm.c_max_reqs = 1; 87*433d6423SLionel Sambuc vmp->m_comm.c_cur_reqs = 0; 88*433d6423SLionel Sambuc vmp->m_comm.c_req_queue = NULL; 89*433d6423SLionel Sambuc } 90*433d6423SLionel Sambuc 91*433d6423SLionel Sambuc /*===========================================================================* 92*433d6423SLionel Sambuc * get_free_vmnt * 93*433d6423SLionel Sambuc *===========================================================================*/ 94*433d6423SLionel Sambuc struct vmnt *get_free_vmnt(void) 95*433d6423SLionel Sambuc { 96*433d6423SLionel Sambuc struct vmnt *vmp; 97*433d6423SLionel Sambuc 98*433d6423SLionel Sambuc for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) { 99*433d6423SLionel Sambuc if (vmp->m_dev == NO_DEV) { 100*433d6423SLionel Sambuc clear_vmnt(vmp); 101*433d6423SLionel Sambuc return(vmp); 102*433d6423SLionel Sambuc } 103*433d6423SLionel Sambuc } 104*433d6423SLionel Sambuc 105*433d6423SLionel Sambuc return(NULL); 106*433d6423SLionel Sambuc } 107*433d6423SLionel Sambuc 108*433d6423SLionel Sambuc /*===========================================================================* 109*433d6423SLionel Sambuc * find_vmnt * 110*433d6423SLionel Sambuc *===========================================================================*/ 111*433d6423SLionel Sambuc struct vmnt *find_vmnt(endpoint_t fs_e) 112*433d6423SLionel Sambuc { 113*433d6423SLionel Sambuc /* Find the vmnt belonging to an FS with endpoint 'fs_e' iff it's in use */ 114*433d6423SLionel Sambuc struct vmnt *vp; 115*433d6423SLionel Sambuc 116*433d6423SLionel Sambuc for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp) 117*433d6423SLionel Sambuc if (vp->m_fs_e == fs_e && vp->m_dev != NO_DEV) 118*433d6423SLionel Sambuc return(vp); 119*433d6423SLionel Sambuc 120*433d6423SLionel Sambuc return(NULL); 121*433d6423SLionel Sambuc } 122*433d6423SLionel Sambuc 123*433d6423SLionel Sambuc /*===========================================================================* 124*433d6423SLionel Sambuc * init_vmnts * 125*433d6423SLionel Sambuc *===========================================================================*/ 126*433d6423SLionel Sambuc void init_vmnts(void) 127*433d6423SLionel Sambuc { 128*433d6423SLionel Sambuc /* Initialize vmnt table */ 129*433d6423SLionel Sambuc struct vmnt *vmp; 130*433d6423SLionel Sambuc 131*433d6423SLionel Sambuc for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) { 132*433d6423SLionel Sambuc clear_vmnt(vmp); 133*433d6423SLionel Sambuc tll_init(&vmp->m_lock); 134*433d6423SLionel Sambuc } 135*433d6423SLionel Sambuc } 136*433d6423SLionel Sambuc 137*433d6423SLionel Sambuc /*===========================================================================* 138*433d6423SLionel Sambuc * is_vmnt_locked * 139*433d6423SLionel Sambuc *===========================================================================*/ 140*433d6423SLionel Sambuc static int is_vmnt_locked(struct vmnt *vmp) 141*433d6423SLionel Sambuc { 142*433d6423SLionel Sambuc ASSERTVMP(vmp); 143*433d6423SLionel Sambuc return(tll_islocked(&vmp->m_lock) || tll_haspendinglock(&vmp->m_lock)); 144*433d6423SLionel Sambuc } 145*433d6423SLionel Sambuc 146*433d6423SLionel Sambuc /*===========================================================================* 147*433d6423SLionel Sambuc * lock_vmnt * 148*433d6423SLionel Sambuc *===========================================================================*/ 149*433d6423SLionel Sambuc int lock_vmnt(struct vmnt *vmp, tll_access_t locktype) 150*433d6423SLionel Sambuc { 151*433d6423SLionel Sambuc int r; 152*433d6423SLionel Sambuc tll_access_t initial_locktype; 153*433d6423SLionel Sambuc 154*433d6423SLionel Sambuc ASSERTVMP(vmp); 155*433d6423SLionel Sambuc 156*433d6423SLionel Sambuc initial_locktype = (locktype == VMNT_EXCL) ? VMNT_WRITE : locktype; 157*433d6423SLionel Sambuc 158*433d6423SLionel Sambuc if (vmp->m_fs_e == who_e) return(EDEADLK); 159*433d6423SLionel Sambuc 160*433d6423SLionel Sambuc r = tll_lock(&vmp->m_lock, initial_locktype); 161*433d6423SLionel Sambuc 162*433d6423SLionel Sambuc if (r == EBUSY) return(r); 163*433d6423SLionel Sambuc 164*433d6423SLionel Sambuc if (initial_locktype != locktype) { 165*433d6423SLionel Sambuc upgrade_vmnt_lock(vmp); 166*433d6423SLionel Sambuc } 167*433d6423SLionel Sambuc 168*433d6423SLionel Sambuc #if LOCK_DEBUG 169*433d6423SLionel Sambuc if (locktype == VMNT_READ) 170*433d6423SLionel Sambuc fp->fp_vmnt_rdlocks++; 171*433d6423SLionel Sambuc #endif 172*433d6423SLionel Sambuc 173*433d6423SLionel Sambuc return(OK); 174*433d6423SLionel Sambuc } 175*433d6423SLionel Sambuc 176*433d6423SLionel Sambuc /*===========================================================================* 177*433d6423SLionel Sambuc * vmnt_unmap_by_endpoint * 178*433d6423SLionel Sambuc *===========================================================================*/ 179*433d6423SLionel Sambuc void vmnt_unmap_by_endpt(endpoint_t proc_e) 180*433d6423SLionel Sambuc { 181*433d6423SLionel Sambuc struct vmnt *vmp; 182*433d6423SLionel Sambuc 183*433d6423SLionel Sambuc if ((vmp = find_vmnt(proc_e)) != NULL) { 184*433d6423SLionel Sambuc mark_vmnt_free(vmp); 185*433d6423SLionel Sambuc fs_cancel(vmp); 186*433d6423SLionel Sambuc invalidate_filp_by_endpt(proc_e); 187*433d6423SLionel Sambuc if (vmp->m_mounted_on) { 188*433d6423SLionel Sambuc /* Only put mount point when it was actually used as mount 189*433d6423SLionel Sambuc * point. That is, the mount was succesful. */ 190*433d6423SLionel Sambuc put_vnode(vmp->m_mounted_on); 191*433d6423SLionel Sambuc } 192*433d6423SLionel Sambuc } 193*433d6423SLionel Sambuc } 194*433d6423SLionel Sambuc 195*433d6423SLionel Sambuc /*===========================================================================* 196*433d6423SLionel Sambuc * unlock_vmnt * 197*433d6423SLionel Sambuc *===========================================================================*/ 198*433d6423SLionel Sambuc void unlock_vmnt(struct vmnt *vmp) 199*433d6423SLionel Sambuc { 200*433d6423SLionel Sambuc ASSERTVMP(vmp); 201*433d6423SLionel Sambuc 202*433d6423SLionel Sambuc #if LOCK_DEBUG 203*433d6423SLionel Sambuc /* Decrease read-only lock counter when not locked as VMNT_WRITE or 204*433d6423SLionel Sambuc * VMNT_EXCL */ 205*433d6423SLionel Sambuc if (!tll_locked_by_me(&vmp->m_lock)) 206*433d6423SLionel Sambuc fp->fp_vmnt_rdlocks--; 207*433d6423SLionel Sambuc #endif 208*433d6423SLionel Sambuc 209*433d6423SLionel Sambuc tll_unlock(&vmp->m_lock); 210*433d6423SLionel Sambuc 211*433d6423SLionel Sambuc #if LOCK_DEBUG 212*433d6423SLionel Sambuc assert(!tll_locked_by_me(&vmp->m_lock)); 213*433d6423SLionel Sambuc #endif 214*433d6423SLionel Sambuc 215*433d6423SLionel Sambuc } 216*433d6423SLionel Sambuc 217*433d6423SLionel Sambuc /*===========================================================================* 218*433d6423SLionel Sambuc * downgrade_vmnt_lock * 219*433d6423SLionel Sambuc *===========================================================================*/ 220*433d6423SLionel Sambuc void downgrade_vmnt_lock(struct vmnt *vmp) 221*433d6423SLionel Sambuc { 222*433d6423SLionel Sambuc ASSERTVMP(vmp); 223*433d6423SLionel Sambuc tll_downgrade(&vmp->m_lock); 224*433d6423SLionel Sambuc 225*433d6423SLionel Sambuc #if LOCK_DEBUG 226*433d6423SLionel Sambuc /* If we're no longer the owner of a lock, we downgraded to VMNT_READ */ 227*433d6423SLionel Sambuc if (!tll_locked_by_me(&vmp->m_lock)) { 228*433d6423SLionel Sambuc fp->fp_vmnt_rdlocks++; 229*433d6423SLionel Sambuc } 230*433d6423SLionel Sambuc #endif 231*433d6423SLionel Sambuc } 232*433d6423SLionel Sambuc 233*433d6423SLionel Sambuc /*===========================================================================* 234*433d6423SLionel Sambuc * upgrade_vmnt_lock * 235*433d6423SLionel Sambuc *===========================================================================*/ 236*433d6423SLionel Sambuc void upgrade_vmnt_lock(struct vmnt *vmp) 237*433d6423SLionel Sambuc { 238*433d6423SLionel Sambuc ASSERTVMP(vmp); 239*433d6423SLionel Sambuc tll_upgrade(&vmp->m_lock); 240*433d6423SLionel Sambuc } 241*433d6423SLionel Sambuc 242*433d6423SLionel Sambuc /*===========================================================================* 243*433d6423SLionel Sambuc * fetch_vmnt_paths * 244*433d6423SLionel Sambuc *===========================================================================*/ 245*433d6423SLionel Sambuc void fetch_vmnt_paths(void) 246*433d6423SLionel Sambuc { 247*433d6423SLionel Sambuc struct vmnt *vmp; 248*433d6423SLionel Sambuc struct vnode *cur_wd; 249*433d6423SLionel Sambuc char orig_path[PATH_MAX]; 250*433d6423SLionel Sambuc 251*433d6423SLionel Sambuc cur_wd = fp->fp_wd; 252*433d6423SLionel Sambuc 253*433d6423SLionel Sambuc for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) { 254*433d6423SLionel Sambuc if (vmp->m_dev == NO_DEV) 255*433d6423SLionel Sambuc continue; 256*433d6423SLionel Sambuc if (vmp->m_fs_e == PFS_PROC_NR) 257*433d6423SLionel Sambuc continue; 258*433d6423SLionel Sambuc 259*433d6423SLionel Sambuc strlcpy(orig_path, vmp->m_mount_path, PATH_MAX); 260*433d6423SLionel Sambuc 261*433d6423SLionel Sambuc /* Find canonical path */ 262*433d6423SLionel Sambuc if (canonical_path(vmp->m_mount_path, fp) != OK) { 263*433d6423SLionel Sambuc /* We failed to find it (moved somewhere else?). Let's try 264*433d6423SLionel Sambuc * again by starting at the node on which we are mounted: 265*433d6423SLionel Sambuc * pretend that node is our working directory and look for the 266*433d6423SLionel Sambuc * canonical path of the relative path to the mount point 267*433d6423SLionel Sambuc * (which should be in our 'working directory'). 268*433d6423SLionel Sambuc */ 269*433d6423SLionel Sambuc char *mp; 270*433d6423SLionel Sambuc int len; 271*433d6423SLionel Sambuc 272*433d6423SLionel Sambuc fp->fp_wd = vmp->m_mounted_on; /* Change our working dir */ 273*433d6423SLionel Sambuc 274*433d6423SLionel Sambuc /* Isolate the mount point name of the full path */ 275*433d6423SLionel Sambuc len = strlen(vmp->m_mount_path); 276*433d6423SLionel Sambuc if (vmp->m_mount_path[len - 1] == '/') { 277*433d6423SLionel Sambuc vmp->m_mount_path[len - 1] = '\0'; 278*433d6423SLionel Sambuc } 279*433d6423SLionel Sambuc mp = strrchr(vmp->m_mount_path, '/'); 280*433d6423SLionel Sambuc strlcpy(vmp->m_mount_path, mp+1, NAME_MAX+1); 281*433d6423SLionel Sambuc 282*433d6423SLionel Sambuc if (canonical_path(vmp->m_mount_path, fp) != OK) { 283*433d6423SLionel Sambuc /* Our second try failed too. Maybe an FS has crashed 284*433d6423SLionel Sambuc * and we're missing part of the tree. Revert path. 285*433d6423SLionel Sambuc */ 286*433d6423SLionel Sambuc strlcpy(vmp->m_mount_path, orig_path, PATH_MAX); 287*433d6423SLionel Sambuc } 288*433d6423SLionel Sambuc fp->fp_wd = cur_wd; /* Revert working dir */ 289*433d6423SLionel Sambuc } 290*433d6423SLionel Sambuc } 291*433d6423SLionel Sambuc } 292