Skip to content

Commit

Permalink
jectl: perform forced unmounts for a jail environment
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Rob Wing committed Jan 7, 2023
1 parent 8451321 commit f6c0032
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 13 deletions.
2 changes: 1 addition & 1 deletion jectl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

30 changes: 26 additions & 4 deletions jectl_mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
36 changes: 29 additions & 7 deletions jectl_unmount.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,38 +29,60 @@

#include "jectl.h"

static void
usage(void)
{
fprintf(stderr, "usage: jectl umount [-f] <jailname>\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 <jailname>\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) {
zfs_close(jds);
return (1);
}

error = je_unmount(je);
error = je_unmount(je, flags);

zfs_close(je);
zfs_close(jds);
Expand Down
2 changes: 1 addition & 1 deletion jectl_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down

0 comments on commit f6c0032

Please sign in to comment.