The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/2979
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> Improces the the logic a little and might come in handy once I figured out how to use loop-file backed lvm pools.
From c8e82645284a17f333b050ce60eb5b2294fdedf1 Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Wed, 1 Mar 2017 00:23:26 +0100 Subject: [PATCH] storage_cgo: detect if loop file is already in use Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- lxd/storage_cgo.go | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 105 insertions(+), 3 deletions(-) diff --git a/lxd/storage_cgo.go b/lxd/storage_cgo.go index 76ae34c..95ede6f 100644 --- a/lxd/storage_cgo.go +++ b/lxd/storage_cgo.go @@ -23,6 +23,100 @@ package main #define LO_FLAGS_AUTOCLEAR 4 #endif +#define LXD_MAXPATH 4096 +#define LXD_NUMSTRLEN64 21 +#define LXD_MAX_LOOP_PATHLEN (2 * sizeof("loop/")) + LXD_NUMSTRLEN64 + sizeof("backing_file") + 1 + +// If a loop file is already associated with a loop device, find it. +static int find_associated_loop_device(const char *loop_file, + char *loop_dev_name) +{ + char looppath[LXD_MAX_LOOP_PATHLEN]; + char buf[LXD_MAXPATH]; + struct dirent *dp; + DIR *dir; + int dfd = -1, fd = -1; + + dir = opendir("/sys/block"); + if (!dir) + return -1; + + while ((dp = readdir(dir))) { + int ret = -1; + size_t totlen; + struct stat fstatbuf; + char *delsuffix = " (deleted)"; + size_t dellen = sizeof(delsuffix); + + if (!dp) + break; + + if (strncmp(dp->d_name, "loop", 4) != 0) + continue; + + dfd = dirfd(dir); + if (dfd < 0) + continue; + + ret = snprintf(looppath, sizeof(looppath), + "%s/loop/backing_file", dp->d_name); + if (ret < 0 || (size_t)ret >= sizeof(looppath)) + continue; + + ret = fstatat(dfd, looppath, &fstatbuf, 0); + if (ret < 0) + continue; + + fd = openat(dfd, looppath, O_RDONLY | O_CLOEXEC, 0); + if (ret < 0) + continue; + + // Clear buffer. + memset(buf, 0, sizeof(buf)); + ret = read(fd, buf, sizeof(buf)); + if (ret < 0) + continue; + + totlen = strlen(buf); + // Trim newline. + if (buf[totlen - 1] == '\n') { + buf[totlen - 1] = '\0'; + totlen--; + } + + if (totlen > dellen) { + char *deleted = &buf[totlen - dellen]; + + // Skip deleted loop files. + if (!strcmp(deleted, delsuffix)) + continue; + } + + if (strcmp(buf, loop_file)) { + close(fd); + fd = -1; + continue; + } + + ret = snprintf(loop_dev_name, LO_NAME_SIZE, "/dev/%s", + dp->d_name); + if (ret < 0 || ret >= LO_NAME_SIZE) { + close(fd); + fd = -1; + continue; + } + + break; + } + + closedir(dir); + + if (fd < 0) + return -1; + + return fd; +} + static int get_unused_loop_dev_legacy(char *loop_name) { struct dirent *dp; @@ -50,14 +144,14 @@ static int get_unused_loop_dev_legacy(char *loop_name) continue; ret = ioctl(fd, LOOP_GET_STATUS64, &lo64); - if (ret < 0) - + if (ret < 0) { if (ioctl(fd, LOOP_GET_STATUS64, &lo64) == 0 || errno != ENXIO) { close(fd); fd = -1; continue; } + } ret = snprintf(loop_name, LO_NAME_SIZE, "/dev/%s", dp->d_name); if (ret < 0 || ret >= LO_NAME_SIZE) { @@ -166,8 +260,16 @@ func prepareLoopDev(source string) (*os.File, error) { cSource := C.CString(source) defer C.free(unsafe.Pointer(cSource)) - loopFd := int(C.prepare_loop_dev(cSource, (*C.char)(cLoopDev))) + loopFd, _ := C.find_associated_loop_device(cSource, (*C.char)(cLoopDev)) + if loopFd >= 0 { + return os.NewFile(uintptr(loopFd), C.GoString((*C.char)(cLoopDev))), nil + } + + loopFd, err := C.prepare_loop_dev(cSource, (*C.char)(cLoopDev)) if loopFd < 0 { + if err != nil { + return nil, fmt.Errorf("Failed to prepare loop device: %s.", err) + } return nil, fmt.Errorf("Failed to prepare loop device.") }
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel