コード例 #1
0
static int
pcfs_umount(am_node *am, mntfs *mf)
{
  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;

  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
}
コード例 #2
0
ファイル: autofs_solaris_v1.c プロジェクト: ryo/netbsd-src
int
autofs_umount_fs(am_node *mp, mntfs *mf)
{
    int err = 0;
    char *space_hack = autofs_strdup_space_hack(mp->am_path);

    /*
     * Autofs v1 doesn't support symlinks,
     * so we ignore the CFM_AUTOFS_USE_LOFS flag
     */
    if (!(mf->mf_flags & MFF_ON_AUTOFS)) {
        err = UMOUNT_FS(mp->am_path, mnttab_file_name, 1);
        if (err)
            goto out;
        rmdir(space_hack);
    }

    /*
     * Multiple sublinks could reference this f/s.
     * Don't actually unmount it unless we're holding the last reference.
     */
    if (mf->mf_refc == 1) {
        if ((err = mf->mf_ops->umount_fs(mp, mf)))
            goto out;

        if (mf->mf_flags & MFF_ON_AUTOFS)
            rmdir(space_hack);
    }

out:
    XFREE(space_hack);
    return err;
}
コード例 #3
0
ファイル: ops_cachefs.c プロジェクト: AzerTyQsdF/osx
static int
cachefs_umount(am_node *am, mntfs *mf)
{
  int error;

  error = UMOUNT_FS(mf->mf_mount, mf->mf_real_mount, mnttab_file_name);

  /*
   * In the case of cachefs, we must fsck the cache directory.  Otherwise,
   * it will remain inconsistent, and the next cachefs mount will fail
   * with the error "no space left on device" (ENOSPC).
   *
   * XXX: this is hacky! use fork/exec/wait instead...
   */
  if (!error) {
    char *cachedir = NULL;
    char cmd[128];

    cachedir = (char *) mf->mf_private;
    plog(XLOG_INFO, "running fsck on cache directory \"%s\"", cachedir);
    sprintf(cmd, "fsck -F cachefs %s", cachedir);
    system(cmd);
  }

  return error;
}
コード例 #4
0
ファイル: amfs_toplvl.c プロジェクト: randy1/DragonFlyBSD
/*
 * Unmount a top-level automount node
 */
int
amfs_toplvl_umount(am_node *mp)
{
    int error;
    struct stat stb;

again:
    /*
     * The lstat is needed if this mount is type=direct.
     * When that happens, the kernel cache gets confused
     * between the underlying type (dir) and the mounted
     * type (link) and so needs to be re-synced before
     * the unmount.  This is all because the unmount system
     * call follows links and so can't actually unmount
     * a link (stupid!).  It was noted that doing an ls -ld
     * of the mount point to see why things were not working
     * actually fixed the problem - so simulate an ls -ld here.
     */
    if (lstat(mp->am_path, &stb) < 0) {
#ifdef DEBUG
        dlog("lstat(%s): %m", mp->am_path);
#endif /* DEBUG */
    }
    error = UMOUNT_FS(mp->am_path, mnttab_file_name);
    if (error == EBUSY) {
        plog(XLOG_WARNING, "amfs_toplvl_unmount retrying %s in 1s", mp->am_path);
        sleep(1);			/* XXX */
        goto again;
    }
    return error;
}
コード例 #5
0
ファイル: amfs_generic.c プロジェクト: IIJ-NetBSD/netbsd-src
/*
 * Unmount an automount sub-node
 */
int
amfs_generic_umount(am_node *mp, mntfs *mf)
{
  int error = 0;

#ifdef HAVE_FS_AUTOFS
  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
  if (mf->mf_flags & MFF_IS_AUTOFS)
    error = UMOUNT_FS(mp->am_path, mnttab_file_name, unmount_flags);
#endif /* HAVE_FS_AUTOFS */

  return error;
}
コード例 #6
0
ファイル: hlfsd.c プロジェクト: gosudream/netbsd-src
RETSIGTYPE
cleanup(int signum)
{
  struct stat stbuf;
  int umount_result;

  if (amuDebug(D_DAEMON)) {
    if (getpid() != masterpid)
      return;

    if (fork() != 0) {
      masterpid = 0;
      am_set_mypid();
      return;
    }
  }
  am_set_mypid();

  for (;;) {
    while ((umount_result = UMOUNT_FS(dir_name, mnttab_file_name, 0)) == EBUSY) {
      dlog("cleanup(): umount delaying for 10 seconds");
      sleep(10);
    }
    if (stat(dir_name, &stbuf) == 0 && stbuf.st_ino == ROOTID) {
      plog(XLOG_ERROR, "unable to unmount %s", dir_name);
      plog(XLOG_ERROR, "suspending, unmount before terminating");
      kill(am_mypid, SIGSTOP);
      continue;			/* retry unmount */
    }
    break;
  }

  if (amuDebug(D_DAEMON)) {
    plog(XLOG_INFO, "cleanup(): killing processes and terminating");
    kill(masterpid, SIGKILL);
    kill(serverpid, SIGKILL);
  }

  plog(XLOG_INFO, "hlfsd terminating with status 0\n");
  _exit(0);
}
コード例 #7
0
ファイル: amfs_host.c プロジェクト: IIJ-NetBSD/netbsd-src
/*
 * Unmount a mount tree
 */
