Browse Source

dm crypt: add 'submit_from_crypt_cpus' option

Make it possible to disable offloading writes by setting the optional
'submit_from_crypt_cpus' table argument.

There are some situations where offloading write bios from the
encryption threads to a single thread degrades performance
significantly.

The default is to offload write bios to the same thread because it
benefits CFQ to have writes submitted using the same IO context.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Mikulas Patocka 10 years ago
parent
commit
0f5d8e6ee7
2 changed files with 23 additions and 3 deletions
  1. 9 1
      Documentation/device-mapper/dm-crypt.txt
  2. 14 2
      drivers/md/dm-crypt.c

+ 9 - 1
Documentation/device-mapper/dm-crypt.txt

@@ -51,7 +51,7 @@ Parameters: <cipher> <key> <iv_offset> <device path> \
     Otherwise #opt_params is the number of following arguments.
     Otherwise #opt_params is the number of following arguments.
 
 
     Example of optional parameters section:
     Example of optional parameters section:
-        2 allow_discards same_cpu_crypt
+        3 allow_discards same_cpu_crypt submit_from_crypt_cpus
 
 
 allow_discards
 allow_discards
     Block discard requests (a.k.a. TRIM) are passed through the crypt device.
     Block discard requests (a.k.a. TRIM) are passed through the crypt device.
@@ -68,6 +68,14 @@ same_cpu_crypt
     The default is to use an unbound workqueue so that encryption work
     The default is to use an unbound workqueue so that encryption work
     is automatically balanced between available CPUs.
     is automatically balanced between available CPUs.
 
 
+submit_from_crypt_cpus
+    Disable offloading writes to a separate thread after encryption.
+    There are some situations where offloading write bios from the
+    encryption threads to a single thread degrades performance
+    significantly.  The default is to offload write bios to the same
+    thread because it benefits CFQ to have writes submitted using the
+    same context.
+
 Example scripts
 Example scripts
 ===============
 ===============
 LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
 LUKS (Linux Unified Key Setup) is now the preferred way to set up disk

+ 14 - 2
drivers/md/dm-crypt.c

@@ -110,7 +110,8 @@ struct iv_tcw_private {
  * Crypt: maps a linear range of a block device
  * Crypt: maps a linear range of a block device
  * and encrypts / decrypts at the same time.
  * and encrypts / decrypts at the same time.
  */
  */
-enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID, DM_CRYPT_SAME_CPU };
+enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID,
+	     DM_CRYPT_SAME_CPU, DM_CRYPT_NO_OFFLOAD };
 
 
 /*
 /*
  * The fields in here must be read only after initialization.
  * The fields in here must be read only after initialization.
@@ -1239,6 +1240,11 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async)
 
 
 	clone->bi_iter.bi_sector = cc->start + io->sector;
 	clone->bi_iter.bi_sector = cc->start + io->sector;
 
 
+	if (likely(!async) && test_bit(DM_CRYPT_NO_OFFLOAD, &cc->flags)) {
+		generic_make_request(clone);
+		return;
+	}
+
 	spin_lock_irqsave(&cc->write_thread_wait.lock, flags);
 	spin_lock_irqsave(&cc->write_thread_wait.lock, flags);
 	list_add_tail(&io->list, &cc->write_thread_list);
 	list_add_tail(&io->list, &cc->write_thread_list);
 	wake_up_locked(&cc->write_thread_wait);
 	wake_up_locked(&cc->write_thread_wait);
@@ -1693,7 +1699,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 	char dummy;
 	char dummy;
 
 
 	static struct dm_arg _args[] = {
 	static struct dm_arg _args[] = {
-		{0, 2, "Invalid number of feature args"},
+		{0, 3, "Invalid number of feature args"},
 	};
 	};
 
 
 	if (argc < 5) {
 	if (argc < 5) {
@@ -1802,6 +1808,9 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 			else if (!strcasecmp(opt_string, "same_cpu_crypt"))
 			else if (!strcasecmp(opt_string, "same_cpu_crypt"))
 				set_bit(DM_CRYPT_SAME_CPU, &cc->flags);
 				set_bit(DM_CRYPT_SAME_CPU, &cc->flags);
 
 
+			else if (!strcasecmp(opt_string, "submit_from_crypt_cpus"))
+				set_bit(DM_CRYPT_NO_OFFLOAD, &cc->flags);
+
 			else {
 			else {
 				ti->error = "Invalid feature arguments";
 				ti->error = "Invalid feature arguments";
 				goto bad;
 				goto bad;
@@ -1905,12 +1914,15 @@ static void crypt_status(struct dm_target *ti, status_type_t type,
 
 
 		num_feature_args += !!ti->num_discard_bios;
 		num_feature_args += !!ti->num_discard_bios;
 		num_feature_args += test_bit(DM_CRYPT_SAME_CPU, &cc->flags);
 		num_feature_args += test_bit(DM_CRYPT_SAME_CPU, &cc->flags);
+		num_feature_args += test_bit(DM_CRYPT_NO_OFFLOAD, &cc->flags);
 		if (num_feature_args) {
 		if (num_feature_args) {
 			DMEMIT(" %d", num_feature_args);
 			DMEMIT(" %d", num_feature_args);
 			if (ti->num_discard_bios)
 			if (ti->num_discard_bios)
 				DMEMIT(" allow_discards");
 				DMEMIT(" allow_discards");
 			if (test_bit(DM_CRYPT_SAME_CPU, &cc->flags))
 			if (test_bit(DM_CRYPT_SAME_CPU, &cc->flags))
 				DMEMIT(" same_cpu_crypt");
 				DMEMIT(" same_cpu_crypt");
+			if (test_bit(DM_CRYPT_NO_OFFLOAD, &cc->flags))
+				DMEMIT(" submit_from_crypt_cpus");
 		}
 		}
 
 
 		break;
 		break;