Blame SOURCES/cryptsetup-1.7.6-crypt_deactivate-fail-earlier-when-holders-detected.patch

7cdc99
From 2e4aaa1adad2d0838593b13efbf5efe79f58255c Mon Sep 17 00:00:00 2001
7cdc99
From: Ondrej Kozina <okozina@redhat.com>
7cdc99
Date: Mon, 16 Oct 2017 16:41:43 +0200
7cdc99
Subject: [PATCH] crypt_deactivate: fail earlier when holders detected
7cdc99
7cdc99
crypt_deactivate fails earlier without noisy dm retries
7cdc99
when other device holders detected. The early detection
7cdc99
works if:
7cdc99
7cdc99
a) other device-mapper device has a hold reference on the
7cdc99
   device
7cdc99
7cdc99
- or -
7cdc99
7cdc99
b) mounted fs is detected on the device
7cdc99
7cdc99
diff -rupN cryptsetup-1.7.4.old/config.h.in cryptsetup-1.7.4/config.h.in
7cdc99
--- cryptsetup-1.7.4.old/config.h.in	2017-03-15 10:43:26.000000000 +0100
7cdc99
+++ cryptsetup-1.7.4/config.h.in	2017-10-19 09:37:17.000000000 +0200
7cdc99
@@ -97,6 +97,14 @@
7cdc99
    */
7cdc99
 #undef HAVE_DCGETTEXT
7cdc99
 
7cdc99
+/* Define to 1 if you have the declaration of `dm_device_has_holders', and to
7cdc99
+   0 if you don't. */
7cdc99
+#undef HAVE_DECL_DM_DEVICE_HAS_HOLDERS
7cdc99
+
7cdc99
+/* Define to 1 if you have the declaration of `dm_device_has_mounted_fs', and
7cdc99
+   to 0 if you don't. */
7cdc99
+#undef HAVE_DECL_DM_DEVICE_HAS_MOUNTED_FS
7cdc99
+
7cdc99
 /* Define to 1 if you have the declaration of `dm_task_retry_remove', and to 0
7cdc99
    if you don't. */
7cdc99
 #undef HAVE_DECL_DM_TASK_RETRY_REMOVE
7cdc99
diff -rupN cryptsetup-1.7.4.old/configure cryptsetup-1.7.4/configure
7cdc99
--- cryptsetup-1.7.4.old/configure	2017-03-15 10:43:13.000000000 +0100
7cdc99
+++ cryptsetup-1.7.4/configure	2017-10-19 09:37:18.590530138 +0200
7cdc99
@@ -16735,6 +16735,30 @@ cat >>confdefs.h <<_ACEOF
7cdc99
 #define HAVE_DECL_DM_TASK_RETRY_REMOVE $ac_have_decl
7cdc99
 _ACEOF
7cdc99
 
7cdc99
+ac_fn_c_check_decl "$LINENO" "dm_device_has_mounted_fs" "ac_cv_have_decl_dm_device_has_mounted_fs" "#include <libdevmapper.h>
7cdc99
+"
7cdc99
+if test "x$ac_cv_have_decl_dm_device_has_mounted_fs" = xyes; then :
7cdc99
+  ac_have_decl=1
7cdc99
+else
7cdc99
+  ac_have_decl=0
7cdc99
+fi
7cdc99
+
7cdc99
+cat >>confdefs.h <<_ACEOF
7cdc99
+#define HAVE_DECL_DM_DEVICE_HAS_MOUNTED_FS $ac_have_decl
7cdc99
+_ACEOF
7cdc99
+
7cdc99
+ac_fn_c_check_decl "$LINENO" "dm_device_has_holders" "ac_cv_have_decl_dm_device_has_holders" "#include <libdevmapper.h>
7cdc99
+"
7cdc99
+if test "x$ac_cv_have_decl_dm_device_has_holders" = xyes; then :
7cdc99
+  ac_have_decl=1
7cdc99
+else
7cdc99
+  ac_have_decl=0
7cdc99
+fi
7cdc99
+
7cdc99
+cat >>confdefs.h <<_ACEOF
7cdc99
+#define HAVE_DECL_DM_DEVICE_HAS_HOLDERS $ac_have_decl
7cdc99
+_ACEOF
7cdc99
+
7cdc99
 ac_fn_c_check_decl "$LINENO" "DM_UDEV_DISABLE_DISK_RULES_FLAG" "ac_cv_have_decl_DM_UDEV_DISABLE_DISK_RULES_FLAG" "#include <libdevmapper.h>
7cdc99
 "
7cdc99
 if test "x$ac_cv_have_decl_DM_UDEV_DISABLE_DISK_RULES_FLAG" = xyes; then :
7cdc99
diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c
7cdc99
index a0d6872..d6017b1 100644
7cdc99
--- a/lib/libdevmapper.c
7cdc99
+++ b/lib/libdevmapper.c
7cdc99
@@ -1181,6 +1181,13 @@ int dm_query_device(struct crypt_device *cd, const char *name,
7cdc99
 			dmd->uuid = strdup(tmp_uuid + DM_UUID_PREFIX_LEN);
7cdc99
 	}
