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; }
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; } }