Exemple #1
0
void
deadboot (void *p)
{
  struct bootinfo *boot = p;
  size_t i;

  munmap (boot->argv, boot->argvlen);
  munmap (boot->envp, boot->envplen);

  for (i = 0; i < boot->dtablesize; ++i)
    mach_port_deallocate (mach_task_self (), boot->dtable[i]);
  for (i = 0; i < boot->nports; ++i)
    mach_port_deallocate (mach_task_self (), boot->portarray[i]);
  munmap (boot->portarray, boot->nports * sizeof (mach_port_t));
  munmap (boot->intarray, boot->nints * sizeof (int));

  /* See if we are going away and this was the last thing keeping us up.  */
  if (ports_count_class (trivfs_cntl_portclasses[0]) == 0)
    {
      /* We have no fsys control port, so we are detached from the
	 parent filesystem.  Maybe we have no users left either.  */
      if (ports_count_class (trivfs_protid_portclasses[0]) == 0)
	{
	  /* We have no user ports left.  Are we still listening for
	     exec_startup RPCs from any tasks we already started?  */
	  if (ports_count_class (execboot_portclass) == 0)
	    /* Nobody talking.  Time to die.  */
	    exit (0);
	  ports_enable_class (execboot_portclass);
	}
      ports_enable_class (trivfs_protid_portclasses[0]);
    }
  ports_enable_class (trivfs_cntl_portclasses[0]);
}
Exemple #2
0
int
main (int argc, char **argv)
{
    error_t err;
    mach_port_t bootstrap;
    struct trivfs_control *fsys;

    fifo_pipe_class = stream_pipe_class;

    argp_parse (&argp, argc, argv, 0, 0, 0);

    task_get_bootstrap_port (mach_task_self (), &bootstrap);
    if (bootstrap == MACH_PORT_NULL)
        error (1, 0, "must be started as a translator");

    /* Reply to our parent */
    err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &fsys);
    mach_port_deallocate (mach_task_self (), bootstrap);
    if (err)
        error (3, err, "Contacting parent");

    /* Launch. */
    do
    {
        ports_enable_class (fsys->protid_class);
        ports_manage_port_operations_multithread (fsys->pi.bucket,
                trivfs_demuxer,
                30*1000, 5*60*1000, 0);
    }
    while (ports_count_class (fsys->protid_class) > 0);

    return 0;
}
Exemple #3
0
error_t
trivfs_goaway (struct trivfs_control *cntl, int flags)
{
    if (flags & FSYS_GOAWAY_FORCE)
        exit (0);
    else
    {
        /* Stop new requests.  */
        ports_inhibit_class_rpcs (pfinet_cntl_portclasses[0]);
        ports_inhibit_class_rpcs (pfinet_protid_portclasses[0]);
        ports_inhibit_class_rpcs (socketport_class);

        if (ports_count_class (socketport_class) != 0)
        {
            /* We won't go away, so start things going again...  */
            ports_enable_class (socketport_class);
            ports_resume_class_rpcs (pfinet_cntl_portclasses[0]);
            ports_resume_class_rpcs (pfinet_protid_portclasses[0]);

            return EBUSY;
        }

        /* There are no sockets, so we can die without breaking anybody
        too badly.  We don't let user ports on the /servers/socket/2
         file keep us alive because those get cached in every process
         that ever makes a PF_INET socket, libc copes with getting
         MACH_SEND_INVALID_DEST and looking up the new translator.  */
        exit (0);
    }
}
error_t
trivfs_goaway (struct trivfs_control *fsys, int flags)
{
  struct dev *const device = fsys->hook;
  error_t err;
  int force = (flags & FSYS_GOAWAY_FORCE);
  int nosync = (flags & FSYS_GOAWAY_NOSYNC);
  struct port_class *root_port_class = fsys->protid_class;

  mutex_lock (&device->lock);

  if (device->store == NULL)
    /* The device is not actually open.
       XXX note that exitting here nukes non-io users, like someone
       in the middle of a stat who will get SIGLOST or something.  */
    exit (0);

  /* Wait until all pending rpcs are done.  */
  err = ports_inhibit_class_rpcs (root_port_class);
  if (err == EINTR || (err && !force))
    {
      mutex_unlock (&device->lock);
      return err;
    }

  if (force && nosync)
    /* Exit with extreme prejudice.  */
    exit (0);

  if (!force && ports_count_class (root_port_class) > 0)
    /* Still users, so don't exit.  */
    goto busy;

  if (! nosync)
    /* Sync the device here, if necessary, so that closing it won't result in
       any I/O (which could get hung up trying to use one of our pagers).  */
    dev_sync (device, 1);

  /* devpager_shutdown may sync the pagers as side-effect (if NOSYNC is 0),
     so we put that first in this test.  */
  if (dev_stop_paging (device, nosync) || force)
    /* Bye-bye.  */
    {
      if (! nosync)
	/* If NOSYNC is true, we don't close DEV, as that could cause data to
	   be written back.  */
	dev_close (device);
      exit (0);
    }

 busy:
  /* Allow normal operations to proceed.  */
  ports_enable_class (root_port_class);
  ports_resume_class_rpcs (root_port_class);
  mutex_unlock (&device->lock);

  /* Complain that there are still users.  */
  return EBUSY;
}
Exemple #5
0
error_t
trivfs_goaway (struct trivfs_control *fsys, int flags)
{
  int count;

  /* Stop new requests.  */
  ports_inhibit_class_rpcs (trivfs_cntl_portclasses[0]);
  ports_inhibit_class_rpcs (trivfs_protid_portclasses[0]);

  /* Are there any extant user ports for the /servers/exec file?  */
  count = ports_count_class (trivfs_protid_portclasses[0]);
  if (count == 0 || (flags & FSYS_GOAWAY_FORCE))
    {
      /* No users.  Disconnect from the filesystem.  */
      mach_port_deallocate (mach_task_self (), fsys->underlying);

      /* Are there remaining exec_startup RPCs to answer?  */
      count = ports_count_class (execboot_portclass);
      if (count == 0)
	/* Nope.  We got no reason to live.  */
	exit (0);

      /* Continue servicing tasks starting up.  */
      ports_enable_class (execboot_portclass);

      /* No more communication with the parent filesystem.  */
      ports_destroy_right (fsys);

      return 0;
    }
  else
    {
      /* We won't go away, so start things going again...  */
      ports_enable_class (trivfs_protid_portclasses[0]);
      ports_resume_class_rpcs (trivfs_cntl_portclasses[0]);
      ports_resume_class_rpcs (trivfs_protid_portclasses[0]);

      return EBUSY;
    }
}
Exemple #6
0
/* someone asks us to die */
error_t trivfs_goaway(struct trivfs_control *cntl, int flags)
{
	const int protid_users = ports_count_class(cntl->protid_class);
	const int force = flags & FSYS_GOAWAY_FORCE;
	const int nosync = flags & FSYS_GOAWAY_NOSYNC;

	/* does our live have a meaning yet? */
	if(protid_users && !force) {
		/* yeah, have to toil a bit longer -> blow it off */
		ports_enable_class(cntl->protid_class);
		return EBUSY;
	}
	/* nope, that was it */
	if(!nosync)    /* we use a liberal interpretation of NOSYNC here */
		cleanup_module();    /* "...as though it never existed..." */
	exit(0);    /* "...now I will just say goodbye" */
}