diff options
-rw-r--r-- | drivers/md/dm-crypt.c | 51 |
1 files changed, 36 insertions, 15 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 4519a7c0098c..713a96237a80 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/backing-dev.h> | 22 | #include <linux/backing-dev.h> |
23 | #include <linux/atomic.h> | 23 | #include <linux/atomic.h> |
24 | #include <linux/scatterlist.h> | 24 | #include <linux/scatterlist.h> |
25 | #include <linux/rbtree.h> | ||
25 | #include <asm/page.h> | 26 | #include <asm/page.h> |
26 | #include <asm/unaligned.h> | 27 | #include <asm/unaligned.h> |
27 | #include <crypto/hash.h> | 28 | #include <crypto/hash.h> |
@@ -60,7 +61,7 @@ struct dm_crypt_io { | |||
60 | int error; | 61 | int error; |
61 | sector_t sector; | 62 | sector_t sector; |
62 | 63 | ||
63 | struct list_head list; | 64 | struct rb_node rb_node; |
64 | } CRYPTO_MINALIGN_ATTR; | 65 | } CRYPTO_MINALIGN_ATTR; |
65 | 66 | ||
66 | struct dm_crypt_request { | 67 | struct dm_crypt_request { |
@@ -134,7 +135,7 @@ struct crypt_config { | |||
134 | 135 | ||
135 | struct task_struct *write_thread; | 136 | struct task_struct *write_thread; |
136 | wait_queue_head_t write_thread_wait; | 137 | wait_queue_head_t write_thread_wait; |
137 | struct list_head write_thread_list; | 138 | struct rb_root write_tree; |
138 | 139 | ||
139 | char *cipher; | 140 | char *cipher; |
140 | char *cipher_string; | 141 | char *cipher_string; |
@@ -1169,11 +1170,15 @@ static void kcryptd_io_write(struct dm_crypt_io *io) | |||
1169 | generic_make_request(clone); | 1170 | generic_make_request(clone); |
1170 | } | 1171 | } |
1171 | 1172 | ||
1173 | #define crypt_io_from_node(node) rb_entry((node), struct dm_crypt_io, rb_node) | ||
1174 | |||
1172 | static int dmcrypt_write(void *data) | 1175 | static int dmcrypt_write(void *data) |
1173 | { | 1176 | { |
1174 | struct crypt_config *cc = data; | 1177 | struct crypt_config *cc = data; |
1178 | struct dm_crypt_io *io; | ||
1179 | |||
1175 | while (1) { | 1180 | while (1) { |
1176 | struct list_head local_list; | 1181 | struct rb_root write_tree; |
1177 | struct blk_plug plug; | 1182 | struct blk_plug plug; |
1178 | 1183 | ||
1179 | DECLARE_WAITQUEUE(wait, current); | 1184 | DECLARE_WAITQUEUE(wait, current); |
@@ -1181,7 +1186,7 @@ static int dmcrypt_write(void *data) | |||
1181 | spin_lock_irq(&cc->write_thread_wait.lock); | 1186 | spin_lock_irq(&cc->write_thread_wait.lock); |
1182 | continue_locked: | 1187 | continue_locked: |
1183 | 1188 | ||
1184 | if (!list_empty(&cc->write_thread_list)) | 1189 | if (!RB_EMPTY_ROOT(&cc->write_tree)) |
1185 | goto pop_from_list; | 1190 | goto pop_from_list; |
1186 | 1191 | ||
1187 | __set_current_state(TASK_INTERRUPTIBLE); | 1192 | __set_current_state(TASK_INTERRUPTIBLE); |
@@ -1203,20 +1208,22 @@ continue_locked: | |||
1203 | goto continue_locked; | 1208 | goto continue_locked; |
1204 | 1209 | ||
1205 | pop_from_list: | 1210 | pop_from_list: |
1206 | local_list = cc->write_thread_list; | 1211 | write_tree = cc->write_tree; |
1207 | local_list.next->prev = &local_list; | 1212 | cc->write_tree = RB_ROOT; |
1208 | local_list.prev->next = &local_list; | ||
1209 | INIT_LIST_HEAD(&cc->write_thread_list); | ||
1210 | |||
1211 | spin_unlock_irq(&cc->write_thread_wait.lock); | 1213 | spin_unlock_irq(&cc->write_thread_wait.lock); |
1212 | 1214 | ||
1215 | BUG_ON(rb_parent(write_tree.rb_node)); | ||
1216 | |||
1217 | /* | ||
1218 | * Note: we cannot walk the tree here with rb_next because | ||
1219 | * the structures may be freed when kcryptd_io_write is called. | ||
1220 | */ | ||
1213 | blk_start_plug(&plug); | 1221 | blk_start_plug(&plug); |
1214 | do { | 1222 | do { |
1215 | struct dm_crypt_io *io = container_of(local_list.next, | 1223 | io = crypt_io_from_node(rb_first(&write_tree)); |
1216 | struct dm_crypt_io, list); | 1224 | rb_erase(&io->rb_node, &write_tree); |
1217 | list_del(&io->list); | ||
1218 | kcryptd_io_write(io); | 1225 | kcryptd_io_write(io); |
1219 | } while (!list_empty(&local_list)); | 1226 | } while (!RB_EMPTY_ROOT(&write_tree)); |
1220 | blk_finish_plug(&plug); | 1227 | blk_finish_plug(&plug); |
1221 | } | 1228 | } |
1222 | return 0; | 1229 | return 0; |
@@ -1227,6 +1234,8 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async) | |||
1227 | struct bio *clone = io->ctx.bio_out; | 1234 | struct bio *clone = io->ctx.bio_out; |
1228 | struct crypt_config *cc = io->cc; | 1235 | struct crypt_config *cc = io->cc; |
1229 | unsigned long flags; | 1236 | unsigned long flags; |
1237 | sector_t sector; | ||
1238 | struct rb_node **rbp, *parent; | ||
1230 | 1239 | ||
1231 | if (unlikely(io->error < 0)) { | 1240 | if (unlikely(io->error < 0)) { |
1232 | crypt_free_buffer_pages(cc, clone); | 1241 | crypt_free_buffer_pages(cc, clone); |
@@ -1246,7 +1255,19 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async) | |||
1246 | } | 1255 | } |
1247 | 1256 | ||
1248 | spin_lock_irqsave(&cc->write_thread_wait.lock, flags); | 1257 | spin_lock_irqsave(&cc->write_thread_wait.lock, flags); |
1249 | list_add_tail(&io->list, &cc->write_thread_list); | 1258 | rbp = &cc->write_tree.rb_node; |
1259 | parent = NULL; | ||
1260 | sector = io->sector; | ||
1261 | while (*rbp) { | ||
1262 | parent = *rbp; | ||
1263 | if (sector < crypt_io_from_node(parent)->sector) | ||
1264 | rbp = &(*rbp)->rb_left; | ||
1265 | else | ||
1266 | rbp = &(*rbp)->rb_right; | ||
1267 | } | ||
1268 | rb_link_node(&io->rb_node, parent, rbp); | ||
1269 | rb_insert_color(&io->rb_node, &cc->write_tree); | ||
1270 | |||
1250 | wake_up_locked(&cc->write_thread_wait); | 1271 | wake_up_locked(&cc->write_thread_wait); |
1251 | spin_unlock_irqrestore(&cc->write_thread_wait.lock, flags); | 1272 | spin_unlock_irqrestore(&cc->write_thread_wait.lock, flags); |
1252 | } | 1273 | } |
@@ -1836,7 +1857,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
1836 | } | 1857 | } |
1837 | 1858 | ||
1838 | init_waitqueue_head(&cc->write_thread_wait); | 1859 | init_waitqueue_head(&cc->write_thread_wait); |
1839 | INIT_LIST_HEAD(&cc->write_thread_list); | 1860 | cc->write_tree = RB_ROOT; |
1840 | 1861 | ||
1841 | cc->write_thread = kthread_create(dmcrypt_write, cc, "dmcrypt_write"); | 1862 | cc->write_thread = kthread_create(dmcrypt_write, cc, "dmcrypt_write"); |
1842 | if (IS_ERR(cc->write_thread)) { | 1863 | if (IS_ERR(cc->write_thread)) { |