Skip to content

Commit 348dd66

Browse files
committed
bectl: Add -E flag to create an empty boot environment
Signed-off-by: Pat Maddox <[email protected]> Test plan: make -C lib/libbe LD_LIBRARY_PATH=$(make -C lib/libbe -V .OBJDIR) make -C lib/libbe check CFLAGS="-I$(realpath lib/libbe)" make -C sbin/bectl PATH=$(make -C sbin/bectl -V .OBJDIR):$PATH LD_LIBRARY_PATH=$(make -C lib/libbe -V .OBJDIR) make -C sbin/bectl check
1 parent d198ad5 commit 348dd66

File tree

8 files changed

+106
-19
lines changed

8 files changed

+106
-19
lines changed

lib/libbe/be.c

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,54 @@ be_create_from_existing(libbe_handle_t *lbh, const char *bename, const char *old
891891
return (set_error(lbh, err));
892892
}
893893

894+
/*
895+
* Create a zfs dataset and map the return to libbe error.
896+
*/
897+
static int
898+
be_zfs_create(libzfs_handle_t *lzh, const char *buf, zfs_type_t t,
899+
nvlist_t *props)
900+
{
901+
int err;
902+
903+
if ((err = zfs_create(lzh, buf, t, props)) != 0) {
904+
switch (err) {
905+
case EZFS_EXISTS:
906+
return (BE_ERR_EXISTS);
907+
case EZFS_NOENT:
908+
return (BE_ERR_NOENT);
909+
case EZFS_BADTYPE:
910+
case EZFS_BADVERSION:
911+
return (BE_ERR_NOPOOL);
912+
case EZFS_BADPROP:
913+
default:
914+
/* We set something up wrong, probably... */
915+
return (BE_ERR_UNKNOWN);
916+
}
917+
}
918+
919+
return (BE_ERR_SUCCESS);
920+
}
921+
922+
923+
/*
924+
* Create an empty boot environment.
925+
*/
926+
int
927+
be_create_empty(libbe_handle_t *lbh, const char *bename)
928+
{
929+
char buf[BE_MAXPATHLEN];
930+
int err;
931+
932+
if ((err = be_validate_name(lbh, bename)) != 0)
933+
return (set_error(lbh, err));
934+
935+
if ((err = be_root_concat(lbh, bename, buf)) != 0)
936+
return (set_error(lbh, err));
937+
938+
err = be_zfs_create(lbh->lzh, buf, ZFS_TYPE_FILESYSTEM, NULL);
939+
return (set_error(lbh, err));
940+
}
941+
894942

