]> git.proxmox.com Git - mirror_lxc.git/blobdiff - src/lxc/storage/nbd.c
tree-wide: fix config.h inclusion
[mirror_lxc.git] / src / lxc / storage / nbd.c
index 5262e4e1f0e406d481ee7f4a62ae3bb3cf6c60d5..e27a98102709fa9f2d95b5c5b18710addffddfe8 100644 (file)
@@ -1,27 +1,7 @@
-/*
- * lxc: linux Container library
- *
- * (C) Copyright IBM Corp. 2007, 2008
- *
- * Authors:
- * Daniel Lezcano <daniel.lezcano at free.fr>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "config.h"
 
-#define _GNU_SOURCE
 #include <errno.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <sys/wait.h>
 
 #include "log.h"
+#include "memory_utils.h"
 #include "nbd.h"
 #include "storage.h"
 #include "storage_utils.h"
+#include "syscall_wrappers.h"
 #include "utils.h"
 
+#ifndef HAVE_STRLCPY
+#include "strlcpy.h"
+#endif
+
 lxc_log_define(nbd, lxc);
 
 struct nbd_attach_data {
@@ -44,8 +30,8 @@ struct nbd_attach_data {
        const char *path;
 };
 
-static bool clone_attach_nbd(const char *nbd, const char *path);
 static int do_attach_nbd(void *d);
+static bool clone_attach_nbd(const char *nbd, const char *path);
 static bool nbd_busy(int idx);
 static void nbd_detach(const char *path);
 static int nbd_get_partition(const char *src);
@@ -53,24 +39,30 @@ static bool wait_for_partition(const char *path);
 
 bool attach_nbd(char *src, struct lxc_conf *conf)
 {
-       char *orig = alloca(strlen(src)+1), *p, path[50];
+       __do_free char *orig = NULL;
+       char *p, path[50];
        int i = 0;
 
-       strcpy(orig, src);
+       orig = must_copy_string(src);
        /* if path is followed by a partition, drop that for now */
        p = strchr(orig, ':');
        if (p)
                *p = '\0';
-       while (1) {
+
+       for (;;) {
                sprintf(path, "/dev/nbd%d", i);
+
                if (!file_exists(path))
                        return false;
+
                if (nbd_busy(i)) {
                        i++;
                        continue;
                }
+
                if (!clone_attach_nbd(path, orig))
                        return false;
+
                conf->nbd_idx = i;
                return true;
        }
@@ -97,7 +89,7 @@ int nbd_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
 }
 
 int nbd_create(struct lxc_storage *bdev, const char *dest, const char *n,
-              struct bdev_specs *specs)
+              struct bdev_specs *specs, const struct lxc_conf *conf)
 {
        return -ENOSYS;
 }
@@ -144,10 +136,10 @@ int nbd_mount(struct lxc_storage *bdev)
        }
 
        /* It might take awhile for the partition files to show up */
-       if (partition) {
+       if (partition)
                if (!wait_for_partition(path))
                        return -2;
-       }
+
        ret = mount_unknown_fs(path, bdev->dest, bdev->mntopts);
        if (ret < 0)
                ERROR("Error mounting %s", bdev->src);
@@ -170,6 +162,7 @@ bool requires_nbd(const char *path)
 {
        if (strncmp(path, "nbd:", 4) == 0)
                return true;
+
        return false;
 }
 
@@ -192,16 +185,17 @@ static int do_attach_nbd(void *d)
 
        if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
                SYSERROR("Error blocking signals for nbd watcher");
-               exit(1);
+               exit(EXIT_FAILURE);
        }
 
        sfd = signalfd(-1, &mask, 0);
        if (sfd == -1) {
                SYSERROR("Error opening signalfd for nbd task");
-               exit(1);
+               exit(EXIT_FAILURE);
        }
 
-       if (prctl(PR_SET_PDEATHSIG, SIGHUP, 0, 0, 0) < 0)
+       if (prctl(PR_SET_PDEATHSIG, prctl_arg(SIGHUP), prctl_arg(0),
+                 prctl_arg(0), prctl_arg(0)) < 0)
                SYSERROR("Error setting parent death signal for nbd watcher");
 
        pid = fork();
@@ -214,16 +208,17 @@ static int do_attach_nbd(void *d)
                        if (fdsi.ssi_signo == SIGHUP) {
                                /* container has exited */
                                nbd_detach(nbd);
-                               exit(0);
+                               exit(EXIT_SUCCESS);
                        } else if (fdsi.ssi_signo == SIGCHLD) {
                                int status;
+
                                /* If qemu-nbd fails, or is killed by a signal,
                                 * then exit */
                                while (waitpid(-1, &status, WNOHANG) > 0) {
                                        if ((WIFEXITED(status) && WEXITSTATUS(status) != 0) ||
                                                        WIFSIGNALED(status)) {
                                                nbd_detach(nbd);
-                                               exit(1);
+                                               exit(EXIT_FAILURE);
                                        }
                                }
                        }
@@ -231,12 +226,13 @@ static int do_attach_nbd(void *d)
        }
 
        close(sfd);
+
        if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1)
                WARN("Warning: unblocking signals for nbd watcher");
 
        execlp("qemu-nbd", "qemu-nbd", "-c", nbd, path, (char *)NULL);
        SYSERROR("Error executing qemu-nbd");
-       exit(1);
+       _exit(EXIT_FAILURE);
 }
 
 static bool clone_attach_nbd(const char *nbd, const char *path)
@@ -247,9 +243,10 @@ static bool clone_attach_nbd(const char *nbd, const char *path)
        data.nbd = nbd;
        data.path = path;
 
-       pid = lxc_clone(do_attach_nbd, &data, CLONE_NEWPID);
+       pid = lxc_clone(do_attach_nbd, &data, CLONE_NEWPID, NULL);
        if (pid < 0)
                return false;
+
        return true;
 }
 
@@ -261,6 +258,7 @@ static bool nbd_busy(int idx)
        ret = snprintf(path, 100, "/sys/block/nbd%d/pid", idx);
        if (ret < 0 || ret >= 100)
                return true;
+
        return file_exists(path);
 }
 
@@ -273,15 +271,17 @@ static void nbd_detach(const char *path)
                SYSERROR("Error forking to detach nbd");
                return;
        }
+
        if (pid) {
                ret = wait_for_pid(pid);
                if (ret < 0)
                        ERROR("nbd disconnect returned an error");
                return;
        }
+
        execlp("qemu-nbd", "qemu-nbd", "-d", path, (char *)NULL);
        SYSERROR("Error executing qemu-nbd");
-       exit(1);
+       _exit(EXIT_FAILURE);
 }
 
 /*
@@ -294,24 +294,31 @@ static int nbd_get_partition(const char *src)
        char *p = strchr(src, ':');
        if (!p)
                return 0;
+
        p = strchr(p+1, ':');
        if (!p)
                return 0;
+
        p++;
+
        if (*p < '1' || *p > '9')
                return 0;
+
        return *p - '0';
 }
 
 static bool wait_for_partition(const char *path)
 {
        int count = 0;
+
        while (count < 5) {
                if (file_exists(path))
                        return true;
+
                sleep(1);
                count++;
        }
+
        ERROR("Device %s did not show up after 5 seconds", path);
        return false;
 }