/*
 * Construct top-level node
 */
void
make_root_node(void)
{
  mntfs *root_mnt;
  char *rootmap = ROOT_MAP;
  root_node = exported_ap_alloc();

  /*
   * Allocate a new map
   */
  init_map(root_node, "");

  /*
   * Allocate a new mounted filesystem
   */
  root_mnt = find_mntfs(&amfs_root_ops, (am_opts *) 0, "", rootmap, "", "", "");

  /*
   * Replace the initial null reference
   */
  free_mntfs(root_node->am_mnt);
  root_node->am_mnt = root_mnt;

  /*
   * Initialize the root
   */
  if (root_mnt->mf_ops->fs_init)
    (*root_mnt->mf_ops->fs_init) (root_mnt);

  /*
   * Mount the root
   */
  root_mnt->mf_error = root_mnt->mf_ops->mount_fs(root_node, root_mnt);
}
Exemple #2
0
/*
 * Handle an amd restart.
 *
 * Scan through the mount list finding all "interesting" mount points.
 * Next hack up partial data structures and add the mounted file
 * system to the list of known filesystems.  This will leave a
 * dangling reference to that filesystems, so when the filesystem is
 * finally inherited, an extra "free" must be done on it.
 *
 * This module relies on internal details of other components.  If
 * you change something else make *sure* restart() still works.
 */
