1 .\" 2 .\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 .\" $FreeBSD$ 29 .\" 30 .Dd October 16, 2019 31 .Dt LIBBE 3 32 .Os 33 .Sh NAME 34 .Nm libbe 35 .Nd library for creating, destroying and modifying ZFS boot environments 36 .Sh LIBRARY 37 .Lb libbe 38 .Sh SYNOPSIS 39 .In be.h 40 .Ft "libbe_handle_t *hdl" Ns 41 .Fn libbe_init "const char *be_root" 42 .Pp 43 .Ft void 44 .Fn libbe_close "libbe_handle_t *hdl" 45 .Pp 46 .Ft const char * Ns 47 .Fn be_active_name "libbe_handle_t *hdl" 48 .Pp 49 .Ft const char * Ns 50 .Fn be_active_path "libbe_handle_t *hdl" 51 .Pp 52 .Ft const char * Ns 53 .Fn be_nextboot_name "libbe_handle_t *hdl" 54 .Pp 55 .Ft const char * Ns 56 .Fn be_nextboot_path "libbe_handle_t *hdl" 57 .Pp 58 .Ft const char * Ns 59 .Fn be_root_path "libbe_handle_t *hdl" 60 .Pp 61 .Ft bool Ns 62 .Fn be_is_auto_snapshot_name "libbe_handle_t *hdl" "const char *snap" 63 .Pp 64 .Ft int 65 .Fn be_create "libbe_handle_t *hdl" "const char *be_name" 66 .Pp 67 .Ft int 68 .Fn be_create_depth "libbe_handle_t *hdl" "const char *be_name" "const char *snap" "int depth" 69 .Pp 70 .Ft int 71 .Fn be_create_from_existing "libbe_handle_t *hdl" "const char *be_name" "const char *be_origin" 72 .Pp 73 .Ft int 74 .Fn be_create_from_existing_snap "libbe_handle_t *hdl" "const char *be_name" "const char *snap" 75 .Pp 76 .Ft int 77 .Fn be_rename "libbe_handle_t *hdl" "const char *be_old" "const char *be_new" 78 .Pp 79 .Ft int 80 .Fn be_activate "libbe_handle_t *hdl" "const char *be_name" "bool temporary" 81 .Ft int 82 .Fn be_destroy "libbe_handle_t *hdl" "const char *be_name" "int options" 83 .Pp 84 .Ft void 85 .Fn be_nicenum "uint64_t num" "char *buf" "size_t bufsz" 86 .Pp 87 .\" TODO: Write up of mount options 88 .\" typedef enum { 89 .\" BE_MNT_FORCE = 1 << 0, 90 .\" BE_MNT_DEEP = 1 << 1, 91 .\" } be_mount_opt_t 92 .Ft int 93 .Fn be_mount "libbe_handle_t *hdl" "char *be_name" "char *mntpoint" "int flags" "char *result" 94 .Pp 95 .Ft int 96 .Fn be_mounted_at "libbe_handle_t *hdl" "const char *path" "nvlist_t *details" 97 .Pp 98 .Ft int 99 .Fn be_unmount "libbe_handle_t *hdl" "char *be_name" "int flags" 100 .Pp 101 .Ft int 102 .Fn libbe_errno "libbe_handle_t *hdl" 103 .Pp 104 .Ft const char * Ns 105 .Fn libbe_error_description "libbe_handle_t *hdl" 106 .Pp 107 .Ft void 108 .Fn libbe_print_on_error "libbe_handle_t *hdl" "bool doprint" 109 .Pp 110 .Ft int 111 .Fn be_root_concat "libbe_handle_t *hdl" "const char *be_name" "char *result" 112 .Pp 113 .Ft int 114 .Fn be_validate_name "libbe_handle_t *hdl" "const char *be_name" 115 .Pp 116 .Ft int 117 .Fn be_validate_snap "libbe_handle_t *hdl" "const char *snap" 118 .Pp 119 .Ft int 120 .Fn be_exists "libbe_handle_t *hdl" "char *be_name" 121 .Pp 122 .Ft int 123 .Fn be_export "libbe_handle_t *hdl" "const char *be_name" "int fd" 124 .Pp 125 .Ft int 126 .Fn be_import "libbe_handle_t *hdl" "const char *be_name" "int fd" 127 .Pp 128 .Ft int 129 .Fn be_prop_list_alloc "nvlist_t **prop_list" 130 .Pp 131 .Ft int 132 .Fn be_get_bootenv_props "libbe_handle_t *hdl" "nvlist_t *be_list" 133 .Pp 134 .Ft int 135 .Fn be_get_dataset_props "libbe_handle_t *hdl" "const char *ds_name" "nvlist_t *props" 136 .Pp 137 .Ft int 138 .Fn be_get_dataset_snapshots "libbe_handle_t *hdl" "const char *ds_name" "nvlist_t *snap_list" 139 .Pp 140 .Ft void 141 .Fn be_prop_list_free "nvlist_t *prop_list" 142 .Sh DESCRIPTION 143 .Nm 144 interfaces with libzfs to provide a set of functions for various operations 145 regarding ZFS boot environments including "deep" boot environments in which 146 a boot environments has child datasets. 147 .Pp 148 A context structure is passed to each function, allowing for a small amount 149 of state to be retained, such as errors from previous operations. 150 .Nm 151 may be configured to print the corresponding error message to 152 .Dv stderr 153 when an error is encountered with 154 .Fn libbe_print_on_error . 155 .Pp 156 All functions returning an 157 .Vt int 158 return 0 on success, or a 159 .Nm 160 errno otherwise as described in 161 .Sx DIAGNOSTICS . 162 .Pp 163 The 164 .Fn libbe_init 165 function takes an optional BE root and initializes 166 .Nm , 167 returning a 168 .Vt "libbe_handle_t *" 169 on success, or 170 .Dv NULL 171 on error. 172 If a BE root is supplied, 173 .Nm 174 will only operate out of that pool and BE root. 175 An error may occur if: 176 .Bl -column 177 .It /boot and / are not on the same filesystem and device, 178 .It libzfs fails to initialize, 179 .It The system has not been properly booted with a ZFS boot 180 environment, 181 .It Nm 182 fails to open the zpool the active boot environment resides on, or 183 .It Nm 184 fails to locate the boot environment that is currently mounted. 185 .El 186 .Pp 187 The 188 .Fn libbe_close 189 function frees all resources previously acquired in 190 .Fn libbe_init , 191 invalidating the handle in the process. 192 .Pp 193 The 194 .Fn be_active_name 195 function returns the name of the currently booted boot environment. 196 This boot environment may not belong to the same BE root as the root libbe 197 is operating on! 198 .Pp 199 The 200 .Fn be_active_path 201 function returns the full path of the currently booted boot environment. 202 This boot environment may not belong to the same BE root as the root libbe 203 is operating on! 204 .Pp 205 The 206 .Fn be_nextboot_name 207 function returns the name of the boot environment that will be active on reboot. 208 .Pp 209 The 210 .Fn be_nextboot_path 211 function returns the full path of the boot environment that will be 212 active on reboot. 213 .Pp 214 The 215 .Fn be_root_path 216 function returns the boot environment root path. 217 .Pp 218 The 219 .Fn be_is_auto_snapshot_name 220 function is used to determine if the given snapshot name matches the format that 221 the 222 .Fn be_snapshot 223 function will use by default if it is not given a snapshot name to use. 224 It returns 225 .Dv true 226 if the name matches the format, and 227 .Dv false 228 if it does not. 229 .Pp 230 The 231 .Fn be_create 232 function creates a boot environment with the given name. 233 The new boot environment will be created from a recursive snapshot of the 234 currently booted boot environment. 235 .Pp 236 The 237 .Fn be_create_depth 238 function creates a boot environment with the given name from an existing 239 snapshot. 240 The depth parameter specifies the depth of recursion that will be cloned from 241 the existing snapshot. 242 A depth of '0' is no recursion and '-1' is unlimited (i.e., a recursive boot 243 environment). 244 .Pp 245 The 246 .Fn be_create_from_existing 247 function creates a boot environment with the given name from the name of an 248 existing boot environment. 249 A recursive snapshot will be made of the origin boot environment, and the new 250 boot environment will be created from that. 251 .Pp 252 The 253 .Fn be_create_from_existing_snap 254 function creates a recursive boot environment with the given name from an 255 existing snapshot. 256 .Pp 257 The 258 .Fn be_rename 259 function renames a boot environment without unmounting it, as if renamed with 260 the 261 .Fl u 262 argument were passed to 263 .Nm zfs 264 .Cm rename 265 .Pp 266 The 267 .Fn be_activate 268 function makes a boot environment active on the next boot. 269 If the 270 .Fa temporary 271 flag is set, then it will be active for the next boot only, as done by 272 .Xr zfsbootcfg 8 . 273 Next boot functionality is currently only available when booting in x86 BIOS 274 mode. 275 .Pp 276 The 277 .Fn be_destroy 278 function will recursively destroy the given boot environment. 279 It will not destroy a mounted boot environment unless the 280 .Dv BE_DESTROY_FORCE 281 option is set in 282 .Fa options . 283 If the 284 .Dv BE_DESTROY_ORIGIN 285 option is set in 286 .Fa options , 287 the 288 .Fn be_destroy 289 function will destroy the origin snapshot to this boot environment as well. 290 .Pp 291 The 292 .Fn be_nicenum 293 function will format 294 .Fa name 295 in a traditional ZFS humanized format, similar to 296 .Xr humanize_number 3 . 297 This function effectively proxies 298 .Fn zfs_nicenum 299 from libzfs. 300 .Pp 301 The 302 .Fn be_mount 303 function will mount the given boot environment. 304 If 305 .Fa mountpoint 306 is 307 .Dv NULL , 308 a mount point will be generated in 309 .Pa /tmp 310 using 311 .Xr mkdtemp 3 . 312 If 313 .Fa result 314 is not 315 .Dv NULL , 316 it should be large enough to accommodate 317 .Dv BE_MAXPATHLEN 318 including the null terminator. 319 the final mount point will be copied into it. 320 Setting the 321 .Dv BE_MNT_FORCE 322 flag will pass 323 .Dv MNT_FORCE 324 to the underlying 325 .Xr mount 2 326 call. 327 .Pp 328 The 329 .Fn be_mounted_at 330 function will check if there is a boot environment mounted at the given 331 .Fa path . 332 If 333 .Fa details 334 is not 335 .Dv NULL , 336 it will be populated with a list of the mounted dataset's properties. 337 This list of properties matches the properties collected by 338 .Fn be_get_bootenv_props . 339 .Pp 340 The 341 .Fn be_unmount 342 function will unmount the given boot environment. 343 Setting the 344 .Dv BE_MNT_FORCE 345 flag will pass 346 .Dv MNT_FORCE 347 to the underlying 348 .Xr mount 2 349 call. 350 .Pp 351 The 352 .Fn libbe_errno 353 function returns the 354 .Nm 355 errno. 356 .Pp 357 The 358 .Fn libbe_error_description 359 function returns a string description of the currently set 360 .Nm 361 errno. 362 .Pp 363 The 364 .Fn libbe_print_on_error 365 function will change whether or not 366 .Nm 367 prints the description of any encountered error to 368 .Dv stderr , 369 based on 370 .Fa doprint . 371 .Pp 372 The 373 .Fn be_root_concat 374 function will concatenate the boot environment root and the given boot 375 environment name into 376 .Fa result . 377 .Pp 378 The 379 .Fn be_validate_name 380 function will validate the given boot environment name for both length 381 restrictions as well as valid character restrictions. 382 This function does not set the internal library error state. 383 .Pp 384 The 385 .Fn be_validate_snap 386 function will validate the given snapshot name. 387 The snapshot must have a valid name, exist, and have a mountpoint of 388 .Pa / . 389 This function does not set the internal library error state. 390 .Pp 391 The 392 .Fn be_exists 393 function will check whether the given boot environment exists and has a 394 mountpoint of 395 .Pa / . 396 This function does not set the internal library error state, but will return 397 the appropriate error. 398 .Pp 399 The 400 .Fn be_export 401 function will export the given boot environment to the file specified by 402 .Fa fd . 403 A snapshot will be created of the boot environment prior to export. 404 .Pp 405 The 406 .Fn be_import 407 function will import the boot environment in the file specified by 408 .Fa fd , 409 and give it the name 410 .Fa be_name . 411 .Pp 412 The 413 .Fn be_prop_list_alloc 414 function allocates a property list suitable for passing to 415 .Fn be_get_bootenv_props , 416 .Fn be_get_dataset_props , 417 or 418 .Fn be_get_dataset_snapshots . 419 It should be freed later by 420 .Fa be_prop_list_free . 421 .Pp 422 The 423 .Fn be_get_bootenv_props 424 function will populate 425 .Fa be_list 426 with 427 .Vt nvpair_t 428 of boot environment names paired with an 429 .Vt nvlist_t 430 of their properties. 431 The following properties are currently collected as appropriate: 432 .Bl -column "Returned name" 433 .It Sy Returned name Ta Sy Description 434 .It dataset Ta - 435 .It name Ta Boot environment name 436 .It mounted Ta Current mount point 437 .It mountpoint Ta Do mountpoint Dc property 438 .It origin Ta Do origin Dc property 439 .It creation Ta Do creation Dc property 440 .It active Ta Currently booted environment 441 .It used Ta Literal Do used Dc property 442 .It usedds Ta Literal Do usedds Dc property 443 .It usedsnap Ta Literal Do usedrefreserv Dc property 444 .It referenced Ta Literal Do referenced Dc property 445 .It nextboot Ta Active on next boot 446 .El 447 .Pp 448 Only the 449 .Dq dataset , 450 .Dq name , 451 .Dq active , 452 and 453 .Dq nextboot 454 returned values will always be present. 455 All other properties may be omitted if not available. 456 .Pp 457 The 458 .Fn be_get_dataset_props 459 function will get properties of the specified dataset. 460 .Fa props 461 is populated directly with a list of the properties as returned by 462 .Fn be_get_bootenv_props . 463 .Pp 464 The 465 .Fn be_get_dataset_snapshots 466 function will retrieve all snapshots of the given dataset. 467 .Fa snap_list 468 will be populated with a list of 469 .Vt nvpair_t 470 exactly as specified by 471 .Fn be_get_bootenv_props . 472 .Pp 473 The 474 .Fn be_prop_list_free 475 function will free the property list. 476 .Sh DIAGNOSTICS 477 Upon error, one of the following values will be returned: 478 .Bl -dash -offset indent -compact 479 .It 480 BE_ERR_SUCCESS 481 .It 482 BE_ERR_INVALIDNAME 483 .It 484 BE_ERR_EXISTS 485 .It 486 BE_ERR_NOENT 487 .It 488 BE_ERR_PERMS 489 .It 490 BE_ERR_DESTROYACT 491 .It 492 BE_ERR_DESTROYMNT 493 .It 494 BE_ERR_BADPATH 495 .It 496 BE_ERR_PATHBUSY 497 .It 498 BE_ERR_PATHLEN 499 .It 500 BE_ERR_BADMOUNT 501 .It 502 BE_ERR_NOORIGIN 503 .It 504 BE_ERR_MOUNTED 505 .It 506 BE_ERR_NOMOUNT 507 .It 508 BE_ERR_ZFSOPEN 509 .It 510 BE_ERR_ZFSCLONE 511 .It 512 BE_ERR_IO 513 .It 514 BE_ERR_NOPOOL 515 .It 516 BE_ERR_NOMEM 517 .It 518 BE_ERR_UNKNOWN 519 .It 520 BE_ERR_INVORIGIN 521 .El 522 .Sh SEE ALSO 523 .Xr bectl 8 524 .Sh HISTORY 525 .Nm 526 and its corresponding command, 527 .Xr bectl 8 , 528 were written as a 2017 Google Summer of Code project with Allan Jude serving 529 as a mentor. 530 Later work was done by 531 .An Kyle Evans Aq Mt kevans@FreeBSD.org . 532