7cdc99
 
7cdc99
+	dmd->holders = 0;
7cdc99
+#if (HAVE_DECL_DM_DEVICE_HAS_HOLDERS && HAVE_DECL_DM_DEVICE_HAS_MOUNTED_FS)
7cdc99
+	if (get_flags & DM_ACTIVE_HOLDERS)
7cdc99
+		dmd->holders = (dm_device_has_mounted_fs(dmi.major, dmi.minor) ||
7cdc99
+				dm_device_has_holders(dmi.major, dmi.minor));
7cdc99
+#endif
7cdc99
+
7cdc99
 	r = (dmi.open_count > 0);
7cdc99
 out:
7cdc99
 	if (dmt)
7cdc99
diff --git a/lib/setup.c b/lib/setup.c
7cdc99
index b2e4396..93e8079 100644
7cdc99
--- a/lib/setup.c
7cdc99
+++ b/lib/setup.c
7cdc99
@@ -2249,6 +2249,7 @@ int crypt_activate_by_volume_key(struct crypt_device *cd,
7cdc99
 int crypt_deactivate(struct crypt_device *cd, const char *name)
7cdc99
 {
7cdc99
 	struct crypt_device *fake_cd = NULL;
7cdc99
+	struct crypt_dm_active_device dmd = {};
7cdc99
 	int r;
7cdc99
 
7cdc99
 	if (!name)
7cdc99
@@ -2266,6 +2267,13 @@ int crypt_deactivate(struct crypt_device *cd, const char *name)
7cdc99
 	switch (crypt_status(cd, name)) {
7cdc99
 		case CRYPT_ACTIVE:
7cdc99
 		case CRYPT_BUSY:
7cdc99
+			r = dm_query_device(cd, name, DM_ACTIVE_HOLDERS, &dmd);
7cdc99
+			if (r >= 0 && dmd.holders) {
7cdc99
+				log_err(cd, _("Device %s is still in use.\n"), name);
7cdc99
+				r = -EBUSY;
7cdc99
+				break;
7cdc99
+			}
7cdc99
+
7cdc99
 			if (isTCRYPT(cd->type))
7cdc99
 				r = TCRYPT_deactivate(cd, name);
7cdc99
 			else
7cdc99
diff --git a/lib/utils_dm.h b/lib/utils_dm.h
7cdc99
index c87e9aa..cf22e12 100644
7cdc99
--- a/lib/utils_dm.h
7cdc99
+++ b/lib/utils_dm.h
7cdc99
@@ -48,14 +48,16 @@ uint32_t dm_flags(void);
7cdc99
 
7cdc99
 #define DM_ACTIVE_DEVICE	(1 << 0)
7cdc99
 #define DM_ACTIVE_UUID		(1 << 1)
7cdc99
+#define DM_ACTIVE_HOLDERS	(1 << 2)
7cdc99
 
7cdc99
-#define DM_ACTIVE_CRYPT_CIPHER	(1 << 2)
7cdc99
-#define DM_ACTIVE_CRYPT_KEYSIZE	(1 << 3)
7cdc99
-#define DM_ACTIVE_CRYPT_KEY	(1 << 4)
7cdc99
+#define DM_ACTIVE_CRYPT_CIPHER	(1 << 3)
7cdc99
+#define DM_ACTIVE_CRYPT_KEYSIZE	(1 << 4)
7cdc99
+#define DM_ACTIVE_CRYPT_KEY	(1 << 5)
7cdc99
+
7cdc99
+#define DM_ACTIVE_VERITY_ROOT_HASH	(1 << 6)
7cdc99
+#define DM_ACTIVE_VERITY_HASH_DEVICE	(1 << 7)
7cdc99
+#define DM_ACTIVE_VERITY_PARAMS		(1 << 8)
7cdc99
 
7cdc99
-#define DM_ACTIVE_VERITY_ROOT_HASH	(1 << 5)
7cdc99
-#define DM_ACTIVE_VERITY_HASH_DEVICE	(1 << 6)
7cdc99
-#define DM_ACTIVE_VERITY_PARAMS		(1 << 7)
7cdc99
 
7cdc99
 struct crypt_dm_active_device {
7cdc99
 	enum { DM_CRYPT = 0, DM_VERITY } target;
7cdc99
@@ -63,6 +65,7 @@ struct crypt_dm_active_device {
7cdc99
 	uint32_t flags;		/* activation flags */
7cdc99
 	const char *uuid;
7cdc99
 	struct device *data_device;
7cdc99
+	unsigned holders:1;
7cdc99
 	union {
7cdc99
 	struct {
7cdc99
 		const char *cipher;
7cdc99
-- 
7cdc99
1.8.3.1
7cdc99