Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142894333
D18796.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D18796.id.diff
View Options
Index: head/lib/libbe/be_access.c
===================================================================
--- head/lib/libbe/be_access.c
+++ head/lib/libbe/be_access.c
@@ -3,6 +3,7 @@
*
* Copyright (c) 2017 Kyle J. Kneitinger <kyle@kneit.in>
* Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org>
+ * Copyright (c) 2019 Wes Maag <wes@jwmaag.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,6 +39,14 @@
char *name;
};
+struct be_mount_info {
+ libbe_handle_t *lbh;
+ const char *be;
+ const char *mountpoint;
+ int mntflags;
+ int deepmount;
+};
+
static int
be_mountcheck_cb(zfs_handle_t *zfs_hdl, void *data)
{
@@ -59,6 +68,105 @@
}
/*
+ * Called from be_mount, uses the given zfs_handle and attempts to
+ * mount it at the passed mountpoint. If the deepmount flag is set, continue
+ * calling the function for each child dataset.
+ */
+static int
+be_mount_iter(zfs_handle_t *zfs_hdl, void *data)
+{
+ int err;
+ char *mountpoint;
+ char tmp[BE_MAXPATHLEN], zfs_mnt[BE_MAXPATHLEN];
+ struct be_mount_info *info;
+
+ info = (struct be_mount_info *)data;
+
+ if (zfs_is_mounted(zfs_hdl, &mountpoint)) {
+ free(mountpoint);
+ return (0);
+ }
+
+ if (zfs_prop_get_int(zfs_hdl, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_OFF)
+ return (0);
+
+ if (zfs_prop_get(zfs_hdl, ZFS_PROP_MOUNTPOINT, zfs_mnt, BE_MAXPATHLEN,
+ NULL, NULL, 0, 1))
+ return (1);
+
+ if (strcmp("none", zfs_mnt) != 0) {
+ char opt = '\0';
+
+ mountpoint = be_mountpoint_augmented(info->lbh, zfs_mnt);
+
+ snprintf(tmp, BE_MAXPATHLEN, "%s%s", info->mountpoint,
+ mountpoint);
+
+ if ((err = zmount(zfs_get_name(zfs_hdl), tmp, info->mntflags,
+ __DECONST(char *, MNTTYPE_ZFS), NULL, 0, &opt, 1)) != 0) {
+ switch (errno) {
+ case ENAMETOOLONG:
+ return (set_error(info->lbh, BE_ERR_PATHLEN));
+ case ELOOP:
+ case ENOENT:
+ case ENOTDIR:
+ return (set_error(info->lbh, BE_ERR_BADPATH));
+ case EPERM:
+ return (set_error(info->lbh, BE_ERR_PERMS));
+ case EBUSY:
+ return (set_error(info->lbh, BE_ERR_PATHBUSY));
+ default:
+ return (set_error(info->lbh, BE_ERR_UNKNOWN));
+ }
+ }
+ }
+
+ if (!info->deepmount)
+ return (0);
+
+ return (zfs_iter_filesystems(zfs_hdl, be_mount_iter, info));
+}
+
+
+static int
+be_umount_iter(zfs_handle_t *zfs_hdl, void *data)
+{
+
+ int err;
+ char *mountpoint;
+ struct be_mount_info *info;
+
+ info = (struct be_mount_info *)data;
+
+ if((err = zfs_iter_filesystems(zfs_hdl, be_umount_iter, info)) != 0) {
+ return (err);
+ }
+
+ if (!zfs_is_mounted(zfs_hdl, &mountpoint)) {
+ return (0);
+ }
+ free(mountpoint);
+
+ if (zfs_unmount(zfs_hdl, NULL, info->mntflags) != 0) {
+ switch (errno) {
+ case ENAMETOOLONG:
+ return (set_error(info->lbh, BE_ERR_PATHLEN));
+ case ELOOP:
+ case ENOENT:
+ case ENOTDIR:
+ return (set_error(info->lbh, BE_ERR_BADPATH));
+ case EPERM:
+ return (set_error(info->lbh, BE_ERR_PERMS));
+ case EBUSY:
+ return (set_error(info->lbh, BE_ERR_PATHBUSY));
+ default:
+ return (set_error(info->lbh, BE_ERR_UNKNOWN));
+ }
+ }
+ return (0);
+}
+
+/*
* usage
*/
int
@@ -108,8 +216,10 @@
{
char be[BE_MAXPATHLEN];
char mnt_temp[BE_MAXPATHLEN];
- int mntflags;
+ int mntflags, mntdeep;
int err;
+ struct be_mount_info info;
+ zfs_handle_t *zhdl;
if ((err = be_root_concat(lbh, bootenv, be)) != 0)
return (set_error(lbh, err));
@@ -120,6 +230,7 @@
if (is_mounted(lbh->lzh, be, NULL))
return (set_error(lbh, BE_ERR_MOUNTED));
+ mntdeep = (flags & BE_MNT_DEEP) ? 1 : 0;
mntflags = (flags & BE_MNT_FORCE) ? MNT_FORCE : 0;
/* Create mountpoint if it is not specified */
@@ -129,24 +240,20 @@
return (set_error(lbh, BE_ERR_IO));
}
- char opt = '\0';
- if ((err = zmount(be, (mountpoint == NULL) ? mnt_temp : mountpoint,
- mntflags, __DECONST(char *, MNTTYPE_ZFS), NULL, 0, &opt, 1)) != 0) {
- switch (errno) {
- case ENAMETOOLONG:
- return (set_error(lbh, BE_ERR_PATHLEN));
- case ELOOP:
- case ENOENT:
- case ENOTDIR:
- return (set_error(lbh, BE_ERR_BADPATH));
- case EPERM:
- return (set_error(lbh, BE_ERR_PERMS));
- case EBUSY:
- return (set_error(lbh, BE_ERR_PATHBUSY));
- default:
- return (set_error(lbh, BE_ERR_UNKNOWN));
- }
+ if ((zhdl = zfs_open(lbh->lzh, be, ZFS_TYPE_FILESYSTEM)) == NULL)
+ return (set_error(lbh, BE_ERR_ZFSOPEN));
+
+ info.lbh = lbh;
+ info.be = be;
+ info.mountpoint = (mountpoint == NULL) ? mnt_temp : mountpoint;
+ info.mntflags = mntflags;
+ info.deepmount = mntdeep;
+
+ if((err = be_mount_iter(zhdl, &info) != 0)) {
+ zfs_close(zhdl);
+ return (err);
}
+ zfs_close(zhdl);
if (result_loc != NULL)
strlcpy(result_loc, mountpoint == NULL ? mnt_temp : mountpoint,
@@ -155,16 +262,16 @@
return (BE_ERR_SUCCESS);
}
-
/*
* usage
*/
int
be_unmount(libbe_handle_t *lbh, char *bootenv, int flags)
{
- int err, mntflags;
+ int err;
char be[BE_MAXPATHLEN];
zfs_handle_t *root_hdl;
+ struct be_mount_info info;
if ((err = be_root_concat(lbh, bootenv, be)) != 0)
return (set_error(lbh, err));
@@ -172,27 +279,17 @@
if ((root_hdl = zfs_open(lbh->lzh, be, ZFS_TYPE_FILESYSTEM)) == NULL)
return (set_error(lbh, BE_ERR_ZFSOPEN));
- mntflags = (flags & BE_MNT_FORCE) ? MS_FORCE : 0;
+ info.lbh = lbh;
+ info.be = be;
+ info.mountpoint = NULL;
+ info.mntflags = (flags & BE_MNT_FORCE) ? MS_FORCE : 0;
- if (zfs_unmount(root_hdl, NULL, mntflags) != 0) {
+ if ((err = be_umount_iter(root_hdl, &info)) != 0) {
zfs_close(root_hdl);
- switch (errno) {
- case ENAMETOOLONG:
- return (set_error(lbh, BE_ERR_PATHLEN));
- case ELOOP:
- case ENOENT:
- case ENOTDIR:
- return (set_error(lbh, BE_ERR_BADPATH));
- case EPERM:
- return (set_error(lbh, BE_ERR_PERMS));
- case EBUSY:
- return (set_error(lbh, BE_ERR_PATHBUSY));
- default:
- return (set_error(lbh, BE_ERR_UNKNOWN));
- }
+ return (err);
}
- zfs_close(root_hdl);
+ zfs_close(root_hdl);
return (BE_ERR_SUCCESS);
}
Index: head/sbin/bectl/bectl.c
===================================================================
--- head/sbin/bectl/bectl.c
+++ head/sbin/bectl/bectl.c
@@ -378,8 +378,10 @@
{
char result_loc[BE_MAXPATHLEN];
char *bootenv, *mountpoint;
- int err;
+ int err, mntflags;
+ /* XXX TODO: Allow shallow */
+ mntflags = BE_MNT_DEEP;
if (argc < 2) {
fprintf(stderr, "bectl mount: missing argument(s)\n");
return (usage(false));
@@ -393,7 +395,7 @@
bootenv = argv[1];
mountpoint = ((argc == 3) ? argv[2] : NULL);
- err = be_mount(be, bootenv, mountpoint, 0, result_loc);
+ err = be_mount(be, bootenv, mountpoint, mntflags, result_loc);
switch (err) {
case BE_ERR_SUCCESS:
Index: head/sbin/bectl/bectl_jail.c
===================================================================
--- head/sbin/bectl/bectl_jail.c
+++ head/sbin/bectl/bectl_jail.c
@@ -180,10 +180,12 @@
bectl_cmd_jail(int argc, char *argv[])
{
char *bootenv, *mountpoint;
- int jid, opt, ret;
+ int jid, mntflags, opt, ret;
bool default_hostname, interactive, unjail;
pid_t pid;
+ /* XXX TODO: Allow shallow */
+ mntflags = BE_MNT_DEEP;
default_hostname = interactive = unjail = true;
jpcnt = INIT_PARAMCOUNT;
jp = malloc(jpcnt * sizeof(*jp));
@@ -250,7 +252,7 @@
mountpoint = NULL;
else
mountpoint = mnt_loc;
- if (be_mount(be, bootenv, mountpoint, 0, mnt_loc) != BE_ERR_SUCCESS) {
+ if (be_mount(be, bootenv, mountpoint, mntflags, mnt_loc) != BE_ERR_SUCCESS) {
fprintf(stderr, "could not mount bootenv\n");
return (1);
}
@@ -301,7 +303,7 @@
if (unjail) {
jail_remove(jid);
- unmount(mnt_loc, 0);
+ be_unmount(be, bootenv, 0);
}
return (0);
@@ -415,7 +417,7 @@
}
jail_remove(jid);
- unmount(path, 0);
+ be_unmount(be, target, 0);
return (0);
}
Index: head/sbin/bectl/tests/bectl_test.sh
===================================================================
--- head/sbin/bectl/tests/bectl_test.sh
+++ head/sbin/bectl/tests/bectl_test.sh
@@ -42,7 +42,21 @@
atf_check zfs create -o mountpoint=/ -o canmount=noauto \
${zpool}/ROOT/default
}
+bectl_create_deep_setup()
+{
+ zpool=$1
+ disk=$2
+ mnt=$3
+ bectl_create_setup ${zpool} ${disk} ${mnt}
+ atf_check mkdir -p ${root}
+ atf_check -o ignore bectl -r ${zpool}/ROOT mount default ${root}
+ atf_check mkdir -p ${root}/usr
+ atf_check zfs create -o mountpoint=/usr -o canmount=noauto \
+ ${zpool}/ROOT/default/usr
+ atf_check -o ignore bectl -r ${zpool}/ROOT umount default
+}
+
bectl_cleanup()
{
zpool=$1
@@ -183,7 +197,7 @@
mount=${cwd}/mnt
root=${mount}/root
- bectl_create_setup ${zpool} ${disk} ${mount}
+ bectl_create_deep_setup ${zpool} ${disk} ${mount}
atf_check mkdir -p ${root}
# Test unmount first...
atf_check -o not-empty bectl -r ${zpool}/ROOT mount default ${root}
@@ -246,7 +260,7 @@
if [ ! -f /rescue/rescue ]; then
atf_skip "This test requires a rescue binary"
fi
- bectl_create_setup ${zpool} ${disk} ${mount}
+ bectl_create_deep_setup ${zpool} ${disk} ${mount}
# Prepare our minimal BE... plop a rescue binary into it
atf_check mkdir -p ${root}
atf_check -o ignore bectl -r ${zpool}/ROOT mount default ${root}
@@ -263,9 +277,9 @@
atf_check -o empty -s exit:0 bectl -r ${zpool}/ROOT unjail default
# Basic command-mode tests, with and without jail cleanup
- atf_check -o inline:"rescue\n" bectl -r ${zpool}/ROOT \
+ atf_check -o inline:"rescue\nusr\n" bectl -r ${zpool}/ROOT \
jail default /rescue/rescue ls -1
- atf_check -o inline:"rescue\n" bectl -r ${zpool}/ROOT \
+ atf_check -o inline:"rescue\nusr\n" bectl -r ${zpool}/ROOT \
jail -Uo path=${root} default /rescue/rescue ls -1
atf_check [ -f ${root}/rescue/rescue ]
atf_check bectl -r ${zpool}/ROOT ujail default
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Jan 25, 1:09 PM (18 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27942242
Default Alt Text
D18796.id.diff (9 KB)
Attached To
Mode
D18796: Change be_mount to mount/unmount child datasets
Attached
Detach File
Event Timeline
Log In to Comment