aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/dm-crypt.c2
-rw-r--r--drivers/md/dm-io.c2
-rw-r--r--drivers/md/dm.c2
-rw-r--r--fs/bio-integrity.c2
-rw-r--r--fs/bio.c191
-rw-r--r--include/linux/bio.h6
6 files changed, 170 insertions, 35 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index ce26c84af064..3326750ec02c 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1060,7 +1060,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
1060 goto bad_page_pool; 1060 goto bad_page_pool;
1061 } 1061 }
1062 1062
1063 cc->bs = bioset_create(MIN_IOS, MIN_IOS); 1063 cc->bs = bioset_create(MIN_IOS, 0);
1064 if (!cc->bs) { 1064 if (!cc->bs) {
1065 ti->error = "Cannot allocate crypt bioset"; 1065 ti->error = "Cannot allocate crypt bioset";
1066 goto bad_bs; 1066 goto bad_bs;
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 2fd6d4450637..a34338567a2a 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -56,7 +56,7 @@ struct dm_io_client *dm_io_client_create(unsigned num_pages)
56 if (!client->pool) 56 if (!client->pool)
57 goto bad; 57 goto bad;
58 58
59 client->bios = bioset_create(16, 16); 59 client->bios = bioset_create(16, 0);
60 if (!client->bios) 60 if (!client->bios)
61 goto bad; 61 goto bad;
62 62
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 343094c3feeb..421c9f02d8ca 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1093,7 +1093,7 @@ static struct mapped_device *alloc_dev(int minor)
1093 if (!md->tio_pool) 1093 if (!md->tio_pool)
1094 goto bad_tio_pool; 1094 goto bad_tio_pool;
1095 1095
1096 md->bs = bioset_create(16, 16); 1096 md->bs = bioset_create(16, 0);
1097 if (!md->bs) 1097 if (!md->bs)
1098 goto bad_no_bioset; 1098 goto bad_no_bioset;
1099 1099
diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c
index 19caf7c962ac..77ebc3c263d6 100644
--- a/fs/bio-integrity.c
+++ b/fs/bio-integrity.c
@@ -111,7 +111,7 @@ void bio_integrity_free(struct bio *bio, struct bio_set *bs)
111 && bip->bip_buf != NULL) 111 && bip->bip_buf != NULL)
112 kfree(bip->bip_buf); 112 kfree(bip->bip_buf);
113 113
114 mempool_free(bip->bip_vec, bs->bvec_pools[bip->bip_pool]); 114 bvec_free_bs(bs, bip->bip_vec, bip->bip_pool);
115 mempool_free(bip, bs->bio_integrity_pool); 115 mempool_free(bip, bs->bio_integrity_pool);
116 116
117 bio->bi_integrity = NULL; 117 bio->bi_integrity = NULL;
diff --git a/fs/bio.c b/fs/bio.c
index 1ab8986b0411..0146f80789e9 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -31,8 +31,6 @@
31 31
32DEFINE_TRACE(block_split); 32DEFINE_TRACE(block_split);
33 33
34static struct kmem_cache *bio_slab __read_mostly;
35
36static mempool_t *bio_split_pool __read_mostly; 34static mempool_t *bio_split_pool __read_mostly;
37 35
38/* 36/*
@@ -40,9 +38,8 @@ static mempool_t *bio_split_pool __read_mostly;
40 * break badly! cannot be bigger than what you can fit into an 38 * break badly! cannot be bigger than what you can fit into an
41 * unsigned short 39 * unsigned short
42 */ 40 */
43
44#define BV(x) { .nr_vecs = x, .name = "biovec-"__stringify(x) } 41#define BV(x) { .nr_vecs = x, .name = "biovec-"__stringify(x) }
45static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = { 42struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = {
46 BV(1), BV(4), BV(16), BV(64), BV(128), BV(BIO_MAX_PAGES), 43 BV(1), BV(4), BV(16), BV(64), BV(128), BV(BIO_MAX_PAGES),
47}; 44};
48#undef BV 45#undef BV
@@ -53,11 +50,119 @@ static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = {
53 */ 50 */
54struct bio_set *fs_bio_set; 51struct bio_set *fs_bio_set;
55 52
53/*
54 * Our slab pool management
55 */
56struct bio_slab {
57 struct kmem_cache *slab;
58 unsigned int slab_ref;
59 unsigned int slab_size;
60 char name[8];
61};
62static DEFINE_MUTEX(bio_slab_lock);
63static struct bio_slab *bio_slabs;
64static unsigned int bio_slab_nr, bio_slab_max;
65
66static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)
67{
68 unsigned int sz = sizeof(struct bio) + extra_size;
69 struct kmem_cache *slab = NULL;
70 struct bio_slab *bslab;
71 unsigned int i, entry = -1;
72
73 mutex_lock(&bio_slab_lock);
74
75 i = 0;
76 while (i < bio_slab_nr) {
77 struct bio_slab *bslab = &bio_slabs[i];
78
79 if (!bslab->slab && entry == -1)
80 entry = i;
81 else if (bslab->slab_size == sz) {
82 slab = bslab->slab;
83 bslab->slab_ref++;
84 break;
85 }
86 i++;
87 }
88
89 if (slab)
90 goto out_unlock;
91
92 if (bio_slab_nr == bio_slab_max && entry == -1) {
93 bio_slab_max <<= 1;
94 bio_slabs = krealloc(bio_slabs,
95 bio_slab_max * sizeof(struct bio_slab),
96 GFP_KERNEL);
97 if (!bio_slabs)
98 goto out_unlock;
99 }
100 if (entry == -1)
101 entry = bio_slab_nr++;
102
103 bslab = &bio_slabs[entry];
104
105 snprintf(bslab->name, sizeof(bslab->name), "bio-%d", entry);
106 slab = kmem_cache_create(bslab->name, sz, 0, SLAB_HWCACHE_ALIGN, NULL);
107 if (!slab)
108 goto out_unlock;
109
110 printk("bio: create slab <%s> at %d\n", bslab->name, entry);
111 bslab->slab = slab;
112 bslab->slab_ref = 1;
113 bslab->slab_size = sz;
114out_unlock:
115 mutex_unlock(&bio_slab_lock);
116 return slab;
117}
118
119static void bio_put_slab(struct bio_set *bs)
120{
121 struct bio_slab *bslab = NULL;
122 unsigned int i;
123
124 mutex_lock(&bio_slab_lock);
125
126 for (i = 0; i < bio_slab_nr; i++) {
127 if (bs->bio_slab == bio_slabs[i].slab) {
128 bslab = &bio_slabs[i];
129 break;
130 }
131 }
132
133 if (WARN(!bslab, KERN_ERR "bio: unable to find slab!\n"))
134 goto out;
135
136 WARN_ON(!bslab->slab_ref);
137
138 if (--bslab->slab_ref)
139 goto out;
140
141 kmem_cache_destroy(bslab->slab);
142 bslab->slab = NULL;
143
144out:
145 mutex_unlock(&bio_slab_lock);
146}
147
56unsigned int bvec_nr_vecs(unsigned short idx) 148unsigned int bvec_nr_vecs(unsigned short idx)
57{ 149{
58 return bvec_slabs[idx].nr_vecs; 150 return bvec_slabs[idx].nr_vecs;
59} 151}
60 152
153void bvec_free_bs(struct bio_set *bs, struct bio_vec *bv, unsigned int idx)
154{
155 BIO_BUG_ON(idx >= BIOVEC_NR_POOLS);
156
157 if (idx == BIOVEC_MAX_IDX)
158 mempool_free(bv, bs->bvec_pool);
159 else {
160 struct biovec_slab *bvs = bvec_slabs + idx;
161
162 kmem_cache_free(bvs->slab, bv);
163 }
164}
165
61struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, 166struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx,
62 struct bio_set *bs) 167 struct bio_set *bs)
63{ 168{
@@ -134,24 +239,22 @@ fallback:
134 239
135void bio_free(struct bio *bio, struct bio_set *bs) 240void bio_free(struct bio *bio, struct bio_set *bs)
136{ 241{
137 if (bio->bi_io_vec) { 242