Пример #1
0
/*===========================================================================*
 *				put_vnode				     *
 *===========================================================================*/
PUBLIC void put_vnode(struct vnode *vp)
{
/* Decrease vnode's usage counter and decrease inode's usage counter in the
 * corresponding FS process. Decreasing the fs_count each time we decrease the
 * ref count would lead to poor performance. Instead, only decrease fs_count
 * when the ref count hits zero. However, this could lead to fs_count to wrap.
 * To prevent this, we drop the counter to 1 when the counter hits 256.
 * We maintain fs_count as a sanity check to make sure VFS and the FS are in
 * sync.
 */
  int r, lock_vp;

  ASSERTVP(vp);

  /* Lock vnode. It's quite possible this thread already has a lock on this
   * vnode. That's no problem, because the reference counter will not decrease
   * to zero in that case. However, if the counter does decrease to zero *and*
   * is already locked, we have a consistency problem somewhere. */
  lock_vp = lock_vnode(vp, VNODE_OPCL);

  if (vp->v_ref_count > 1) {
	/* Decrease counter */
	vp->v_ref_count--;
	if (vp->v_fs_count > 256)
		vnode_clean_refs(vp);
	if (lock_vp != EBUSY) unlock_vnode(vp);
	return;
  }

  /* If we already had a lock, there is a consistency problem */
  assert(lock_vp != EBUSY);
  tll_upgrade(&vp->v_lock);	/* Make sure nobody else accesses this vnode */

  /* A vnode that's not in use can't be put back. */
  if (vp->v_ref_count <= 0)
	panic("put_vnode failed: bad v_ref_count %d\n", vp->v_ref_count);

  /* fs_count should indicate that the file is in use. */
  if (vp->v_fs_count <= 0)
	panic("put_vnode failed: bad v_fs_count %d\n", vp->v_fs_count);

  /* Tell FS we don't need this inode to be open anymore. */
  r = req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count);

  if (r != OK) {
	printf("VFS: putnode failed: %d\n", r);
	util_stacktrace();
  }

  /* This inode could've been mapped. If so, tell mapped FS to close it as
   * well. If mapped onto same FS, this putnode is not needed. */
  if (vp->v_mapfs_e != NONE && vp->v_mapfs_e != vp->v_fs_e)
	req_putnode(vp->v_mapfs_e, vp->v_mapinode_nr, vp->v_mapfs_count);

  vp->v_fs_count = 0;
  vp->v_ref_count = 0;
  vp->v_mapfs_count = 0;

  unlock_vnode(vp);
}
Пример #2
0
/*===========================================================================*
 *				put_vnode				     *
 *===========================================================================*/
PUBLIC void put_vnode(struct vnode *vp)
{
/* Decrease vnode's usage counter and decrease inode's usage counter in the 
 * corresponding FS process. Decreasing the fs_count each time we decrease the
 * ref count would lead to poor performance. Instead, only decrease fs_count
 * when the ref count hits zero. However, this could lead to fs_count to wrap.
 * To prevent this, we drop the counter to 1 when the counter hits 256.
 * We maintain fs_count as a sanity check to make sure VFS and the FS are in
 * sync.
 */
  ASSERTVP(vp);

  if (vp->v_ref_count > 1) {
	/* Decrease counter */
	vp->v_ref_count--;
	if (vp->v_fs_count > 256) 
		vnode_clean_refs(vp);

	return;
  }

  /* A vnode that's not in use can't be put. */
  if (vp->v_ref_count <= 0) {
	printf("put_vnode: bad v_ref_count %d\n", vp->v_ref_count);
	panic(__FILE__, "put_vnode failed", NO_NUM);
  }

  /* fs_count should indicate that the file is in use. */
  if (vp->v_fs_count <= 0) {
	printf("put_vnode: bad v_fs_count %d\n", vp->v_fs_count);
	panic(__FILE__, "put_vnode failed", NO_NUM);
  }

  /* Tell FS we don't need this inode to be open anymore. */
  req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count); 

  /* This inode could've been mapped. If so, tell PFS to close it as well. */
  if(vp->v_mapfs_e != 0  && vp->v_mapinode_nr != vp->v_inode_nr &&
     vp->v_mapfs_e != vp->v_fs_e) {
	req_putnode(vp->v_mapfs_e, vp->v_mapinode_nr, vp->v_mapfs_count); 
  }

  vp->v_fs_count = 0;
  vp->v_ref_count = 0;
  vp->v_pipe = NO_PIPE;
  vp->v_sdev = NO_DEV;
  vp->v_mapfs_e = 0;
  vp->v_mapinode_nr = 0;
  vp->v_mapfs_count = 0;
}
Пример #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);
}