xref: /freebsd/lib/libbe/libbe.3 (revision 745c6c0431d01b4fc3247f4eac08a2181d71e008)
1.\"
2.\" SPDX-License-Identifier: BSD-2-Clause
3.\"
4.\" Copyright (c) 2017 Kyle Kneitinger
5.\" Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org>
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\"    notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\"    notice, this list of conditions and the following disclaimer in the
14.\"    documentation and/or other materials provided with the distribution.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.Dd December 11, 2025
29.Dt LIBBE 3
30.Os
31.Sh NAME
32.Nm libbe
33.Nd library for creating, destroying and modifying ZFS boot environments
34.Sh LIBRARY
35.Lb libbe
36.Sh SYNOPSIS
37.In be.h
38.Ft "libbe_handle_t *hdl" Ns
39.Fn libbe_init "const char *be_root"
40.Pp
41.Ft void
42.Fn libbe_close "libbe_handle_t *hdl"
43.Pp
44.Ft const char * Ns
45.Fn be_active_name "libbe_handle_t *hdl"
46.Pp
47.Ft const char * Ns
48.Fn be_active_path "libbe_handle_t *hdl"
49.Pp
50.Ft const char * Ns
51.Fn be_nextboot_name "libbe_handle_t *hdl"
52.Pp
53.Ft const char * Ns
54.Fn be_nextboot_path "libbe_handle_t *hdl"
55.Pp
56.Ft const char * Ns
57.Fn be_root_path "libbe_handle_t *hdl"
58.Pp
59.Ft int Ns
60.Fn be_snapshot "libbe_handle_t *hdl" "const char *be_name" "const char *snap_name" "bool recursive" "char *result"
61.Pp
62.Ft bool Ns
63.Fn be_is_auto_snapshot_name "libbe_handle_t *hdl" "const char *snap"
64.Pp
65.Ft int
66.Fn be_create "libbe_handle_t *hdl" "const char *be_name"
67.Pp
68.Ft int
69.Fn be_create_depth "libbe_handle_t *hdl" "const char *be_name" "const char *snap" "int depth"
70.Pp
71.Ft int
72.Fn be_create_from_existing "libbe_handle_t *hdl" "const char *be_name" "const char *be_origin"
73.Pp
74.Ft int
75.Fn be_create_from_existing_snap "libbe_handle_t *hdl" "const char *be_name" "const char *snap"
76.Pp
77.Ft int
78.Fn be_rename "libbe_handle_t *hdl" "const char *be_old" "const char *be_new"
79.Pp
80.Ft int
81.Fn be_activate "libbe_handle_t *hdl" "const char *be_name" "bool temporary"
82.Pp
83.Ft int
84.Fn be_deactivate "libbe_handle_t *hdl" "const char *be_name" "bool temporary"
85.Pp
86.Ft int
87.Fn be_destroy "libbe_handle_t *hdl" "const char *be_name" "int options"
88.Pp
89.Ft void
90.Fn be_nicenum "uint64_t num" "char *buf" "size_t bufsz"
91.Pp
92.\" TODO: Write up of mount options
93.\" typedef enum {
94.\"	BE_MNT_FORCE		= 1 << 0,
95.\"	BE_MNT_DEEP		= 1 << 1,
96.\" } be_mount_opt_t
97.Ft int
98.Fn be_mount "libbe_handle_t *hdl" "const char *be_name" "const char *mntpoint" "int flags" "char *result"
99.Pp
100.Ft int
101.Fn be_mounted_at "libbe_handle_t *hdl" "const char *path" "nvlist_t *details"
102.Pp
103.Ft int
104.Fn be_unmount "libbe_handle_t *hdl" "const char *be_name" "int flags"
105.Pp
106.Ft int
107.Fn libbe_errno "libbe_handle_t *hdl"
108.Pp
109.Ft const char * Ns
110.Fn libbe_error_description "libbe_handle_t *hdl"
111.Pp
112.Ft void
113.Fn libbe_print_on_error "libbe_handle_t *hdl" "bool doprint"
114.Pp
115.Ft int
116.Fn be_root_concat "libbe_handle_t *hdl" "const char *be_name" "char *result"
117.Pp
118.Ft int
119.Fn be_validate_name "libbe_handle_t *hdl" "const char *be_name"
120.Pp
121.Ft int
122.Fn be_validate_snap "libbe_handle_t *hdl" "const char *snap"
123.Pp
124.Ft int
125.Fn be_exists "libbe_handle_t *hdl" "const char *be_name"
126.Pp
127.Ft int
128.Fn be_export "libbe_handle_t *hdl" "const char *be_name" "int fd"
129.Pp
130.Ft int
131.Fn be_import "libbe_handle_t *hdl" "const char *be_name" "int fd"
132.Pp
133.Ft int
134.Fn be_prop_list_alloc "nvlist_t **prop_list"
135.Pp
136.Ft int
137.Fn be_get_bootenv_props "libbe_handle_t *hdl" "nvlist_t *be_list"
138.Pp
139.Ft int
140.Fn be_get_dataset_props "libbe_handle_t *hdl" "const char *ds_name" "nvlist_t *props"
141.Pp
142.Ft int
143.Fn be_get_dataset_snapshots "libbe_handle_t *hdl" "const char *ds_name" "nvlist_t *snap_list"
144.Pp
145.Ft void
146.Fn be_prop_list_free "nvlist_t *prop_list"
147.Pp
148.Ft int
149.Fn be_log_history "libbe_handle_t *hdl" "const char *message"
150.Sh DESCRIPTION
151.Nm
152interfaces with libzfs to provide a set of functions for various operations
153regarding ZFS boot environments, including "deep" boot environments in which
154a boot environment has child datasets.
155.Pp
156A context structure is passed to each function, allowing for a small amount
157of state to be retained, such as errors from previous operations.
158.Nm
159may be configured to print the corresponding error message to
160.Dv stderr
161when an error is encountered with
162.Fn libbe_print_on_error .
163.Pp
164All functions returning an
165.Vt int
166return 0 on success, or a
167.Nm
168errno otherwise as described in
169.Sx DIAGNOSTICS .
170.Pp
171The
172.Fn libbe_init
173function takes an optional BE root and initializes
174.Nm ,
175returning a
176.Vt "libbe_handle_t *"
177on success, or
178.Dv NULL
179on error.
180If a BE root is supplied,
181.Nm
182will only operate out of that pool and BE root.
183An error may occur if:
184.Bl -bullet
185.It
186.Pa /boot
187and
188.Pa /
189are not on the same filesystem and device,
190.It
191libzfs fails to initialize,
192.It
193The system has not been properly booted with a ZFS boot
194environment,
195.It
196.Nm
197fails to open the zpool the active boot environment resides on, or
198.It
199.Nm
200fails to locate the boot environment that is currently mounted.
201.El
202.Pp
203The
204.Fn libbe_close
205function frees all resources previously acquired in
206.Fn libbe_init ,
207invalidating the handle in the process.
208.Pp
209The
210.Fn be_active_name
211function returns the name of the currently booted boot environment.
212This boot environment may not belong to the same BE root as the root libbe
213is operating on!
214.Pp
215The
216.Fn be_active_path
217function returns the full path of the currently booted boot environment.
218This boot environment may not belong to the same BE root as the root libbe
219is operating on!
220.Pp
221The
222.Fn be_nextboot_name
223function returns the name of the boot environment that will be active on reboot.
224.Pp
225The
226.Fn be_nextboot_path
227function returns the full path of the boot environment that will be
228active on reboot.
229.Pp
230The
231.Fn be_root_path
232function returns the boot environment root path.
233.Pp
234The
235.Fn be_snapshot
236function creates a snapshot of
237.Fa be_name
238named
239.Fa snap_name .
240A value of
241.Dv NULL
242may be used, indicating that
243.Fn be_snaphot
244should derive the snapshot name from the current date and time.
245If
246.Fa recursive
247is set, then
248.Fn be_snapshot
249will recursively snapshot the dataset.
250If
251.Fa result
252is not
253.Dv NULL ,
254then it will be populated with the final
255.Dq Fa be_name Ns @ Ns Fa snap_name .
256.Pp
257The
258.Fn be_is_auto_snapshot_name
259function is used to determine if the given snapshot name matches the format that
260the
261.Fn be_snapshot
262function will use by default if it is not given a snapshot name to use.
263It returns
264.Dv true
265if the name matches the format, and
266.Dv false
267if it does not.
268.Pp
269The
270.Fn be_create
271function creates a boot environment with the given name.
272The new boot environment will be created from a recursive snapshot of the
273currently booted boot environment.
274.Pp
275The
276.Fn be_create_depth
277function creates a boot environment with the given name from an existing
278snapshot.
279The depth parameter specifies the depth of recursion that will be cloned from
280the existing snapshot.
281A depth of '0' is no recursion and '-1' is unlimited (i.e., a recursive boot
282environment).
283.Pp
284The
285.Fn be_create_from_existing
286function creates a boot environment with the given name from the name of an
287existing boot environment.
288A recursive snapshot will be made of the origin boot environment, and the new
289boot environment will be created from that.
290.Pp
291The
292.Fn be_create_from_existing_snap
293function creates a recursive boot environment with the given name from an
294existing snapshot.
295.Pp
296The
297.Fn be_rename
298function renames a boot environment without unmounting it, as if renamed with
299the
300.Fl u
301argument were passed to
302.Nm zfs
303.Cm rename
304.Pp
305The
306.Fn be_activate
307function makes a boot environment active on the next boot.
308If the
309.Fa temporary
310flag is set, then it will be active for the next boot only, as done by
311.Xr zfsbootcfg 8 .
312.Pp
313The
314.Fn be_deactivate
315function deactivates a boot environment.
316If the
317.Fa temporary
318flag is set, then it will cause removal of boot once configuration, set by
319.Fn be_activate
320function or by
321.Xr zfsbootcfg 8 .
322If the
323.Fa temporary
324flag is not set,
325.Fn be_deactivate
326function will set zfs
327.Dv canmount
328property to
329.Dv noauto .
330.Pp
331The
332.Fn be_destroy
333function will recursively destroy the given boot environment.
334It will not destroy a mounted boot environment unless the
335.Dv BE_DESTROY_FORCE
336option is set in
337.Fa options .
338If the
339.Dv BE_DESTROY_ORIGIN
340option is set in
341.Fa options ,
342the
343.Fn be_destroy
344function will destroy the origin snapshot to this boot environment as well.
345.Pp
346The
347.Fn be_nicenum
348function will format
349.Fa name
350in a traditional ZFS humanized format, similar to
351.Xr humanize_number 3 .
352This function effectively proxies
353.Fn zfs_nicenum
354from libzfs.
355.Pp
356The
357.Fn be_mount
358function will mount the given boot environment.
359If
360.Fa mountpoint
361is
362.Dv NULL ,
363a mount point will be generated in
364.Ev TMPDIR
365or, if
366.Ev TMPDIR
367is not set,
368.Pa /tmp
369using
370.Xr mkdtemp 3 .
371If
372.Fa result
373is not
374.Dv NULL ,
375it should be large enough to accommodate
376.Dv BE_MAXPATHLEN
377including the null terminator.
378the final mount point will be copied into it.
379Setting the
380.Dv BE_MNT_FORCE
381flag will pass
382.Dv MNT_FORCE
383to the underlying
384.Xr mount 2
385call.
386.Pp
387The
388.Fn be_mounted_at
389function will check if there is a boot environment mounted at the given
390.Fa path .
391If
392.Fa details
393is not
394.Dv NULL ,
395it will be populated with a list of the mounted dataset's properties.
396This list of properties matches the properties collected by
397.Fn be_get_bootenv_props .
398.Pp
399The
400.Fn be_unmount
401function will unmount the given boot environment.
402If the mount point looks like it was created by
403.Fn be_mount ,
404then
405.Fn be_unmount
406will attempt to
407.Xr rmdir 2
408the mountpoint after a successful unmount.
409Setting the
410.Dv BE_MNT_FORCE
411flag will pass
412.Dv MNT_FORCE
413to the underlying
414.Xr mount 2
415call.
416.Pp
417The
418.Fn libbe_errno
419function returns the
420.Nm
421errno.
422.Pp
423The
424.Fn libbe_error_description
425function returns a string description of the currently set
426.Nm
427errno.
428.Pp
429The
430.Fn libbe_print_on_error
431function will change whether or not
432.Nm
433prints the description of any encountered error to
434.Dv stderr ,
435based on
436.Fa doprint .
437.Pp
438The
439.Fn be_root_concat
440function will concatenate the boot environment root and the given boot
441environment name into
442.Fa result .
443.Pp
444The
445.Fn be_validate_name
446function will validate the given boot environment name for both length
447restrictions as well as valid character restrictions.
448This function does not set the internal library error state.
449.Pp
450The
451.Fn be_validate_snap
452function will validate the given snapshot name.
453The snapshot must have a valid name, exist, and have a mountpoint of
454.Pa / .
455This function does not set the internal library error state.
456.Pp
457The
458.Fn be_exists
459function will check whether the given boot environment exists and has a
460mountpoint of
461.Pa / .
462This function does not set the internal library error state, but will return
463the appropriate error.
464.Pp
465The
466.Fn be_export
467function will export the given boot environment to the file specified by
468.Fa fd .
469A snapshot will be created of the boot environment prior to export.
470.Pp
471The
472.Fn be_import
473function will import the boot environment in the file specified by
474.Fa fd ,
475and give it the name
476.Fa be_name .
477.Pp
478The
479.Fn be_prop_list_alloc
480function allocates a property list suitable for passing to
481.Fn be_get_bootenv_props ,
482.Fn be_get_dataset_props ,
483or
484.Fn be_get_dataset_snapshots .
485It should be freed later by
486.Fa be_prop_list_free .
487.Pp
488The
489.Fn be_get_bootenv_props
490function will populate
491.Fa be_list
492with
493.Vt nvpair_t
494of boot environment names paired with an
495.Vt nvlist_t
496of their properties.
497The following properties are currently collected as appropriate:
498.Bl -column "Returned name"
499.It Sy Returned name Ta Sy Description
500.It dataset Ta -
501.It name Ta Boot environment name
502.It mounted Ta Current mount point
503.It mountpoint Ta Do mountpoint Dc property
504.It origin Ta Do origin Dc property
505.It creation Ta Do creation Dc property
506.It active Ta Currently booted environment
507.It used Ta Literal Do used Dc property
508.It usedds Ta Literal Do usedds Dc property
509.It usedsnap Ta Literal Do usedrefreserv Dc property
510.It referenced Ta Literal Do referenced Dc property
511.It nextboot Ta Active on next boot
512.El
513.Pp
514Only the
515.Dq dataset ,
516.Dq name ,
517.Dq active ,
518and
519.Dq nextboot
520returned values will always be present.
521All other properties may be omitted if not available.
522.Pp
523The
524.Fn be_get_dataset_props
525function will get properties of the specified dataset.
526.Fa props
527is populated directly with a list of the properties as returned by
528.Fn be_get_bootenv_props .
529.Pp
530The
531.Fn be_get_dataset_snapshots
532function will retrieve all snapshots of the given dataset.
533.Fa snap_list
534will be populated with a list of
535.Vt nvpair_t
536exactly as specified by
537.Fn be_get_bootenv_props .
538.Pp
539The
540.Fn be_prop_list_free
541function will free the property list.
542.Pp
543The
544.Fn be_log_history
545function will log the given
546.Fa message
547to the zpool history, which can be later retrieved using the
548.Xr zpool-history 8
549command.
550.Sh DIAGNOSTICS
551Upon error, one of the following values will be returned:
552.Bl -bullet -offset indent -compact
553.It
554BE_ERR_SUCCESS
555.It
556BE_ERR_INVALIDNAME
557.It
558BE_ERR_EXISTS
559.It
560BE_ERR_NOENT
561.It
562BE_ERR_PERMS
563.It
564BE_ERR_DESTROYACT
565.It
566BE_ERR_DESTROYMNT
567.It
568BE_ERR_BADPATH
569.It
570BE_ERR_PATHBUSY
571.It
572BE_ERR_PATHLEN
573.It
574BE_ERR_BADMOUNT
575.It
576BE_ERR_NOORIGIN
577.It
578BE_ERR_MOUNTED
579.It
580BE_ERR_NOMOUNT
581.It
582BE_ERR_ZFSOPEN
583.It
584BE_ERR_ZFSCLONE
585.It
586BE_ERR_IO
587.It
588BE_ERR_NOPOOL
589.It
590BE_ERR_NOMEM
591.It
592BE_ERR_UNKNOWN
593.It
594BE_ERR_INVORIGIN
595.El
596.Sh SEE ALSO
597.Xr bectl 8 ,
598.Xr zpool-history 8
599.Sh HISTORY
600.Xr bectl 8
601and
602.Nm
603were written by
604.An Kyle Kneitinger (kneitinger) Aq Mt kyle@kneit.in
605as a 2017 Google Summer of Code project, with
606.An Allan Jude (allanjude) Aq Mt allanjude@freebsd.org
607as mentor.
608.Sh AUTHORS
609Kyle Kneitinger, mentored as above.
610.Pp
611Post-GSoC changes were written by
612.An Kyle Evans (kevans) Aq Mt kevans@freebsd.org .
613