summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoravg <avg@FreeBSD.org>2013-07-24 09:59:16 +0000
committeravg <avg@FreeBSD.org>2013-07-24 09:59:16 +0000
commitfc2b4ba2ffb7384dfd6bda9952535e29f6d83a9a (patch)
tree52a5befc3fba3545afbeaaefeceb07e2d0f88dff
parent11666a98e959676f153fd1c3900c6f8339e46006 (diff)
downloadFreeBSD-src-fc2b4ba2ffb7384dfd6bda9952535e29f6d83a9a.zip
FreeBSD-src-fc2b4ba2ffb7384dfd6bda9952535e29f6d83a9a.tar.gz
zfs module: perform cleanup during shutdown in addition to module unload
- move init and fini code into separate functions (like it is done upstream) - invoke fini code via shutdown_post_sync event hook This should make zfs close its underlying devices during shutdown, which may be important for their drivers. MFC after: 20 days
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c112
1 files changed, 77 insertions, 35 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
index a4ae7aa..f87a6dd 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
@@ -6187,54 +6187,96 @@ _info(struct modinfo *modinfop)
}
#endif /* sun */
-static int
-zfs_modevent(module_t mod, int type, void *unused __unused)
+static int zfs__init(void);
+static int zfs__fini(void);
+static void zfs_shutdown(void *, int);
+
+static eventhandler_tag zfs_shutdown_event_tag;
+
+int
+zfs__init(void)
{
- int error = 0;
- switch (type) {
- case MOD_LOAD:
- zfs_root_token = root_mount_hold("ZFS");
+ zfs_root_token = root_mount_hold("ZFS");
- mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL);
+ mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL);
- spa_init(FREAD | FWRITE);
- zfs_init();
- zvol_init();
- zfs_ioctl_init();
+ spa_init(FREAD | FWRITE);
+ zfs_init();
+ zvol_init();
+ zfs_ioctl_init();
- tsd_create(&zfs_fsyncer_key, NULL);
- tsd_create(&rrw_tsd_key, rrw_tsd_destroy);
- tsd_create(&zfs_allow_log_key, zfs_allow_log_destroy);
+ tsd_create(&zfs_fsyncer_key, NULL);
+ tsd_create(&rrw_tsd_key, rrw_tsd_destroy);
+ tsd_create(&zfs_allow_log_key, zfs_allow_log_destroy);
- printf("ZFS storage pool version: features support (" SPA_VERSION_STRING ")\n");
- root_mount_rel(zfs_root_token);
+ printf("ZFS storage pool version: features support (" SPA_VERSION_STRING ")\n");
+ root_mount_rel(zfs_root_token);
- zfsdev_init();
- break;
- case MOD_UNLOAD:
- if (spa_busy() || zfs_busy() || zvol_busy() ||
- zio_injection_enabled) {
- error = EBUSY;
- break;
- }
+ zfsdev_init();
- zfsdev_fini();
- zvol_fini();
- zfs_fini();
- spa_fini();
+ return (0);
+}
- tsd_destroy(&zfs_fsyncer_key);
- tsd_destroy(&rrw_tsd_key);
- tsd_destroy(&zfs_allow_log_key);
+int
+zfs__fini(void)
+{
+ if (spa_busy() || zfs_busy() || zvol_busy() ||
+ zio_injection_enabled) {
+ return (EBUSY);
+ }
- mutex_destroy(&zfs_share_lock);
- break;
+ zfsdev_fini();
+ zvol_fini();
+ zfs_fini();
+ spa_fini();
+
+ tsd_destroy(&zfs_fsyncer_key);
+ tsd_destroy(&rrw_tsd_key);
+ tsd_destroy(&zfs_allow_log_key);
+
+ mutex_destroy(&zfs_share_lock);
+
+ return (0);
+}
+
+static void
+zfs_shutdown(void *arg __unused, int howto __unused)
+{
+
+ /*
+ * ZFS fini routines can not properly work in a panic-ed system.
+ */
+ if (panicstr == NULL)
+ (void)zfs__fini();
+}
+
+
+static int
+zfs_modevent(module_t mod, int type, void *unused __unused)
+{
+ int err;
+
+ switch (type) {
+ case MOD_LOAD:
+ err = zfs__init();
+ if (err == 0)
+ zfs_shutdown_event_tag = EVENTHANDLER_REGISTER(
+ shutdown_post_sync, zfs_shutdown, NULL,
+ SHUTDOWN_PRI_FIRST);
+ return (err);
+ case MOD_UNLOAD:
+ err = zfs__fini();
+ if (err == 0 && zfs_shutdown_event_tag != NULL)
+ EVENTHANDLER_DEREGISTER(shutdown_post_sync,
+ zfs_shutdown_event_tag);
+ return (err);
+ case MOD_SHUTDOWN:
+ return (0);
default:
- error = EOPNOTSUPP;
break;
}
- return (error);
+ return (EOPNOTSUPP);
}
static moduledata_t zfs_mod = {
OpenPOWER on IntegriCloud