aboutsummaryrefslogtreecommitdiffstats
path: root/fs/bio.c
diff options
context:
space:
mode:
authorKent Overstreet <koverstreet@google.com>2012-10-12 18:29:33 -0400
committerKent Overstreet <koverstreet@google.com>2013-03-23 17:15:27 -0400
commit9f060e2231ca96ca94f2ffcff730acd72606b280 (patch)
tree4818da8b59010493810e04d7a6273707875dc73c /fs/bio.c
parent6fda981cafbf908acd11e1e636fec50e99d56a47 (diff)
block: Convert integrity to bvec_alloc_bs()
This adds a pointer to the bvec array to struct bio_integrity_payload, instead of the bvecs always being inline; then the bvecs are allocated with bvec_alloc_bs(). Changed bvec_alloc_bs() and bvec_free_bs() to take a pointer to a mempool instead of the bioset, so that bio integrity can use a different mempool for its bvecs, and thus avoid a potential deadlock. This is eventually for immutable bio vecs - immutable bvecs aren't useful if we still have to copy them, hence the need for the pointer. Less code is always nice too, though. Also, bio_integrity_alloc() was using fs_bio_set if no bio_set was specified. This was wrong - using the bio_set doesn't protect us from memory allocation failures, because we just used kmalloc for the bio_integrity_payload. But it does introduce the possibility of deadlock, if for some reason we weren't supposed to be using fs_bio_set. Signed-off-by: Kent Overstreet <koverstreet@google.com> CC: Jens Axboe <axboe@kernel.dk> CC: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'fs/bio.c')
-rw-r--r--fs/bio.c36
1 files changed, 15 insertions, 21 deletions
diff --git a/fs/bio.c b/fs/bio.c
index 73b544709945..40aa96eae99f 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -160,12 +160,12 @@ unsigned int bvec_nr_vecs(unsigned short idx)
160 return bvec_slabs[idx].nr_vecs; 160 return bvec_slabs[idx].nr_vecs;
161} 161}
162 162
163void bvec_free_bs(struct bio_set *bs, struct bio_vec *bv, unsigned int idx) 163void bvec_free(mempool_t *pool, struct bio_vec *bv, unsigned int idx)
164{ 164{
165 BIO_BUG_ON(idx >= BIOVEC_NR_POOLS); 165 BIO_BUG_ON(idx >= BIOVEC_NR_POOLS);
166 166
167 if (idx == BIOVEC_MAX_IDX) 167 if (idx == BIOVEC_MAX_IDX)
168 mempool_free(bv, bs->bvec_pool); 168 mempool_free(bv, pool);
169 else { 169 else {
170 struct biovec_slab *bvs = bvec_slabs + idx; 170 struct biovec_slab *bvs = bvec_slabs + idx;
171 171
@@ -173,8 +173,8 @@ void bvec_free_bs(struct bio_set *bs, struct bio_vec *bv, unsigned int idx)
173 } 173 }
174} 174}
175 175
176struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, 176struct bio_vec *bvec_alloc(gfp_t gfp_mask, int nr, unsigned long *idx,
177 struct bio_set *bs) 177 mempool_t *pool)
178{ 178{
179 struct bio_vec *bvl; 179 struct bio_vec *bvl;
180 180
@@ -210,7 +210,7 @@ struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx,
210 */ 210 */
211 if (*idx == BIOVEC_MAX_IDX) { 211 if (*idx == BIOVEC_MAX_IDX) {
212fallback: 212fallback:
213 bvl = mempool_alloc(bs->bvec_pool, gfp_mask); 213 bvl = mempool_alloc(pool, gfp_mask);
214 } else { 214 } else {
215 struct biovec_slab *bvs = bvec_slabs + *idx; 215 struct biovec_slab *bvs = bvec_slabs + *idx;
216 gfp_t __gfp_mask = gfp_mask & ~(__GFP_WAIT | __GFP_IO); 216 gfp_t __gfp_mask = gfp_mask & ~(__GFP_WAIT | __GFP_IO);
@@ -253,7 +253,7 @@ static void bio_free(struct bio *bio)
253 253
254 if (bs) { 254 if (bs) {
255 if (bio_has_allocated_vec(bio)) 255 if (bio_has_allocated_vec(bio))
256 bvec_free_bs(bs, bio->bi_io_vec, BIO_POOL_IDX(bio)); 256 bvec_free(bs->bvec_pool, bio->bi_io_vec, BIO_POOL_IDX(bio));
257 257
258 /* 258 /*
259 * If we have front padding, adjust the bio pointer before freeing 259 * If we have front padding, adjust the bio pointer before freeing
@@ -442,11 +442,11 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
442 bio_init(bio); 442 bio_init(bio);
443 443
444 if (nr_iovecs > inline_vecs) { 444 if (nr_iovecs > inline_vecs) {
445 bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs); 445 bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx, bs->bvec_pool);
446 if (!bvl && gfp_mask != saved_gfp) { 446 if (!bvl && gfp_mask != saved_gfp) {
447 punt_bios_to_rescuer(bs); 447 punt_bios_to_rescuer(bs);
448 gfp_mask = saved_gfp; 448 gfp_mask = saved_gfp;
449 bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs); 449 bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx, bs->bvec_pool);
450 } 450 }
451 451
452 if (unlikely(!bvl)) 452 if (unlikely(!bvl))
@@ -1661,20 +1661,11 @@ EXPORT_SYMBOL(bio_sector_offset);
1661 * create memory pools for biovec's in a bio_set. 1661 * create memory pools for biovec's in a bio_set.
1662 * use the global biovec slabs created for general use. 1662 * use the global biovec slabs created for general use.
1663 */ 1663 */
1664static int biovec_create_pools(struct bio_set *bs, int pool_entries) 1664mempool_t *biovec_create_pool(struct bio_set *bs, int pool_entries)
1665{ 1665{
1666 struct biovec_slab *bp = bvec_slabs + BIOVEC_MAX_IDX; 1666 struct biovec_slab *bp = bvec_slabs + BIOVEC_MAX_IDX;
1667 1667
1668 bs->bvec_pool = mempool_create_slab_pool(pool_entries, bp->slab); 1668 return mempool_create_slab_pool(pool_entries, bp->slab);
1669 if (!bs->bvec_pool)
1670 return -ENOMEM;
1671
1672 return 0;
1673}
1674
1675static void biovec_free_pools(struct bio_set *bs)
1676{
1677 mempool_destroy(bs->bvec_pool);
1678} 1669}
1679 1670
1680void bioset_free(struct bio_set *bs) 1671void bioset_free(struct bio_set *bs)
@@ -1685,8 +1676,10 @@ void bioset_free(struct bio_set *bs)
1685 if (bs->bio_pool) 1676 if (bs->bio_pool)
1686 mempool_destroy(bs->bio_pool); 1677 mempool_destroy(bs->bio_pool);
1687 1678
1679 if (bs->bvec_pool)
1680 mempool_destroy(bs->bvec_pool);
1681
1688 bioset_integrity_free(bs); 1682 bioset_integrity_free(bs);
1689 biovec_free_pools(bs);
1690 bio_put_slab(bs); 1683 bio_put_slab(bs);
1691 1684
1692 kfree(bs); 1685 kfree(bs);
@@ -1731,7 +1724,8 @@ struct bio_set *bioset_create(unsigned int pool_size, unsigned int front_pad)
1731 if (!bs->bio_pool) 1724 if (!bs->bio_pool)
1732 goto bad; 1725 goto bad;
1733 1726
1734 if (biovec_create_pools(bs, pool_size)) 1727 bs->bvec_pool = biovec_create_pool(bs, pool_size);
1728 if (!bs->bvec_pool)
1735 goto bad; 1729 goto bad;
1736 1730
1737 bs->rescue_workqueue = alloc_workqueue("bioset", WQ_MEM_RECLAIM, 0); 1731 bs->rescue_workqueue = alloc_workqueue("bioset", WQ_MEM_RECLAIM, 0);