diff options
Diffstat (limited to 'libdiskfs/init-startup.c')
-rw-r--r-- | libdiskfs/init-startup.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/libdiskfs/init-startup.c b/libdiskfs/init-startup.c index 4251e0b3..a2e3638d 100644 --- a/libdiskfs/init-startup.c +++ b/libdiskfs/init-startup.c @@ -126,15 +126,47 @@ diskfs_startup_diskfs (mach_port_t bootstrap, int flags) error_t diskfs_S_startup_dosync (mach_port_t handle) { + error_t err = 0; struct port_info *pi = ports_lookup_port (diskfs_port_bucket, handle, diskfs_shutdown_notification_class); if (!pi) return EOPNOTSUPP; + + if (! diskfs_readonly) + { + /* First start a sync so that if something goes wrong + we at least get this much done. */ + diskfs_sync_everything (0); + diskfs_set_hypermetadata (0, 0); + + pthread_rwlock_wrlock (&diskfs_fsys_lock); + + /* Permit all the current RPC's to finish, and then suspend new ones */ + err = ports_inhibit_class_rpcs (diskfs_protid_class); + if (! err) + { + diskfs_sync_everything (1); + diskfs_set_hypermetadata (1, 1); + _diskfs_diskdirty = 0; + + /* XXX: if some application writes something after that, we will + * crash. That is still better than creating pending writes before + * poweroff, and thus fsck on next reboot. + */ + diskfs_readonly = 1; + diskfs_readonly_changed (1); + + ports_resume_class_rpcs (diskfs_protid_class); + } + + pthread_rwlock_unlock (&diskfs_fsys_lock); + } + ports_port_deref (pi); - return diskfs_shutdown (FSYS_GOAWAY_FORCE || FSYS_GOAWAY_RECURSE); + return err; } /* This is called when we have an ordinary environment, complete |