1.\" 2.\" This file and its contents are supplied under the terms of the 3.\" Common Development and Distribution License ("CDDL"), version 1.0. 4.\" You may only use this file in accordance with the terms of version 5.\" 1.0 of the CDDL. 6.\" 7.\" A full copy of the text of the CDDL should have accompanied this 8.\" source. A copy of the CDDL is also available via the Internet at 9.\" http://www.illumos.org/license/CDDL. 10.\" 11.\" Copyright (c) 2016, 2019 by Delphix. All Rights Reserved. 12.\" Copyright (c) 2019, 2020 by Christian Schwarz. All Rights Reserved. 13.\" Copyright 2020 Joyent, Inc. 14.\" 15.Dd May 27, 2021 16.Dt ZFS-PROGRAM 8 17.Os 18. 19.Sh NAME 20.Nm zfs-program 21.Nd execute ZFS channel programs 22.Sh SYNOPSIS 23.Nm zfs 24.Cm program 25.Op Fl jn 26.Op Fl t Ar instruction-limit 27.Op Fl m Ar memory-limit 28.Ar pool 29.Ar script 30.Op Ar script arguments 31. 32.Sh DESCRIPTION 33The ZFS channel program interface allows ZFS administrative operations to be 34run programmatically as a Lua script. 35The entire script is executed atomically, with no other administrative 36operations taking effect concurrently. 37A library of ZFS calls is made available to channel program scripts. 38Channel programs may only be run with root privileges. 39.Pp 40A modified version of the Lua 5.2 interpreter is used to run channel program 41scripts. 42The Lua 5.2 manual can be found at 43.Lk http://www.lua.org/manual/5.2/ 44.Pp 45The channel program given by 46.Ar script 47will be run on 48.Ar pool , 49and any attempts to access or modify other pools will cause an error. 50. 51.Sh OPTIONS 52.Bl -tag -width "-t" 53.It Fl j 54Display channel program output in JSON format. 55When this flag is specified and standard output is empty - 56channel program encountered an error. 57The details of such an error will be printed to standard error in plain text. 58.It Fl n 59Executes a read-only channel program, which runs faster. 60The program cannot change on-disk state by calling functions from the 61zfs.sync submodule. 62The program can be used to gather information such as properties and 63determining if changes would succeed (zfs.check.*). 64Without this flag, all pending changes must be synced to disk before a 65channel program can complete. 66.It Fl t Ar instruction-limit 67Limit the number of Lua instructions to execute. 68If a channel program executes more than the specified number of instructions, 69it will be stopped and an error will be returned. 70The default limit is 10 million instructions, and it can be set to a maximum of 71100 million instructions. 72.It Fl m Ar memory-limit 73Memory limit, in bytes. 74If a channel program attempts to allocate more memory than the given limit, it 75will be stopped and an error returned. 76The default memory limit is 10 MiB, and can be set to a maximum of 100 MiB. 77.El 78.Pp 79All remaining argument strings will be passed directly to the Lua script as 80described in the 81.Sx LUA INTERFACE 82section below. 83. 84.Sh LUA INTERFACE 85A channel program can be invoked either from the command line, or via a library 86call to 87.Fn lzc_channel_program . 88. 89.Ss Arguments 90Arguments passed to the channel program are converted to a Lua table. 91If invoked from the command line, extra arguments to the Lua script will be 92accessible as an array stored in the argument table with the key 'argv': 93.Bd -literal -compact -offset indent 94args = ... 95argv = args["argv"] 96-- argv == {1="arg1", 2="arg2", ...} 97.Ed 98.Pp 99If invoked from the libzfs interface, an arbitrary argument list can be 100passed to the channel program, which is accessible via the same 101.Qq Li ... 102syntax in Lua: 103.Bd -literal -compact -offset indent 104args = ... 105-- args == {"foo"="bar", "baz"={...}, ...} 106.Ed 107.Pp 108Note that because Lua arrays are 1-indexed, arrays passed to Lua from the 109libzfs interface will have their indices incremented by 1. 110That is, the element 111in 112.Va arr[0] 113in a C array passed to a channel program will be stored in 114.Va arr[1] 115when accessed from Lua. 116. 117.Ss Return Values 118Lua return statements take the form: 119.Dl return ret0, ret1, ret2, ... 120.Pp 121Return statements returning multiple values are permitted internally in a 122channel program script, but attempting to return more than one value from the 123top level of the channel program is not permitted and will throw an error. 124However, tables containing multiple values can still be returned. 125If invoked from the command line, a return statement: 126.Bd -literal -compact -offset indent 127a = {foo="bar", baz=2} 128return a 129.Ed 130.Pp 131Will be output formatted as: 132.Bd -literal -compact -offset indent 133Channel program fully executed with return value: 134 return: 135 baz: 2 136 foo: 'bar' 137.Ed 138. 139.Ss Fatal Errors 140If the channel program encounters a fatal error while running, a non-zero exit 141status will be returned. 142If more information about the error is available, a singleton list will be 143returned detailing the error: 144.Dl error: \&"error string, including Lua stack trace" 145.Pp 146If a fatal error is returned, the channel program may have not executed at all, 147may have partially executed, or may have fully executed but failed to pass a 148return value back to userland. 149.Pp 150If the channel program exhausts an instruction or memory limit, a fatal error 151will be generated and the program will be stopped, leaving the program partially 152executed. 153No attempt is made to reverse or undo any operations already performed. 154Note that because both the instruction count and amount of memory used by a 155channel program are deterministic when run against the same inputs and 156filesystem state, as long as a channel program has run successfully once, you 157can guarantee that it will finish successfully against a similar size system. 158.Pp 159If a channel program attempts to return too large a value, the program will 160fully execute but exit with a nonzero status code and no return value. 161.Pp 162.Em Note : 163ZFS API functions do not generate Fatal Errors when correctly invoked, they 164return an error code and the channel program continues executing. 165See the 166.Sx ZFS API 167section below for function-specific details on error return codes. 168. 169.Ss Lua to C Value Conversion 170When invoking a channel program via the libzfs interface, it is necessary to 171translate arguments and return values from Lua values to their C equivalents, 172and vice-versa. 173.Pp 174There is a correspondence between nvlist values in C and Lua tables. 175A Lua table which is returned from the channel program will be recursively 176converted to an nvlist, with table values converted to their natural 177equivalents: 178.TS 179cw3 l c l . 180 string -> string 181 number -> int64 182 boolean -> boolean_value 183 nil -> boolean (no value) 184 table -> nvlist 185.TE 186.Pp 187Likewise, table keys are replaced by string equivalents as follows: 188.TS 189cw3 l c l . 190 string -> no change 191 number -> signed decimal string ("%lld") 192 boolean -> "true" | "false" 193.TE 194.Pp 195Any collision of table key strings (for example, the string "true" and a 196true boolean value) will cause a fatal error. 197.Pp 198Lua numbers are represented internally as signed 64-bit integers. 199. 200.Sh LUA STANDARD LIBRARY 201The following Lua built-in base library functions are available: 202.TS 203cw3 l l l l . 204 assert rawlen collectgarbage rawget 205 error rawset getmetatable select 206 ipairs setmetatable next tonumber 207 pairs tostring rawequal type 208.TE 209.Pp 210All functions in the 211.Em coroutine , 212.Em string , 213and 214.Em table 215built-in submodules are also available. 216A complete list and documentation of these modules is available in the Lua 217manual. 218.Pp 219The following functions base library functions have been disabled and are 220not available for use in channel programs: 221.TS 222cw3 l l l l l l . 223 dofile loadfile load pcall print xpcall 224.TE 225. 226.Sh ZFS API 227. 228.Ss Function Arguments 229Each API function takes a fixed set of required positional arguments and 230optional keyword arguments. 231For example, the destroy function takes a single positional string argument 232(the name of the dataset to destroy) and an optional "defer" keyword boolean 233argument. 234When using parentheses to specify the arguments to a Lua function, only 235positional arguments can be used: 236.Dl Sy zfs.sync.destroy Ns Pq \&"rpool@snap" 237.Pp 238To use keyword arguments, functions must be called with a single argument that 239is a Lua table containing entries mapping integers to positional arguments and 240strings to keyword arguments: 241.Dl Sy zfs.sync.destroy Ns Pq {1="rpool@snap", defer=true} 242.Pp 243The Lua language allows curly braces to be used in place of parenthesis as 244syntactic sugar for this calling convention: 245.Dl Sy zfs.sync.snapshot Ns {"rpool@snap", defer=true} 246. 247.Ss Function Return Values 248If an API function succeeds, it returns 0. 249If it fails, it returns an error code and the channel program continues 250executing. 251API functions do not generate Fatal Errors except in the case of an 252unrecoverable internal file system error. 253.Pp 254In addition to returning an error code, some functions also return extra 255details describing what caused the error. 256This extra description is given as a second return value, and will always be a 257Lua table, or Nil if no error details were returned. 258Different keys will exist in the error details table depending on the function 259and error case. 260Any such function may be called expecting a single return value: 261.Dl errno = Sy zfs.sync.promote Ns Pq dataset 262.Pp 263Or, the error details can be retrieved: 264.Bd -literal -compact -offset indent 265.No errno, details = Sy zfs.sync.promote Ns Pq dataset 266if (errno == EEXIST) then 267 assert(details ~= Nil) 268 list_of_conflicting_snapshots = details 269end 270.Ed 271.Pp 272The following global aliases for API function error return codes are defined 273for use in channel programs: 274.TS 275cw3 l l l l l l l . 276 EPERM ECHILD ENODEV ENOSPC ENOENT EAGAIN ENOTDIR 277 ESPIPE ESRCH ENOMEM EISDIR EROFS EINTR EACCES 278 EINVAL EMLINK EIO EFAULT ENFILE EPIPE ENXIO 279 ENOTBLK EMFILE EDOM E2BIG EBUSY ENOTTY ERANGE 280 ENOEXEC EEXIST ETXTBSY EDQUOT EBADF EXDEV EFBIG 281.TE 282. 283.Ss API Functions 284For detailed descriptions of the exact behavior of any ZFS administrative 285operations, see the main 286.Xr zfs 8 287manual page. 288.Bl -tag -width "xx" 289.It Fn zfs.debug msg 290Record a debug message in the zfs_dbgmsg log. 291A log of these messages can be printed via mdb's "::zfs_dbgmsg" command, or 292can be monitored live by running 293.Dl dtrace -n 'zfs-dbgmsg{trace(stringof(arg0))}' 294.Pp 295.Bl -tag -compact -width "property (string)" 296.It Ar msg Pq string 297Debug message to be printed. 298.El 299.It Fn zfs.exists dataset 300Returns true if the given dataset exists, or false if it doesn't. 301A fatal error will be thrown if the dataset is not in the target pool. 302That is, in a channel program running on rpool, 303.Sy zfs.exists Ns Pq \&"rpool/nonexistent_fs" 304returns false, but 305.Sy zfs.exists Ns Pq \&"somepool/fs_that_may_exist" 306will error. 307.Pp 308.Bl -tag -compact -width "property (string)" 309.It Ar dataset Pq string 310Dataset to check for existence. 311Must be in the target pool. 312.El 313.It Fn zfs.get_prop dataset property 314Returns two values. 315First, a string, number or table containing the property value for the given 316dataset. 317Second, a string containing the source of the property (i.e. the name of the 318dataset in which it was set or nil if it is readonly). 319Throws a Lua error if the dataset is invalid or the property doesn't exist. 320Note that Lua only supports int64 number types whereas ZFS number properties 321are uint64. 322This means very large values (like GUIDs) may wrap around and appear negative. 323.Pp 324.Bl -tag -compact -width "property (string)" 325.It Ar dataset Pq string 326Filesystem or snapshot path to retrieve properties from. 327.It Ar property Pq string 328Name of property to retrieve. 329All filesystem, snapshot and volume properties are supported except for 330.Sy mounted 331and 332.Sy iscsioptions . 333Also supports the 334.Sy written@ Ns Ar snap 335and 336.Sy written# Ns Ar bookmark 337properties and the 338.Ao Sy user Ns | Ns Sy group Ac Ns Ao Sy quota Ns | Ns Sy used Ac Ns Sy @ Ns Ar id 339properties, though the id must be in numeric form. 340.El 341.El 342.Bl -tag -width "xx" 343.It Sy zfs.sync submodule 344The sync submodule contains functions that modify the on-disk state. 345They are executed in "syncing context". 346.Pp 347The available sync submodule functions are as follows: 348.Bl -tag -width "xx" 349.It Sy zfs.sync.destroy Ns Pq Ar dataset , Op Ar defer Ns = Ns Sy true Ns | Ns Sy false 350Destroy the given dataset. 351Returns 0 on successful destroy, or a nonzero error code if the dataset could 352not be destroyed (for example, if the dataset has any active children or 353clones). 354.Pp 355.Bl -tag -compact -width "newbookmark (string)" 356.It Ar dataset Pq string 357Filesystem or snapshot to be destroyed. 358.It Op Ar defer Pq boolean 359Valid only for destroying snapshots. 360If set to true, and the snapshot has holds or clones, allows the snapshot to be 361marked for deferred deletion rather than failing. 362.El 363.It Fn zfs.sync.inherit dataset property 364Clears the specified property in the given dataset, causing it to be inherited 365from an ancestor, or restored to the default if no ancestor property is set. 366The 367.Nm zfs Cm inherit Fl S 368option has not been implemented. 369Returns 0 on success, or a nonzero error code if the property could not be 370cleared. 371.Pp 372.Bl -tag -compact -width "newbookmark (string)" 373.It Ar dataset Pq string 374Filesystem or snapshot containing the property to clear. 375.It Ar property Pq string 376The property to clear. 377Allowed properties are the same as those for the 378.Nm zfs Cm inherit 379command. 380.El 381.It Fn zfs.sync.promote dataset 382Promote the given clone to a filesystem. 383Returns 0 on successful promotion, or a nonzero error code otherwise. 384If EEXIST is returned, the second return value will be an array of the clone's 385snapshots whose names collide with snapshots of the parent filesystem. 386.Pp 387.Bl -tag -compact -width "newbookmark (string)" 388.It Ar dataset Pq string 389Clone to be promoted. 390.El 391.It Fn zfs.sync.rollback filesystem 392Rollback to the previous snapshot for a dataset. 393Returns 0 on successful rollback, or a nonzero error code otherwise. 394Rollbacks can be performed on filesystems or zvols, but not on snapshots 395or mounted datasets. 396EBUSY is returned in the case where the filesystem is mounted. 397.Pp 398.Bl -tag -compact -width "newbookmark (string)" 399.It Ar filesystem Pq string 400Filesystem to rollback. 401.El 402.It Fn zfs.sync.set_prop dataset property value 403Sets the given property on a dataset. 404Currently only user properties are supported. 405Returns 0 if the property was set, or a nonzero error code otherwise. 406.Pp 407.Bl -tag -compact -width "newbookmark (string)" 408.It Ar dataset Pq string 409The dataset where the property will be set. 410.It Ar property Pq string 411The property to set. 412.It Ar value Pq string 413The value of the property to be set. 414.El 415.It Fn zfs.sync.snapshot dataset 416Create a snapshot of a filesystem. 417Returns 0 if the snapshot was successfully created, 418and a nonzero error code otherwise. 419.Pp 420Note: Taking a snapshot will fail on any pool older than legacy version 27. 421To enable taking snapshots from ZCP scripts, the pool must be upgraded. 422.Pp 423.Bl -tag -compact -width "newbookmark (string)" 424.It Ar dataset Pq string 425Name of snapshot to create. 426.El 427.It Fn zfs.sync.bookmark source newbookmark 428Create a bookmark of an existing source snapshot or bookmark. 429Returns 0 if the new bookmark was successfully created, 430and a nonzero error code otherwise. 431.Pp 432Note: Bookmarking requires the corresponding pool feature to be enabled. 433.Pp 434.Bl -tag -compact -width "newbookmark (string)" 435.It Ar source Pq string 436Full name of the existing snapshot or bookmark. 437.It Ar newbookmark Pq string 438Full name of the new bookmark. 439.El 440.El 441.It Sy zfs.check submodule 442For each function in the 443.Sy zfs.sync 444submodule, there is a corresponding 445.Sy zfs.check 446function which performs a "dry run" of the same operation. 447Each takes the same arguments as its 448.Sy zfs.sync 449counterpart and returns 0 if the operation would succeed, 450or a non-zero error code if it would fail, along with any other error details. 451That is, each has the same behavior as the corresponding sync function except 452for actually executing the requested change. 453For example, 454.Fn zfs.check.destroy \&"fs" 455returns 0 if 456.Fn zfs.sync.destroy \&"fs" 457would successfully destroy the dataset. 458.Pp 459The available 460.Sy zfs.check 461functions are: 462.Bl -tag -compact -width "xx" 463.It Sy zfs.check.destroy Ns Pq Ar dataset , Op Ar defer Ns = Ns Sy true Ns | Ns Sy false 464.It Fn zfs.check.promote dataset 465.It Fn zfs.check.rollback filesystem 466.It Fn zfs.check.set_property dataset property value 467.It Fn zfs.check.snapshot dataset 468.El 469.It Sy zfs.list submodule 470The zfs.list submodule provides functions for iterating over datasets and 471properties. 472Rather than returning tables, these functions act as Lua iterators, and are 473generally used as follows: 474.Bd -literal -compact -offset indent 475.No for child in Fn zfs.list.children \&"rpool" No do 476 ... 477end 478.Ed 479.Pp 480The available 481.Sy zfs.list 482functions are: 483.Bl -tag -width "xx" 484.It Fn zfs.list.clones snapshot 485Iterate through all clones of the given snapshot. 486.Pp 487.Bl -tag -compact -width "snapshot (string)" 488.It Ar snapshot Pq string 489Must be a valid snapshot path in the current pool. 490.El 491.It Fn zfs.list.snapshots dataset 492Iterate through all snapshots of the given dataset. 493Each snapshot is returned as a string containing the full dataset name, 494e.g. "pool/fs@snap". 495.Pp 496.Bl -tag -compact -width "snapshot (string)" 497.It Ar dataset Pq string 498Must be a valid filesystem or volume. 499.El 500.It Fn zfs.list.children dataset 501Iterate through all direct children of the given dataset. 502Each child is returned as a string containing the full dataset name, 503e.g. "pool/fs/child". 504.Pp 505.Bl -tag -compact -width "snapshot (string)" 506.It Ar dataset Pq string 507Must be a valid filesystem or volume. 508.El 509.It Fn zfs.list.bookmarks dataset 510Iterate through all bookmarks of the given dataset. 511Each bookmark is returned as a string containing the full dataset name, 512e.g. "pool/fs#bookmark". 513.Pp 514.Bl -tag -compact -width "snapshot (string)" 515.It Ar dataset Pq string 516Must be a valid filesystem or volume. 517.El 518.It Fn zfs.list.holds snapshot 519Iterate through all user holds on the given snapshot. 520Each hold is returned 521as a pair of the hold's tag and the timestamp (in seconds since the epoch) at 522which it was created. 523.Pp 524.Bl -tag -compact -width "snapshot (string)" 525.It Ar snapshot Pq string 526Must be a valid snapshot. 527.El 528.It Fn zfs.list.properties dataset 529An alias for zfs.list.user_properties (see relevant entry). 530.Pp 531.Bl -tag -compact -width "snapshot (string)" 532.It Ar dataset Pq string 533Must be a valid filesystem, snapshot, or volume. 534.El 535.It Fn zfs.list.user_properties dataset 536Iterate through all user properties for the given dataset. 537For each step of the iteration, output the property name, its value, 538and its source. 539Throws a Lua error if the dataset is invalid. 540.Pp 541.Bl -tag -compact -width "snapshot (string)" 542.It Ar dataset Pq string 543Must be a valid filesystem, snapshot, or volume. 544.El 545.It Fn zfs.list.system_properties dataset 546Returns an array of strings, the names of the valid system (non-user defined) 547properties for the given dataset. 548Throws a Lua error if the dataset is invalid. 549.Pp 550.Bl -tag -compact -width "snapshot (string)" 551.It Ar dataset Pq string 552Must be a valid filesystem, snapshot or volume. 553.El 554.El 555.El 556. 557.Sh EXAMPLES 558. 559.Ss Example 1 560The following channel program recursively destroys a filesystem and all its 561snapshots and children in a naive manner. 562Note that this does not involve any error handling or reporting. 563.Bd -literal -offset indent 564function destroy_recursive(root) 565 for child in zfs.list.children(root) do 566 destroy_recursive(child) 567 end 568 for snap in zfs.list.snapshots(root) do 569 zfs.sync.destroy(snap) 570 end 571 zfs.sync.destroy(root) 572end 573destroy_recursive("pool/somefs") 574.Ed 575. 576.Ss Example 2 577A more verbose and robust version of the same channel program, which 578properly detects and reports errors, and also takes the dataset to destroy 579as a command line argument, would be as follows: 580.Bd -literal -offset indent 581succeeded = {} 582failed = {} 583 584function destroy_recursive(root) 585 for child in zfs.list.children(root) do 586 destroy_recursive(child) 587 end 588 for snap in zfs.list.snapshots(root) do 589 err = zfs.sync.destroy(snap) 590 if (err ~= 0) then 591 failed[snap] = err 592 else 593 succeeded[snap] = err 594 end 595 end 596 err = zfs.sync.destroy(root) 597 if (err ~= 0) then 598 failed[root] = err 599 else 600 succeeded[root] = err 601 end 602end 603 604args = ... 605argv = args["argv"] 606 607destroy_recursive(argv[1]) 608 609results = {} 610results["succeeded"] = succeeded 611results["failed"] = failed 612return results 613.Ed 614. 615.Ss Example 3 616The following function performs a forced promote operation by attempting to 617promote the given clone and destroying any conflicting snapshots. 618.Bd -literal -offset indent 619function force_promote(ds) 620 errno, details = zfs.check.promote(ds) 621 if (errno == EEXIST) then 622 assert(details ~= Nil) 623 for i, snap in ipairs(details) do 624 zfs.sync.destroy(ds .. "@" .. snap) 625 end 626 elseif (errno ~= 0) then 627 return errno 628 end 629 return zfs.sync.promote(ds) 630end 631.Ed 632