Beispiel #1
0
am_node *
amfs_generic_mount_child(am_node *new_mp, int *error_return)
{
  int error;
  struct continuation *cp;	/* Continuation structure if need to mount */

  dlog("in amfs_generic_mount_child");

  *error_return = error = 0;	/* Error so far */

  /* we have an errorfs attached to the am_node, free it */
  if (new_mp->am_al)
    free_loc(new_mp->am_al);
  new_mp->am_al = NULL;

  /*
   * Construct a continuation
   */
  cp = ALLOC(struct continuation);
  cp->callout = 0;
  cp->mp = new_mp;
  cp->retry = TRUE;
  cp->start = clocktime(NULL);
  cp->al = new_mp->am_alarray;

  /*
   * Try and mount the file system.  If this succeeds immediately (possible
   * for a ufs file system) then return the attributes, otherwise just
   * return an error.
   */
  error = amfs_bgmount(cp);
  reschedule_timeout_mp();
  if (!error)
    return new_mp;

  /*
   * Code for quick reply.  If current_transp is set, then it's the
   * transp that's been passed down from nfs_dispatcher() or from
   * autofs_program_[123]().
   * If new_mp->am_transp is not already set, set it by copying in
   * current_transp.  Once am_transp is set, nfs_quick_reply() and
   * autofs_mount_succeeded() can use it to send a reply to the
   * client that requested this mount.
   */
  if (current_transp && !new_mp->am_transp) {
    dlog("Saving RPC transport for %s", new_mp->am_path);
    new_mp->am_transp = (SVCXPRT *) xmalloc(sizeof(SVCXPRT));
    *(new_mp->am_transp) = *current_transp;
  }
  if (error && new_mp->am_al && new_mp->am_al->al_mnt &&
      (new_mp->am_al->al_mnt->mf_ops == &amfs_error_ops))
    new_mp->am_error = error;

  if (new_mp->am_error > 0)
    assign_error_mntfs(new_mp);

  ereturn(error);
}
Beispiel #2
0
Datei: emit.c Projekt: a8m/c
static void
stmt(Node *n)
{
	switch(n->t){
	case NDECL:
		decl(n);
		out(".text\n");
		break;
	case NRETURN:
		ereturn(n);
		break;
	case NIF:
		eif(n);
		break;
	case NWHILE:
		ewhile(n);
		break;
	case NFOR:
		efor(n);
		break;
	case NDOWHILE:
		dowhile(n);
		break;
	case NBLOCK:
		block(n);
		break;
	case NSWITCH:
		eswitch(n);
		break;
	case NGOTO:
		outi("jmp %s\n", n->Goto.l);
		break;
	case NCASE:
		out("%s:\n", n->Case.l);
		stmt(n->Case.stmt);
		break;
	case NLABELED:
		out("%s:\n", n->Labeled.l);
		stmt(n->Labeled.stmt);
		break;
	case NEXPRSTMT:
		if(n->ExprStmt.expr)
			expr(n->ExprStmt.expr);
		break;
	default:
		errorf("unimplemented emit stmt %d\n", n->t);
	}	
}
Beispiel #3
0
/*
 * Automount interface to RPC lookup routine
 * Find the corresponding entry and return
 * the file handle for it.
 */
am_node *
amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op)
{
  am_node *new_mp;
  am_loc **al_array;

  dlog("in amfs_generic_lookup_child");

  *error_return = 0;
  new_mp = amfs_lookup_node(mp, fname, error_return);

  /* return if we got an error */
  if (!new_mp || *error_return > 0)
    return new_mp;

  /* also return if it's already mounted and known to be up */
  if (*error_return == 0 && FSRV_ISUP(new_mp->am_al->al_mnt->mf_server))
    return new_mp;

  switch (op) {
  case VLOOK_DELETE:
    /*
     * If doing a delete then don't create again!
     */
    ereturn(ENOENT);
  case VLOOK_LOOKUP:
    return new_mp;
  }

  al_array = amfs_lookup_loc(new_mp, error_return);
  if (!al_array) {
    new_mp->am_error = new_mp->am_al->al_mnt->mf_error = *error_return;
    free_map(new_mp);
    return NULL;
  }

  /* store the array inside the am_node */
  new_mp->am_alarray = al_array;

  /*
   * Note: while it might seem like a good idea to prioritize
   * the list of mntfs's we got here, it probably isn't.
   * It would ignore the ordering of entries specified by the user,
   * which is counterintuitive and confusing.
   */
  return new_mp;
}
Beispiel #4
0
/****************************************************************************
 *** FUNCTIONS                                                             ***
 ****************************************************************************/
