From 157ccf52eaa4eeeefeee4a74c719a79a47896b3a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 28 Mar 2012 16:10:15 -0700 Subject: [PATCH] 3.0-stable patches added patches: dm-crypt-add-missing-error-handling.patch dm-crypt-fix-mempool-deadlock.patch dm-exception-store-fix-init-error-path.patch --- .../dm-crypt-add-missing-error-handling.patch | 114 ++++++++++++++++++ queue-3.0/dm-crypt-fix-mempool-deadlock.patch | 63 ++++++++++ ...-exception-store-fix-init-error-path.patch | 31 +++++ queue-3.0/series | 3 + 4 files changed, 211 insertions(+) create mode 100644 queue-3.0/dm-crypt-add-missing-error-handling.patch create mode 100644 queue-3.0/dm-crypt-fix-mempool-deadlock.patch create mode 100644 queue-3.0/dm-exception-store-fix-init-error-path.patch diff --git a/queue-3.0/dm-crypt-add-missing-error-handling.patch b/queue-3.0/dm-crypt-add-missing-error-handling.patch new file mode 100644 index 00000000000..96555534e6e --- /dev/null +++ b/queue-3.0/dm-crypt-add-missing-error-handling.patch @@ -0,0 +1,114 @@ +From 72c6e7afc43e19f68a31dea204fc366624d6eee9 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Wed, 28 Mar 2012 18:41:22 +0100 +Subject: dm crypt: add missing error handling + +From: Mikulas Patocka + +commit 72c6e7afc43e19f68a31dea204fc366624d6eee9 upstream. + +Always set io->error to -EIO when an error is detected in dm-crypt. + +There were cases where an error code would be set only if we finish +processing the last sector. If there were other encryption operations in +flight, the error would be ignored and bio would be returned with +success as if no error happened. + +This bug is present in kcryptd_crypt_write_convert, kcryptd_crypt_read_convert +and kcryptd_async_done. + +Signed-off-by: Mikulas Patocka +Reviewed-by: Milan Broz +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-crypt.c | 28 ++++++++++++++++------------ + 1 file changed, 16 insertions(+), 12 deletions(-) + +--- a/drivers/md/dm-crypt.c ++++ b/drivers/md/dm-crypt.c +@@ -1045,16 +1045,14 @@ static void kcryptd_queue_io(struct dm_c + queue_work(cc->io_queue, &io->work); + } + +-static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, +- int error, int async) ++static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async) + { + struct bio *clone = io->ctx.bio_out; + struct crypt_config *cc = io->target->private; + +- if (unlikely(error < 0)) { ++ if (unlikely(io->error < 0)) { + crypt_free_buffer_pages(cc, clone); + bio_put(clone); +- io->error = -EIO; + crypt_dec_pending(io); + return; + } +@@ -1105,12 +1103,16 @@ static void kcryptd_crypt_write_convert( + sector += bio_sectors(clone); + + crypt_inc_pending(io); ++ + r = crypt_convert(cc, &io->ctx); ++ if (r < 0) ++ io->error = -EIO; ++ + crypt_finished = atomic_dec_and_test(&io->ctx.pending); + + /* Encryption was already finished, submit io now */ + if (crypt_finished) { +- kcryptd_crypt_write_io_submit(io, r, 0); ++ kcryptd_crypt_write_io_submit(io, 0); + + /* + * If there was an error, do not try next fragments. +@@ -1161,11 +1163,8 @@ static void kcryptd_crypt_write_convert( + crypt_dec_pending(io); + } + +-static void kcryptd_crypt_read_done(struct dm_crypt_io *io, int error) ++static void kcryptd_crypt_read_done(struct dm_crypt_io *io) + { +- if (unlikely(error < 0)) +- io->error = -EIO; +- + crypt_dec_pending(io); + } + +@@ -1180,9 +1179,11 @@ static void kcryptd_crypt_read_convert(s + io->sector); + + r = crypt_convert(cc, &io->ctx); ++ if (r < 0) ++ io->error = -EIO; + + if (atomic_dec_and_test(&io->ctx.pending)) +- kcryptd_crypt_read_done(io, r); ++ kcryptd_crypt_read_done(io); + + crypt_dec_pending(io); + } +@@ -1203,15 +1204,18 @@ static void kcryptd_async_done(struct cr + if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post) + error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq); + ++ if (error < 0) ++ io->error = -EIO; ++ + mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool); + + if (!atomic_dec_and_test(&ctx->pending)) + return; + + if (bio_data_dir(io->base_bio) == READ) +- kcryptd_crypt_read_done(io, error); ++ kcryptd_crypt_read_done(io); + else +- kcryptd_crypt_write_io_submit(io, error, 1); ++ kcryptd_crypt_write_io_submit(io, 1); + } + + static void kcryptd_crypt(struct work_struct *work) diff --git a/queue-3.0/dm-crypt-fix-mempool-deadlock.patch b/queue-3.0/dm-crypt-fix-mempool-deadlock.patch new file mode 100644 index 00000000000..88c7615f281 --- /dev/null +++ b/queue-3.0/dm-crypt-fix-mempool-deadlock.patch @@ -0,0 +1,63 @@ +From aeb2deae2660a1773c83d3c6e9e6575daa3855d6 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Wed, 28 Mar 2012 18:41:22 +0100 +Subject: dm crypt: fix mempool deadlock + +From: Mikulas Patocka + +commit aeb2deae2660a1773c83d3c6e9e6575daa3855d6 upstream. + +This patch fixes a possible deadlock in dm-crypt's mempool use. + +Currently, dm-crypt reserves a mempool of MIN_BIO_PAGES reserved pages. +It allocates first MIN_BIO_PAGES with non-failing allocation (the allocation +cannot fail and waits until the mempool is refilled). Further pages are +allocated with different gfp flags that allow failing. + +Because allocations may be done in parallel, this code can deadlock. Example: +There are two processes, each tries to allocate MIN_BIO_PAGES and the processes +run simultaneously. +It may end up in a situation where each process allocates (MIN_BIO_PAGES / 2) +pages. The mempool is exhausted. Each process waits for more pages to be freed +to the mempool, which never happens. + +To avoid this deadlock scenario, this patch changes the code so that only +the first page is allocated with non-failing gfp mask. Allocation of further +pages may fail. + +Signed-off-by: Mikulas Patocka +Signed-off-by: Milan Broz +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-crypt.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/md/dm-crypt.c ++++ b/drivers/md/dm-crypt.c +@@ -177,7 +177,6 @@ struct crypt_config { + + #define MIN_IOS 16 + #define MIN_POOL_PAGES 32 +-#define MIN_BIO_PAGES 8 + + static struct kmem_cache *_crypt_io_pool; + +@@ -849,12 +848,11 @@ static struct bio *crypt_alloc_buffer(st + } + + /* +- * if additional pages cannot be allocated without waiting, +- * return a partially allocated bio, the caller will then try +- * to allocate additional bios while submitting this partial bio ++ * If additional pages cannot be allocated without waiting, ++ * return a partially-allocated bio. The caller will then try ++ * to allocate more bios while submitting this partial bio. + */ +- if (i == (MIN_BIO_PAGES - 1)) +- gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT; ++ gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT; + + len = (size > PAGE_SIZE) ? PAGE_SIZE : size; + diff --git a/queue-3.0/dm-exception-store-fix-init-error-path.patch b/queue-3.0/dm-exception-store-fix-init-error-path.patch new file mode 100644 index 00000000000..ac456b7731b --- /dev/null +++ b/queue-3.0/dm-exception-store-fix-init-error-path.patch @@ -0,0 +1,31 @@ +From aadbe266f2f89ccc68b52f4effc7b3a8b29521ef Mon Sep 17 00:00:00 2001 +From: Andrei Warkentin +Date: Wed, 28 Mar 2012 18:41:22 +0100 +Subject: dm exception store: fix init error path + +From: Andrei Warkentin + +commit aadbe266f2f89ccc68b52f4effc7b3a8b29521ef upstream. + +Call the correct exit function on failure in dm_exception_store_init. + +Signed-off-by: Andrei Warkentin +Acked-by: Mike Snitzer +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-exception-store.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/md/dm-exception-store.c ++++ b/drivers/md/dm-exception-store.c +@@ -282,7 +282,7 @@ int dm_exception_store_init(void) + return 0; + + persistent_fail: +- dm_persistent_snapshot_exit(); ++ dm_transient_snapshot_exit(); + transient_fail: + return r; + } diff --git a/queue-3.0/series b/queue-3.0/series index 896181f86aa..79c06b719e5 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -84,3 +84,6 @@ ext4-ignore-ext4_inode_journal_data-flag-with-delalloc.patch ext4-check-for-zero-length-extent.patch vfs-fix-d_ancestor-case-in-d_materialize_unique.patch udf-fix-deadlock-in-udf_release_file.patch +dm-crypt-fix-mempool-deadlock.patch +dm-crypt-add-missing-error-handling.patch +dm-exception-store-fix-init-error-path.patch -- 2.47.3