Richard W.M. Jones
2009-Sep-09 11:51 UTC
[Libguestfs] [PATCH] Non-daemon actions indirect through generated code
Matt asked me this morning if we could generate guestfish scripts automatically from running programs like virt-v2v. Good idea. This patch however doesn't do this, but it lays the groundwork for it: In order for us to generate code for any functions which don't go through the daemon, we need to add an indirection to those calls via some generated code. This will allow us to add guestfish tracing at some point in the future. If you want to debug calls to libguestfs code, then the easiest thing to do is to use ltrace(1). Sample ltrace output is attached. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into Xen guests. http://et.redhat.com/~rjones/virt-p2v -------------- next part -------------->From c2411cb88bc535eb1f31cf837aecf586cc36e769 Mon Sep 17 00:00:00 2001From: Richard Jones <rjones at trick.home.annexia.org> Date: Wed, 9 Sep 2009 12:34:13 +0100 Subject: [PATCH] Non-daemon actions indirect through generated code. Previously non-daemon actions were called directly by user code, eg: /* Non-generated */ int guestfs_set_verbose (guestfs_h *g, int v) { g->verbose = !!v; return 0; } This changes these actions so they go indirectly via some generated code, eg: /* Generated */ int guestfs_set_verbose (guestfs_h *g, int verbose) { return guestfs__set_verbose (g, verbose); } /* Non-generated */ int guestfs__set_verbose (guestfs_h *g, int v) { g->verbose = !!v; return 0; } The aim is to have a place in the generated code where we can add debug or tracing information for these non- daemon calls. --- .gitignore | 1 + src/Makefile.am | 1 + src/generator.ml | 37 ++++++++++++++++++++++++++++-- src/guestfs.c | 65 +++++++++++++++++++++++++++-------------------------- 4 files changed, 69 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index e3137c8..720630a 100644 --- a/.gitignore +++ b/.gitignore @@ -178,6 +178,7 @@ ruby/Rakefile src/guestfs-actions.c src/guestfs-actions.h src/guestfs-bindtests.c +src/guestfs-internal-actions.h src/guestfs_protocol.c src/guestfs_protocol.h src/guestfs_protocol.x diff --git a/src/Makefile.am b/src/Makefile.am index e38c336..cd0022d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -46,6 +46,7 @@ BUILT_SOURCES = \ guestfs-structs.h \ guestfs-actions.h \ guestfs-actions.c \ + guestfs-internal-actions.h \ guestfs-bindtests.c # This convenience library is solely to avoid compiler warnings diff --git a/src/generator.ml b/src/generator.ml index 2e2b70e..765cb16 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -4548,6 +4548,16 @@ and generate_actions_h () name style ) all_functions +(* Generate the guestfs-internal-actions.h file. *) +and generate_internal_actions_h () + generate_header CStyle LGPLv2; + List.iter ( + fun (shortname, style, _, _, _, _, _) -> + let name = "guestfs__" ^ shortname in + generate_prototype ~single_line:true ~newline:true ~handle:"handle" + name style + ) non_daemon_functions + (* Generate the client-side dispatch stubs. *) and generate_client_actions () generate_header CStyle LGPLv2; @@ -4557,6 +4567,7 @@ and generate_client_actions () #include <stdlib.h> #include \"guestfs.h\" +#include \"guestfs-internal-actions.h\" #include \"guestfs_protocol.h\" #define error guestfs_error @@ -4619,6 +4630,21 @@ check_state (guestfs_h *g, const char *caller) "; + (* For non-daemon functions, generate a wrapper around each function. *) + List.iter ( + fun (shortname, style, _, _, _, _, _) -> + let name = "guestfs_" ^ shortname in + + generate_prototype ~extern:false ~semicolon:false ~newline:true + ~handle:"g" name style; + pr "{\n"; + pr " return guestfs__%s " shortname; + generate_c_call_args ~handle:"g" style; + pr ";\n"; + pr "}\n"; + pr "\n" + ) non_daemon_functions; + (* Client-side stubs for each function. *) List.iter ( fun (shortname, style, _, _, _, _, _) -> @@ -9089,6 +9115,7 @@ and generate_bindtests () #include <string.h> #include \"guestfs.h\" +#include \"guestfs-internal-actions.h\" #include \"guestfs_protocol.h\" #define error guestfs_error @@ -9119,7 +9146,7 @@ print_strings (char *const *argv) let () let (name, style, _, _, _, _, _) = test0 in generate_prototype ~extern:false ~semicolon:false ~newline:true - ~handle:"g" ~prefix:"guestfs_" name style; + ~handle:"g" ~prefix:"guestfs__" name style; pr "{\n"; List.iter ( function @@ -9144,7 +9171,7 @@ print_strings (char *const *argv) if String.sub name (String.length name - 3) 3 <> "err" then ( pr "/* Test normal return. */\n"; generate_prototype ~extern:false ~semicolon:false ~newline:true - ~handle:"g" ~prefix:"guestfs_" name style; + ~handle:"g" ~prefix:"guestfs__" name style; pr "{\n"; (match fst style with | RErr -> @@ -9210,7 +9237,7 @@ print_strings (char *const *argv) ) else ( pr "/* Test error return. */\n"; generate_prototype ~extern:false ~semicolon:false ~newline:true - ~handle:"g" ~prefix:"guestfs_" name style; + ~handle:"g" ~prefix:"guestfs__" name style; pr "{\n"; pr " error (g, \"error\");\n"; (match fst style with @@ -9533,6 +9560,10 @@ Run it from the top source directory using the command generate_actions_h (); close (); + let close = output_to "src/guestfs-internal-actions.h" in + generate_internal_actions_h (); + close (); + let close = output_to "src/guestfs-actions.c" in generate_client_actions (); close (); diff --git a/src/guestfs.c b/src/guestfs.c index 20afb63..571205f 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -57,6 +57,7 @@ #endif #include "guestfs.h" +#include "guestfs-internal-actions.h" #include "guestfs_protocol.h" #include "ignore-value.h" @@ -608,33 +609,33 @@ guestfs_get_error_handler (guestfs_h *g, void **data_rtn) } int -guestfs_set_verbose (guestfs_h *g, int v) +guestfs__set_verbose (guestfs_h *g, int v) { g->verbose = !!v; return 0; } int -guestfs_get_verbose (guestfs_h *g) +guestfs__get_verbose (guestfs_h *g) { return g->verbose; } int -guestfs_set_autosync (guestfs_h *g, int a) +guestfs__set_autosync (guestfs_h *g, int a) { g->autosync = !!a; return 0; } int -guestfs_get_autosync (guestfs_h *g) +guestfs__get_autosync (guestfs_h *g) { return g->autosync; } int -guestfs_set_path (guestfs_h *g, const char *path) +guestfs__set_path (guestfs_h *g, const char *path) { free (g->path); g->path = NULL; @@ -646,13 +647,13 @@ guestfs_set_path (guestfs_h *g, const char *path) } const char * -guestfs_get_path (guestfs_h *g) +guestfs__get_path (guestfs_h *g) { return g->path; } int -guestfs_set_qemu (guestfs_h *g, const char *qemu) +guestfs__set_qemu (guestfs_h *g, const char *qemu) { free (g->qemu); g->qemu = NULL; @@ -662,13 +663,13 @@ guestfs_set_qemu (guestfs_h *g, const char *qemu) } const char * -guestfs_get_qemu (guestfs_h *g) +guestfs__get_qemu (guestfs_h *g) { return g->qemu; } int -guestfs_set_append (guestfs_h *g, const char *append) +guestfs__set_append (guestfs_h *g, const char *append) { free (g->append); g->append = NULL; @@ -678,39 +679,39 @@ guestfs_set_append (guestfs_h *g, const char *append) } const char * -guestfs_get_append (guestfs_h *g) +guestfs__get_append (guestfs_h *g) { return g->append; } int -guestfs_set_memsize (guestfs_h *g, int memsize) +guestfs__set_memsize (guestfs_h *g, int memsize) { g->memsize = memsize; return 0; } int -guestfs_get_memsize (guestfs_h *g) +guestfs__get_memsize (guestfs_h *g) { return g->memsize; } int -guestfs_set_selinux (guestfs_h *g, int selinux) +guestfs__set_selinux (guestfs_h *g, int selinux) { g->selinux = selinux; return 0; } int -guestfs_get_selinux (guestfs_h *g) +guestfs__get_selinux (guestfs_h *g) { return g->selinux; } int -guestfs_get_pid (guestfs_h *g) +guestfs__get_pid (guestfs_h *g) { if (g->pid > 0) return g->pid; @@ -721,7 +722,7 @@ guestfs_get_pid (guestfs_h *g) } struct guestfs_version * -guestfs_version (guestfs_h *g) +guestfs__version (guestfs_h *g) { struct guestfs_version *r; @@ -763,8 +764,8 @@ add_cmdline (guestfs_h *g, const char *str) } int -guestfs_config (guestfs_h *g, - const char *qemu_param, const char *qemu_value) +guestfs__config (guestfs_h *g, + const char *qemu_param, const char *qemu_value) { if (qemu_param[0] != '-') { error (g, _("guestfs_config: parameter must begin with '-' character")); @@ -795,7 +796,7 @@ guestfs_config (guestfs_h *g, } int -guestfs_add_drive (guestfs_h *g, const char *filename) +guestfs__add_drive (guestfs_h *g, const char *filename) { size_t len = strlen (filename) + 64; char buf[len]; @@ -834,7 +835,7 @@ guestfs_add_drive (guestfs_h *g, const char *filename) } int -guestfs_add_drive_ro (guestfs_h *g, const char *filename) +guestfs__add_drive_ro (guestfs_h *g, const char *filename) { size_t len = strlen (filename) + 64; char buf[len]; @@ -855,7 +856,7 @@ guestfs_add_drive_ro (guestfs_h *g, const char *filename) } int -guestfs_add_cdrom (guestfs_h *g, const char *filename) +guestfs__add_cdrom (guestfs_h *g, const char *filename) { if (strchr (filename, ',') != NULL) { error (g, _("filename cannot contain ',' (comma) character")); @@ -914,7 +915,7 @@ static const char *supermin_hostfiles_name "initramfs." REPO "." host_cpu ".supermin.hostfiles"; int -guestfs_launch (guestfs_h *g) +guestfs__launch (guestfs_h *g) { const char *tmpdir; char dir_template[PATH_MAX]; @@ -1506,7 +1507,7 @@ finish_wait_ready (guestfs_h *g, void *vp) } int -guestfs_wait_ready (guestfs_h *g) +guestfs__wait_ready (guestfs_h *g) { int finished = 0, r; @@ -1549,7 +1550,7 @@ guestfs_wait_ready (guestfs_h *g) } int -guestfs_kill_subprocess (guestfs_h *g) +guestfs__kill_subprocess (guestfs_h *g) { if (g->state == CONFIG) { error (g, _("no subprocess to kill")); @@ -1567,37 +1568,37 @@ guestfs_kill_subprocess (guestfs_h *g) /* Access current state. */ int -guestfs_is_config (guestfs_h *g) +guestfs__is_config (guestfs_h *g) { return g->state == CONFIG; } int -guestfs_is_launching (guestfs_h *g) +guestfs__is_launching (guestfs_h *g) { return g->state == LAUNCHING; } int -guestfs_is_ready (guestfs_h *g) +guestfs__is_ready (guestfs_h *g) { return g->state == READY; } int -guestfs_is_busy (guestfs_h *g) +guestfs__is_busy (guestfs_h *g) { return g->state == BUSY; } int -guestfs_get_state (guestfs_h *g) +guestfs__get_state (guestfs_h *g) { return g->state; } int -guestfs_set_ready (guestfs_h *g) +guestfs__set_ready (guestfs_h *g) { if (g->state != BUSY) { error (g, _("guestfs_set_ready: called when in state %d != BUSY"), @@ -1609,7 +1610,7 @@ guestfs_set_ready (guestfs_h *g) } int -guestfs_set_busy (guestfs_h *g) +guestfs__set_busy (guestfs_h *g) { if (g->state != READY) { error (g, _("guestfs_set_busy: called when in state %d != READY"), @@ -1621,7 +1622,7 @@ guestfs_set_busy (guestfs_h *g) } int -guestfs_end_busy (guestfs_h *g) +guestfs__end_busy (guestfs_h *g) { switch (g->state) { -- 1.6.2.5 -------------- next part -------------- __libc_start_main(0x415b80, 6, 0x7fff9ec0e4b8, 0x419380, 0x419370 <unfinished ...> strrchr("./fish/.libs/lt-guestfish", '/') = "/lt-guestfish" __cxa_atexit(0x417b20, 0, 0, 0, 7) = 0 getenv("HOME") = "/home/rjones" __snprintf_chk(0x631640, 1024, 1, 1024, 0x42b206) = 23 using_history(0x631657, 0x42b208, 0x631657, 11, 0x42b213) = 0x7ff6c7a839d8 read_history(0x631640, 0x42b208, 0, 11, 0x42b213 <unfinished ...> malloc(24) = 0x1fa1010 [...] malloc(23) = 0x1fbc5f0 <... read_history resumed> ) = 0 sigaction(13, 0x7fff9ec0e300, NULL) = 0 guestfs_create(13, 0x7fff9ec0de20, 0, -1, 0) = 0x1fbc610 guestfs_set_autosync(0x1fbc610, 1, 0, 3, 0) = 0 getenv("LIBGUESTFS_PATH") = NULL guestfs_set_path(0x1fbc610, 0x42c2f0, 0x7fff9ec0f539, 4, 0x42b214) = 0 getopt_long(6, 0x7fff9ec0e4b8, "a:Df:h::im:nrv?Vx", 0x42ca00, 0x7fff9ec0e39c) = -1 strcasecmp("alloc", "help") = -7 strcasecmp("alloc", "quit") = -16 strcasecmp("alloc", "exit") = -4 strcasecmp("alloc", "q") = -16 strcasecmp("alloc", "alloc") = 0 sscanf(0x7fff9ec0f567, 0x419528, 0x7fff9ec0de40, 0x7fff9ec0de4f, 0) = 2 guestfs_is_config(0x1fbc610, 0, 0x7fff9ec0de50, 0x41952d, 0x7fff9ec0d790) = 1 open("/tmp/test.img", 833, 0666) = 3 posix_fallocate(3, 0, 0xa00000, -1, 0x7fff9ec0d790) = 0 close(3) = 0 guestfs_add_drive(0x1fbc610, 0x7fff9ec0f559, 0, -1, 0xa00000) = 0 fflush(0x7ff6c7619780) = 0 strcasecmp("run", "help") = 10 strcasecmp("run", "quit") = 1 strcasecmp("run", "exit") = 13 strcasecmp("run", "q") = 1 strcasecmp("run", "alloc") = 17 strcasecmp("run", "allocate") = 17 strcasecmp("run", "echo") = 13 strcasecmp("run", "edit") = 13 strcasecmp("run", "vi") = -4 strcasecmp("run", "emacs") = 13 strcasecmp("run", "lcd") = 6 strcasecmp("run", "glob") = 11 strcasecmp("run", "more") = 5 strcasecmp("run", "less") = 6 strcasecmp("run", "reopen") = 16 strcasecmp("run", "time") = -2 strcasecmp("run", "launch") = 6 strcasecmp("run", "run") = 0 guestfs_is_config(0x1fbc610, 0x4196b3, 0x7ff6c73cad40, 0, 0) = 1 guestfs_launch(0x1fbc610, 0x4196b3, 0x7ff6c73cad40, 0, 0 <unfinished ...> --- SIGCHLD (Child exited) --- --- SIGCHLD (Child exited) --- --- SIGCHLD (Child exited) --- <... guestfs_launch resumed> ) = 0 guestfs_wait_ready(0x1fbc610, 9, 0x1fbc890, 72, 0x7ff6c7a93480) = 0 fflush(0x7ff6c7619780) = 0 open("/home/rjones/.guestfish", 65, 0644) = 6 close(6) = 0 append_history(0, 0x631640, 420, -1, 0x7ff6c7eb9700 <unfinished ...> malloc(24) = 0x1fbc800 <... append_history resumed> ) = 0 exit(0 <unfinished ...> --- SIGCHLD (Child exited) --- --- SIGCHLD (Child exited) --- __fpending(0x7ff6c7619780, 0, 0x7ff6c761a330, 0x7ff6c761a330, 0x7ff6c761aed0) = 0 ferror(0x7ff6c7619780) = 0 fclose(0x7ff6c7619780) = 0 __fpending(0x7ff6c7619860, 0, 0x7ff6c761ae10, 0, 0x7ff6c7eb9700) = 0 ferror(0x7ff6c7619860) = 0 fclose(0x7ff6c7619860) = 0 +++ exited (status 0) +++
Matthew Booth
2009-Sep-10 13:52 UTC
[Libguestfs] [PATCH] Non-daemon actions indirect through generated code
On 09/09/09 12:51, Richard W.M. Jones wrote:> Matt asked me this morning if we could generate guestfish scripts > automatically from running programs like virt-v2v. Good idea. > > This patch however doesn't do this, but it lays the groundwork for it: > In order for us to generate code for any functions which don't go > through the daemon, we need to add an indirection to those calls via > some generated code. This will allow us to add guestfish tracing at > some point in the future. > > If you want to debug calls to libguestfs code, then the easiest thing > to do is to use ltrace(1). Sample ltrace output is attached.ACK (as discussed on IRC, conditional on trace too). Matt -- Matthew Booth, RHCA, RHCSS Red Hat Engineering, Virtualisation Team M: +44 (0)7977 267231 GPG ID: D33C3490 GPG FPR: 3733 612D 2D05 5458 8A8A 1600 3441 EA19 D33C 3490