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
One more problem is that this qemu-nbd process still remains when error occurred.
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.
#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) {
static const char *keyTemplate = "secret,id=sec0,data=%s";
static const char *fileNameTemplate = "driver=qcow2,encrypt.format=luks,encrypt.key-secret=sec0,file.filename=%s";
num = 6 + (sync ? 1 : 0);
ret = (char **)malloc(sizeof(*ret) * num);
ret[pos++] = (char *)"qemu-nbd"; // 0
ret[pos++] = (char *)"--object"; // 1
ret[pos] = (char *)malloc(strlen(keyTemplate) + strlen(key_encrypted_qcow2)); // 2
sprintf(ret[pos], keyTemplate, key_encrypted_qcow2);
pos++;
ret[pos++] = (char *)"--image-opts"; // 3
ret[pos] = (char *)malloc(strlen(fileNameTemplate) + strlen(fileName)); // 4
sprintf(ret[pos], fileNameTemplate, fileName);
pos++;
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) {
nbd_close(openNbd(pinfo, false));
} else {
uint64_t i;
for (i = 0; i < 10000000; i++) {
kill(pid, SIGUSR1);
}
fprintf(stderr, "kill end\n");
}
}
Debug output is like this.
Before nbd_create
libnbd: debug: nbd1: nbd_create: opening handle
Before nbd_connect_systemd_socket_activation
libnbd: debug: nbd1: nbd_connect_systemd_socket_activation: enter: argv=<list>
libnbd: debug: nbd1: nbd_connect_systemd_socket_activation: event CmdConnectSA: START -> CONNECT_SA.START
libnbd: debug: nbd1: nbd_connect_systemd_socket_activation: transition: CONNECT_SA.START -> CONNECT.START
libnbd: debug: nbd1: nbd_connect_systemd_socket_activation: poll start: events=4
libnbd: debug: nbd1: nbd_connect_systemd_socket_activation: poll end: r=1 revents=4
libnbd: debug: nbd1: nbd_connect_systemd_socket_activation: event NotifyWrite: CONNECT.START -> CONNECT.CONNECTING
libnbd: debug: nbd1: nbd_connect_systemd_socket_activation: transition: CONNECT.CONNECTING -> MAGIC.START
libnbd: debug: nbd1: nbd_connect_systemd_socket_activation: transition: MAGIC.START -> MAGIC.RECV_MAGIC
libnbd: debug: nbd1: nbd_connect_systemd_socket_activation: poll start: events=1
libnbd: debug: nbd1: nbd_connect_systemd_socket_activation: poll end: r=-1 revents=0
libnbd: debug: nbd1: nbd_connect_systemd_socket_activation: leave: error="nbd_connect_systemd_socket_activation: poll: Interrupted system call"
nbd_connect_systemd_socket_activation failed. nbd_connect_systemd_socket_activation: poll: Interrupted system call
libnbd: debug: nbd1: nbd_close: closing handle
kill end
Many thanks,
Motohiro Kawahito