static int
amfs_host_umount(am_node *am, mntfs *mf)
{
  mntlist *ml, *mprev;
  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
  int xerror = 0;

  /*
   * Read the mount list
   */
  mntlist *mlist = read_mtab(mf->mf_mount, mnttab_file_name);

#ifdef MOUNT_TABLE_ON_FILE
  /*
   * Unlock the mount list
   */
  unlock_mntlist();
#endif /* MOUNT_TABLE_ON_FILE */

  /*
   * Reverse list...
   */
  ml = mlist;
  mprev = NULL;
  while (ml) {
    mntlist *ml2 = ml->mnext;
    ml->mnext = mprev;
    mprev = ml;
    ml = ml2;
  }
  mlist = mprev;

  /*
   * Unmount all filesystems...
   */
  for (ml = mlist; ml && !xerror; ml = ml->mnext) {
    char *dir = ml->mnt->mnt_dir;
    if (directory_prefix(mf->mf_mount, dir)) {
      int error;
      dlog("amfs_host: unmounts %s", dir);
      /*
       * Unmount "dir"
       */
      error = UMOUNT_FS(dir, mnttab_file_name, unmount_flags);
      /*
       * Keep track of errors
       */
      if (error) {
	/*
	 * If we have not already set xerror and error is not ENOENT,
	 * then set xerror equal to error and log it.
	 * 'xerror' is the return value for this function.
	 *
	 * We do not want to pass ENOENT as an error because if the
	 * directory does not exists our work is done anyway.
	 */
	if (!xerror && error != ENOENT)
	  xerror = error;
	if (error != EBUSY) {
	  errno = error;
	  plog(XLOG_ERROR, "Tree unmount of %s failed: %m", ml->mnt->mnt_dir);
	}
      } else {
	(void) rmdirs(dir);
      }
    }
  }

  /*
   * Throw away mount list
   */
  discard_mntlist(mlist);

  /*
   * Try to remount, except when we are shutting down.
   */
  if (xerror && amd_state != Finishing) {
    xerror = amfs_host_mount(am, mf);
    if (!xerror) {
      /*
       * Don't log this - it's usually too verbose
       plog(XLOG_INFO, "Remounted host %s", mf->mf_info);
       */
      xerror = EBUSY;
    }
  }
  return xerror;
}
コード例 #8
0
ファイル: amfs_toplvl.c プロジェクト: enukane/netbsd-src
/*
 * Unmount a top-level automount node
 */