static am_node *
amfs_lookup_node(am_node *mp, char *fname, int *error_return)
{
  am_node *new_mp;
  int error = 0;		/* Error so far */
  int in_progress = 0;		/* # of (un)mount in progress */
  mntfs *mf;
  char *expanded_fname = NULL;

  dlog("in amfs_lookup_node");

  /*
   * If the server is shutting down
   * then don't return information
   * about the mount point.
   */
  if (amd_state == Finishing) {
    if (mp->am_al == NULL || mp->am_al->al_mnt == NULL || mp->am_al->al_mnt->mf_fsflags & FS_DIRECT) {
      dlog("%s mount ignored - going down", fname);
    } else {
      dlog("%s/%s mount ignored - going down", mp->am_path, fname);
    }
    ereturn(ENOENT);
  }

  /*
   * Handle special case of "." and ".."
   */
  if (fname[0] == '.') {
    if (fname[1] == '\0')
      return mp;		/* "." is the current node */
    if (fname[1] == '.' && fname[2] == '\0') {
      if (mp->am_parent) {
	dlog(".. in %s gives %s", mp->am_path, mp->am_parent->am_path);
	return mp->am_parent;	/* ".." is the parent node */
      }
      ereturn(ESTALE);
    }
  }

  /*
   * Check for valid key name.
   * If it is invalid then pretend it doesn't exist.
   */
  if (!valid_key(fname)) {
    plog(XLOG_WARNING, "Key \"%s\" contains a disallowed character", fname);
    ereturn(ENOENT);
  }

  /*
   * Expand key name.
   * expanded_fname is now a private copy.
   */
  expanded_fname = expand_selectors(fname);

  /*
   * Search children of this node
   */
  for (new_mp = mp->am_child; new_mp; new_mp = new_mp->am_osib) {
    if (FSTREQ(new_mp->am_name, expanded_fname)) {
      if (new_mp->am_error) {
	error = new_mp->am_error;
	continue;
      }

      /*
       * If the error code is undefined then it must be
       * in progress.
       */
      mf = new_mp->am_al->al_mnt;
      if (mf->mf_error < 0)
	goto in_progrss;

      /*
       * If there was a previous error with this node
       * then return that error code.
       */
      if (mf->mf_flags & MFF_ERROR) {
	error = mf->mf_error;
	continue;
      }
      if (!(mf->mf_flags & MFF_MOUNTED) || (mf->mf_flags & MFF_UNMOUNTING)) {
      in_progrss:
	/*
	 * If the fs is not mounted or it is unmounting then there
	 * is a background (un)mount in progress.  In this case
	 * we just drop the RPC request (return nil) and
	 * wait for a retry, by which time the (un)mount may
	 * have completed.
	 */
	dlog("ignoring mount of %s in %s -- %smounting in progress, flags %x",
	     expanded_fname, mf->mf_mount,
	     (mf->mf_flags & MFF_UNMOUNTING) ? "un" : "", mf->mf_flags);
	in_progress++;
	if (mf->mf_flags & MFF_UNMOUNTING) {
	  dlog("will remount later");
	  new_mp->am_flags |= AMF_REMOUNT;
	}
	continue;
      }

      /*
       * Otherwise we have a hit: return the current mount point.
       */
      dlog("matched %s in %s", expanded_fname, new_mp->am_path);
      XFREE(expanded_fname);
      return new_mp;
    }
  }

  if (in_progress) {
    dlog("Waiting while %d mount(s) in progress", in_progress);
    XFREE(expanded_fname);
    ereturn(-1);
  }

  /*
   * If an error occurred then return it.
   */
  if (error) {
    dlog("Returning error: %s", strerror(error));
    XFREE(expanded_fname);
    ereturn(error);
  }

  /*
   * If the server is going down then just return,
   * don't try to mount any more file systems
   */
  if ((int) amd_state >= (int) Finishing) {
    dlog("not found - server going down anyway");
    ereturn(ENOENT);
  }

  /*
   * Allocate a new map
   */
  new_mp = get_ap_child(mp, expanded_fname);
  XFREE(expanded_fname);
  if (new_mp == NULL)
    ereturn(ENOSPC);

  *error_return = -1;
  return new_mp;
}
Beispiel #5
0
/*
 * Automount interface to RPC lookup routine
 * Find the corresponding entry and return
 * the file handle for it.
 */
