diff options
author | Kent Overstreet <koverstreet@google.com> | 2012-10-12 18:29:33 -0400 |
---|---|---|
committer | Kent Overstreet <koverstreet@google.com> | 2013-03-23 17:15:27 -0400 |
commit | 9f060e2231ca96ca94f2ffcff730acd72606b280 (patch) | |
tree | 4818da8b59010493810e04d7a6273707875dc73c /fs/bio.c | |
parent | 6fda981cafbf908acd11e1e636fec50e99d56a47 (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.c | 36 |
1 files changed, 15 insertions, 21 deletions
@@ -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 | ||
163 | void bvec_free_bs(struct bio_set *bs, struct bio_vec *bv, unsigned int idx) | 163 | void 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 | ||
176 | struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, | 176 | struct 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) { |
212 | fallback: | 212 | fallback: |
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 | */ |
1664 | static int biovec_create_pools(struct bio_set *bs, int pool_entries) | 1664 | mempool_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 | |||
1675 | static void biovec_free_pools(struct bio_set *bs) | ||
1676 | { | ||
1677 | mempool_destroy(bs->bvec_pool); | ||
1678 | } | 1669 | } |
1679 | 1670 | ||
1680 | void bioset_free(struct bio_set *bs) | 1671 | void 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); |