Hi, Id 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