Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a0d96b0 authored by Jens Axboe's avatar Jens Axboe
Browse files

block: add bio_kmalloc()



Not all callers need (or want!) the mempool backing guarentee, it
essentially means that you can only use bio_alloc() for short allocations
and not for preallocating some bio's at setup or init time.

So add bio_kmalloc() which does the same thing as bio_alloc(), except
it just uses kmalloc() as the backing instead of the bio mempools.

Signed-off-by: default avatarJens Axboe <jens.axboe@oracle.com>
parent 3e6053d7
Loading
Loading
Loading
Loading
+75 −21
Original line number Original line Diff line number Diff line
@@ -59,26 +59,47 @@ struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, struct
{
{
	struct bio_vec *bvl;
	struct bio_vec *bvl;


	/*
	 * If 'bs' is given, lookup the pool and do the mempool alloc.
	 * If not, this is a bio_kmalloc() allocation and just do a
	 * kzalloc() for the exact number of vecs right away.
	 */
	if (bs) {
		/*
		/*
		 * see comment near bvec_array define!
		 * see comment near bvec_array define!
		 */
		 */
		switch (nr) {
		switch (nr) {
		case   1        : *idx = 0; break;
		case 1:
		case   2 ...   4: *idx = 1; break;
			*idx = 0;
		case   5 ...  16: *idx = 2; break;
			break;
		case  17 ...  64: *idx = 3; break;
		case 2 ... 4:
		case  65 ... 128: *idx = 4; break;
			*idx = 1;
		case 129 ... BIO_MAX_PAGES: *idx = 5; break;
			break;
		case 5 ... 16:
			*idx = 2;
			break;
		case 17 ... 64:
			*idx = 3;
			break;
		case 65 ... 128:
			*idx = 4;
			break;
		case 129 ... BIO_MAX_PAGES:
			*idx = 5;
			break;
		default:
		default:
			return NULL;
			return NULL;
		}
		}

		/*
		/*
		 * idx now points to the pool we want to allocate from
		 * idx now points to the pool we want to allocate from
		 */
		 */

		bvl = mempool_alloc(bs->bvec_pools[*idx], gfp_mask);
		bvl = mempool_alloc(bs->bvec_pools[*idx], gfp_mask);
		if (bvl)
		if (bvl)
		memset(bvl, 0, bvec_nr_vecs(*idx) * sizeof(struct bio_vec));
			memset(bvl, 0,
				bvec_nr_vecs(*idx) * sizeof(struct bio_vec));
	} else
		bvl = kzalloc(nr * sizeof(struct bio_vec), gfp_mask);


	return bvl;
	return bvl;
}
}
@@ -107,6 +128,12 @@ static void bio_fs_destructor(struct bio *bio)
	bio_free(bio, fs_bio_set);
	bio_free(bio, fs_bio_set);
}
}


static void bio_kmalloc_destructor(struct bio *bio)
{
	kfree(bio->bi_io_vec);
	kfree(bio);
}

void bio_init(struct bio *bio)
void bio_init(struct bio *bio)
{
{
	memset(bio, 0, sizeof(*bio));
	memset(bio, 0, sizeof(*bio));
@@ -119,19 +146,25 @@ void bio_init(struct bio *bio)
 * bio_alloc_bioset - allocate a bio for I/O
 * bio_alloc_bioset - allocate a bio for I/O
 * @gfp_mask:   the GFP_ mask given to the slab allocator
 * @gfp_mask:   the GFP_ mask given to the slab allocator
 * @nr_iovecs:	number of iovecs to pre-allocate
 * @nr_iovecs:	number of iovecs to pre-allocate
 * @bs:		the bio_set to allocate from
 * @bs:		the bio_set to allocate from. If %NULL, just use kmalloc
 *
 *
 * Description:
 * Description:
 *   bio_alloc_bioset will first try it's on mempool to satisfy the allocation.
 *   bio_alloc_bioset will first try its own mempool to satisfy the allocation.
 *   If %__GFP_WAIT is set then we will block on the internal pool waiting
 *   If %__GFP_WAIT is set then we will block on the internal pool waiting
 *   for a &struct bio to become free.
 *   for a &struct bio to become free. If a %NULL @bs is passed in, we will
 *   fall back to just using @kmalloc to allocate the required memory.
 *
 *
 *   allocate bio and iovecs from the memory pools specified by the
 *   allocate bio and iovecs from the memory pools specified by the
 *   bio_set structure.
 *   bio_set structure, or @kmalloc if none given.
 **/
 **/
struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
{
{
	struct bio *bio = mempool_alloc(bs->bio_pool, gfp_mask);
	struct bio *bio;

	if (bs)
		bio = mempool_alloc(bs->bio_pool, gfp_mask);
	else
		bio = kmalloc(sizeof(*bio), gfp_mask);


	if (likely(bio)) {
	if (likely(bio)) {
		struct bio_vec *bvl = NULL;
		struct bio_vec *bvl = NULL;
@@ -142,7 +175,10 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)


			bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs);
			bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs);
			if (unlikely(!bvl)) {
			if (unlikely(!bvl)) {
				if (bs)
					mempool_free(bio, bs->bio_pool);
					mempool_free(bio, bs->bio_pool);
				else
					kfree(bio);
				bio = NULL;
				bio = NULL;
				goto out;
				goto out;
			}
			}
@@ -165,6 +201,23 @@ struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs)
	return bio;
	return bio;
}
}


/*
 * Like bio_alloc(), but doesn't use a mempool backing. This means that
 * it CAN fail, but while bio_alloc() can only be used for allocations
 * that have a short (finite) life span, bio_kmalloc() should be used
 * for more permanent bio allocations (like allocating some bio's for
 * initalization or setup purposes).
 */
struct bio *bio_kmalloc(gfp_t gfp_mask, int nr_iovecs)
{
	struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, NULL);

	if (bio)
		bio->bi_destructor = bio_kmalloc_destructor;

	return bio;
}

void zero_fill_bio(struct bio *bio)
void zero_fill_bio(struct bio *bio)
{
{
	unsigned long flags;
	unsigned long flags;
@@ -1349,6 +1402,7 @@ static int __init init_bio(void)
subsys_initcall(init_bio);
subsys_initcall(init_bio);


EXPORT_SYMBOL(bio_alloc);
EXPORT_SYMBOL(bio_alloc);
EXPORT_SYMBOL(bio_kmalloc);
EXPORT_SYMBOL(bio_put);
EXPORT_SYMBOL(bio_put);
EXPORT_SYMBOL(bio_free);
EXPORT_SYMBOL(bio_free);
EXPORT_SYMBOL(bio_endio);
EXPORT_SYMBOL(bio_endio);
+1 −0
Original line number Original line Diff line number Diff line
@@ -308,6 +308,7 @@ extern struct bio_set *bioset_create(int, int);
extern void bioset_free(struct bio_set *);
extern void bioset_free(struct bio_set *);


extern struct bio *bio_alloc(gfp_t, int);
extern struct bio *bio_alloc(gfp_t, int);
extern struct bio *bio_kmalloc(gfp_t, int);
extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *);
extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *);
extern void bio_put(struct bio *);
extern void bio_put(struct bio *);
extern void bio_free(struct bio *, struct bio_set *);
extern void bio_free(struct bio *, struct bio_set *);