Beispiel #1
0
int
mount_lofs(char *mntdir, char *fs_name, char *opts, int on_autofs)
{
  mntent_t mnt;
  int flags;

  /*
   * Figure out the name of the file system type.
   */
  MTYPE_TYPE type = MOUNT_TYPE_LOFS;

  /*
   * Fill in the mount structure
   */
  memset((voidp) &mnt, 0, sizeof(mnt));
  mnt.mnt_dir = mntdir;
  mnt.mnt_fsname = fs_name;
  mnt.mnt_type = MNTTAB_TYPE_LOFS;
  mnt.mnt_opts = opts;

  flags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
  if (on_autofs)
    flags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */

  /*
   * Call generic mount routine
   */
  return mount_fs(&mnt, flags, NULL, 0, type, 0, NULL, mnttab_file_name, on_autofs);
}
Beispiel #2
0
static int
mount_efs(char *mntdir, char *fs_name, char *opts, int on_autofs)
{
  efs_args_t efs_args;
  mntent_t mnt;
  int flags;

  /*
   * Figure out the name of the file system type.
   */
  MTYPE_TYPE type = MOUNT_TYPE_EFS;

  memset((voidp) &efs_args, 0, sizeof(efs_args)); /* Paranoid */

  /*
   * Fill in the mount structure
   */
  memset((voidp) &mnt, 0, sizeof(mnt));
  mnt.mnt_dir = mntdir;
  mnt.mnt_fsname = fs_name;
  mnt.mnt_type = MNTTAB_TYPE_EFS;
  mnt.mnt_opts = opts;

  flags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
  if (on_autofs)
    flags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */

#ifdef HAVE_EFS_ARGS_T_FLAGS
  efs_args.flags = 0;		/* XXX: fix this to correct flags */
#endif /* HAVE_EFS_ARGS_T_FLAGS */
#ifdef HAVE_EFS_ARGS_T_FSPEC
  efs_args.fspec = fs_name;
#endif /* HAVE_EFS_ARGS_T_FSPEC */
#if defined(HAVE_EFS_ARGS_T_VERSION) && defined(EFS_MNT_VERSION)
  efs_args.version = EFS_MNT_VERSION;
#endif /* HAVE_EFS_ARGS_T_VERSION && EFS_MNT_VERSION */

  /*
   * Call generic mount routine
   */
  return mount_fs(&mnt, flags, (caddr_t) &efs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
}
Beispiel #3
0
static int
lustre_mount(am_node *am, mntfs *mf)
{
  mntent_t mnt;
  int genflags, error;
  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;

  /*
   * Figure out the name of the file system type.
   */
  MTYPE_TYPE type = MOUNT_TYPE_LUSTRE;

  /*
   * Fill in the mount structure
   */
  memset(&mnt, 0, sizeof(mnt));
  mnt.mnt_dir = mf->mf_mount;
  mnt.mnt_fsname = mf->mf_info;
  mnt.mnt_type = MNTTAB_TYPE_LUSTRE;
  mnt.mnt_opts = mf->mf_mopts;

  genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
  if (on_autofs)
    genflags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */

  /*
   * Call generic mount routine
   */
  error = mount_fs(&mnt, genflags, NULL, 0, type, 0,
      NULL, mnttab_file_name, on_autofs);
  if (error) {
    errno = error;
    plog(XLOG_ERROR, "mount_lustre: %m");
    return error;
  }

  return 0;
}
Beispiel #4
0
static int
mount_pcfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
{
  pcfs_args_t pcfs_args;
  mntent_t mnt;
  int flags;
#if defined(HAVE_PCFS_ARGS_T_MASK) || defined(HAVE_PCFS_ARGS_T_DIRMASK)
  int mask;
#endif /* defined(HAVE_PCFS_ARGS_T_MASK) || defined(HAVE_PCFS_ARGS_T_DIRMASK) */
#if defined(HAVE_PCFS_ARGS_T_UID) || defined(HAVE_PCFS_ARGS_T_UID)
  char *str;
#endif /* defined(HAVE_PCFS_ARGS_T_UID) || defined(HAVE_PCFS_ARGS_T_UID) */

  /*
   * Figure out the name of the file system type.
   */
  MTYPE_TYPE type = MOUNT_TYPE_PCFS;

  memset((voidp) &pcfs_args, 0, sizeof(pcfs_args)); /* Paranoid */

  /*
   * Fill in the mount structure
   */
  memset((voidp) &mnt, 0, sizeof(mnt));
  mnt.mnt_dir = mntdir;
  mnt.mnt_fsname = fs_name;
  mnt.mnt_type = MNTTAB_TYPE_PCFS;
  mnt.mnt_opts = opts;

  flags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
  if (on_autofs)
    flags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
  if (amuDebug(D_TRACE))
    plog(XLOG_DEBUG, "mount_pcfs: flags=0x%x", (u_int) flags);

#ifdef HAVE_PCFS_ARGS_T_FSPEC
  pcfs_args.fspec = fs_name;
#endif /* HAVE_PCFS_ARGS_T_FSPEC */

#ifdef HAVE_PCFS_ARGS_T_MASK
  pcfs_args.mask = 0777;	/* this may be the msdos file modes */
  if ((mask = hasmntval(&mnt, MNTTAB_OPT_MASK)) > 0)
    pcfs_args.mask = mask;
  if (amuDebug(D_TRACE))
    plog(XLOG_DEBUG, "mount_pcfs: mask=%o (octal)", (u_int) pcfs_args.mask);
#endif /* HAVE_PCFS_ARGS_T_MASK */

#ifdef HAVE_PCFS_ARGS_T_DIRMASK
  pcfs_args.dirmask = 0777;    /* this may be the msdos dir modes */
  if ((mask = hasmntval(&mnt, MNTTAB_OPT_DIRMASK)) > 0)
    pcfs_args.dirmask = mask;
  if (amuDebug(D_TRACE))
    plog(XLOG_DEBUG, "mount_pcfs: dirmask=%o (octal)", (u_int) pcfs_args.dirmask);
#endif /* HAVE_PCFS_ARGS_T_DIRMASK */

#ifdef HAVE_PCFS_ARGS_T_UID
  pcfs_args.uid = 0;		/* default to root */
  if ((str = hasmntstr(&mnt, MNTTAB_OPT_USER)) != NULL) {
    struct passwd *pw;
    if ((pw = getpwnam(str)) != NULL)
      pcfs_args.uid = pw->pw_uid;
    else		 /* maybe used passed a UID number, not user name */
      pcfs_args.uid = atoi(str); /* atoi returns '0' if it failed */
    XFREE(str);
  }
  if (amuDebug(D_TRACE))
    plog(XLOG_DEBUG, "mount_pcfs: uid=%d", (int) pcfs_args.uid);
#endif /* HAVE_PCFS_ARGS_T_UID */

#ifdef HAVE_PCFS_ARGS_T_GID
  pcfs_args.gid = 0;		/* default to wheel/root group */
  if ((str = hasmntstr(&mnt, MNTTAB_OPT_GROUP)) != NULL) {
    struct group *gr;
    if ((gr = getgrnam(str)) != NULL)
      pcfs_args.gid = gr->gr_gid;
    else		/* maybe used passed a GID number, not group name */
      pcfs_args.gid = atoi(str); /* atoi returns '0' if it failed */
    XFREE(str);
  }
  if (amuDebug(D_TRACE))
    plog(XLOG_DEBUG, "mount_pcfs: gid=%d", (int) pcfs_args.gid);
#endif /* HAVE_PCFS_ARGS_T_GID */

#ifdef HAVE_PCFS_ARGS_T_SECONDSWEST
  pcfs_args.secondswest = 0;	/* XXX: fill in correct values */
#endif /* HAVE_PCFS_ARGS_T_SECONDSWEST */
#ifdef HAVE_PCFS_ARGS_T_DSTTIME
  pcfs_args.dsttime = 0;	/* XXX: fill in correct values */
#endif /* HAVE_PCFS_ARGS_T_DSTTIME */

  /*
   * Call generic mount routine
   */
  return mount_fs(&mnt, flags, (caddr_t) & pcfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
}
Beispiel #5
0
/*
 * mntpt is the mount point ($fs) [XXX: was 'dir']
 * backdir is the mounted pathname ($rfs) [XXX: was 'fs_name']
 * cachedir is the cache directory ($cachedir)
 */
static int
mount_cachefs(char *mntdir, char *real_mntdir, char *backdir, char *cachedir,
	      char *opts, int on_autofs)
{
  cachefs_args_t ca;
  mntent_t mnt;
  int flags;
  char *cp;
  MTYPE_TYPE type = MOUNT_TYPE_CACHEFS;	/* F/S mount type */

  memset((voidp) &ca, 0, sizeof(ca)); /* Paranoid */

  /*
   * Fill in the mount structure
   */
  memset((voidp) &mnt, 0, sizeof(mnt));
  mnt.mnt_dir = mntdir;
  mnt.mnt_fsname = backdir;
  mnt.mnt_type = MNTTAB_TYPE_CACHEFS;
  mnt.mnt_opts = opts;

  flags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
  if (on_autofs)
    flags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */

  /* Fill in cachefs mount arguments */

  /*
   * XXX: Caveats
   * (1) cache directory is NOT checked for sanity beforehand, nor is it
   * purged.  Maybe it should be purged first?
   * (2) cache directory is NOT locked.  Should we?
   */

  /* mount flags */
  ca.cfs_options.opt_flags = CFS_WRITE_AROUND | CFS_ACCESS_BACKFS;
  /* cache population size */
  ca.cfs_options.opt_popsize = DEF_POP_SIZE; /* default: 64K */
  /* filegrp size */
  ca.cfs_options.opt_fgsize = DEF_FILEGRP_SIZE; /* default: 256 */

  /* CFS ID for file system (must be unique) */
  ca.cfs_fsid = cachedir;

  /* CFS fscdir name */
  memset(ca.cfs_cacheid, 0, sizeof(ca.cfs_cacheid));
  /* append cacheid and mountpoint */
  sprintf(ca.cfs_cacheid, "%s:%s", ca.cfs_fsid, mntdir);
  /* convert '/' to '_' (Solaris does that...) */
  cp = ca.cfs_cacheid;
  while ((cp = strpbrk(cp, "/")) != NULL)
    *cp = '_';

  /* path for this cache dir */
  ca.cfs_cachedir = cachedir;

  /* back filesystem dir */
  ca.cfs_backfs = backdir;

  /* same as nfs values (XXX: need to handle these options) */
  ca.cfs_acregmin = 0;
  ca.cfs_acregmax = 0;
  ca.cfs_acdirmin = 0;
  ca.cfs_acdirmax = 0;

  /*
   * Call generic mount routine
   */
  return mount_fs2(&mnt, real_mntdir, flags, (caddr_t) &ca, 0, type, 0, NULL, mnttab_file_name);
}
Beispiel #6
0
static int
mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
{
  cdfs_args_t cdfs_args;
  mntent_t mnt;
  int genflags, cdfs_flags, retval;

  /*
   * Figure out the name of the file system type.
   */
  MTYPE_TYPE type = MOUNT_TYPE_CDFS;

  memset((voidp) &cdfs_args, 0, sizeof(cdfs_args)); /* Paranoid */
  cdfs_flags = 0;

  /*
   * Fill in the mount structure
   */
  memset((voidp) &mnt, 0, sizeof(mnt));
  mnt.mnt_dir = mntdir;
  mnt.mnt_fsname = fs_name;
  mnt.mnt_type = MNTTAB_TYPE_CDFS;
  mnt.mnt_opts = opts;

#if defined(MNT2_CDFS_OPT_DEFPERM) && defined(MNTTAB_OPT_DEFPERM)
  if (amu_hasmntopt(&mnt, MNTTAB_OPT_DEFPERM))
# ifdef MNT2_CDFS_OPT_DEFPERM
    cdfs_flags |= MNT2_CDFS_OPT_DEFPERM;
# else /* not MNT2_CDFS_OPT_DEFPERM */
    cdfs_flags &= ~MNT2_CDFS_OPT_NODEFPERM;
# endif /* not MNT2_CDFS_OPT_DEFPERM */
#endif /* defined(MNT2_CDFS_OPT_DEFPERM) && defined(MNTTAB_OPT_DEFPERM) */

#if defined(MNT2_CDFS_OPT_NODEFPERM) && defined(MNTTAB_OPT_NODEFPERM)
  if (amu_hasmntopt(&mnt, MNTTAB_OPT_NODEFPERM))
    cdfs_flags |= MNT2_CDFS_OPT_NODEFPERM;
#endif /* MNTTAB_OPT_NODEFPERM */

#if defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION)
  if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOVERSION))
    cdfs_flags |= MNT2_CDFS_OPT_NOVERSION;
#endif /* defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION) */

#if defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP)
  if (amu_hasmntopt(&mnt, MNTTAB_OPT_RRIP))
    cdfs_flags |= MNT2_CDFS_OPT_RRIP;
#endif /* defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP) */
#if defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP)
  if (amu_hasmntopt(&mnt, MNTTAB_OPT_NORRIP))
    cdfs_flags |= MNT2_CDFS_OPT_NORRIP;
#endif /* defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP) */

#if defined(MNT2_CDFS_OPT_GENS) && defined(MNTTAB_OPT_GENS)
  if (amu_hasmntopt(&mnt, MNTTAB_OPT_GENS))
    cdfs_flags |= MNT2_CDFS_OPT_GENS;
#endif /* defined(MNT2_CDFS_OPT_GENS) && defined(MNTTAB_OPT_GENS) */
#if defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT)
  if (amu_hasmntopt(&mnt, MNTTAB_OPT_EXTATT))
    cdfs_flags |= MNT2_CDFS_OPT_EXTATT;
#endif /* defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT) */

  genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
  if (on_autofs)
    genflags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */

#ifdef HAVE_CDFS_ARGS_T_FLAGS
  cdfs_args.flags = cdfs_flags;
#endif /* HAVE_CDFS_ARGS_T_FLAGS */

#ifdef HAVE_CDFS_ARGS_T_ISO_FLAGS
  cdfs_args.iso_flags = genflags | cdfs_flags;
#endif /* HAVE_CDFS_ARGS_T_ISO_FLAGS */

#ifdef HAVE_CDFS_ARGS_T_ISO_PGTHRESH
  cdfs_args.iso_pgthresh = hasmntval(&mnt, MNTTAB_OPT_PGTHRESH);
#endif /* HAVE_CDFS_ARGS_T_ISO_PGTHRESH */

#ifdef HAVE_CDFS_ARGS_T_NORRIP
  /* XXX: need to provide norrip mount opt */
  cdfs_args.norrip = 0;		/* use Rock-Ridge Protocol extensions */
#endif /* HAVE_CDFS_ARGS_T_NORRIP */

#ifdef HAVE_CDFS_ARGS_T_SSECTOR
  /* XXX: need to provide ssector mount option */
  cdfs_args.ssector = 0;	/* use 1st session on disk */
#endif /* HAVE_CDFS_ARGS_T_SSECTOR */

#ifdef HAVE_CDFS_ARGS_T_FSPEC
  cdfs_args.fspec = fs_name;
#endif /* HAVE_CDFS_ARGS_T_FSPEC */

  /*
   * Call generic mount routine
   */
  retval = mount_fs(&mnt, genflags, (caddr_t) &cdfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);

  return retval;
}
Beispiel #7
0
static int
mount_tmpfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
{
  tmpfs_args_t tmpfs_args;
  mntent_t mnt;
  int flags;
  const char *p;

  /*
   * Figure out the name of the file system type.
   */
  MTYPE_TYPE type = MOUNT_TYPE_TMPFS;

  p = NULL;
  memset((voidp) &tmpfs_args, 0, sizeof(tmpfs_args)); /* Paranoid */

  /*
   * Fill in the mount structure
   */
  memset((voidp) &mnt, 0, sizeof(mnt));
  mnt.mnt_dir = mntdir;
  mnt.mnt_fsname = fs_name;
  mnt.mnt_type = MNTTAB_TYPE_TMPFS;
  mnt.mnt_opts = opts;

  flags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
  if (on_autofs)
    flags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */

#if defined(HAVE_TMPFS_ARGS_T_TA_VERSION) && defined(TMPFS_ARGS_VERSION)
  tmpfs_args.ta_version = TMPFS_ARGS_VERSION;
#endif /* HAVE_TMPFS_ARGS_T_TA_VERSION && TMPFS_ARGS_VERSION */
#ifdef HAVE_TMPFS_ARGS_T_TA_NODES_MAX
  if ((p = amu_hasmntopt(&mnt, "nodes")) == NULL)
	p = "1000000";
  tmpfs_args.ta_nodes_max = atoi(p);
#endif /* HAVE_TMPFS_ARGS_T_TA_SIZE_MAX */
#ifdef HAVE_TMPFS_ARGS_T_TA_SIZE_MAX
  if ((p = amu_hasmntopt(&mnt, "size")) == NULL)
	p = "10000000";
  tmpfs_args.ta_size_max = atoi(p);
#endif /* HAVE_TMPFS_ARGS_T_TA_SIZE_MAX */
#ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_UID
  if ((p = amu_hasmntopt(&mnt, "uid")) == NULL)
	p = "0";
  tmpfs_args.ta_root_uid = atoi(p);
#endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_UID */
#ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_GID
  if ((p = amu_hasmntopt(&mnt, "gid")) == NULL)
	p = "0";
  tmpfs_args.ta_root_gid = atoi(p);
#endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_GID */
#ifdef HAVE_TMPFS_ARGS_T_TA_ROOT_MODE
  if ((p = amu_hasmntopt(&mnt, "mode")) == NULL)
	p = "01777";
  tmpfs_args.ta_root_mode = strtol(p, NULL, 8);
#endif /* HAVE_TMPFS_ARGS_T_TA_ROOT_MODE */

  /*
   * Call generic mount routine
   */
  return mount_fs(&mnt, flags, (caddr_t) &tmpfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
}
Beispiel #8
0
/*
 * 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;
}