public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Tejun Heo <tj@kernel.org>
To: axboe@kernel.dk, bharrosh@panasas.com, linux-kernel@vger.kernel.org
Cc: Tejun Heo <tj@kernel.org>
Subject: [PATCH 5/8] bio: fix bio_kmalloc()
Date: Wed,  1 Apr 2009 20:04:41 +0900	[thread overview]
Message-ID: <1238583884-13517-6-git-send-email-tj@kernel.org> (raw)
In-Reply-To: <1238583884-13517-1-git-send-email-tj@kernel.org>

Impact: fix bio_kmalloc() and its destruction path

bio_kmalloc() was broken in two ways.

* bvec_alloc_bs() first allocates bvec using kmalloc() and then
  ignores it and allocates again like non-kmalloc bvecs.

* bio_kmalloc_destructor() didn't check for and free bio integrity
  data.

This patch fixes the above problems.  kmalloc bvec allocation is moved
to bio_alloc_bioset().  While at it, also make the following changes.

* define and use BIO_POOL_NONE so that pool index check in
  bvec_free_bs() triggers if inline or kmalloc allocated bvec gets
  there.

* relocate destructors on top of each allocation function so that how
  they're used is more clear.

Signed-off-by: Tejun Heo <tj@kernel.org>
---
 fs/bio.c            |   74 +++++++++++++++++++++++++++++----------------------
 include/linux/bio.h |    1 +
 2 files changed, 43 insertions(+), 32 deletions(-)

diff --git a/fs/bio.c b/fs/bio.c
index 7574839..e15e457 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -169,14 +169,6 @@ struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx,
 	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)
-		bvl = kmalloc(nr * sizeof(struct bio_vec), gfp_mask);
-
-	/*
 	 * see comment near bvec_array define!
 	 */
 	switch (nr) {
@@ -254,21 +246,6 @@ void bio_free(struct bio *bio, struct bio_set *bs)
 	mempool_free(p, bs->bio_pool);
 }
 
-/*
- * default destructor for a bio allocated with bio_alloc_bioset()
- */
-static void bio_fs_destructor(struct bio *bio)
-{
-	bio_free(bio, fs_bio_set);
-}
-
-static void bio_kmalloc_destructor(struct bio *bio)
-{
-	if (bio_has_allocated_vec(bio))
-		kfree(bio->bi_io_vec);
-	kfree(bio);
-}
-
 void bio_init(struct bio *bio)
 {
 	memset(bio, 0, sizeof(*bio));
@@ -297,7 +274,7 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
 {
 	struct bio_vec *bvl = NULL;
 	struct bio *bio = NULL;
-	unsigned long idx = 0;
+	unsigned long idx = BIO_POOL_NONE;
 	void *p = NULL;
 
 	if (bs) {
@@ -319,12 +296,15 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
 	if (nr_iovecs <= BIO_INLINE_VECS) {
 		bvl = bio->bi_inline_vecs;
 		nr_iovecs = BIO_INLINE_VECS;
-	} else {
+	} else if (bs) {
 		bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs);
 		if (unlikely(!bvl))
 			goto err_free;
-
 		nr_iovecs = bvec_nr_vecs(idx);
+	} else {
+		bvl = kmalloc(nr_iovecs * sizeof(struct bio_vec), gfp_mask);
+		if (unlikely(!bvl))
+			goto err_free;
 	}
 	bio->bi_flags |= idx << BIO_POOL_OFFSET;
 	bio->bi_max_vecs = nr_iovecs;
@@ -342,6 +322,22 @@ err:
 	return NULL;
 }
 
+static void bio_fs_destructor(struct bio *bio)
+{
+	bio_free(bio, fs_bio_set);
+}
+
+/**
+ *	bio_alloc - allocate a new bio, memory pool backed
+ *	@gfp_mask: allocation mask to use
+ *	@nr_iovecs: number of iovecs
+ *
+ *	Allocate a new bio with @nr_iovecs bvecs.  If @gfp_mask
+ *	contains __GFP_WAIT, the allocation is guaranteed to succeed.
+ *
+ *	RETURNS:
+ *	Pointer to new bio on success, NULL on failure.
+ */
 struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs)
 {
 	struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
@@ -352,12 +348,26 @@ struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs)
 	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).
