dm crypt: add 'submit_from_crypt_cpus' option
authorMikulas Patocka <mpatocka@redhat.com>
Fri, 13 Feb 2015 13:27:08 +0000 (08:27 -0500)
committerMike Snitzer <snitzer@redhat.com>
Mon, 16 Feb 2015 16:11:15 +0000 (11:11 -0500)
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>
Documentation/device-mapper/dm-crypt.txt
drivers/md/dm-crypt.c

index 571f24ffc91c42a8a175688fa70dacce7c1643f9..ad697781f9ac478477cfed76978b047685eda2b6 100644 (file)
@@ -51,7 +51,7 @@ Parameters: <cipher> <key> <iv_offset> <device path> \
     Otherwise #opt_params is the number of following arguments.
 
     Example of optional parameters section:
     Otherwise #opt_params is the number of following arguments.
 
     Example of optional parameters section:
-        2 allow_discards same_cpu_crypt
+        3 allow_discards same_cpu_crypt submit_from_crypt_cpus
 
 allow_discards
     Block discard requests (a.k.a. TRIM) are passed through the crypt device.
 
 allow_discards
     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
     is automatically balanced between available CPUs.
 
     The default is to use an unbound workqueue so that encryption work
     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
 ===============
 LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
 Example scripts
 ===============
 LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
index 8c0e36b1d0ed84ebd0932f25dec1f6e200508407..4519a7c0098cf6c2cffc4a6a6d36f4e353628c7c 100644 (file)
@@ -110,7 +110,8 @@ struct iv_tcw_private {
  * Crypt: maps a linear range of a block device
  * and encrypts / decrypts at the same time.
  */
  * Crypt: maps a linear range of a block device
  * 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);
        list_add_tail(&io->list, &cc->write_thread_list);
        wake_up_locked(&cc->write_thread_wait);
        spin_lock_irqsave(&cc->write_thread_wait.lock, flags);
        list_add_tail(&io->list, &cc->write_thread_list);
        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;
 
        static struct dm_arg _args[] = {
        char dummy;
 
        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"))
                                set_bit(DM_CRYPT_SAME_CPU, &cc->flags);
 
                        else if (!strcasecmp(opt_string, "same_cpu_crypt"))
                                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 {
                                ti->error = "Invalid feature arguments";
                                goto bad;
                        else {
                                ti->error = "Invalid feature arguments";
                                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 += test_bit(DM_CRYPT_SAME_CPU, &cc->flags);
 
                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_NO_OFFLOAD, &cc->flags);
                if (num_feature_args) {
                        DMEMIT(" %d", num_feature_args);
                        if (ti->num_discard_bios)
                                DMEMIT(" allow_discards");
                        if (test_bit(DM_CRYPT_SAME_CPU, &cc->flags))
                                DMEMIT(" same_cpu_crypt");
                if (num_feature_args) {
                        DMEMIT(" %d", num_feature_args);
                        if (ti->num_discard_bios)
                                DMEMIT(" allow_discards");
                        if (test_bit(DM_CRYPT_SAME_CPU, &cc->flags))
                                DMEMIT(" same_cpu_crypt");
+                       if (test_bit(DM_CRYPT_NO_OFFLOAD, &cc->flags))
+                               DMEMIT(" submit_from_crypt_cpus");
                }
 
                break;
                }
 
                break;