From f6c00320c13f58147ee9f1f2f952ca0c49117f95 Mon Sep 17 00:00:00 2001 From: Rob Wing Date: Fri, 6 Jan 2023 23:16:43 -0900 Subject: [PATCH] jectl: perform forced unmounts for a jail environment When a jail is in a dying state it prevents the backing dataset from being unmounted. Workaround this for now by performing forced unmounts of jail environment datasets. --- jectl.h | 2 +- jectl_mount.c | 30 ++++++++++++++++++++++++++---- jectl_unmount.c | 36 +++++++++++++++++++++++++++++------- jectl_util.c | 2 +- 4 files changed, 57 insertions(+), 13 deletions(-) diff --git a/jectl.h b/jectl.h index ac0ac55..a956fdb 100644 --- a/jectl.h +++ b/jectl.h @@ -56,5 +56,5 @@ int je_activate(zfs_handle_t *, const char *); int je_destroy(zfs_handle_t *); int je_mount(zfs_handle_t *, const char *); int je_swapin(zfs_handle_t *, zfs_handle_t *); -int je_unmount(zfs_handle_t *); +int je_unmount(zfs_handle_t *, int); diff --git a/jectl_mount.c b/jectl_mount.c index 04b1fcf..22243af 100644 --- a/jectl_mount.c +++ b/jectl_mount.c @@ -60,14 +60,36 @@ je_mount(zfs_handle_t *jds, const char *mountpoint) zfs_handle_t *je; get_all_cb_t cb = { 0 }; - if ((je = get_active_je(jds)) == NULL) + if ((je = get_active_je(jds)) == NULL) { + fprintf(stderr, + "je_mount: cannot find active jail environment for '%s'\n", + zfs_get_name(jds)); return (1); + } - if (zfs_prop_set(je, "mountpoint", mountpoint) != 0) + /* + * XXX: work-around dying jails + * + * A dying jail can prevent the backing dataset from being unmounted. + * Do a forced unmount until dying jails can be cleaned properly. + */ + if (je_unmount(je, MNT_FORCE) != 0) { + char mp[ZFS_MAXPROPLEN]; + + zfs_prop_get(je, ZFS_PROP_MOUNTPOINT, mp, sizeof(mp), + NULL, NULL, 0, B_FALSE); + fprintf(stderr, + "je_mount: cannot unmount '%s' from '%s'\n", + zfs_get_name(je), mp); return (1); + } - if (zfs_is_mounted(je, NULL)) - return (0); + if (zfs_prop_set(je, "mountpoint", mountpoint) != 0) { + fprintf(stderr, + "je_mount: cannot set mountpoint for '%s' at '%s'\n", + zfs_get_name(je), mountpoint); + return (1); + } libzfs_add_handle(&cb, je); zfs_iter_dependents(je, B_TRUE, gather_cb, &cb); diff --git a/jectl_unmount.c b/jectl_unmount.c index 1d23b46..cfcd8d1 100644 --- a/jectl_unmount.c +++ b/jectl_unmount.c @@ -29,30 +29,52 @@ #include "jectl.h" +static void +usage(void) +{ + fprintf(stderr, "usage: jectl umount [-f] \n"); + exit(1); +} + /* * unmount zhp and child datasets inheriting zhp's mountpoint */ int -je_unmount(zfs_handle_t *zhp) +je_unmount(zfs_handle_t *zhp, int flags) { if (!zfs_is_mounted(zhp, NULL)) return (0); - return (zfs_unmountall(zhp, 0)); + return (zfs_unmountall(zhp, flags)); } static int jectl_unmount(int argc, char **argv) { + int c; int error; + int flags = 0; zfs_handle_t *je, *jds; - if (argc != 2) { - fprintf(stderr, "usage: jectl umount \n"); - return (1); + while ((c = getopt(argc, argv, "f")) != -1) { + switch (c) { + case 'f': + flags |= MNT_FORCE; + break; + case '?': + usage(); + } + } + + argc -= optind; + argv += optind; + + if (argc != 1) { + fprintf(stderr, "must provide jail name\n"); + usage(); } - if ((jds = get_jail_dataset(argv[1])) == NULL) + if ((jds = get_jail_dataset(argv[0])) == NULL) return (1); if ((je = get_active_je(jds)) == NULL) { @@ -60,7 +82,7 @@ jectl_unmount(int argc, char **argv) return (1); } - error = je_unmount(je); + error = je_unmount(je, flags); zfs_close(je); zfs_close(jds); diff --git a/jectl_util.c b/jectl_util.c index 9665339..6c9c1c5 100644 --- a/jectl_util.c +++ b/jectl_util.c @@ -240,7 +240,7 @@ je_swapin(zfs_handle_t *jds, zfs_handle_t *target) return (0); } - if (je_unmount(src) != 0 || je_unmount(target) != 0) { + if (je_unmount(src, 0) != 0 || je_unmount(target, 0) != 0) { zfs_close(src); return (1); }