コード例 #1
0
ファイル: autil.c プロジェクト: AzerTyQsdF/osx
void
am_unmounted(am_node *mp)
{
  mntfs *mf = mp->am_mnt;

  if (!foreground)		/* firewall - should never happen */
    return;

  /*
   * Do unmounted callback
   */
  if (mf->mf_ops->umounted)
    mf->mf_ops->umounted(mf);

  /*
   * This is ugly, but essentially unavoidable.
   * Sublinks must be treated separately as type==link
   * when the base type is different.
   */
  if (mp->am_link && mp->am_mnt->mf_ops != &amfs_link_ops)
    amfs_link_ops.umount_fs(mp, mp->am_mnt);

#ifdef HAVE_FS_AUTOFS
  if (mp->am_flags & AMF_AUTOFS)
    autofs_umount_succeeded(mp);
#endif /* HAVE_FS_AUTOFS */

  /*
   * Clean up any directories that were made
   *
   * If we remove the mount point of a pending mount, any queued access
   * to it will fail. So don't do it in that case.
   */
  if (mf->mf_flags & MFF_MKMNT &&
      !(mp->am_flags & AMF_REMOUNT)) {
    plog(XLOG_INFO, "removing mountpoint directory '%s'", mf->mf_real_mount);
    rmdirs(mf->mf_real_mount);
  }

  /*
   * If this is a pseudo-directory then adjust the link count
   * in the parent
   */
  if (mp->am_parent && mp->am_fattr.na_type == NFDIR)
    --mp->am_parent->am_fattr.na_nlink;

  /*
   * Update mtime of parent node
   */
  if (mp->am_parent && mp->am_parent->am_mnt)
    mp->am_parent->am_fattr.na_mtime.nt_seconds = clocktime();

  if (mp->am_flags & AMF_REMOUNT) {
    char *fname = strdup(mp->am_name);
    am_node *mp_parent = mp->am_parent;
    int error = 0;

    free_map(mp);
    plog(XLOG_INFO, "am_unmounted: remounting %s", fname);
    mp = amfs_auto_lookup_child(mp_parent, fname, &error, VLOOK_CREATE);
    if (mp && error < 0)
      mp = amfs_auto_mount_child(mp, &error);
    if (error > 0) {
      errno = error;
      plog(XLOG_ERROR, "am_unmounted: could not remount %s: %m", fname);
    }
    XFREE(fname);
  } else
    free_map(mp);
}
コード例 #2
0
ファイル: autil.c プロジェクト: 0mp/freebsd
void
am_unmounted(am_node *mp)
{
  mntfs *mf = mp->am_al->al_mnt;

  if (!foreground) {		/* firewall - should never happen */
    /*
     * This is a coding error.  Make sure we hear about it!
     */
    plog(XLOG_FATAL, "am_unmounted: illegal use in background (%s)",
	mp->am_name);
    notify_child(mp, AMQ_UMNT_OK, 0, 0);	/* XXX - be safe? */
    return;
  }

  /*
   * Do unmounted callback
   */
  if (mf->mf_ops->umounted)
    mf->mf_ops->umounted(mf);

  /*
   * This is ugly, but essentially unavoidable.
   * Sublinks must be treated separately as type==link
   * when the base type is different.
   */
  if (mp->am_link && mf->mf_ops != &amfs_link_ops)
    amfs_link_ops.umount_fs(mp, mf);

#ifdef HAVE_FS_AUTOFS
  if (mf->mf_flags & MFF_IS_AUTOFS)
    autofs_release_fh(mp);
  if (mp->am_flags & AMF_AUTOFS)
    autofs_umount_succeeded(mp);
#endif /* HAVE_FS_AUTOFS */

  /*
   * Clean up any directories that were made
   *
   * If we remove the mount point of a pending mount, any queued access
   * to it will fail. So don't do it in that case.
   * Also don't do it if the refcount is > 1.
   */
  if (mf->mf_flags & MFF_MKMNT &&
      mf->mf_refc == 1 &&
      !(mp->am_flags & AMF_REMOUNT)) {
    plog(XLOG_INFO, "removing mountpoint directory '%s'", mf->mf_mount);
    rmdirs(mf->mf_mount);
    mf->mf_flags &= ~MFF_MKMNT;
  }

  /*
   * If this is a pseudo-directory then adjust the link count
   * in the parent
   */
  if (mp->am_parent && mp->am_fattr.na_type == NFDIR)
    --mp->am_parent->am_fattr.na_nlink;

  /*
   * Update mtime of parent node
   */
  if (mp->am_parent && mp->am_parent->am_al->al_mnt)
    clocktime(&mp->am_parent->am_fattr.na_mtime);

  if (mp->am_parent && (mp->am_flags & AMF_REMOUNT)) {
    char *fname = xstrdup(mp->am_name);
    am_node *mp_parent = mp->am_parent;
    mntfs *mf_parent = mp_parent->am_al->al_mnt;
    am_node fake_mp;
    int error = 0;

    /*
     * We need to use notify_child() after free_map(), so save enough
     * to do that in fake_mp.
     */
    fake_mp.am_fd[1] = mp->am_fd[1];
    mp->am_fd[1] = -1;

    free_map(mp);
    plog(XLOG_INFO, "am_unmounted: remounting %s", fname);
    mp = mf_parent->mf_ops->lookup_child(mp_parent, fname, &error, VLOOK_CREATE);
    if (mp && error < 0)
      (void)mf_parent->mf_ops->mount_child(mp, &error);
    if (error > 0) {
      errno = error;
      plog(XLOG_ERROR, "am_unmounted: could not remount %s: %m", fname);
      notify_child(&fake_mp, AMQ_UMNT_OK, 0, 0);
    } else {
      notify_child(&fake_mp, AMQ_UMNT_FAILED, EBUSY, 0);
    }
    XFREE(fname);
  } else {
    /*
     * We have a race here.
     * If this node has a pending mount and amd is going down (unmounting
     * everything in the process), then we could potentially free it here
     * while a struct continuation still has a reference to it. So when
     * amfs_cont is called, it blows up.
     * We avoid the race by refusing to free any nodes that have
     * pending mounts (defined as having a non-NULL am_alarray).
     */
    notify_child(mp, AMQ_UMNT_OK, 0, 0);	/* do this regardless */
    if (!mp->am_alarray)
      free_map(mp);
  }
}