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.
}
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);
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)
{
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
static void end_bio_bh_io_sync(struct bio *bio)
{
- struct buffer_head *bh = bio->bi_private;
-
- if (unlikely(bio_flagged(bio, BIO_QUIET)))
- set_bit(BH_Quiet, &bh->b_state);
+ struct buffer_head *bh;
+ bool uptodate = bio_endio_bh(bio, &bh);
- 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,