+static void bio_kmalloc_destructor(struct bio *bio)
+{
+	if (bio_has_allocated_vec(bio))
+		kfree(bio->bi_io_vec);
+	if (bio_integrity(bio))
+		bio_integrity_free(bio);
+	kfree(bio);
+}
+
+/**
+ *	bio_kmalloc - allocate a new bio
+ *	@gfp_mask: allocation mask to use
+ *	@nr_iovecs: number of iovecs
+ *
+ *	Similar to bio_alloc() but uses regular kmalloc for allocation
+ *	and can fail unless __GFP_NOFAIL is set in @gfp_mask.  This is
+ *	useful for more permanant or over-sized bio allocations.
+ *
+ *	RETURNS:
+ *	Poitner to new bio on success, NULL on failure.
  */
 struct bio *bio_kmalloc(gfp_t gfp_mask, int nr_iovecs)
 {
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 14e5f42..e01e41d 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -133,6 +133,7 @@ struct bio {
  * top 4 bits of bio flags indicate the pool this bio came from
  */
 #define BIO_POOL_BITS		(4)
+#define BIO_POOL_NONE		((1 << BIO_POOL_BITS) - 1)
 #define BIO_POOL_OFFSET		(BITS_PER_LONG - BIO_POOL_BITS)
 #define BIO_POOL_MASK		(1UL << BIO_POOL_OFFSET)
 #define BIO_POOL_IDX(bio)	((bio)->bi_flags >> BIO_POOL_OFFSET)	
-- 
1.6.0.2


  parent reply	other threads:[~2009-04-01 11:07 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-04-01 11:04 [GIT PATCHSET block#for-linus] block: blk-map related fixes Tejun Heo
2009-04-01 11:04 ` [PATCH 1/8] scatterlist: make sure sg_miter_next() doesn't return 0 sized mappings Tejun Heo
2009-04-01 11:04 ` [PATCH 2/8] block: fix SG_IO vector request data length handling Tejun Heo
2009-04-01 11:47   ` FUJITA Tomonori
2009-04-01 11:50     ` Jens Axboe
2009-04-01 12:18       ` FUJITA Tomonori
2009-04-01 12:24         ` Jens Axboe
2009-04-01 12:27         ` Tejun Heo
2009-04-01 12:29           ` Jens Axboe
2009-04-01 11:04 ` [PATCH 3/8] block: fix queue bounce limit setting Tejun Heo
2009-04-01 11:04 ` [PATCH 4/8] bio: actually inline inline bvecs into bio Tejun Heo
2009-04-01 12:47   ` Jens Axboe
2009-04-01 12:55     ` Tejun Heo
2009-04-01 12:59       ` Jens Axboe
2009-04-01 11:04 ` Tejun Heo [this message]
2009-04-01 11:04 ` [PATCH 6/8] bio: remove size/segments limit on bio_{copy|map}_{user|kern}*() Tejun Heo
2009-04-01 11:04 ` [PATCH 7/8] blk-map: let blk_rq_map_user_iov() support null mapping Tejun Heo
2009-04-01 11:54   ` FUJITA Tomonori
2009-04-01 12:03     ` Tejun Heo
2009-04-01 11:04 ` [PATCH 8/8] blk-map: reimplement blk_rq_map_user() using blk_rq_map_user_iov() Tejun Heo
2009-04-01 12:44   ` FUJITA Tomonori
2009-04-01 12:50     ` Tejun Heo
2009-04-01 12:59       ` FUJITA Tomonori
2009-04-01 13:03         ` Tejun Heo
2009-04-01 13:10           ` FUJITA Tomonori
2009-04-01 13:17             ` Tejun Heo
2009-04-01 13:18               ` Tejun Heo
2009-04-01 13:22               ` FUJITA Tomonori
2009-04-01 13:28                 ` Tejun Heo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1238583884-13517-6-git-send-email-tj@kernel.org \
    --to=tj@kernel.org \
    --cc=axboe@kernel.dk \
    --cc=bharrosh@panasas.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox