From d9ed5f9739feabf44d24fa2af31efc98ed635562 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Fri, 24 Jan 2014 08:08:55 -0600 Subject: [PATCH] device-mapper-multipath-0.4.9-63 Add 0074-RHBZ-1056976-dm-mpath-rules.patch * Add rules to keep from doing work in udev if there are no active paths, or if the event was for a multipath device reloading its table due to a path change. Add 0075-RHBZ-1056976-reload-flag.patch * multipath code to identify reloads that the new rules can ignore Add 0076-RHBZ-1056686-add-hw_str_match.patch * add a new default config paramter, "hw_str_match", to make user device configs only overwrite builtin device configs if the identifier strings match exactly, like the default in RHEL6. --- 0074-RHBZ-1056976-dm-mpath-rules.patch | 64 ++++++ 0075-RHBZ-1056976-reload-flag.patch | 246 +++++++++++++++++++++++ 0076-RHBZ-1056686-add-hw_str_match.patch | 100 +++++++++ device-mapper-multipath.spec | 26 ++- 4 files changed, 433 insertions(+), 3 deletions(-) create mode 100644 0074-RHBZ-1056976-dm-mpath-rules.patch create mode 100644 0075-RHBZ-1056976-reload-flag.patch create mode 100644 0076-RHBZ-1056686-add-hw_str_match.patch diff --git a/0074-RHBZ-1056976-dm-mpath-rules.patch b/0074-RHBZ-1056976-dm-mpath-rules.patch new file mode 100644 index 0000000..9f6c880 --- /dev/null +++ b/0074-RHBZ-1056976-dm-mpath-rules.patch @@ -0,0 +1,64 @@ +--- + multipath/11-dm-mpath.rules | 34 ++++++++++++++++++++++++++++++++++ + multipath/Makefile | 2 ++ + 2 files changed, 36 insertions(+) + +Index: multipath-tools-130222/multipath/11-dm-mpath.rules +=================================================================== +--- /dev/null ++++ multipath-tools-130222/multipath/11-dm-mpath.rules +@@ -0,0 +1,34 @@ ++ACTION!="add|change", GOTO="mpath_end" ++ENV{DM_UDEV_RULES_VSN}!="?*", GOTO="mpath_end" ++ENV{DM_UUID}!="mpath-?*", GOTO="mpath_end" ++ ++# Do not initiate scanning if no path is available, ++# otherwise there would be a hang or IO error on access. ++# We'd like to avoid this, especially within udev processing. ++ENV{DM_NR_VALID_PATHS}!="?*", IMPORT{db}="DM_NR_VALID_PATHS" ++ENV{DM_NR_VALID_PATHS}=="0", ENV{DM_NOSCAN}="1" ++ ++# Also skip all foreign rules if no path is available. ++# Remember the original value of DM_DISABLE_OTHER_RULES_FLAG ++# and restore it back once we have at least one path available. ++IMPORT{db}="DM_DISABLE_OTHER_RULES_FLAG_OLD" ++ENV{DM_ACTION}=="PATH_FAILED",\ ++ ENV{DM_NR_VALID_PATHS}=="0",\ ++ ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}=="",\ ++ ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}",\ ++ ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1" ++ENV{DM_ACTION}=="PATH_REINSTATED",\ ++ ENV{DM_NR_VALID_PATHS}=="1",\ ++ ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="$env{DM_DISABLE_OTHER_RULES_FLAG_OLD}",\ ++ ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}="",\ ++ ENV{DM_ACTIVATION}="1" ++ ++# DM_SUBSYSTEM_UDEV_FLAG0 is the "RELOAD" flag for multipath subsystem. ++# Drop the DM_ACTIVATION flag here as mpath reloads tables if any of its ++# paths are lost/recovered. For any stack above the mpath device, this is not ++# something that should be reacted upon since it would be useless extra work. ++# It's exactly mpath's job to provide *seamless* device access to any of the ++# paths that are available underneath. ++ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", ENV{DM_ACTIVATION}="0" ++ ++LABEL="mpath_end" +Index: multipath-tools-130222/multipath/Makefile +=================================================================== +--- multipath-tools-130222.orig/multipath/Makefile ++++ multipath-tools-130222/multipath/Makefile +@@ -25,6 +25,7 @@ install: + $(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/ + $(INSTALL_PROGRAM) -d $(DESTDIR)/usr/lib/udev/rules.d + $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/usr/lib/udev/rules.d/62-multipath.rules ++ $(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)/usr/lib/udev/rules.d/11-dm-mpath.rules + $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir) +@@ -33,6 +34,7 @@ install: + + uninstall: + rm $(DESTDIR)/usr/lib/udev/rules.d/62-multipath.rules ++ rm $(DESTDIR)/usr/lib/udev/rules.d/11-dm-mpath.rules + rm $(DESTDIR)$(bindir)/$(EXEC) + rm $(DESTDIR)$(bindir)/mpathconf + rm $(DESTDIR)$(mandir)/$(EXEC).8.gz diff --git a/0075-RHBZ-1056976-reload-flag.patch b/0075-RHBZ-1056976-reload-flag.patch new file mode 100644 index 0000000..ee2cdee --- /dev/null +++ b/0075-RHBZ-1056976-reload-flag.patch @@ -0,0 +1,246 @@ +--- + kpartx/devmapper.c | 4 ++-- + kpartx/devmapper.h | 8 +++++++- + kpartx/kpartx.c | 6 +++--- + libmultipath/configure.c | 4 ++-- + libmultipath/devmapper.c | 26 ++++++++++++++------------ + libmultipath/devmapper.h | 10 ++++++++-- + multipathd/cli_handlers.c | 4 ++-- + 7 files changed, 38 insertions(+), 24 deletions(-) + +Index: multipath-tools-130222/kpartx/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/devmapper.c ++++ multipath-tools-130222/kpartx/devmapper.c +@@ -60,7 +60,7 @@ dm_prereq (char * str, int x, int y, int + } + + extern int +-dm_simplecmd (int task, const char *name, int no_flush, uint32_t *cookie) { ++dm_simplecmd (int task, const char *name, int no_flush, uint32_t *cookie, uint16_t udev_flags) { + int r = 0; + int udev_wait_flag = (task == DM_DEVICE_RESUME || + task == DM_DEVICE_REMOVE); +@@ -78,7 +78,7 @@ dm_simplecmd (int task, const char *name + if (no_flush) + dm_task_no_flush(dmt); + +- if (udev_wait_flag && !dm_task_set_cookie(dmt, cookie, (udev_sync)? 0 : DM_UDEV_DISABLE_LIBRARY_FALLBACK)) ++ if (udev_wait_flag && !dm_task_set_cookie(dmt, cookie, ((udev_sync)? 0 : DM_UDEV_DISABLE_LIBRARY_FALLBACK) | udev_flags)) + goto out; + r = dm_task_run(dmt); + +Index: multipath-tools-130222/kpartx/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/kpartx/devmapper.h ++++ multipath-tools-130222/kpartx/devmapper.h +@@ -2,10 +2,16 @@ + #define MINOR(dev) ((dev & 0xff) | ((dev >> 12) & 0xfff00)) + #define MKDEV(ma,mi) ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12)) + ++#ifdef DM_SUBSYSTEM_UDEV_FLAG0 ++#define MPATH_UDEV_RELOAD_FLAG DM_SUBSYSTEM_UDEV_FLAG0 ++#else ++#define MPATH_UDEV_RELOAD_FLAG 0 ++#endif ++ + extern int udev_sync; + + int dm_prereq (char *, int, int, int); +-int dm_simplecmd (int, const char *, int, uint32_t *); ++int dm_simplecmd (int, const char *, int, uint32_t *, uint16_t); + int dm_addmap (int, const char *, const char *, const char *, uint64_t, + int, const char *, int, mode_t, uid_t, gid_t, uint32_t *); + int dm_map_present (char *); +Index: multipath-tools-130222/kpartx/kpartx.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/kpartx.c ++++ multipath-tools-130222/kpartx/kpartx.c +@@ -421,7 +421,7 @@ main(int argc, char **argv){ + continue; + + if (!dm_simplecmd(DM_DEVICE_REMOVE, partname, +- 0, &cookie)) { ++ 0, &cookie, 0)) { + r++; + continue; + } +@@ -473,7 +473,7 @@ main(int argc, char **argv){ + } + if (op == DM_DEVICE_RELOAD && + !dm_simplecmd(DM_DEVICE_RESUME, partname, +- 1, &cookie)) { ++ 1, &cookie, MPATH_UDEV_RELOAD_FLAG)) { + fprintf(stderr, "resume failed on %s\n", + partname); + r++; +@@ -505,7 +505,7 @@ main(int argc, char **argv){ + continue; + + if (!dm_simplecmd(DM_DEVICE_REMOVE, +- partname, 1, &cookie)) { ++ partname, 1, &cookie, 0)) { + r++; + continue; + } +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -390,13 +390,13 @@ domap (struct multipath * mpp, char * pa + case ACT_RELOAD: + r = dm_addmap_reload(mpp, params); + if (r) +- r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias); ++ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, MPATH_UDEV_RELOAD_FLAG); + break; + + case ACT_RESIZE: + r = dm_addmap_reload(mpp, params); + if (r) +- r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias, 1); ++ r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias, 1, 0); + break; + + case ACT_RENAME: +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -103,7 +103,9 @@ dm_lib_prereq (void) + { + char version[64]; + int v[3]; +-#ifdef LIBDM_API_COOKIE ++#if defined(DM_SUBSYSTEM_UDEV_FLAG0) ++ int minv[3] = {1, 2, 82}; ++#elif defined(LIBDM_API_COOKIE) + int minv[3] = {1, 2, 38}; + #else + int minv[3] = {1, 2, 8}; +@@ -200,7 +202,7 @@ dm_prereq (void) + } + + static int +-dm_simplecmd (int task, const char *name, int no_flush, int need_sync) { ++dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t udev_flags) { + int r = 0; + int udev_wait_flag = (need_sync && (task == DM_DEVICE_RESUME || + task == DM_DEVICE_REMOVE)); +@@ -219,7 +221,7 @@ dm_simplecmd (int task, const char *name + dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ + #endif + +- if (udev_wait_flag && !dm_task_set_cookie(dmt, &conf->cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0)) ++ if (udev_wait_flag && !dm_task_set_cookie(dmt, &conf->cookie, ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | udev_flags)) + goto out; + r = dm_task_run (dmt); + +@@ -229,13 +231,13 @@ dm_simplecmd (int task, const char *name + } + + extern int +-dm_simplecmd_flush (int task, const char *name, int needsync) { +- return dm_simplecmd(task, name, 0, needsync); ++dm_simplecmd_flush (int task, const char *name, int needsync, uint16_t udev_flags) { ++ return dm_simplecmd(task, name, 0, needsync, udev_flags); + } + + extern int +-dm_simplecmd_noflush (int task, const char *name) { +- return dm_simplecmd(task, name, 1, 1); ++dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags) { ++ return dm_simplecmd(task, name, 1, 1, udev_flags); + } + + extern int +@@ -670,7 +672,7 @@ _dm_flush_map (const char * mapname, int + return 1; + } + +- r = dm_simplecmd_flush(DM_DEVICE_REMOVE, mapname, need_sync); ++ r = dm_simplecmd_flush(DM_DEVICE_REMOVE, mapname, need_sync, 0); + + if (r) { + condlog(4, "multipath map %s removed", mapname); +@@ -703,14 +705,14 @@ dm_suspend_and_flush_map (const char * m + if (s) + queue_if_no_path = 0; + else +- s = dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0); ++ s = dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0, 0); + + if (!dm_flush_map(mapname)) { + condlog(4, "multipath map %s removed", mapname); + return 0; + } + condlog(2, "failed to remove multipath map %s", mapname); +- dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname); ++ dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, 0); + if (queue_if_no_path) + s = dm_queue_if_no_path((char *)mapname, 1); + return 1; +@@ -1077,7 +1079,7 @@ dm_remove_partmaps (const char * mapname + condlog(4, "partition map %s removed", + names->name); + dm_simplecmd_flush(DM_DEVICE_REMOVE, names->name, +- need_sync); ++ need_sync, 0); + } + + next = names->next; +@@ -1305,7 +1307,7 @@ int dm_reassign_table(const char *name, + condlog(3, "%s: failed to reassign targets", name); + goto out_reload; + } +- dm_simplecmd_noflush(DM_DEVICE_RESUME, name); ++ dm_simplecmd_noflush(DM_DEVICE_RESUME, name, MPATH_UDEV_RELOAD_FLAG); + } + r = 1; + +Index: multipath-tools-130222/libmultipath/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.h ++++ multipath-tools-130222/libmultipath/devmapper.h +@@ -6,11 +6,17 @@ + #define TGT_MPATH "multipath" + #define TGT_PART "linear" + ++#ifdef DM_SUBSYSTEM_UDEV_FLAG0 ++#define MPATH_UDEV_RELOAD_FLAG DM_SUBSYSTEM_UDEV_FLAG0 ++#else ++#define MPATH_UDEV_RELOAD_FLAG 0 ++#endif ++ + void dm_init(void); + int dm_prereq (void); + int dm_drv_version (unsigned int * version, char * str); +-int dm_simplecmd_flush (int, const char *, int); +-int dm_simplecmd_noflush (int, const char *); ++int dm_simplecmd_flush (int, const char *, int, uint16_t); ++int dm_simplecmd_noflush (int, const char *, uint16_t); + int dm_addmap_create (struct multipath *mpp, char *params); + int dm_addmap_reload (struct multipath *mpp, char *params); + int dm_map_present (const char *); +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -783,7 +783,7 @@ cli_suspend(void * v, char ** reply, int + { + struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, MAP); +- int r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param); ++ int r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param, 0); + + param = convert_dev(param, 0); + condlog(2, "%s: suspend (operator)", param); +@@ -805,7 +805,7 @@ cli_resume(void * v, char ** reply, int + { + struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, MAP); +- int r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param); ++ int r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0); + + param = convert_dev(param, 0); + condlog(2, "%s: resume (operator)", param); diff --git a/0076-RHBZ-1056686-add-hw_str_match.patch b/0076-RHBZ-1056686-add-hw_str_match.patch new file mode 100644 index 0000000..8febb10 --- /dev/null +++ b/0076-RHBZ-1056686-add-hw_str_match.patch @@ -0,0 +1,100 @@ +--- + libmultipath/config.c | 10 ++++++++-- + libmultipath/config.h | 1 + + libmultipath/dict.c | 26 ++++++++++++++++++++++++++ + 3 files changed, 35 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -431,11 +431,16 @@ restart: + break; + j = n; + vector_foreach_slot_after(hw, hwe2, j) { +- if (hwe_regmatch(hwe1, hwe2)) ++ if (conf->hw_strmatch) { ++ if (hwe_strmatch(hwe2, hwe1)) ++ continue; ++ } ++ else if (hwe_regmatch(hwe1, hwe2)) + continue; + /* dup */ + merge_hwe(hwe2, hwe1); +- if (hwe_strmatch(hwe2, hwe1) == 0) { ++ if (conf->hw_strmatch || ++ hwe_strmatch(hwe2, hwe1) == 0) { + vector_del_slot(hw, i); + free_hwe(hwe1); + n -= 1; +@@ -550,6 +555,7 @@ load_config (char * file, struct udev *u + conf->fast_io_fail = DEFAULT_FAST_IO_FAIL; + conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER; + conf->detect_prio = DEFAULT_DETECT_PRIO; ++ conf->hw_strmatch = 0; + + /* + * preload default hwtable +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -107,6 +107,7 @@ struct config { + int log_checker_err; + int allow_queueing; + int find_multipaths; ++ int hw_strmatch; + uid_t uid; + gid_t gid; + mode_t mode; +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -693,6 +693,23 @@ def_detect_prio_handler(vector strvec) + return 0; + } + ++static int ++def_hw_strmatch_handler(vector strvec) ++{ ++ char *buff; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if (!strncmp(buff, "on", 2) || !strncmp(buff, "yes", 3) || ++ !strncmp(buff, "1", 1)) ++ conf->hw_strmatch = 1; ++ else ++ conf->hw_strmatch = 0; ++ return 0; ++} ++ + /* + * blacklist block handlers + */ +@@ -2795,6 +2812,14 @@ snprint_def_detect_prio(char * buff, int + } + + static int ++snprint_def_hw_strmatch(char * buff, int len, void * data) ++{ ++ if (conf->hw_strmatch) ++ return snprintf(buff, len, "yes"); ++ return snprintf(buff, len, "no"); ++} ++ ++static int + snprint_ble_simple (char * buff, int len, void * data) + { + struct blentry * ble = (struct blentry *)data; +@@ -2861,6 +2886,7 @@ init_keywords(void) + install_keyword("find_multipaths", &def_find_multipaths_handler, &snprint_def_find_multipaths); + install_keyword("retain_attached_hw_handler", &def_retain_hwhandler_handler, &snprint_def_retain_hwhandler_handler); + install_keyword("detect_prio", &def_detect_prio_handler, &snprint_def_detect_prio); ++ install_keyword("hw_str_match", &def_hw_strmatch_handler, &snprint_def_hw_strmatch); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); + __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); + __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 340e4a2..537d1dc 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,7 +1,7 @@ Summary: Tools to manage multipath devices using device-mapper Name: device-mapper-multipath Version: 0.4.9 -Release: 62%{?dist} +Release: 63%{?dist} License: GPL+ Group: System Environment/Base URL: http://christophe.varoqui.free.fr/ @@ -81,18 +81,21 @@ Patch0070: 0070-RHBZ-1036503-blacklist-td-devs.patch Patch0071: 0071-RHBZ-1031546-strip-dev.patch Patch0072: 0072-RHBZ-1039199-check-loop-control.patch Patch0073: 0073-RH-update-build-flags.patch +Patch0074: 0074-RHBZ-1056976-dm-mpath-rules.patch +Patch0075: 0075-RHBZ-1056976-reload-flag.patch +Patch0076: 0076-RHBZ-1056686-add-hw_str_match.patch # runtime Requires: %{name}-libs = %{version}-%{release} Requires: kpartx = %{version}-%{release} -Requires: device-mapper >= 1.02.39-1 +Requires: device-mapper >= 1.02.82-2 Requires: initscripts Requires(post): systemd-units systemd-sysv chkconfig Requires(preun): systemd-units Requires(postun): systemd-units # build/setup -BuildRequires: libaio-devel, device-mapper-devel >= 1.02.39-1 +BuildRequires: libaio-devel, device-mapper-devel >= 1.02.82-2 BuildRequires: libselinux-devel, libsepol-devel BuildRequires: readline-devel, ncurses-devel BuildRequires: systemd-units, systemd-devel @@ -206,6 +209,9 @@ kpartx manages partition creation and removal for device-mapper devices. %patch0071 -p1 %patch0072 -p1 %patch0073 -p1 +%patch0074 -p1 +%patch0075 -p1 +%patch0076 -p1 cp %{SOURCE1} . %build @@ -272,6 +278,7 @@ bin/systemctl --no-reload enable multipathd.service >/dev/null 2>&1 ||: %{_mandir}/man8/mpathconf.8.gz %{_mandir}/man8/mpathpersist.8.gz %config /usr/lib/udev/rules.d/62-multipath.rules +%config /usr/lib/udev/rules.d/11-dm-mpath.rules %doc AUTHOR COPYING FAQ %doc multipath.conf %dir /etc/multipath @@ -299,6 +306,19 @@ bin/systemctl --no-reload enable multipathd.service >/dev/null 2>&1 ||: %{_mandir}/man8/kpartx.8.gz %changelog +* Fri Jan 24 2014 Benjamin Marzinski 0.4.9-63 +- Add 0074-RHBZ-1056976-dm-mpath-rules.patch + * Add rules to keep from doing work in udev if there are no + active paths, or if the event was for a multipath device + reloading its table due to a path change. +- Add 0075-RHBZ-1056976-reload-flag.patch + * multipath code to identify reloads that the new rules can + ignore +- Add 0076-RHBZ-1056686-add-hw_str_match.patch + * add a new default config paramter, "hw_str_match", to make user + device configs only overwrite builtin device configs if the + identifier strings match exactly, like the default in RHEL6. + * Fri Jan 10 2014 Benjamin Marzinski 0.4.9-62 - Modify 0072-RHBZ-1039199-check-loop-control.patch * only call close on the /dev/loop-control fd the open succeeds