=head1 NAME

nbdkit-lua-plugin - nbdkit Lua plugin

=head1 SYNOPSIS

 nbdkit lua /path/to/plugin.lua [arguments...]

=head1 DESCRIPTION

C<nbdkit-lua-plugin> is an embedded Lua interpreter for
L<nbdkit(1)>, allowing you to write nbdkit plugins in Lua.

=head2 If you have been given an nbdkit Lua plugin

Assuming you have a Lua script which is an nbdkit plugin, you run it
like this:

 nbdkit lua /path/to/plugin.lua

You may have to add further C<key=value> arguments to the command
line.  Read the Lua script to see if it requires any.

=head1 WRITING A LUA NBDKIT PLUGIN

For an example plugin written in Lua, see:
L<https://github.com/libguestfs/nbdkit/blob/master/plugins/lua/example.lua>

Broadly speaking, Lua nbdkit plugins work like C ones, so you should
read L<nbdkit-plugin(3)> first.

To write a Lua nbdkit plugin, you create a Lua file which contains
at least the following required functions:

 function open (readonly)
     -- see below
     return h
 end
 function get_size (h)
     -- see below
     return size
 end
 function pread (h, count, offset)
     -- see below
     return buf
 end

Note that the subroutines must have those literal names (like
C<open>), because the C part looks up and calls those functions
directly.  You may want to include documentation and globals (eg. for
storing global state).  Also any top-level statements are run when
nbdkit starts up.

=head2 Executable script

If you want you can make the script executable and include a "shebang"
at the top:

 #!/usr/sbin/nbdkit lua

See also L<nbdkit(1)/Shebang scripts>.

These scripts can also be installed in the C<$plugindir>.  See
L<nbdkit-plugin(3)/WRITING PLUGINS IN OTHER PROGRAMMING LANGUAGES>.

=head2 Errors

Lua plugin methods can indicate an error by calling C<error> or
C<assert>.  The error message will contain the method name, filename
and line number where the error occurred, eg:

 error ("could not open " .. filename)
 --> nbdkit: error: open: myplugin.lua:123: could not open disk.img

=head2 Lua callbacks

This just documents the arguments to the callbacks in Lua, and any
way that they differ from the C callbacks.  In all other respects they
work the same way as the C callbacks, so you should go and read
L<nbdkit-plugin(3)>.

=over 4

=item C<dump_plugin>

(Optional)

There are no arguments or return value.

=item C<config>

(Optional)

 function config (key, value)
     -- No return value.
 end

=item C<config_complete>

(Optional)

There are no arguments or return value.

=item C<open>

(Required)

 function open (readonly)
     local handle
     handle=...
     return handle
 end

The C<readonly> flag is a boolean.

You can return any Lua string or object as the handle.  It is passed
back to subsequent calls.

=item C<close>

(Optional)

 function close (h)
     -- No return value
 end

After C<close> returns, the reference count of the handle is
decremented in the C part, which usually means that the handle and its
contents will be garbage collected.

=item C<get_size>

(Required)

 function get_size (h)
     local size
     size= .. the size of the disk ..
     return size
 end

This returns the size of the disk.

=item C<can_write>

(Optional)

 function can_write (h)
     return bool
 end

Return a boolean indicating whether the disk is writable.

=item C<can_flush>

(Optional)

 function can_flush (h)
     return bool
 end

Return a boolean indicating whether flush can be performed.

=item C<is_rotational>

(Optional)

 function is_rotational (h)
     return bool
 end

Return a boolean indicating whether the disk is rotational.

=item C<can_trim>

(Optional)

 function can_trim (h)
     return bool
 end

Return a boolean indicating whether trim/discard can be performed.

=item C<pread>

(Required)

 function pread (h, count, offset)
    -- Construct a buffer of length count bytes and return it.
    return buf
 end

The body of your C<pread> function should construct a buffer of length
(at least) C<count> bytes.  You should read C<count> bytes from the
disk starting at C<offset>.

NBD only supports whole reads, so your function should try to read the
whole region (perhaps requiring a loop).  If the read fails or is
partial, your function should call C<error>.

=item C<pwrite>

(Optional)

 function pwrite (h, buf, offset)
    -- No return value
 end

The body of your C<pwrite> function should write the C<buf> string to
the disk.  You should write C<count> bytes to the disk starting at
C<offset>.

NBD only supports whole writes, so your function should try to write
the whole region (perhaps requiring a loop).  If the write fails or is
partial, your function should call C<error>.

=item C<flush>

(Optional)

 function flush (h)
     -- No return value
 end

The body of your C<flush> function should do a L<sync(2)> or
L<fdatasync(2)> or equivalent on the backing store.

=item C<trim>

(Optional)

 function trim (h, count, offset)
     -- No return value
 end

The body of your C<trim> function should "punch a hole" in the backing
store.

=item C<zero>

(Optional)

 function zero (h, count, offset, may_trim)
    -- No return value
 end

The body of your C<zero> function should ensure that C<count> bytes
of the disk, starting at C<offset>, will read back as zero.  If
C<may_trim> is true, the operation may be optimized as a trim as long
as subsequent reads see zeroes.

NBD only supports whole writes, so your function should try to write
the whole region (perhaps requiring a loop).  If the write fails or is
partial, your function should call C<error>.

=back

=head2 Missing callbacks

=over 4

=item Missing: C<load>, C<unload>, C<name>, C<version>, C<longname>,
C<description>, C<config_help>, C<can_zero>, C<can_fua>, C<can_cache>,
C<cache>

These are not yet supported.

=back

=head2 Threads

The thread model for Lua callbacks currently cannot be set from Lua.
It is hard-coded in the C part to
C<NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS>.  This may change or be
settable in future.

=head1 FILES

=over 4

=item F<$plugindir/nbdkit-lua-plugin.so>

The plugin.

Use C<nbdkit --dump-config> to find the location of C<$plugindir>.

=back

=head1 VERSION

C<nbdkit-lua-plugin> first appeared in nbdkit 1.6.

=head1 SEE ALSO

L<nbdkit(1)>,
L<nbdkit-plugin(3)>.

=head1 AUTHORS

Richard W.M. Jones

=head1 COPYRIGHT

Copyright (C) 2018 Red Hat Inc.
