Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12:Update
util-linux-systemd.3352
util-linux-loop-reuse-16.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File util-linux-loop-reuse-16.patch of Package util-linux-systemd.3352
This backport removes short option -L for --nooverlap, as it conflicts with --logical-blocksize introduced in util-linux-losetup-Add-support-for-setting-logical-blocksize.patch. From 9a94b634a343e83bfa2a9d311074e3e520abdddd Mon Sep 17 00:00:00 2001 From: Karel Zak <kzak@redhat.com> Date: Wed, 17 Aug 2016 12:28:33 +0200 Subject: [PATCH 16/20] losetup: add --nooverlap options This patch introduces overlap detections and loop devices re-use for losetup(8). We already support this feature for mount(8) where it's enabled by default (because we mount filesystems and it's always mistake to share the same filesystem between more loop devices). Stanislav has suggested to enable this feature also for losetup by default. I'm not sure about it, IMHO it's better to keep losetup(8) simple and stupid by default, and inform users about possible problems and solutions in the man page. The feature forces losetup to scan all loop devices always when new one is requested. This maybe disadvantage (especially when we use control-loop to avoid /sys or /dev scans) on system with huge number of loop devices. Co-Author: Stanislav Brabec <sbrabec@suse.cz> Signed-off-by: Karel Zak <kzak@redhat.com> --- lib/loopdev.c | 14 ++++-- sys-utils/losetup.8 | 11 +++++ sys-utils/losetup.c | 136 ++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 114 insertions(+), 47 deletions(-) Index: util-linux-2.25/lib/loopdev.c =================================================================== --- util-linux-2.25.orig/lib/loopdev.c +++ util-linux-2.25/lib/loopdev.c @@ -371,10 +371,8 @@ int loopcxt_deinit_iterator(struct loopd fclose(iter->proc); if (iter->sysblock) closedir(iter->sysblock); - iter->minors = NULL; - iter->proc = NULL; - iter->sysblock = NULL; - iter->done = 1; + + memset(iter, 0, sizeof(*iter)); return 0; } @@ -1426,8 +1424,11 @@ int loopcxt_find_unused(struct loopdev_c DBG(lc, loopdev_debug("find_unused requested")); if (lc->flags & LOOPDEV_FL_CONTROL) { - int ctl = open(_PATH_DEV_LOOPCTL, O_RDWR|O_CLOEXEC); + int ctl; + + DBG(lc, loopdev_debug("using loop-control")); + ctl = open(_PATH_DEV_LOOPCTL, O_RDWR|O_CLOEXEC); if (ctl >= 0) rc = ioctl(ctl, LOOP_CTL_GET_FREE); if (rc >= 0) { @@ -1443,6 +1444,7 @@ int loopcxt_find_unused(struct loopdev_c } if (rc < 0) { + DBG(lc, loopdev_debug("using loop scan")); rc = loopcxt_init_iterator(lc, LOOPITER_FL_FREE); if (rc) return rc; @@ -1577,6 +1579,7 @@ int loopcxt_find_overlap(struct loopdev_ if (!filename) return -EINVAL; + DBG(lc, loopdev_debug("find_overlap requested")); hasst = !stat(filename, &st); rc = loopcxt_init_iterator(lc, LOOPITER_FL_USED); @@ -1633,6 +1636,7 @@ int loopcxt_find_overlap(struct loopdev_ rc = 0; /* not found */ found: loopcxt_deinit_iterator(lc); + DBG(lc, loopdev_debug("find_overlap done [rc=%d]", rc)); return rc; } Index: util-linux-2.25/sys-utils/losetup.8 =================================================================== --- util-linux-2.25.orig/sys-utils/losetup.8 +++ util-linux-2.25/sys-utils/losetup.8 @@ -67,6 +67,11 @@ device is shown. If no option is given, .sp Note that the old output format (i.e. \fBlosetup -a\fR) with comma-delimited strings is deprecated in favour of the \fB--list\fR output format. +.sp +It's possible to create more independent loop devices for the same backing +file. +.B This setup may be dangerous, can cause data loss, corruption and overwrites. +Use \fB\-\-nooverlap\fR to avoid this problem. .SH OPTIONS The \fIsize\fR and \fIoffset\fR @@ -96,6 +101,12 @@ Find the first unused loop device. If a .I file argument is present, use the found device as loop device. Otherwise, just print its name. +.BR \-L , " \-\-nooverlap" +Check for conflicts between loop devices to avoid situation when the same +backing file is shared between more loop devices. If the file is already used +by another device then re-use the device rather than a new one. The option +makes sense only with \fB\-\-find\fP. +.TP .IP "\fB\-j, \-\-associated \fIfile\fP" Show the status of all loop devices associated with the given .IR file . Index: util-linux-2.25/sys-utils/losetup.c =================================================================== --- util-linux-2.25.orig/sys-utils/losetup.c +++ util-linux-2.25/sys-utils/losetup.c @@ -375,6 +375,7 @@ static void usage(FILE *out) fputs(_(" -f, --find find first unused device\n"), out); fputs(_(" -c, --set-capacity <loopdev> resize the device\n"), out); fputs(_(" -j, --associated <file> list all devices associated with <file>\n"), out); + fputs(_(" --nooverlap avoid possible conflict between devices\n"), out); fputs(USAGE_SEPARATOR, out); @@ -425,10 +426,96 @@ static void warn_size(const char *filena filename); } +static int create_loop(struct loopdev_cxt *lc, + int nooverlap, int lo_flags, int flags, + const char *file, uint64_t offset, uint64_t sizelimit) +{ + int hasdev = loopcxt_has_device(lc); + int rc = 0; + + /* Check for conflicts and re-user loop device if possible */ + if (!hasdev && nooverlap) { + rc = loopcxt_find_overlap(lc, file, offset, sizelimit); + switch (rc) { + case 0: /* not found */ + break; + + case 1: /* overlap */ + loopcxt_deinit(lc); + errx(EXIT_FAILURE, _("%s: overlapping loop device exists"), file); + + case 2: /* overlap -- full size and offset match (reuse) */ + { + uint32_t lc_encrypt_type; + + /* Once a loop is initialized RO, there is no + * way to change its parameters. */ + if (loopcxt_is_readonly(lc) + && !(lo_flags & LO_FLAGS_READ_ONLY)) { + loopcxt_deinit(lc); + errx(EXIT_FAILURE, _("%s: overlapping read-only loop device exists"), file); + } + + /* This is no more supported, but check to be safe. */ + if (loopcxt_get_encrypt_type(lc, &lc_encrypt_type) == 0 + && lc_encrypt_type != LO_CRYPT_NONE) { + loopcxt_deinit(lc); + errx(EXIT_FAILURE, _("%s: overlapping encrypted loop device exists"), file); + } + return 0; /* success, re-use */ + } + default: /* error */ + loopcxt_deinit(lc); + errx(EXIT_FAILURE, _("failed to inspect loop devices")); + return -errno; + } + } + + if (hasdev && !is_loopdev(loopcxt_get_device(lc))) + loopcxt_add_device(lc); + + /* Create a new device */ + do { + const char *errpre; + + /* Note that loopcxt_{find_unused,set_device}() resets + * loopcxt struct. + */ + if (!hasdev && (rc = loopcxt_find_unused(lc))) { + warnx(_("cannot find an unused loop device")); + break; + } + if (flags & LOOPDEV_FL_OFFSET) + loopcxt_set_offset(lc, offset); + if (flags & LOOPDEV_FL_SIZELIMIT) + loopcxt_set_sizelimit(lc, sizelimit); + if (lo_flags) + loopcxt_set_flags(lc, lo_flags); + if ((rc = loopcxt_set_backing_file(lc, file))) { + warn(_("%s: failed to use backing file"), file); + break; + } + errno = 0; + rc = loopcxt_setup_device(lc); + if (rc == 0) + break; /* success */ + if (errno == EBUSY && !hasdev) + continue; + + /* errors */ + errpre = hasdev && loopcxt_get_fd(lc) < 0 ? + loopcxt_get_device(lc) : file; + warn(_("%s: failed to set up loop device"), errpre); + break; + } while (hasdev == 0); + + return rc; +} + int main(int argc, char **argv) { struct loopdev_cxt lc; - int act = 0, flags = 0, c; + int act = 0, flags = 0, no_overlap = 0, c; char *file = NULL; uint64_t offset = 0, sizelimit = 0; int res = 0, showdev = 0, lo_flags = 0; @@ -438,7 +525,8 @@ int main(int argc, char **argv) enum { OPT_SIZELIMIT = CHAR_MAX + 1, OPT_SHOW, - OPT_RAW + OPT_RAW, + OPT_NOOVERLAP }; static const struct option longopts[] = { { "all", 0, 0, 'a' }, @@ -446,6 +534,7 @@ int main(int argc, char **argv) { "detach", 1, 0, 'd' }, { "detach-all", 0, 0, 'D' }, { "find", 0, 0, 'f' }, + { "nooverlaps", 0, 0, OPT_NOOVERLAP }, { "help", 0, 0, 'h' }, { "associated", 1, 0, 'j' }, { "list", 0, 0, 'l' }, @@ -520,6 +609,9 @@ int main(int argc, char **argv) case 'l': list = 1; break; + case OPT_NOOVERLAP: + no_overlap = 1; + break; case 'n': no_headings = 1; break; @@ -630,52 +722,13 @@ int main(int argc, char **argv) switch (act) { case A_CREATE: - { - int hasdev = loopcxt_has_device(&lc); - - if (hasdev && !is_loopdev(loopcxt_get_device(&lc))) - loopcxt_add_device(&lc); - do { - const char *errpre; - - /* Note that loopcxt_{find_unused,set_device}() resets - * loopcxt struct. - */ - if (!hasdev && (res = loopcxt_find_unused(&lc))) { - warnx(_("cannot find an unused loop device")); - break; - } - if (flags & LOOPDEV_FL_OFFSET) - loopcxt_set_offset(&lc, offset); - if (flags & LOOPDEV_FL_SIZELIMIT) - loopcxt_set_sizelimit(&lc, sizelimit); - if (lo_flags) - loopcxt_set_flags(&lc, lo_flags); - if ((res = loopcxt_set_backing_file(&lc, file))) { - warn(_("%s: failed to use backing file"), file); - break; - } - errno = 0; - res = loopcxt_setup_device(&lc); - if (res == 0) - break; /* success */ - if (errno == EBUSY && !hasdev) - continue; - - /* errors */ - errpre = hasdev && loopcxt_get_fd(&lc) < 0 ? - loopcxt_get_device(&lc) : file; - warn(_("%s: failed to set up loop device"), errpre); - break; - } while (hasdev == 0); - + res = create_loop(&lc, no_overlap, lo_flags, flags, file, offset, sizelimit); if (res == 0) { if (showdev) printf("%s\n", loopcxt_get_device(&lc)); warn_size(file, sizelimit); } break; - } case A_DELETE: res = delete_loop(&lc); while (optind < argc) {
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor