/* Virtual mount table related routines. * */ #include "fs.h" #include "threads.h" #include "vmnt.h" #include #include "fproc.h" FORWARD _PROTOTYPE( int is_vmnt_locked, (struct vmnt *vmp) ); /* Is vmp pointer reasonable? */ #define SANEVMP(v) ((((v) >= &vmnt[0] && (v) < &vmnt[NR_MNTS]))) #define BADVMP(v, f, l) printf("%s:%d: bad vmp %p\n", f, l, v) /* vp check that panics */ #define ASSERTVMP(v) if(!SANEVMP(v)) { \ BADVMP(v, __FILE__, __LINE__); panic("bad vmp"); } #if LOCK_DEBUG /*===========================================================================* * check_vmnt_locks_by_me * *===========================================================================*/ PUBLIC void check_vmnt_locks_by_me(struct fproc *rfp) { /* Check whether this thread still has locks held on vmnts */ struct vmnt *vmp; for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) { if (tll_locked_by_me(&vmp->m_lock)) panic("Thread %d still holds vmnt lock on vmp %p call_nr=%d\n", mthread_self(), vmp, call_nr); } if (rfp->fp_vmnt_rdlocks != 0) panic("Thread %d still holds read locks on a vmnt (%d) call_nr=%d\n", mthread_self(), rfp->fp_vmnt_rdlocks, call_nr); } #endif /*===========================================================================* * check_vmnt_locks * *===========================================================================*/ PUBLIC void check_vmnt_locks() { struct vmnt *vmp; int count = 0; for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) if (is_vmnt_locked(vmp)) { count++; printf("vmnt %p is %s, fs_e=%d dev=%d\n", vmp, (tll_islocked(&vmp->m_lock) ? "locked":"pending locked"), vmp->m_fs_e, vmp->m_dev); } if (count) panic("%d locked vmnts\n", count); #if 0 printf("check_vmnt_locks OK\n"); #endif } /*===========================================================================* * get_free_vmnt * *===========================================================================*/ PUBLIC struct vmnt *get_free_vmnt(void) { struct vmnt *vp; for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp) if (vp->m_dev == NO_DEV) return(vp); return(NULL); } /*===========================================================================* * find_vmnt * *===========================================================================*/ PUBLIC struct vmnt *find_vmnt(endpoint_t fs_e) { /* Find the vmnt belonging to an FS with endpoint 'fs_e' iff it's in use */ struct vmnt *vp; for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp) if (vp->m_fs_e == fs_e && vp->m_dev != NO_DEV) return(vp); return(NULL); } /*===========================================================================* * init_vmnts * *===========================================================================*/ PUBLIC void init_vmnts(void) { /* Initialize vmnt table */ struct vmnt *vp; for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; vp++) { vp->m_fs_e = NONE; vp->m_dev = NO_DEV; vp->m_flags = 0; vp->m_mounted_on = NULL; vp->m_root_node = NULL; vp->m_label[0] = '\0'; vp->m_comm.c_max_reqs = 1; vp->m_comm.c_cur_reqs = 0; vp->m_comm.c_req_queue = NULL; tll_init(&vp->m_lock); } } /*===========================================================================* * is_vmnt_locked * *===========================================================================*/ PRIVATE int is_vmnt_locked(struct vmnt *vmp) { ASSERTVMP(vmp); return(tll_islocked(&vmp->m_lock) || tll_haspendinglock(&vmp->m_lock)); } /*===========================================================================* * lock_vmnt * *===========================================================================*/ PUBLIC int lock_vmnt(struct vmnt *vmp, tll_access_t locktype) { int r; tll_access_t initial_locktype; ASSERTVMP(vmp); initial_locktype = (locktype == VMNT_EXCL) ? VMNT_WRITE : locktype; r = tll_lock(&vmp->m_lock, initial_locktype); if (r == EBUSY) return(r); if (initial_locktype != locktype) { tll_upgrade(&vmp->m_lock); } #if LOCK_DEBUG if (locktype == VMNT_READ) fp->fp_vmnt_rdlocks++; #endif return(OK); } /*===========================================================================* * unlock_vmnt * *===========================================================================*/ PUBLIC void unlock_vmnt(struct vmnt *vmp) { ASSERTVMP(vmp); #if LOCK_DEBUG /* Decrease read-only lock counter when not locked as VMNT_WRITE or * VMNT_EXCL */ if (!tll_locked_by_me(&vmp->m_lock)) fp->fp_vmnt_rdlocks--; #endif tll_unlock(&vmp->m_lock); #if LOCK_DEBUG assert(!tll_locked_by_me(&vmp->m_lock)); #endif }