int
amfs_toplvl_umount(am_node *mp, mntfs *mf)
{
  struct stat stb;
  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
  int error;
  int count = 0;		/* how many times did we try to unmount? */

again:
  /*
   * The lstat is needed if this mount is type=direct.
   * When that happens, the kernel cache gets confused
   * between the underlying type (dir) and the mounted
   * type (link) and so needs to be re-synced before
   * the unmount.  This is all because the unmount system
   * call follows links and so can't actually unmount
   * a link (stupid!).  It was noted that doing an ls -ld
   * of the mount point to see why things were not working
   * actually fixed the problem - so simulate an ls -ld here.
   */
  if (lstat(mp->am_path, &stb) < 0) {
    error = errno;
    dlog("lstat(%s): %m", mp->am_path);
    goto out;
  }
  if ((stb.st_mode & S_IFMT) != S_IFDIR) {
    plog(XLOG_ERROR, "amfs_toplvl_umount: %s is not a directory, aborting.", mp->am_path);
    error = ENOTDIR;
    goto out;
  }

  error = UMOUNT_FS(mp->am_path, mnttab_file_name, unmount_flags);
  if (error == EBUSY) {
#ifdef HAVE_FS_AUTOFS
    /*
     * autofs mounts are "in place", so it is possible
     * that we can't just unmount our mount points and go away.
     * If that's the case, just give up.
     */
    if (mf->mf_flags & MFF_IS_AUTOFS)
      return error;
#endif /* HAVE_FS_AUTOFS */
    plog(XLOG_WARNING, "amfs_toplvl_unmount retrying %s in 1s", mp->am_path);
    count++;
    sleep(1);
    /*
     * If user wants forced/lazy unmount semantics, then set those flags,
     * but only after we've tried normal lstat/umount a few times --
     * otherwise forced unmounts may hang this very same Amd (by preventing
     * it from achieving a clean unmount).
     */
    if (gopt.flags & CFM_FORCED_UNMOUNTS) {
      if (count == 5) {		/* after 5 seconds, try MNT_FORCE */
	dlog("enabling forced unmounts for toplvl node %s", mp->am_path);
	unmount_flags |= AMU_UMOUNT_FORCE;
      }
      if (count == 10) {	/* after 10 seconds, try MNT_DETACH */
	dlog("enabling detached unmounts for toplvl node %s", mp->am_path);
	unmount_flags |= AMU_UMOUNT_DETACH;
      }
    }
    goto again;
  }
out:
  return error;
}
コード例 #9
0
ファイル: autil.c プロジェクト: 0mp/freebsd
/*
 * Mount an automounter directory.
 * The automounter is connected into the system
 * as a user-level NFS server.  amfs_mount constructs
 * the necessary NFS parameters to be given to the
 * kernel so that it will talk back to us.
 *
 * NOTE: automounter mounts in themselves are using NFS Version 2 (UDP).
 *
 * NEW: on certain systems, mounting can be done using the
 * kernel-level automount (autofs) support. In that case,
 * we don't need NFS at all here.
 */
int
amfs_mount(am_node *mp, mntfs *mf, char *opts)
{
  char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1];
  int retry, error = 0, genflags;
  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
  char *dir = mf->mf_mount;
  mntent_t mnt;
  MTYPE_TYPE type;
  int forced_unmount = 0;	/* are we using forced unmounts? */
  u_long nfs_version = get_nfs_dispatcher_version(nfs_dispatcher);

  memset(&mnt, 0, sizeof(mnt));
  mnt.mnt_dir = dir;
  mnt.mnt_fsname = pid_fsname;
  mnt.mnt_opts = opts;

#ifdef HAVE_FS_AUTOFS
  if (mf->mf_flags & MFF_IS_AUTOFS) {
    type = MOUNT_TYPE_AUTOFS;
    /*
     * Make sure that amd's top-level autofs mounts are hidden by default
     * from df.
     * XXX: It works ok on Linux, might not work on other systems.
     */
    mnt.mnt_type = "autofs";
  } else
#endif /* HAVE_FS_AUTOFS */
  {
    type = MOUNT_TYPE_NFS;
    /*
     * Make sure that amd's top-level NFS mounts are hidden by default
     * from df.
     * If they don't appear to support the either the "ignore" mnttab
     * option entry, or the "auto" one, set the mount type to "nfs".
     */
    mnt.mnt_type = HIDE_MOUNT_TYPE;
  }

  retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
  if (retry <= 0)
    retry = 2;			/* XXX: default to 2 retries */

  /*
   * SET MOUNT ARGS
   */

  /*
   * Make a ``hostname'' string for the kernel
   */
  xsnprintf(fs_hostname, sizeof(fs_hostname), "pid%ld@%s:%s",
	    get_server_pid(), am_get_hostname(), dir);
  /*
   * Most kernels have a name length restriction (64 bytes)...
   */
  if (strlen(fs_hostname) >= MAXHOSTNAMELEN)
    xstrlcpy(fs_hostname + MAXHOSTNAMELEN - 3, "..",
	     sizeof(fs_hostname) - MAXHOSTNAMELEN + 3);
#ifdef HOSTNAMESZ
  /*
   * ... and some of these restrictions are 32 bytes (HOSTNAMESZ)
   * If you need to get the definition for HOSTNAMESZ found, you may
   * add the proper header file to the conf/nfs_prot/nfs_prot_*.h file.
   */
  if (strlen(fs_hostname) >= HOSTNAMESZ)
    xstrlcpy(fs_hostname + HOSTNAMESZ - 3, "..",
	     sizeof(fs_hostname) - HOSTNAMESZ + 3);
#endif /* HOSTNAMESZ */

  /*
   * Finally we can compute the mount genflags set above,
   * and add any automounter specific flags.
   */
  genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
  if (on_autofs)
    genflags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
  genflags |= compute_automounter_mount_flags(&mnt);

