]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 28 Mar 2012 23:10:15 +0000 (16:10 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 28 Mar 2012 23:10:15 +0000 (16:10 -0700)
added patches:
dm-crypt-add-missing-error-handling.patch
dm-crypt-fix-mempool-deadlock.patch
dm-exception-store-fix-init-error-path.patch

queue-3.0/dm-crypt-add-missing-error-handling.patch [new file with mode: 0644]
queue-3.0/dm-crypt-fix-mempool-deadlock.patch [new file with mode: 0644]
queue-3.0/dm-exception-store-fix-init-error-path.patch [new file with mode: 0644]
queue-3.0/series

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 (file)
index 0000000..9655553
--- /dev/null
@@ -0,0 +1,114 @@
+From 72c6e7afc43e19f68a31dea204fc366624d6eee9 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Wed, 28 Mar 2012 18:41:22 +0100
+Subject: dm crypt: add missing error handling
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+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 <mpatocka@redhat.com>
+Reviewed-by: Milan Broz <mbroz@redhat.com>
+Signed-off-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..88c7615
--- /dev/null
@@ -0,0 +1,63 @@
+From aeb2deae2660a1773c83d3c6e9e6575daa3855d6 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Wed, 28 Mar 2012 18:41:22 +0100
+Subject: dm crypt: fix mempool deadlock
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+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 <mpatocka@redhat.com>
+Signed-off-by: Milan Broz <mbroz@redhat.com>
+Signed-off-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..ac456b7
--- /dev/null
@@ -0,0 +1,31 @@
+From aadbe266f2f89ccc68b52f4effc7b3a8b29521ef Mon Sep 17 00:00:00 2001
+From: Andrei Warkentin <andrey.warkentin@gmail.com>
+Date: Wed, 28 Mar 2012 18:41:22 +0100
+Subject: dm exception store: fix init error path
+
+From: Andrei Warkentin <andrey.warkentin@gmail.com>
+
+commit aadbe266f2f89ccc68b52f4effc7b3a8b29521ef upstream.
+
+Call the correct exit function on failure in dm_exception_store_init.
+
+Signed-off-by: Andrei Warkentin <andrey.warkentin@gmail.com>
+Acked-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;
+ }
index 896181f86aabdbb7c263fef4c52c40f18aa37d87..79c06b719e5c784b3536430c20087a7f0caebcc6 100644 (file)
@@ -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