[Libguestfs] Error ret=-1 with EINTR in nbd_connect_systemd_socket_activation()
Richard W.M. Jones
rjones at redhat.com
Tue Jul 12 12:51:19 UTC 2022
On Tue, Jul 12, 2022 at 05:33:41AM +0000, Motohiro Kawahito wrote:
> Hi, I’d like to connect to an encrypted QCOW2 file by
> nbd_connect_systemd_socket_activation(), but I got ret=-1 with EINTR. In our
> program, signals are frequently occurred, so I think this is the background of
> the problem. Could you advise me what should I do next? (such as open issue in
> https://gitlab.com/nbdkit/libnbd or something).
>
> The arg parameter I used is
>
> qemu-nbd --object secret,id=sec0,data=abc123 --image-opts driver=
> qcow2,encrypt.format=luks,encrypt.key-secret=sec0,file.filename=/tmp/
> empty.qcow2
The program worked OK for me. I cleaned up a few things. The
attached program contains my clean-ups.
$ ./nbd
Before nbd_create
Before nbd_connect_systemd_socket_activation
After nbd_connect_systemd_socket_activation
size=8539292672
kill end
However I'm using a slightly newer libnbd & qemu-nbd:
libnbd-1.12.0-1.fc37.x86_64
qemu-img-6.1.0-14.fc35.x86_64
> One more problem is that this qemu-nbd process still remains when error
> occurred.
qemu-nbd should be cleaned up if you call nbd_close, otherwise it
won't be cleaned up (eg. if you immediately exit on error). See:
https://gitlab.com/nbdkit/libnbd/-/blob/e714b9a7403311a1a173a31d86234324e554ce5b/lib/handle.c#L152
nbdkit has a feature called --exit-on-error which means it will always
be cleaned up when the parent process goes away, but qemu-nbd does not
have this feature as far as I know. It would be a useful addition.
https://libguestfs.org/nbdkit-captive.1.html#EXIT-WITH-PARENT
> I also attached a test program below. Is there any problem in my test program?
> The version of qemu-nbd is
>
> $ qemu-nbd -V
>
> qemu-nbd 4.2.1 (Debian 1:4.2-3ubuntu6.23)
>
> I created this encrypted QCOW2 image by the following command.
>
> qemu-img create --object secret,id=sec0,data=abc123 -f qcow2 -o encrypt.format=
> luks,encrypt.key-secret=sec0 /tmp/empty.qcow2 8539292672
>
> Here is a test program I made. I found that this error occurred even for a
> normal QCOW2 file (not encrypted one). If you need more information, please let
> me know.
>
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-builder quickly builds VMs from scratch
http://libguestfs.org/virt-builder.1.html
-------------- next part --------------
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <libnbd.h>
typedef struct _processInfo {
char *fname;
int64_t filesize;
} processInfo;
processInfo pinfo[1024];
int pnum;
static char **
makeCommandQemuNbd(bool sync, char *key_encrypted_qcow2, char *fileName)
{
int num = 0;
int pos = 0;
char **ret;
if (key_encrypted_qcow2) {
num = 6 + (sync ? 1 : 0);
ret = (char **)malloc(sizeof(*ret) * num);
ret[pos++] = (char *)"qemu-nbd"; // 0
ret[pos++] = (char *)"--object"; // 1
asprintf (&ret[pos++], "secret,id=sec0,data=%s",
key_encrypted_qcow2);
ret[pos++] = (char *)"--image-opts"; // 3
asprintf (&ret[pos++], "driver=qcow2,encrypt.format=luks,encrypt.key-secret=sec0,file.filename=%s",
fileName);
if (sync)
ret[pos++] = (char *)"--cache=writethrough"; // 5
ret[pos++] = NULL; // 5 or 6
} else {
num = 5 + (sync ? 1 : 0);
ret = (char **)malloc(sizeof(*ret) * num);
ret[pos++] = (char *)"qemu-nbd"; // 0
ret[pos++] = (char *)"-f"; // 1
ret[pos++] = (char *)"qcow2"; // 2
ret[pos++] = fileName; // 3
if (sync)
ret[pos++] = (char *)"--cache=writethrough"; // 4
ret[pos++] = NULL; // 4 or 5
}
return ret;
}
void sigHandler(int num)
{
// do nothing
}
#define TEST_NORMAL 0
struct nbd_handle *
openNbd(processInfo *pi, bool isWritethrough)
{
struct nbd_handle *nbd;
fprintf(stderr, "Before nbd_create\n");
nbd = nbd_create ();
if (nbd == NULL) {
fprintf(stderr, "nbd_create failed. %s\n", nbd_get_error ());
return nbd;
}
#if TEST_NORMAL // not encrypted file
char **args = makeCommandQemuNbd(isWritethrough, (char*)NULL, (char *)"/tmp/my.qcow2");
#else
char **args = makeCommandQemuNbd(isWritethrough, (char*)"abc123", pi->fname);
#endif
fprintf(stderr, "Before nbd_connect_systemd_socket_activation\n");
int ret = nbd_connect_systemd_socket_activation (nbd, args);
free(args);
if (ret == -1) {
fprintf(stderr, "nbd_connect_systemd_socket_activation failed. %s\n", nbd_get_error ());
return nbd;
}
fprintf(stderr, "After nbd_connect_systemd_socket_activation\n");
pi->filesize = nbd_get_size(nbd);
fprintf(stderr, "size=%ld\n", pi->filesize);
return nbd;
}
int main(int argc, char *argv[])
{
pnum = 0;
pinfo[0].fname = (char*)"/tmp/empty.qcow2";
signal(SIGUSR1, sigHandler);
pid_t pid;
if ((pid = fork()) == 0) {
struct nbd_handle *nbd = openNbd(pinfo, false);
if (nbd) {
nbd_shutdown (nbd, 0);
nbd_close (nbd);
}
} else {
uint64_t i;
for (i = 0; i < 10000000; i++) {
kill(pid, SIGUSR1);
}
fprintf(stderr, "kill end\n");
}
}
More information about the Libguestfs
mailing list