again:
  if (!(mf->mf_flags & MFF_IS_AUTOFS)) {
    nfs_args_t nfs_args;
    am_nfs_handle_t *fhp, anh;
#ifndef HAVE_TRANSPORT_TYPE_TLI
    u_short port;
    struct sockaddr_in sin;
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

    /*
     * get fhandle of remote path for automount point
     */
    fhp = get_root_nfs_fh(dir, &anh);
    if (!fhp) {
      plog(XLOG_FATAL, "Can't find root file handle for %s", dir);
      return EINVAL;
    }

#ifndef HAVE_TRANSPORT_TYPE_TLI
    /*
     * Create sockaddr to point to the local machine.
     */
    memset(&sin, 0, sizeof(sin));
    /* as per POSIX, sin_len need not be set (used internally by kernel) */
    sin.sin_family = AF_INET;
    sin.sin_addr = myipaddr;
    port = hasmntval(&mnt, MNTTAB_OPT_PORT);
    if (port) {
      sin.sin_port = htons(port);
    } else {
      plog(XLOG_ERROR, "no port number specified for %s", dir);
      return EINVAL;
    }
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

    /* setup the many fields and flags within nfs_args */
#ifdef HAVE_TRANSPORT_TYPE_TLI
    compute_nfs_args(&nfs_args,
		     &mnt,
		     genflags,
		     nfsncp,
		     NULL,	/* remote host IP addr is set below */
		     nfs_version,
		     "udp",
		     fhp,
		     fs_hostname,
		     pid_fsname);
    /*
     * IMPORTANT: set the correct IP address AFTERWARDS.  It cannot
     * be done using the normal mechanism of compute_nfs_args(), because
     * that one will allocate a new address and use NFS_SA_DREF() to copy
     * parts to it, while assuming that the ip_addr passed is always
     * a "struct sockaddr_in".  That assumption is incorrect on TLI systems,
     * because they define a special macro HOST_SELF which is DIFFERENT
     * than localhost (127.0.0.1)!
     */
    nfs_args.addr = &nfsxprt->xp_ltaddr;
#else /* not HAVE_TRANSPORT_TYPE_TLI */
    compute_nfs_args(&nfs_args,
		     &mnt,
		     genflags,
		     NULL,
		     &sin,
		     nfs_version,
		     "udp",
		     fhp,
		     fs_hostname,
		     pid_fsname);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

    /*************************************************************************
     * NOTE: while compute_nfs_args() works ok for regular NFS mounts	     *
     * the toplvl one is not quite regular, and so some options must be      *
     * corrected by hand more carefully, *after* compute_nfs_args() runs.    *
     *************************************************************************/
    compute_automounter_nfs_args(&nfs_args, &mnt);

    if (amuDebug(D_TRACE)) {
      print_nfs_args(&nfs_args, 0);
      plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags);
    }

    /* This is it!  Here we try to mount amd on its mount points */
    error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args,
		     retry, type, 0, NULL, mnttab_file_name, on_autofs);

#ifdef HAVE_TRANSPORT_TYPE_TLI
    free_knetconfig(nfs_args.knconf);
    /*
     * local automounter mounts do not allocate a special address, so
     * no need to XFREE(nfs_args.addr) under TLI.
     */
#endif /* HAVE_TRANSPORT_TYPE_TLI */

#ifdef HAVE_FS_AUTOFS
  } else {
    /* This is it!  Here we try to mount amd on its mount points */
    error = mount_fs(&mnt, genflags, (caddr_t) mp->am_autofs_fh,
		     retry, type, 0, NULL, mnttab_file_name, on_autofs);
#endif /* HAVE_FS_AUTOFS */
  }
  if (error == 0 || forced_unmount)
     return error;

  /*
   * If user wants forced/lazy unmount semantics, then try it iff the
   * current mount failed with EIO or ESTALE.
   */
  if (gopt.flags & CFM_FORCED_UNMOUNTS) {
    switch (errno) {
    case ESTALE:
    case EIO:
      forced_unmount = errno;
      plog(XLOG_WARNING, "Mount %s failed (%m); force unmount.", mp->am_path);
      if ((error = UMOUNT_FS(mp->am_path, mnttab_file_name,
			     AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH)) < 0) {
	plog(XLOG_WARNING, "Forced umount %s failed: %m.", mp->am_path);
	errno = forced_unmount;
      } else
	goto again;
    default:
      break;
    }
  }

  return error;
}