/*===========================================================================* * check_vnode_locks * *===========================================================================*/ PUBLIC void check_vnode_locks() { struct vnode *vp; int count = 0; for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) if (is_vnode_locked(vp)) { count++; } if (count) panic("%d locked vnodes\n", count); #if 0 printf("check_vnode_locks OK\n"); #endif }
/*===========================================================================* * get_free_vnode * *===========================================================================*/ struct vnode *get_free_vnode() { /* Find a free vnode slot in the vnode table (it's not actually allocated) */ struct vnode *vp; for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) { if (vp->v_ref_count == 0 && !is_vnode_locked(vp)) { vp->v_uid = -1; vp->v_gid = -1; vp->v_sdev = NO_DEV; vp->v_mapfs_e = NONE; vp->v_mapfs_count = 0; vp->v_mapinode_nr = 0; return(vp); } } err_code = ENFILE; return(NULL); }
/*===========================================================================* * unmount * *===========================================================================*/ int unmount( dev_t dev, /* block-special device */ char label[LABEL_MAX] /* buffer to retrieve label, or NULL */ ) { struct vnode *vp; struct vmnt *vmp_i = NULL, *vmp = NULL; int count, locks, r; /* Find vmnt that is to be unmounted */ for (vmp_i = &vmnt[0]; vmp_i < &vmnt[NR_MNTS]; ++vmp_i) { if (vmp_i->m_dev == dev) { if(vmp) panic("device mounted more than once: %d", dev); vmp = vmp_i; } } /* Did we find the vmnt (i.e., was dev a mounted device)? */ if(!vmp) return(EINVAL); if ((r = lock_vmnt(vmp, VMNT_EXCL)) != OK) return(r); /* See if the mounted device is busy. Only 1 vnode using it should be * open -- the root vnode -- and that inode only 1 time. */ locks = count = 0; for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) if (vp->v_ref_count > 0 && vp->v_dev == dev) { count += vp->v_ref_count; if (is_vnode_locked(vp)) locks++; } if (count > 1 || locks > 1 || tll_haspendinglock(&vmp->m_lock)) { unlock_vmnt(vmp); return(EBUSY); /* can't umount a busy file system */ } /* Tell FS to drop all inode references for root inode except 1. */ vnode_clean_refs(vmp->m_root_node); if (vmp->m_mounted_on) { put_vnode(vmp->m_mounted_on); vmp->m_mounted_on = NULL; } vmp->m_comm.c_max_reqs = 1; /* Force max concurrent reqs to just one, so * we won't send any messages after the * unmount request */ /* Tell FS to unmount */ if ((r = req_unmount(vmp->m_fs_e)) != OK) /* Not recoverable. */ printf("VFS: ignoring failed umount attempt FS endpoint: %d (%d)\n", vmp->m_fs_e, r); if (is_nonedev(vmp->m_dev)) free_nonedev(vmp->m_dev); if (label != NULL) strlcpy(label, vmp->m_label, LABEL_MAX); if (vmp->m_root_node) { /* PFS lacks a root node */ vmp->m_root_node->v_ref_count = 0; vmp->m_root_node->v_fs_count = 0; vmp->m_root_node->v_sdev = NO_DEV; vmp->m_root_node = NULL; } mark_vmnt_free(vmp); unlock_vmnt(vmp); /* The root FS will handle block I/O requests for this device now. */ lock_bsf(); update_bspec(dev, ROOT_FS_E, 1 /* send new driver endpoint */); unlock_bsf(); return(OK); }