Skip to content

Commit

Permalink
block: Add bio_reset()
Browse files Browse the repository at this point in the history
Reusing bios is something that's been highly frowned upon in the past,
but driver code keeps doing it anyways. If it's going to happen anyways,
we should provide a generic method.

This'll help with getting rid of bi_destructor - drivers/block/pktcdvd.c
was open coding it, by doing a bio_init() and resetting bi_destructor.

This required reordering struct bio, but the block layer is not yet
nearly fast enough for any cacheline effects to matter here.

v5: Add a define BIO_RESET_BITS, to be very explicit about what parts of
bio->bi_flags are saved.
v6: Further commenting verbosity, per Tejun
v9: Add a function comment

Signed-off-by: Kent Overstreet <koverstreet@google.com>
CC: Jens Axboe <axboe@kernel.dk>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
  • Loading branch information
Kent Overstreet authored and axboe committed Sep 9, 2012
1 parent 9481874 commit f44b48c
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 6 deletions.
24 changes: 24 additions & 0 deletions fs/bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,30 @@ void bio_init(struct bio *bio)
}
EXPORT_SYMBOL(bio_init);

/**
* bio_reset - reinitialize a bio
* @bio: bio to reset
*
* Description:
* After calling bio_reset(), @bio will be in the same state as a freshly
* allocated bio returned bio bio_alloc_bioset() - the only fields that are
* preserved are the ones that are initialized by bio_alloc_bioset(). See
* comment in struct bio.
*/
void bio_reset(struct bio *bio)
{
unsigned long flags = bio->bi_flags & (~0UL << BIO_RESET_BITS);

if (bio_integrity(bio))
bio_integrity_free(bio);

bio_disassociate_task(bio);

memset(bio, 0, BIO_RESET_BYTES);
bio->bi_flags = flags|(1 << BIO_UPTODATE);
}
EXPORT_SYMBOL(bio_reset);

/**
* bio_alloc_bioset - allocate a bio for I/O
* @gfp_mask: the GFP_ mask given to the slab allocator
Expand Down
1 change: 1 addition & 0 deletions include/linux/bio.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ extern void __bio_clone(struct bio *, struct bio *);
extern struct bio *bio_clone(struct bio *, gfp_t);

extern void bio_init(struct bio *);
extern void bio_reset(struct bio *);

extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int);
extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *,
Expand Down
25 changes: 19 additions & 6 deletions include/linux/blk_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,6 @@ struct bio {
unsigned int bi_seg_front_size;
unsigned int bi_seg_back_size;

unsigned int bi_max_vecs; /* max bvl_vecs we can hold */

atomic_t bi_cnt; /* pin count */

struct bio_vec *bi_io_vec; /* the actual vec list */

bio_end_io_t *bi_end_io;

void *bi_private;
Expand All @@ -80,6 +74,16 @@ struct bio {
struct bio_integrity_payload *bi_integrity; /* data integrity */
#endif

/*
* Everything starting with bi_max_vecs will be preserved by bio_reset()
*/

unsigned int bi_max_vecs; /* max bvl_vecs we can hold */

atomic_t bi_cnt; /* pin count */

struct bio_vec *bi_io_vec; /* the actual vec list */

/* If bi_pool is non NULL, bi_destructor is not called */
struct bio_set *bi_pool;

Expand All @@ -93,6 +97,8 @@ struct bio {
struct bio_vec bi_inline_vecs[0];
};

#define BIO_RESET_BYTES offsetof(struct bio, bi_max_vecs)

/*
* bio flags
*/
Expand All @@ -108,6 +114,13 @@ struct bio {
#define BIO_FS_INTEGRITY 9 /* fs owns integrity data, not block layer */
#define BIO_QUIET 10 /* Make BIO Quiet */
#define BIO_MAPPED_INTEGRITY 11/* integrity metadata has been remapped */

/*
* Flags starting here get preserved by bio_reset() - this includes
* BIO_POOL_IDX()
*/
#define BIO_RESET_BITS 12

#define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag)))

/*
Expand Down

0 comments on commit f44b48c

Please sign in to comment.