void
restart(void)
{
  /*
   * Read the existing mount table
   */
  mntlist *ml, *mlp;

  /*
   * For each entry, find nfs, ufs or auto mounts
   * and create a partial am_node to represent it.
   */
  for (mlp = ml = read_mtab("restart", mnttab_file_name);
       mlp;
       mlp = mlp->mnext) {
    mntent_t *me = mlp->mnt;
    am_ops *fs_ops = 0;
    if (STREQ(me->mnt_type, MNTTAB_TYPE_UFS)) {
      /*
       * UFS entry
       */
      fs_ops = &ufs_ops;
    } else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
      /*
       * NFS entry, or possibly an Amd entry...
       * The mnt_fsname for daemon mount points is
       * 	host:(pidXXX)
       * or (seen on Solaris)
       *        host:daemon(pidXXX)
       */
      char *colon = strchr(me->mnt_fsname, ':');

      if (colon && strstr(colon, "(pid")) {
	plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir);
	fs_ops = &amfs_link_ops;
      } else {
	fs_ops = &nfs_ops;
      }
#ifdef MNTTAB_TYPE_NFS3
    } else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS3)) {
      fs_ops = &nfs_ops;
#endif /* MNTTAB_TYPE_NFS3 */
#ifdef MNTTAB_TYPE_LOFS
    } else if (STREQ(me->mnt_type, MNTTAB_TYPE_LOFS)) {
      fs_ops = &lofs_ops;
#endif /* MNTTAB_TYPE_LOFS */
#ifdef MNTTAB_TYPE_CDFS
    } else if (STREQ(me->mnt_type, MNTTAB_TYPE_CDFS)) {
      fs_ops = &cdfs_ops;
#endif /* MNTTAB_TYPE_CDFS */
#ifdef MNTTAB_TYPE_PCFS
    } else if (STREQ(me->mnt_type, MNTTAB_TYPE_PCFS)) {
      fs_ops = &pcfs_ops;
#endif /* MNTTAB_TYPE_PCFS */
#ifdef MNTTAB_TYPE_MFS
    } else if (STREQ(me->mnt_type, MNTTAB_TYPE_MFS)) {
      /*
       * MFS entry.  Fake with a symlink.
       */
      fs_ops = &amfs_link_ops;
#endif /* MNTTAB_TYPE_MFS */
    } else {
      /*
       * Catch everything else with symlinks to
       * avoid recursive mounts.  This is debatable...
       */
      fs_ops = &amfs_link_ops;
    }

    /*
     * If we found something to do
     */
    if (fs_ops) {
      mntfs *mf;
      am_opts mo;
      char *cp;
      cp = strchr(me->mnt_fsname, ':');

      /*
       * Partially fake up an opts structure
       */
      memset(&mo, 0, sizeof(mo));
      mo.opt_rhost = 0;
      mo.opt_rfs = 0;
      if (cp) {
	*cp = '\0';
	mo.opt_rhost = strdup(me->mnt_fsname);
	mo.opt_rfs = strdup(cp + 1);
	*cp = ':';
      } else if (fs_ops->ffserver == find_nfs_srvr) {
	/*
	 * Prototype 4.4 BSD used to end up here -
	 * might as well keep the workaround for now
	 */
	plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname);
	mo.opt_rhost = strdup(me->mnt_fsname);
	mo.opt_rfs = strdup("/");
	me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/");
      }
      mo.opt_fs = me->mnt_dir;
      mo.opt_opts = me->mnt_opts;

      /*
       * Make a new mounted filesystem
       */
      mf = find_mntfs(fs_ops, &mo, me->mnt_dir,
		      me->mnt_fsname, "", me->mnt_opts, "");
      if (mf->mf_refc == 1) {
	mf->mf_flags |= MFF_RESTART | MFF_MOUNTED;
	mf->mf_error = 0;	/* Already mounted correctly */
	mf->mf_fo = 0;
	/*
	 * If the restarted type is a link then
	 * don't time out.
	 */
	if (fs_ops == &amfs_link_ops || fs_ops == &ufs_ops)
	  mf->mf_flags |= MFF_RSTKEEP;
	if (fs_ops->fs_init) {
	  /*
	   * Don't care whether this worked since
	   * it is checked again when the fs is
	   * inherited.
	   */
	  (void) (*fs_ops->fs_init) (mf);
	}
	plog(XLOG_INFO, "%s restarted fstype %s on %s",
	     me->mnt_fsname, fs_ops->fs_type, me->mnt_dir);
      } else {
	/* Something strange happened - two mounts at the same place! */
	free_mntfs(mf);
      }
      /*
       * Clean up mo
       */
      if (mo.opt_rhost)
	XFREE(mo.opt_rhost);
      if (mo.opt_rfs)
	XFREE(mo.opt_rfs);
    }
  }

  /*
   * Free the mount list
   */
  free_mntlist(ml);
}
Exemple #3
0
static am_loc *
amfs_lookup_one_location(am_node *new_mp, mntfs *mf, char *ivec,
			char *def_opts, char *pfname)
{
  am_ops *p;
  am_opts *fs_opts;
  am_loc *new_al;
  mntfs *new_mf;
  char *mp_dir = NULL;
#ifdef HAVE_FS_AUTOFS
  int on_autofs = 1;
#endif /* HAVE_FS_AUTOFS */

  /* match the operators */
  /*
   * although we alloc the fs_opts here, the pointer is 'owned' by the am_loc and will
   * be free'd on destruction of the am_loc. If we don't allocate a loc, then we need
   * to free this.
   */
  fs_opts = CALLOC(am_opts);
  p = ops_match(fs_opts, ivec, def_opts, new_mp->am_path,
		pfname, mf->mf_info);
#ifdef HAVE_FS_AUTOFS
  /* XXX: this should be factored out into an autofs-specific function */
  if (new_mp->am_flags & AMF_AUTOFS) {
    /* ignore user-provided fs if we're using autofs */
    if (fs_opts->opt_sublink && fs_opts->opt_sublink[0]) {
      /*
       * For sublinks we need to use a hack with autofs:
       * mount the filesystem on the original opt_fs (which is NOT an
       * autofs mountpoint) and symlink (or lofs-mount) to it from
       * the autofs mountpoint.
       */
      on_autofs = 0;
      mp_dir = fs_opts->opt_fs;
    } else {
      if (p->autofs_fs_flags & FS_ON_AUTOFS) {
	mp_dir = new_mp->am_path;
      } else {
	mp_dir = fs_opts->opt_fs;
	on_autofs = 0;
      }
    }
  } else
#endif /* HAVE_FS_AUTOFS */
    mp_dir = fs_opts->opt_fs;

  /*
   * Find or allocate a filesystem for this node.
   * we search for a matching backend share, since
   * we will construct our own al_loc to handle
   * any customisations for this usage.
   */
  new_mf = find_mntfs(p, fs_opts,
		      mp_dir,
		      fs_opts->fs_mtab,
		      def_opts,
		      fs_opts->opt_opts,
		      fs_opts->opt_remopts);


  /*
   * See whether this is a real filesystem
   */
  p = new_mf->mf_ops;
  if (p == &amfs_error_ops) {
    plog(XLOG_MAP, "Map entry %s for %s did not match", ivec, new_mp->am_path);
    free_mntfs(new_mf);
    free_opts(fs_opts);
    XFREE(fs_opts);
    return NULL;
  }

  dlog("Got a hit with %s", p->fs_type);
  new_al = new_loc();
  free_mntfs(new_al->al_mnt);
  new_al->al_mnt = new_mf;
  new_al->al_fo = fs_opts; /* now the loc is in charge of free'ing this mem */

#ifdef HAVE_FS_AUTOFS
  if (new_mp->am_flags & AMF_AUTOFS && on_autofs) {
    new_mf->mf_flags |= MFF_ON_AUTOFS;
    new_mf->mf_fsflags = new_mf->mf_ops->autofs_fs_flags;
  }
  /*
   * A new filesystem is an autofs filesystems if:
   * 1. it claims it can be one (has the FS_AUTOFS flag)
   * 2. autofs is enabled system-wide
   * 3. either has an autofs parent,
   *    or it is explicitly requested to be autofs.
   */
  if (new_mf->mf_ops->autofs_fs_flags & FS_AUTOFS &&
      amd_use_autofs &&
      ((mf->mf_flags & MFF_IS_AUTOFS) ||
       (new_mf->mf_fo && new_mf->mf_fo->opt_mount_type &&
	STREQ(new_mf->mf_fo->opt_mount_type, "autofs"))))
    new_mf->mf_flags |= MFF_IS_AUTOFS;
#endif /* HAVE_FS_AUTOFS */

  return new_al;
}
Exemple #4
0
static int
amfs_nfsx_init(mntfs *mf)
{
  /*
   * mf_info has the form:
   *   host:/prefix/path,sub,sub,sub
   */
  int i;
  int glob_error;
  struct amfs_nfsx *nx;
  int asked_for_wakeup = 0;

  nx = (struct amfs_nfsx *) mf->mf_private;

  if (nx == 0) {
    char **ivec;
    char *info = 0;
    char *host;
    char *pref;
    int error = 0;

    info = strdup(mf->mf_info);
    host = strchr(info, ':');
    if (!host) {
      error = EINVAL;
      goto errexit;
    }
    pref = host + 1;
    host = info;

    /*
     * Split the prefix off from the suffices
     */
    ivec = strsplit(pref, ',', '\'');

    /*
     * Count array size
     */
    for (i = 0; ivec[i]; i++)
      /* nothing */;

    nx = ALLOC(struct amfs_nfsx);
    mf->mf_private = (opaque_t) nx;
    mf->mf_prfree = amfs_nfsx_prfree;

    nx->nx_c = i - 1;		/* i-1 because we don't want the prefix */
    nx->nx_v = (amfs_nfsx_mnt *) xmalloc(nx->nx_c * sizeof(amfs_nfsx_mnt));
    nx->nx_mp = 0;
    {
      char *mp = 0;
      char *xinfo = 0;
      char *fs = mf->mf_fo->opt_fs;
      char *rfs = 0;
      for (i = 0; i < nx->nx_c; i++) {
	char *path = ivec[i + 1];
	rfs = str3cat(rfs, pref, "/", path);
	/*
	 * Determine the mount point.
	 * If this is the root, then don't remove
	 * the trailing slash to avoid mntfs name clashes.
	 */
	mp = str3cat(mp, fs, "/", rfs);
	normalize_slash(mp);
	deslashify(mp);
	/*
	 * Determine the mount info
	 */
	xinfo = str3cat(xinfo, host, *path == '/' ? "" : "/", path);
	normalize_slash(xinfo);
	if (pref[1] != '\0')
	  deslashify(xinfo);
	dlog("amfs_nfsx: init mount for %s on %s", xinfo, mp);
	nx->nx_v[i].n_error = -1;
	nx->nx_v[i].n_mnt = find_mntfs(&nfs_ops, mf->mf_fo, mp, xinfo, "", mf->mf_mopts, mf->mf_remopts);
	/* propagate the on_autofs flag */
	nx->nx_v[i].n_mnt->mf_flags |= mf->mf_flags & MFF_ON_AUTOFS;
      }
      if (rfs)
	XFREE(rfs);
      if (mp)
	XFREE(mp);
      if (xinfo)
	XFREE(xinfo);
    }

    XFREE(ivec);
  errexit:
    if (info)
      XFREE(info);
    if (error)
      return error;
  }
Exemple #5
0
static mntfs *
amfs_lookup_one_mntfs(am_node *new_mp, mntfs *mf, char *ivec,
		      char *def_opts, char *pfname)
{
  am_ops *p;
  am_opts *fs_opts;
  mntfs *new_mf;
  char *mp_dir = 0;
#ifdef HAVE_FS_AUTOFS
  int on_autofs = 1;
#endif /* HAVE_FS_AUTOFS */

  /* match the operators */
  fs_opts = CALLOC(am_opts);
  p = ops_match(fs_opts, ivec, def_opts, new_mp->am_path,
		pfname, mf->mf_info);
#ifdef HAVE_FS_AUTOFS
  /* XXX: this should be factored out into an autofs-specific function */
  if (new_mp->am_flags & AMF_AUTOFS) {
    /* ignore user-provided fs if we're using autofs */
    if (fs_opts->opt_sublink) {
      /*
       * For sublinks we need to use a hack with autofs:
       * mount the filesystem on the original opt_fs (which is NOT an
       * autofs mountpoint) and symlink (or lofs-mount) to it from
       * the autofs mountpoint.
       */
      on_autofs = 0;
      mp_dir = fs_opts->opt_fs;
    } else {
      if (p->autofs_fs_flags & FS_ON_AUTOFS) {
	mp_dir = new_mp->am_path;
      } else {
	mp_dir = fs_opts->opt_fs;
	on_autofs = 0;
      }
    }
  } else
#endif /* HAVE_FS_AUTOFS */
    mp_dir = fs_opts->opt_fs;

  /*
   * Find or allocate a filesystem for this node.
   */
  new_mf = find_mntfs(p, fs_opts,
		      mp_dir,
		      fs_opts->fs_mtab,
		      def_opts,
		      fs_opts->opt_opts,
		      fs_opts->opt_remopts);

  /*
   * See whether this is a real filesystem
   */
  p = new_mf->mf_ops;
  if (p == &amfs_error_ops) {
    plog(XLOG_MAP, "Map entry %s for %s did not match", ivec, new_mp->am_path);
    free_mntfs(new_mf);
    return NULL;
  }

  dlog("Got a hit with %s", p->fs_type);

#ifdef HAVE_FS_AUTOFS
  if (new_mp->am_flags & AMF_AUTOFS && on_autofs) {
    new_mf->mf_flags |= MFF_ON_AUTOFS;
    new_mf->mf_fsflags = new_mf->mf_ops->autofs_fs_flags;
  }
  /*
   * A new filesystem is an autofs filesystems if:
   * 1. it claims it can be one (has the FS_AUTOFS flag)
   * 2. autofs is enabled system-wide
   * 3. either has an autofs parent,
   *    or it is explicitly requested to be autofs.
   */
  if (new_mf->mf_ops->autofs_fs_flags & FS_AUTOFS &&
      amd_use_autofs &&
      ((mf->mf_flags & MFF_IS_AUTOFS) ||
       (new_mf->mf_fo && new_mf->mf_fo->opt_mount_type &&
	STREQ(new_mf->mf_fo->opt_mount_type, "autofs"))))
    new_mf->mf_flags |= MFF_IS_AUTOFS;
#endif /* HAVE_FS_AUTOFS */

  return new_mf;
}
Exemple #6
0
static void
restart_fake_mntfs(mntent_t *me, am_ops *fs_ops)
{
  mntfs *mf;
  am_opts mo;
  char *cp;

  /*
   * Partially fake up an opts structure
   */
  memset(&mo, 0, sizeof(mo));
  mo.opt_rhost = NULL;
  mo.opt_rfs = NULL;
  cp = strchr(me->mnt_fsname, ':');
  if (cp) {
    *cp = '\0';
    mo.opt_rhost = xstrdup(me->mnt_fsname);
    mo.opt_rfs = xstrdup(cp + 1);
    *cp = ':';
  } else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) {
    /*
     * Hacky workaround for mnttab NFS entries that only list the server
     */
    plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname);
    mo.opt_rhost = xstrdup(me->mnt_fsname);
    mo.opt_rfs = xstrdup("/");
    me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/");
  }
  mo.opt_fs = me->mnt_dir;
  mo.opt_opts = me->mnt_opts;

  /*
   * Make a new mounted filesystem
   */
  mf = find_mntfs(fs_ops, &mo, me->mnt_dir,
		  me->mnt_fsname, "", me->mnt_opts, "");
  if (mf->mf_refc == 1) {
    mf->mf_flags |= MFF_RESTART | MFF_MOUNTED;
    mf->mf_error = 0;		     /* Already mounted correctly */
    /*
     * Only timeout non-NFS entries
     */
    if (!STREQ(me->mnt_type, MNTTAB_TYPE_NFS))
      mf->mf_flags |= MFF_RSTKEEP;
    if (fs_ops->fs_init) {
      /*
       * Don't care whether this worked since
       * it is checked again when the fs is
       * inherited.
       */
      (void) (*fs_ops->fs_init) (mf);
    }
    plog(XLOG_INFO, "%s restarted fstype %s on %s, flags 0x%x",
	 me->mnt_fsname, fs_ops->fs_type, me->mnt_dir, mf->mf_flags);
  } else {
    /* Something strange happened - two mounts at the same place! */
    free_mntfs(mf);
  }
  /*
   * Clean up mo
   */
  XFREE(mo.opt_rhost);
  XFREE(mo.opt_rfs);
}
Exemple #7
0
static int
nfsx_init(mntfs *mf)
{
	/*
	 * mf_info has the form:
	 *   host:/prefix/path,sub,sub,sub
	 */
	int i;
	int glob_error;
	struct nfsx *nx;
	int asked_for_wakeup = 0;

	nx = (struct nfsx *) mf->mf_private;

	if (nx == 0) {
		char **ivec;
		char *info = 0;
		char *host;
		char *pref;
		int error = 0;

		info = strdup(mf->mf_info);
		host = strchr(info, ':');
		if (!host) {
			error = EINVAL;
			goto errexit;
		}

		pref = host+1;
		host = info;

		/*
		 * Split the prefix off from the suffices
		 */
		ivec = strsplit(pref, ',', '\'');

		/*
		 * Count array size
		 */
		for (i = 0; ivec[i]; i++)
			;

		nx = ALLOC(nfsx);
		mf->mf_private = nx;
		mf->mf_prfree = nfsx_prfree;

		nx->nx_c = i - 1;	/* i-1 because we don't want the prefix */
		nx->nx_v = xreallocarray(NULL, nx->nx_c, sizeof *nx->nx_v);
		{ char *mp = 0;
		  char *xinfo = 0;
		  char *fs = mf->mf_fo->opt_fs;
		  char *rfs = 0;
		  for (i = 0; i < nx->nx_c; i++) {
			char *path = ivec[i+1];
			rfs = str3cat(rfs, pref, "/", path);
			/*
			 * Determine the mount point.
			 * If this is the root, then don't remove
			 * the trailing slash to avoid mntfs name clashes.
			 */
			mp = str3cat(mp, fs, "/", rfs);
			normalize_slash(mp);
			deslashify(mp);
			/*
			 * Determine the mount info
			 */
			xinfo = str3cat(xinfo, host, *path == '/' ? "" : "/", path);
			normalize_slash(xinfo);
			if (pref[1] != '\0')
				deslashify(xinfo);
#ifdef DEBUG
			dlog("nfsx: init mount for %s on %s", xinfo, mp);
#endif
			nx->nx_v[i].n_error = -1;
			nx->nx_v[i].n_mnt = find_mntfs(&nfs_ops, mf->mf_fo, mp, xinfo, "", mf->mf_mopts, mf->mf_remopts);
		  }
		  free(rfs);
		  free(mp);
		  free(xinfo);
		}

		free(ivec);
errexit:
		free(info);
		if (error)
			return error;
	}

	/*
	 * Iterate through the mntfs's and call
	 * the underlying init routine on each
	 */
	glob_error = 0;
	for (i = 0; i < nx->nx_c; i++) {
		nfsx_mnt *n = &nx->nx_v[i];
		mntfs *m = n->n_mnt;
		int error = (*m->mf_ops->fs_init)(m);
		/*
		 * If HARD_NFSX_ERRORS is defined, make any
		 * initialisation failure a hard error and
		 * fail the entire group.  Otherwise only fail
		 * if none of the group is mountable (see nfsx_fmount).
		 */
#ifdef HARD_NFSX_ERRORS
		if (error > 0)
			return error;
#else
		if (error > 0)
			n->n_error = error;
#endif
		else if (error < 0) {
			glob_error = -1;
			if (!asked_for_wakeup) {
				asked_for_wakeup = 1;
				sched_task(wakeup_task, mf, m);
			}
		}
	}

	return glob_error;
}