]>
Commit | Line | Data |
---|---|---|
101a7448 ŁK |
1 | dm-crypt: avoid deadlock in mempools |
2 | ||
3 | This patch fixes a theoretical deadlock introduced in the previous patch. | |
4 | ||
5 | The function crypt_alloc_buffer may be called concurrently. If we allocate | |
6 | from the mempool concurrently, there is a possibility of deadlock. | |
7 | For example, if we have mempool of 256 pages, two processes, each wanting 256, | |
8 | pages allocate from the mempool concurrently, it may deadlock in a situation | |
9 | where both processes have allocated 128 pages and the mempool is exhausted. | |
10 | ||
11 | In order to avoid this scenarios, we allocate the pages under a mutex. | |
12 | ||
13 | In order to not degrade performance with excessive locking, we try | |
14 | non-blocking allocations without a mutex first and if it fails, we fallback | |
15 | to a blocking allocation with a mutex. | |
16 | ||
17 | Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> | |
18 | ||
19 | --- | |
0a2e4279 ŁK |
20 | drivers/md/dm-crypt.c | 41 ++++++++++++++++++++++++++++++++++++----- |
21 | 1 file changed, 36 insertions(+), 5 deletions(-) | |
101a7448 | 22 | |
0a2e4279 | 23 | Index: linux-3.14/drivers/md/dm-crypt.c |
101a7448 | 24 | =================================================================== |
0a2e4279 ŁK |
25 | --- linux-3.14.orig/drivers/md/dm-crypt.c 2014-04-04 20:59:46.000000000 +0200 |
26 | +++ linux-3.14/drivers/md/dm-crypt.c 2014-04-04 21:04:40.000000000 +0200 | |
27 | @@ -124,6 +124,7 @@ struct crypt_config { | |
101a7448 ŁK |
28 | mempool_t *req_pool; |
29 | mempool_t *page_pool; | |
30 | struct bio_set *bs; | |
31 | + struct mutex bio_alloc_lock; | |
32 | ||
33 | struct workqueue_struct *io_queue; | |
34 | struct workqueue_struct *crypt_queue; | |
0a2e4279 | 35 | @@ -954,27 +955,51 @@ static void crypt_free_buffer_pages(stru |
101a7448 ŁK |
36 | /* |
37 | * Generate a new unfragmented bio with the given size | |
38 | * This should never violate the device limitations | |
39 | + * | |
40 | + * This function may be called concurrently. If we allocate from the mempool | |
41 | + * concurrently, there is a possibility of deadlock. For example, if we have | |
42 | + * mempool of 256 pages, two processes, each wanting 256, pages allocate from | |
43 | + * the mempool concurrently, it may deadlock in a situation where both processes | |
44 | + * have allocated 128 pages and the mempool is exhausted. | |
45 | + * | |
46 | + * In order to avoid this scenarios, we allocate the pages under a mutex. | |
47 | + * | |
48 | + * In order to not degrade performance with excessive locking, we try | |
49 | + * non-blocking allocations without a mutex first and if it fails, we fallback | |
50 | + * to a blocking allocation with a mutex. | |
51 | */ | |
52 | static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size) | |
53 | { | |
54 | struct crypt_config *cc = io->cc; | |
55 | struct bio *clone; | |
56 | unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; | |
57 | - gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM; | |
0a2e4279 | 58 | - unsigned i, len; |
101a7448 | 59 | + gfp_t gfp_mask = GFP_NOWAIT | __GFP_HIGHMEM; |
0a2e4279 | 60 | + unsigned i, len, remaining_size; |
101a7448 | 61 | struct page *page; |
0a2e4279 | 62 | struct bio_vec *bvec; |
101a7448 ŁK |
63 | |
64 | +retry: | |
65 | + if (unlikely(gfp_mask & __GFP_WAIT)) | |
66 | + mutex_lock(&cc->bio_alloc_lock); | |
67 | + | |
68 | clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, cc->bs); | |
69 | if (!clone) | |
70 | - return NULL; | |
71 | + goto return_clone; | |
72 | ||
73 | clone_init(io, clone); | |
74 | ||
0a2e4279 ŁK |
75 | + remaining_size = size; |
76 | + | |
101a7448 ŁK |
77 | for (i = 0; i < nr_iovecs; i++) { |
78 | page = mempool_alloc(cc->page_pool, gfp_mask); | |
79 | + if (!page) { | |
80 | + crypt_free_buffer_pages(cc, clone); | |
81 | + bio_put(clone); | |
82 | + gfp_mask |= __GFP_WAIT; | |
83 | + goto retry; | |
84 | + } | |
85 | ||
0a2e4279 ŁK |
86 | - len = (size > PAGE_SIZE) ? PAGE_SIZE : size; |
87 | + len = (remaining_size > PAGE_SIZE) ? PAGE_SIZE : remaining_size; | |
88 | ||
89 | bvec = &clone->bi_io_vec[clone->bi_vcnt++]; | |
90 | bvec->bv_page = page; | |
91 | @@ -983,9 +1008,13 @@ static struct bio *crypt_alloc_buffer(st | |
101a7448 | 92 | |
0a2e4279 | 93 | clone->bi_iter.bi_size += len; |
101a7448 | 94 | |
0a2e4279 ŁK |
95 | - size -= len; |
96 | + remaining_size -= len; | |
101a7448 ŁK |
97 | } |
98 | ||
99 | +return_clone: | |
100 | + if (unlikely(gfp_mask & __GFP_WAIT)) | |
101 | + mutex_unlock(&cc->bio_alloc_lock); | |
102 | + | |
103 | return clone; | |
104 | } | |
105 | ||
0a2e4279 | 106 | @@ -1671,6 +1700,8 @@ static int crypt_ctr(struct dm_target *t |
101a7448 ŁK |
107 | goto bad; |
108 | } | |
109 | ||
110 | + mutex_init(&cc->bio_alloc_lock); | |
111 | + | |
112 | ret = -EINVAL; | |
113 | if (sscanf(argv[2], "%llu%c", &tmpll, &dummy) != 1) { | |
114 | ti->error = "Invalid iv_offset sector"; |