895943
/*
896944
* Verifies that a snapshot has a valid name, exists, and has a mountpoint of
@@ -1118,21 +1166,9 @@ be_create_child_noent(libbe_handle_t *lbh, const char *active,
11181166
nvlist_add_string(props, "mountpoint", child_path);
11191167

11201168
/* Create */
1121-
if ((err = zfs_create(lbh->lzh, active, ZFS_TYPE_DATASET,
1169+
if ((err = be_zfs_create(lbh->lzh, active, ZFS_TYPE_DATASET,
11221170
props)) != 0) {
1123-
switch (err) {
1124-
case EZFS_EXISTS:
1125-
return (set_error(lbh, BE_ERR_EXISTS));
1126-
case EZFS_NOENT:
1127-
return (set_error(lbh, BE_ERR_NOENT));
1128-
case EZFS_BADTYPE:
1129-
case EZFS_BADVERSION:
1130-
return (set_error(lbh, BE_ERR_NOPOOL));
1131-
case EZFS_BADPROP:
1132-
default:
1133-
/* We set something up wrong, probably... */
1134-
return (set_error(lbh, BE_ERR_UNKNOWN));
1135-
}
1171+
return (set_error(lbh, err));
11361172
}
11371173
nvlist_free(props);
11381174

lib/libbe/be.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ bool be_is_auto_snapshot_name(libbe_handle_t *, const char *);
6565
/* Bootenv creation functions */
6666
int be_create(libbe_handle_t *, const char *);
6767
int be_create_depth(libbe_handle_t *, const char *, const char *, int);
68+
int be_create_empty(libbe_handle_t *, const char *);
6869
int be_create_from_existing(libbe_handle_t *, const char *, const char *);
6970
int be_create_from_existing_snap(libbe_handle_t *, const char *, const char *);
7071
int be_snapshot(libbe_handle_t *, const char *, const char *, bool, char *);

lib/libbe/libbe.3

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@
6969
.Fn be_create_depth "libbe_handle_t *hdl" "const char *be_name" "const char *snap" "int depth"
7070
.Pp
7171
.Ft int
72+
.Fn be_create_empty "libbe_handle_t *hdl" "const char *be_name"
73+
.Pp
74+
.Ft int
7275
.Fn be_create_from_existing "libbe_handle_t *hdl" "const char *be_name" "const char *be_origin"
7376
.Pp
7477
.Ft int
@@ -282,6 +285,10 @@ A depth of '0' is no recursion and '-1' is unlimited (i.e., a recursive boot
282285
environment).
283286
.Pp
284287
The
288+
.Fn be_create_empty
289+
function creates an empty boot environment with the given name.
290+
.Pp
291+
The
285292
.Fn be_create_from_existing
286293
function creates a boot environment with the given name from the name of an
287294
existing boot environment.

lib/libbe/tests/be_create.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,15 @@ libbe_create_body()
174174
# the child dataset should exist
175175
atf_check -o not-empty \
176176
zfs list "${zpool}/ROOT/relative-snap/usr"
177+
178+
# test empty BE creation.
179+
atf_check $prog "${zpool}/ROOT" \
180+
empty \
181+
ignored \
182+
0
183+
# the dataset should exist
184+
atf_check -o not-empty \
185+
zfs list "${zpool}/ROOT/empty"
177186
}
178187

179188
libbe_create_cleanup()

lib/libbe/tests/target_prog.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include <sys/cdefs.h>
2929
#include <be.h>
30+
#include <string.h>
3031

3132
/*
3233
* argv[1] = root boot environment (e.g. zroot/ROOT),
@@ -36,15 +37,17 @@
3637
*/
3738
int main(int argc, char *argv[]) {
3839

39-
libbe_handle_t *lbh;
40+
libbe_handle_t *lbh;
4041

4142
if (argc != 5)
4243
return -1;
4344

44-
if ((lbh = libbe_init(argv[1])) == NULL)
45-
return -1;
45+
if ((lbh = libbe_init(argv[1])) == NULL)
46+
return -1;
4647

4748
libbe_print_on_error(lbh, true);
4849

50+
if (strcmp(argv[2], "empty") == 0)
51+
return (be_create_empty(lbh, argv[2]));
4952
return (be_create_depth(lbh, argv[2], argv[3], atoi(argv[4])));
5053
}

sbin/bectl/bectl.8

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@
3333
.Ar beName@snapshot
3434
.Nm
3535
.Op Fl r Ar beroot
36+
.Cm create
37+
.Op Fl E
38+
.Ar newBeName
39+
.Nm
40+
.Op Fl r Ar beroot
3641
.Cm destroy
3742
.Op Fl \&Fo
3843
.Ar beName Ns Op Cm @ Ns Ar snapshot
@@ -181,6 +186,13 @@ for a discussion on different layouts.
181186
.Pp
182187
No new boot environment is created with this subcommand.
183188
.It Xo
189+
.Cm create
190+
.Op Fl E
191+
.Ar newBeName
192+
.Xc
193+
Create a new empty boot environment named
194+
.Ar newBeName .
195+
.It Xo
184196
.Cm destroy
185197
.Op Fl \&Fo
186198
.Ar beName Ns Op Cm @ Ns Ar snapshot

sbin/bectl/bectl.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ usage(bool explicit)
5353
"\tbectl [-r beroot] check\n"
5454
"\tbectl [-r beroot] create [-r] [-e {nonActiveBe | beName@snapshot}] beName\n"
5555
"\tbectl [-r beroot] create [-r] beName@snapshot\n"
56+
"\tbectl [-r beroot] create [-E]\n"
5657
"\tbectl [-r beroot] destroy [-Fo] {beName | beName@snapshot}\n"
5758
"\tbectl [-r beroot] export sourceBe\n"
5859
"\tbectl [-r beroot] import targetBe\n"
@@ -184,15 +185,19 @@ bectl_cmd_create(int argc, char *argv[])
184185
char snapshot[BE_MAXPATHLEN];
185186
char *atpos, *bootenv, *snapname;
186187
int err, opt;
187-
bool recursive;
188+
bool empty, recursive;
188189

189190
snapname = NULL;
191+
empty = false;
190192
recursive = false;
191-
while ((opt = getopt(argc, argv, "e:r")) != -1) {
193+
while ((opt = getopt(argc, argv, "e:Er")) != -1) {
192194
switch (opt) {
193195
case 'e':
194196
snapname = optarg;
195197
break;
198+
case 'E':
199+
empty = true;
200+
break;
196201
case 'r':
197202
recursive = true;
198203
break;
@@ -221,6 +226,12 @@ bectl_cmd_create(int argc, char *argv[])
221226
*/
222227
*atpos++ = '\0';
223228
err = be_snapshot(be, bootenv, atpos, recursive, NULL);
229+
} else if (empty) {
230+
if (snapname || recursive) {
231+
fprintf(stderr, "bectl create: -E cannot be combined with -e or -r\n");
232+
return (usage(false));
233+
}
234+
err = be_create_empty(be, bootenv);
224235
} else {
225236
if (snapname == NULL)
226237
/* Create from currently booted BE */

sbin/bectl/tests/bectl_test.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,14 @@ bectl_create_body()
126126
zfs list "${zpool}/ROOT/recursive/usr"
127127
atf_check -o not-empty \
128128
zfs list "${zpool}/ROOT/recursive-snap/usr"
129+
130+
# Test creation of an empty BE.
131+
atf_check bectl -r ${zpool}/ROOT create -E empty
132+
atf_check -o inline:"-\n" zfs get -H -o value origin ${zpool}/ROOT/empty
133+
atf_check -e match:"cannot be combined" -s not-exit:0 \
134+
bectl -r ${zpool}/ROOT create -E -e not-allowed empty-existing
135+
atf_check -e match:"cannot be combined" -s not-exit:0 \
136+
bectl -r ${zpool}/ROOT create -E -r empty-recursive
129137
}
130138
bectl_create_cleanup()
131139
{

0 commit comments

Comments
 (0)