Пример #1
0
/* 终止线程 */
void thread::stop()
{
    if ( !_run )
    {
        ERROR( "thread::stop:thread not running" );
        return;
    }

    assert( "thread join zero thread id", 0 != _thread );

    _run = false;
    notify_child( EXIT );
    int32 ecode = pthread_join( _thread,NULL );
    if ( ecode )
    {
        /* On success, pthread_join() returns 0; on error, it returns an error
         * number.errno is not use.
         * not strerror(errno)
         */
        FATAL( "thread join fail:%s",strerror( ecode ) );
    }
    _join = true;

    if ( _watcher.is_active() ) _watcher.stop();
    if ( _fd[0] >= 0 ) { ::close( _fd[0] );_fd[0] = -1; }
    if ( _fd[1] >= 0 ) { ::close( _fd[1] );_fd[1] = -1; }
}
Пример #2
0
void
forcibly_timeout_mp(am_node *mp)
{
  mntfs *mf = mp->am_al->al_mnt;
  /*
   * Arrange to timeout this node
   */
  if (mf && ((mp->am_flags & AMF_ROOT) ||
	     (mf->mf_flags & (MFF_MOUNTING | MFF_UNMOUNTING)))) {
    /*
     * We aren't going to schedule a timeout, so we need to notify the
     * child here unless we are already unmounting, in which case that
     * process is responsible for notifying the child.
     */
    if (mf->mf_flags & MFF_UNMOUNTING)
      plog(XLOG_WARNING, "node %s is currently being unmounted, ignoring timeout request", mp->am_path);
    else {
      plog(XLOG_WARNING, "ignoring timeout request for active node %s", mp->am_path);
      notify_child(mp, AMQ_UMNT_FAILED, EBUSY, 0);
    }
  } else {
    plog(XLOG_INFO, "\"%s\" forcibly timed out", mp->am_path);
    mp->am_flags &= ~AMF_NOTIMEOUT;
    mp->am_ttl = clocktime(NULL);
    /*
     * Force mtime update of parent dir, to prevent DNLC/dcache from caching
     * the old entry, which could result in ESTALE errors, bad symlinks, and
     * more.
     */
    clocktime(&mp->am_parent->am_fattr.na_mtime);
    reschedule_timeout_mp();
  }
}
Пример #3
0
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);
  }
}