Richard W.M. Jones
2014-Mar-17 12:32 UTC
[Libguestfs] [PATCH 1/4] ocaml: Add Guestfs.Errno submodule exposing useful raw errno numbers.
For use when calling G.last_errno. --- generator/ocaml.ml | 15 +++++++++++++++ ocaml/guestfs-c.c | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/generator/ocaml.ml b/generator/ocaml.ml index 78cff89..29a9eb6 100644 --- a/generator/ocaml.ml +++ b/generator/ocaml.ml @@ -121,10 +121,20 @@ val last_errno : t -> int (or [0] if there was no errno). Note that the returned integer is the raw errno number, and it is {i not} related to the {!Unix.error} type. + Some raw errno numbers are exposed by the {!Guestfs.Errno} submodule, + and we can add more as required. + [last_errno] can be overwritten by subsequent operations on a handle, so if you want to capture the errno correctly, you must call this in the {!Error} exception handler, before any other operation on [g]. *) +(** The [Guestfs.Errno] submodule exposes some raw errno numbers, + which you can use to test the return value of {!Guestfs.last_errno}. *) + +module Errno : sig + val errno_ENOTSUP : int +end + "; generate_ocaml_structure_decls (); @@ -253,6 +263,11 @@ external event_to_string : event list -> string external last_errno : t -> int = \"ocaml_guestfs_last_errno\" +module Errno = struct + external enotsup : unit -> int = \"ocaml_guestfs_get_ENOTSUP\" \"noalloc\" + let errno_ENOTSUP = enotsup () +end + (* Give the exceptions names, so they can be raised from the C code. *) let () Callback.register_exception \"ocaml_guestfs_error\" (Error \"\"); diff --git a/ocaml/guestfs-c.c b/ocaml/guestfs-c.c index 98a9ba0..bd1ffb7 100644 --- a/ocaml/guestfs-c.c +++ b/ocaml/guestfs-c.c @@ -63,6 +63,7 @@ value ocaml_guestfs_set_event_callback (value gv, value closure, value events); value ocaml_guestfs_delete_event_callback (value gv, value eh); value ocaml_guestfs_event_to_string (value events); value ocaml_guestfs_last_errno (value gv); +value ocaml_guestfs_get_ENOTSUP (value unitv); /* Allocate handles and deal with finalization. */ static void @@ -438,3 +439,10 @@ ocaml_guestfs_last_errno (value gv) rv = Val_int (r); CAMLreturn (rv); } + +/* NB: "noalloc" function. */ +value +ocaml_guestfs_get_ENOTSUP (value unitv) +{ + return Val_int (ENOTSUP); +} -- 1.8.5.3
Richard W.M. Jones
2014-Mar-17 12:32 UTC
[Libguestfs] [PATCH 2/4] launch: Return errno == ENOTSUP if discard is not supported.
--- src/launch-direct.c | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/src/launch-direct.c b/src/launch-direct.c index 3d478c7..0f6e2fc 100644 --- a/src/launch-direct.c +++ b/src/launch-direct.c @@ -1417,46 +1417,43 @@ guestfs___discard_possible (guestfs_h *g, struct drive *drv, */ bool qemu16 = qemu_version >= 1006000; - if (!qemu15) { - error (g, _("discard cannot be enabled on this drive: " - "qemu < 1.5")); - return false; - } + if (!qemu15) + NOT_SUPPORTED (g, false, + _("discard cannot be enabled on this drive: " + "qemu < 1.5")); /* If it's an overlay, discard is not possible (on the underlying * file). This has probably been caught earlier since we already * checked that the drive is !readonly. Nevertheless ... */ - if (drv->overlay) { - error (g, _("discard cannot be enabled on this drive: " - "the drive has a read-only overlay")); - return false; - } + if (drv->overlay) + NOT_SUPPORTED (g, false, + _("discard cannot be enabled on this drive: " + "the drive has a read-only overlay")); /* Look at the source format. */ if (drv->src.format == NULL) { /* We could autodetect the format, but we don't ... yet. XXX */ - error (g, _("discard cannot be enabled on this drive: " - "you have to specify the format of the file")); - return false; + NOT_SUPPORTED (g, false, + _("discard cannot be enabled on this drive: " + "you have to specify the format of the file")); } else if (STREQ (drv->src.format, "raw")) /* OK */ ; else if (STREQ (drv->src.format, "qcow2")) { - if (!qemu16) { - error (g, _("discard cannot be enabled on this drive: " - "qemu < 1.6 cannot do discard on qcow2 files")); - return false; - } + if (!qemu16) + NOT_SUPPORTED (g, false, + _("discard cannot be enabled on this drive: " + "qemu < 1.6 cannot do discard on qcow2 files")); } else { /* It's possible in future other formats will support discard, but * currently (qemu 1.7) none of them do. */ - error (g, _("discard cannot be enabled on this drive: " - "qemu does not support discard for '%s' format files"), - drv->src.format); - return false; + NOT_SUPPORTED (g, false, + _("discard cannot be enabled on this drive: " + "qemu does not support discard for '%s' format files"), + drv->src.format); } switch (drv->src.protocol) { @@ -1476,10 +1473,10 @@ guestfs___discard_possible (guestfs_h *g, struct drive *drv, case drive_protocol_https: case drive_protocol_ssh: case drive_protocol_tftp: - error (g, _("discard cannot be enabled on this drive: " - "protocol '%s' does not support discard"), - guestfs___drive_protocol_to_string (drv->src.protocol)); - return false; + NOT_SUPPORTED (g, -1, + _("discard cannot be enabled on this drive: " + "protocol '%s' does not support discard"), + guestfs___drive_protocol_to_string (drv->src.protocol)); } return true; -- 1.8.5.3
Richard W.M. Jones
2014-Mar-17 12:32 UTC
[Libguestfs] [PATCH 3/4] mllib: Allow exit code to be specified when calling 'error' function.
--- mllib/common_utils.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml index de3bd40..094ef10 100644 --- a/mllib/common_utils.ml +++ b/mllib/common_utils.ml @@ -187,7 +187,7 @@ let make_message_function ~quiet fs in ksprintf p fs -let error ~prog fs +let error ~prog ?(exit_code = 1) fs let display str wrap ~chan:stderr (sprintf (f_"%s: error: %s") prog str); prerr_newline (); @@ -196,7 +196,7 @@ let error ~prog fs (sprintf (f_"%s: If reporting bugs, run %s with debugging enabled (-v) and include the complete output.") prog prog); prerr_newline (); - exit 1 + exit exit_code in ksprintf display fs -- 1.8.5.3
Richard W.M. Jones
2014-Mar-17 12:32 UTC
[Libguestfs] [PATCH 4/4] virt-sparsify --in-place: Exit with code 3 if discard is not supported.
Also skip the test in this case instead of failing. --- sparsify/cmdline.ml | 2 +- sparsify/in_place.ml | 13 ++++++++++++- sparsify/test-virt-sparsify-in-place.sh | 8 +++++++- sparsify/virt-sparsify.pod | 19 +++++++++++++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/sparsify/cmdline.ml b/sparsify/cmdline.ml index d25e9e9..c96de57 100644 --- a/sparsify/cmdline.ml +++ b/sparsify/cmdline.ml @@ -24,7 +24,7 @@ open Common_gettext.Gettext open Common_utils let prog = Filename.basename Sys.executable_name -let error fs = error ~prog fs +let error ?exit_code fs = error ~prog ?exit_code fs type mode_t | Mode_copying of string * check_t * bool * string option * string option diff --git a/sparsify/in_place.ml b/sparsify/in_place.ml index 9f46ad3..624f676 100644 --- a/sparsify/in_place.ml +++ b/sparsify/in_place.ml @@ -28,12 +28,23 @@ module G = Guestfs open Common_utils open Cmdline -let run disk format ignores machine_readable quiet verbose trace zeroes +let rec run disk format ignores machine_readable quiet verbose trace zeroes (* Connect to libguestfs. *) let g = new G.guestfs () in if trace then g#set_trace true; if verbose then g#set_verbose true; + try + perform g disk format ignores machine_readable quiet zeroes + with + G.Error msg as exn -> + if g#last_errno () = G.Errno.errno_ENOTSUP then ( + (* for exit code 3, see man page *) + error ~exit_code:3 (f_"discard/trim is not supported: %s") msg; + ) + else raise exn + +and perform g disk format ignores machine_readable quiet zeroes (* XXX Current limitation of the API. Can remove this hunk in future. *) let format match format with diff --git a/sparsify/test-virt-sparsify-in-place.sh b/sparsify/test-virt-sparsify-in-place.sh index 56311a0..dd32963 100755 --- a/sparsify/test-virt-sparsify-in-place.sh +++ b/sparsify/test-virt-sparsify-in-place.sh @@ -49,7 +49,13 @@ EOF size_before=$(du -s test-virt-sparsify-in-place.img | awk '{print $1}') -$VG ./virt-sparsify --debug-gc --in-place test-virt-sparsify-in-place.img +$VG ./virt-sparsify --debug-gc --in-place test-virt-sparsify-in-place.img || { + if [ "$?" -eq 3 ]; then + echo "$0: discard not supported in virt-sparsify" + exit 77 + fi + exit 1 +} size_after=$(du -s test-virt-sparsify-in-place.img | awk '{print $1}') diff --git a/sparsify/virt-sparsify.pod b/sparsify/virt-sparsify.pod index c12a15f..de07439 100644 --- a/sparsify/virt-sparsify.pod +++ b/sparsify/virt-sparsify.pod @@ -381,6 +381,25 @@ temporary space are B<not> required. For other environment variables, see L<guestfs(3)/ENVIRONMENT VARIABLES>. +=head1 EXIT STATUS + +This program returns 0 if the operation completed without errors. +(This doesn't necessarily mean that space could be freed up.) + +A non-zero exit code indicates an error. + +If the exit code is C<3> and the I<--in-place> option was used, that +indicates that discard support is not available in libguestfs, so +copying mode must be used instead. + +=over 4 + +=item 0 + +successful exit + +=back + =head1 SEE ALSO L<virt-filesystems(1)>, -- 1.8.5.3
Richard W.M. Jones
2014-Mar-17 12:36 UTC
Re: [Libguestfs] [PATCH 4/4] virt-sparsify --in-place: Exit with code 3 if discard is not supported.
On Mon, Mar 17, 2014 at 12:32:25PM +0000, Richard W.M. Jones wrote:> + > +=over 4 > + > +=item 0 > + > +successful exit > + > +=backSorry, this part should be deleted. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://people.redhat.com/~rjones/virt-top