mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
buffer: Add bh_end_read(), bh_end_write() and bh_end_async_write()
These are the bio_end_io_t versions of end_buffer_read_sync(), end_buffer_write_sync() and end_buffer_async_write(). They do not contain a put_bh() call as it is no longer necessary. Also add the helper function bio_endio_bh(). Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Link: https://patch.msgid.link/20260528173150.1093780-5-willy@infradead.org Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
parent
df21e33ff9
commit
86ecf5704e
89
fs/buffer.c
89
fs/buffer.c
|
|
@ -129,6 +129,34 @@ static void buffer_io_error(struct buffer_head *bh, char *msg)
|
|||
bh->b_bdev, (unsigned long long)bh->b_blocknr, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* bio_endio_bh - Discard the bio used to submit a buffer.
|
||||
* @bio: The bio.
|
||||
* @bhp: Where to return the buffer_head.
|
||||
*
|
||||
* Call this in your bio_end_io handler to retrieve the buffer_head
|
||||
* submitted in bh_submit(). If you did not call bh_submit(), do not
|
||||
* call this function; it will return garbage.
|
||||
*
|
||||
* This function consumes the bio refcount which will probably free the
|
||||
* bio.
|
||||
*
|
||||
* Return: True if the I/O succeeded.
|
||||
*/
|
||||
bool bio_endio_bh(struct bio *bio, struct buffer_head **bhp)
|
||||
{
|
||||
bool success = bio->bi_status == BLK_STS_OK;
|
||||
struct buffer_head *bh = bio->bi_private;
|
||||
|
||||
if (unlikely(bio_flagged(bio, BIO_QUIET)))
|
||||
set_bit(BH_Quiet, &bh->b_state);
|
||||
bio_put(bio);
|
||||
|
||||
*bhp = bh;
|
||||
return success;
|
||||
}
|
||||
EXPORT_SYMBOL(bio_endio_bh);
|
||||
|
||||
/*
|
||||
* End-of-IO handler helper function which does not touch the bh after
|
||||
* unlocking it.
|
||||
|
|
@ -159,7 +187,22 @@ void end_buffer_read_sync(struct buffer_head *bh, int uptodate)
|
|||
}
|
||||
EXPORT_SYMBOL(end_buffer_read_sync);
|
||||
|
||||
void end_buffer_write_sync(struct buffer_head *bh, int uptodate)
|
||||
/**
|
||||
* bh_end_read - I/O end handler for reads
|
||||
* @bio: The bio being completed.
|
||||
*
|
||||
* Pass this function to bh_submit() if you're reading into the buffer,
|
||||
* unless you need your own special I/O end handler.
|
||||
*/
|
||||
void bh_end_read(struct bio *bio)
|
||||
{
|
||||
struct buffer_head *bh;
|
||||
bool uptodate = bio_endio_bh(bio, &bh);
|
||||
__end_buffer_read_notouch(bh, uptodate);
|
||||
}
|
||||
EXPORT_SYMBOL(bh_end_read);
|
||||
|
||||
static void __end_buffer_write_sync(struct buffer_head *bh, int uptodate)
|
||||
{
|
||||
if (uptodate) {
|
||||
set_buffer_uptodate(bh);
|
||||
|
|
@ -169,10 +212,30 @@ void end_buffer_write_sync(struct buffer_head *bh, int uptodate)
|
|||
clear_buffer_uptodate(bh);
|
||||
}
|
||||
unlock_buffer(bh);
|
||||
}
|
||||
|
||||
void end_buffer_write_sync(struct buffer_head *bh, int uptodate)
|
||||
{
|
||||
__end_buffer_write_sync(bh, uptodate);
|
||||
put_bh(bh);
|
||||
}
|
||||
EXPORT_SYMBOL(end_buffer_write_sync);
|
||||
|
||||
/**
|
||||
* bh_end_write - I/O end handler for writes
|
||||
* @bio: The bio being completed.
|
||||
*
|
||||
* Pass this function to bh_submit() if you're writing from the buffer,
|
||||
* unless you need your own special I/O end handler.
|
||||
*/
|
||||
void bh_end_write(struct bio *bio)
|
||||
{
|
||||
struct buffer_head *bh;
|
||||
bool success = bio_endio_bh(bio, &bh);
|
||||
__end_buffer_write_sync(bh, success);
|
||||
}
|
||||
EXPORT_SYMBOL(bh_end_write);
|
||||
|
||||
static struct buffer_head *
|
||||
__find_get_block_slow(struct block_device *bdev, sector_t block, bool atomic)
|
||||
{
|
||||
|
|
@ -416,6 +479,21 @@ static void end_buffer_async_write(struct buffer_head *bh, int uptodate)
|
|||
spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* bh_end_async_write - I/O end handler for async folio writes
|
||||
* @bio: The bio being completed.
|
||||
*
|
||||
* Pass this function to bh_submit() if you're doing the equivalent of
|
||||
* block_write_full_folio().
|
||||
*/
|
||||
void bh_end_async_write(struct bio *bio)
|
||||
{
|
||||
struct buffer_head *bh;
|
||||
bool success = bio_endio_bh(bio, &bh);
|
||||
end_buffer_async_write(bh, success);
|
||||
}
|
||||
EXPORT_SYMBOL(bh_end_async_write);
|
||||
|
||||
/*
|
||||
* If a page's buffers are under async readin (end_buffer_async_read
|
||||
* completion) then there is a possibility that another thread of
|
||||
|
|
@ -1150,13 +1228,10 @@ EXPORT_SYMBOL(__bforget);
|
|||
|
||||
static void end_bio_bh_io_sync(struct bio *bio)
|
||||
{
|
||||
struct buffer_head *bh = bio->bi_private;
|
||||
struct buffer_head *bh;
|
||||
bool uptodate = bio_endio_bh(bio, &bh);
|
||||
|
||||
if (unlikely(bio_flagged(bio, BIO_QUIET)))
|
||||
set_bit(BH_Quiet, &bh->b_state);
|
||||
|
||||
bh->b_end_io(bh, !bio->bi_status);
|
||||
bio_put(bio);
|
||||
bh->b_end_io(bh, uptodate);
|
||||
}
|
||||
|
||||
static void buffer_set_crypto_ctx(struct bio *bio, const struct buffer_head *bh,
|
||||
|
|
|
|||
|
|
@ -204,6 +204,12 @@ struct buffer_head *create_empty_buffers(struct folio *folio,
|
|||
unsigned long blocksize, unsigned long b_state);
|
||||
void end_buffer_read_sync(struct buffer_head *bh, int uptodate);
|
||||
void end_buffer_write_sync(struct buffer_head *bh, int uptodate);
|
||||
bool bio_endio_bh(struct bio *bio, struct buffer_head **bhp);
|
||||
|
||||
/* Completion routines suitable for passing to bh_submit() */
|
||||
void bh_end_read(struct bio *bio);
|
||||
void bh_end_write(struct bio *bio);
|
||||
void bh_end_async_write(struct bio *bio);
|
||||
|
||||
/* Things to do with metadata buffers list */
|
||||
void mmb_mark_buffer_dirty(struct buffer_head *bh, struct mapping_metadata_bhs *mmb);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user