am_node *
amfs_generic_lookup_child(am_node *mp, char *fname, int *error_return, int op)
{
  am_node *new_mp;
  mntfs **mf_array;
  int mp_error;

  dlog("in amfs_generic_lookup_child");

  *error_return = 0;
  new_mp = amfs_lookup_node(mp, fname, error_return);

  /* return if we got an error */
  if (!new_mp || *error_return > 0)
    return new_mp;

  /* also return if it's already mounted and known to be up */
  if (*error_return == 0 && FSRV_ISUP(new_mp->am_mnt->mf_server))
    return new_mp;

  switch (op) {
  case VLOOK_DELETE:
    /*
     * If doing a delete then don't create again!
     */
    ereturn(ENOENT);
  case VLOOK_LOOKUP:
    return new_mp;
  }

  /* save error_return */
  mp_error = *error_return;

  mf_array = amfs_lookup_mntfs(new_mp, error_return);
  if (!mf_array) {
    new_mp->am_error = new_mp->am_mnt->mf_error = *error_return;
    free_map(new_mp);
    return NULL;
  }

  /*
   * Already mounted but known to be down:
   * check if we have any alternatives to mount
   */
  if (mp_error == 0) {
    mntfs **mfp;
    for (mfp = mf_array; *mfp; mfp++)
      if (*mfp != new_mp->am_mnt)
	break;
    if (*mfp != NULL) {
      /*
       * we found an alternative, so try mounting again.
       */
      *error_return = -1;
    } else {
      for (mfp = mf_array; *mfp; mfp++)
	free_mntfs(*mfp);
      XFREE(mf_array);
      if (new_mp->am_flags & AMF_SOFTLOOKUP) {
	ereturn(EIO);
      } else {
	*error_return = 0;
	return new_mp;
      }
    }
  }

  /* store the array inside the am_node */
  new_mp->am_mfarray = mf_array;

  /*
   * Note: while it might seem like a good idea to prioritize
   * the list of mntfs's we got here, it probably isn't.
   * It would ignore the ordering of entries specified by the user,
   * which is counterintuitive and confusing.
   */
  return new_mp;
}
Beispiel #6
0
rt_public EIF_REFERENCE edclone(EIF_CONTEXT EIF_REFERENCE source)
{
    /* Recursive Eiffel clone. This function recursively clones the source
     * object and returns a pointer to the top of the new tree.
     */
    RT_GET_CONTEXT
    EIF_GET_CONTEXT
    EIF_REFERENCE root = (EIF_REFERENCE)  0;		/* Root of the deep cloned object */
    jmp_buf exenv;					/* Environment saving */
    struct {
        union overhead discard;		/* Pseudo object header */
        EIF_REFERENCE boot;					/* Anchor point for cloning process */
    } anchor;
    struct rt_traversal_context traversal_context;
    int volatile is_locked;

#ifdef DEBUG
    int xobjs;
#endif

    if (source == NULL) {
        return NULL;			/* Void source */
    }

    /* The deep clone of the source will be attached in the 'boot' entry from
     * the anchor structure. It all happens as if we were in fact deep cloning
     * the anchor pseudo-object.
     */

    memset (&anchor, 0, sizeof(anchor));	/* Reset header */
    anchor.boot = (EIF_REFERENCE)  &root;	/* To boostrap cloning process */

    RT_GC_PROTECT(source);	/* Protect source: allocation will occur */

#ifdef DEBUG
    xobjs = nomark(source);
    printf("Source has %x %d objects\n", source, xobjs);
#endif

    /* Set up an exception trap. If any exception occurs, control will be
     * transferred back here by the run-time to give us a chance to clean-up
     * our structures.
     */

    {
        RTXDRH;							/* Save stack contexts */
        EIF_EO_STORE_LOCK;				/* Because we perform a traversal that marks
										   objects, we need to be sure we are the
										   only one doing it. */
        is_locked = 1;

        excatch(&exenv);		/* Record pseudo-execution vector */
        if (setjmp(exenv)) {
            RTXSCH;						/* Restore stack contexts */
            map_reset(1);				/* Reset in emergency situation */
            /* If we locked the EO_STORE_MUTEX, then we need to unmark objects
             * and unlock it. */
            if (is_locked) {
                /* We are only concerned abount unmarking objects, so we do not perform any
                 * accounting. */
                CHECK ("Not accounting", traversal_context.accounting == 0);
                CHECK ("Not unmarking", traversal_context.is_unmarking == 0);
                /* First we mark again all objects. */
                traversal_context.is_unmarking = 0;
                traversal(&traversal_context, source);
                /* Then we unmark them. */
                traversal_context.is_unmarking = 1;
                traversal(&traversal_context, source);
                /* Now we can unlock our mutex. */
                EIF_EO_STORE_UNLOCK;
            }
            ereturn(MTC_NOARG);					/* And propagate the exception */
        }

        /* Now start the traversal of the source, allocating all the objects as
         * needed and stuffing them into a FIFO stack for later perusal by the
         * cloning process.
         */

        memset (&traversal_context, 0, sizeof(struct rt_traversal_context));
        traversal_context.accounting = TR_MAP;
        traversal(&traversal_context, source);		/* Object traversal, mark with EO_STORE */
        hash_malloc(&hclone, traversal_context.obj_nb);	/* Hash table allocation */
        map_start();					/* Restart at bottom of FIFO stack */

#ifdef DEBUG
        printf("Computed %x %d objects\n\n", source, traversal_context.obj_nb);
#endif

        /* Throughout the deep cloning process, we need to maintain the notion of
         * enclosing object for GC aging tests. The enclosing object is defined as
         * being the object to which the currently cloned tree will be attached.
         *
         * We need to initialize the cloning process by computing a valid reference
         * into the root variable. That will be the enclosing object, and of course
         * it cannot be void, ever, or something really really weird is happening.
         *
         * To get rid of code duplication, I am initially calling rdeepclone with
         * an enclosing object address set to anchor.boot. The anchor structure
         * represents a pseudo anchor object for the object hierarchy being cloned.
         */

        rdeepclone(source, (EIF_REFERENCE) &anchor.boot, 0);	/* Recursive clone */
        hash_free(&hclone);						/* Free hash table */
        map_reset(0);							/* And eif_free maping table */
        /* Release all the hector pointers asked for during the map table
         * construction (obj_nb exactly) */
        CHECK("Has objects", traversal_context.obj_nb > 0);
        eif_ostack_npop(&hec_stack, traversal_context.obj_nb);

#ifdef DEBUG
        xobjs= nomark(source);
        printf("Source now has %d objects\n", xobjs);
        xobjs = nomark(anchor.boot);
        printf("Result has %d objects\n", xobjs);
#endif

        RT_GC_WEAN(source);			/* Release GC protection */
        expop(&eif_stack);			/* Remove pseudo execution vector */
    }

    EIF_EO_STORE_UNLOCK;		/* Free marking mutex */
    is_locked = 0;

    return anchor.boot;			/* The cloned object tree */
}