Ejemplo n.º 1
0
/*===========================================================================*
 *				is_vnode_locked				     *
 *===========================================================================*/
PUBLIC int is_vnode_locked(struct vnode *vp)
{
/* Find out whether a thread holds a lock on this vnode or is trying to obtain
 * a lock. */
  ASSERTVP(vp);

  return(tll_islocked(&vp->v_lock) || tll_haspendinglock(&vp->v_lock));
}
Ejemplo n.º 2
0
/*===========================================================================*
 *                             is_vmnt_locked				     *
 *===========================================================================*/
PRIVATE int is_vmnt_locked(struct vmnt *vmp)
{
  ASSERTVMP(vmp);
  return(tll_islocked(&vmp->m_lock) || tll_haspendinglock(&vmp->m_lock));
}
Ejemplo n.º 3
0
/*===========================================================================*
 *                              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);
}