Skip to content

Commit 1260bb5

Browse files
committed
dm-crypt: limit the size of encryption requests
jira LE-3201 Rebuild_History Non-Buildable kernel-rt-4.18.0-553.22.1.rt7.363.el8_10 commit-author Mikulas Patocka <[email protected]> commit 0d815e3 Empty-Commit: Cherry-Pick Conflicts during history rebuild. Will be included in final tarball splat. Ref for failed cherry-pick at: ciq/ciq_backports/kernel-rt-4.18.0-553.22.1.rt7.363.el8_10/0d815e34.failed There was a performance regression reported where dm-crypt would perform worse on new kernels than on old kernels. The reason is that the old kernels split the bios to NVMe request size (that is usually 65536 or 131072 bytes) and the new kernels pass the big bios through dm-crypt and split them underneath. If a big 1MiB bio is passed to dm-crypt, dm-crypt processes it on a single core without parallelization and this is what causes the performance degradation. This commit introduces new tunable variables /sys/module/dm_crypt/parameters/max_read_size and /sys/module/dm_crypt/parameters/max_write_size that specify the maximum bio size for dm-crypt. Bios larger than this value are split, so that they can be encrypted in parallel by multiple cores. If these variables are '0', a default 131072 is used. Splitting bios may cause performance regressions in other workloads - if this happens, the user should increase the value in max_read_size and max_write_size variables. max_read_size: 128k 2399MiB/s 256k 2368MiB/s 512k 1986MiB/s 1024 1790MiB/s max_write_size: 128k 1712MiB/s 256k 1651MiB/s 512k 1537MiB/s 1024k 1332MiB/s Note that if you run dm-crypt inside a virtual machine, you may need to do "echo numa >/sys/module/workqueue/parameters/default_affinity_scope" to improve performance. Signed-off-by: Mikulas Patocka <[email protected]> Tested-by: Laurence Oberman <[email protected]> (cherry picked from commit 0d815e3) Signed-off-by: Jonathan Maple <[email protected]> # Conflicts: # drivers/md/dm-crypt.c
1 parent 19843bc commit 1260bb5

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
dm-crypt: limit the size of encryption requests
2+
3+
jira LE-3201
4+
Rebuild_History Non-Buildable kernel-rt-4.18.0-553.22.1.rt7.363.el8_10
5+
commit-author Mikulas Patocka <[email protected]>
6+
commit 0d815e3400e631d227a3a95968b8c8e7e0c0ef9e
7+
Empty-Commit: Cherry-Pick Conflicts during history rebuild.
8+
Will be included in final tarball splat. Ref for failed cherry-pick at:
9+
ciq/ciq_backports/kernel-rt-4.18.0-553.22.1.rt7.363.el8_10/0d815e34.failed
10+
11+
There was a performance regression reported where dm-crypt would perform
12+
worse on new kernels than on old kernels. The reason is that the old
13+
kernels split the bios to NVMe request size (that is usually 65536 or
14+
131072 bytes) and the new kernels pass the big bios through dm-crypt and
15+
split them underneath.
16+
17+
If a big 1MiB bio is passed to dm-crypt, dm-crypt processes it on a single
18+
core without parallelization and this is what causes the performance
19+
degradation.
20+
21+
This commit introduces new tunable variables
22+
/sys/module/dm_crypt/parameters/max_read_size and
23+
/sys/module/dm_crypt/parameters/max_write_size that specify the maximum
24+
bio size for dm-crypt. Bios larger than this value are split, so that
25+
they can be encrypted in parallel by multiple cores. If these variables
26+
are '0', a default 131072 is used.
27+
28+
Splitting bios may cause performance regressions in other workloads - if
29+
this happens, the user should increase the value in max_read_size and
30+
max_write_size variables.
31+
32+
max_read_size:
33+
128k 2399MiB/s
34+
256k 2368MiB/s
35+
512k 1986MiB/s
36+
1024 1790MiB/s
37+
38+
max_write_size:
39+
128k 1712MiB/s
40+
256k 1651MiB/s
41+
512k 1537MiB/s
42+
1024k 1332MiB/s
43+
44+
Note that if you run dm-crypt inside a virtual machine, you may need to do
45+
"echo numa >/sys/module/workqueue/parameters/default_affinity_scope" to
46+
improve performance.
47+
48+
Signed-off-by: Mikulas Patocka <[email protected]>
49+
Tested-by: Laurence Oberman <[email protected]>
50+
(cherry picked from commit 0d815e3400e631d227a3a95968b8c8e7e0c0ef9e)
51+
Signed-off-by: Jonathan Maple <[email protected]>
52+
53+
# Conflicts:
54+
# drivers/md/dm-crypt.c
55+
diff --cc drivers/md/dm-crypt.c
56+
index ba5dbca6ca9f,f46ff843d4c3..000000000000
57+
--- a/drivers/md/dm-crypt.c
58+
+++ b/drivers/md/dm-crypt.c
59+
@@@ -229,12 -237,37 +229,41 @@@ struct crypt_config
60+
#define POOL_ENTRY_SIZE 512
61+
62+
static DEFINE_SPINLOCK(dm_crypt_clients_lock);
63+
-static unsigned int dm_crypt_clients_n;
64+
+static unsigned dm_crypt_clients_n = 0;
65+
static volatile unsigned long dm_crypt_pages_per_client;
66+
#define DM_CRYPT_MEMORY_PERCENT 2
67+
++<<<<<<< HEAD
68+
+#define DM_CRYPT_MIN_PAGES_PER_CLIENT (BIO_MAX_PAGES * 16)
69+
++=======
70+
+ #define DM_CRYPT_MIN_PAGES_PER_CLIENT (BIO_MAX_VECS * 16)
71+
+ #define DM_CRYPT_DEFAULT_MAX_READ_SIZE 131072
72+
+ #define DM_CRYPT_DEFAULT_MAX_WRITE_SIZE 131072
73+
+
74+
+ static unsigned int max_read_size = 0;
75+
+ module_param(max_read_size, uint, 0644);
76+
+ MODULE_PARM_DESC(max_read_size, "Maximum size of a read request");
77+
+ static unsigned int max_write_size = 0;
78+
+ module_param(max_write_size, uint, 0644);
79+
+ MODULE_PARM_DESC(max_write_size, "Maximum size of a write request");
80+
+ static unsigned get_max_request_size(struct crypt_config *cc, bool wrt)
81+
+ {
82+
+ unsigned val, sector_align;
83+
+ val = !wrt ? READ_ONCE(max_read_size) : READ_ONCE(max_write_size);
84+
+ if (likely(!val))
85+
+ val = !wrt ? DM_CRYPT_DEFAULT_MAX_READ_SIZE : DM_CRYPT_DEFAULT_MAX_WRITE_SIZE;
86+
+ if (wrt || cc->on_disk_tag_size) {
87+
+ if (unlikely(val > BIO_MAX_VECS << PAGE_SHIFT))
88+
+ val = BIO_MAX_VECS << PAGE_SHIFT;
89+
+ }
90+
+ sector_align = max(bdev_logical_block_size(cc->dev->bdev), (unsigned)cc->sector_size);
91+
+ val = round_down(val, sector_align);
92+
+ if (unlikely(!val))
93+
+ val = sector_align;
94+
+ return val >> SECTOR_SHIFT;
95+
+ }
96+
++>>>>>>> 0d815e3400e6 (dm-crypt: limit the size of encryption requests)
97+
98+
-static void crypt_endio(struct bio *clone);
99+
+static void clone_init(struct dm_crypt_io *, struct bio *);
100+
static void kcryptd_queue_crypt(struct dm_crypt_io *io);
101+
static struct scatterlist *crypt_get_sg_data(struct crypt_config *cc,
102+
struct scatterlist *sg);
103+
@@@ -3345,9 -3518,9 +3375,15 @@@ static int crypt_map(struct dm_target *
104+
/*
105+
* Check if bio is too large, split as needed.
106+
*/
107+
++<<<<<<< HEAD
108+
+ if (unlikely(bio->bi_iter.bi_size > (BIO_MAX_PAGES << PAGE_SHIFT)) &&
109+
+ (bio_data_dir(bio) == WRITE || cc->on_disk_tag_size))
110+
+ dm_accept_partial_bio(bio, ((BIO_MAX_PAGES << PAGE_SHIFT) >> SECTOR_SHIFT));
111+
++=======
112+
+ max_sectors = get_max_request_size(cc, bio_data_dir(bio) == WRITE);
113+
+ if (unlikely(bio_sectors(bio) > max_sectors))
114+
+ dm_accept_partial_bio(bio, max_sectors);
115+
++>>>>>>> 0d815e3400e6 (dm-crypt: limit the size of encryption requests)
116+
117+
/*
118+
* Ensure that bio is a multiple of internal sector encryption size
119+
diff --git a/Documentation/admin-guide/device-mapper/dm-crypt.rst b/Documentation/admin-guide/device-mapper/dm-crypt.rst
120+
index 4ba56c256c05..8d9af4ba1948 100644
121+
--- a/Documentation/admin-guide/device-mapper/dm-crypt.rst
122+
+++ b/Documentation/admin-guide/device-mapper/dm-crypt.rst
123+
@@ -155,6 +155,17 @@ iv_large_sectors
124+
The <iv_offset> must be multiple of <sector_size> (in 512 bytes units)
125+
if this flag is specified.
126+
127+
+
128+
+Module parameters::
129+
+max_read_size
130+
+max_write_size
131+
+ Maximum size of read or write requests. When a request larger than this size
132+
+ is received, dm-crypt will split the request. The splitting improves
133+
+ concurrency (the split requests could be encrypted in parallel by multiple
134+
+ cores), but it also causes overhead. The user should tune these parameters to
135+
+ fit the actual workload.
136+
+
137+
+
138+
Example scripts
139+
===============
140+
LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
141+
* Unmerged path drivers/md/dm-crypt.c

0 commit comments

Comments
 (0)