Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 51 additions & 30 deletions block/bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1481,11 +1481,41 @@ void bio_iov_iter_unbounce(struct bio *bio, bool is_error, bool mark_dirty)
bio_iov_iter_unbounce_read(bio, is_error, mark_dirty);
}

static void submit_bio_wait_endio(struct bio *bio)
static void bio_wait_end_io(struct bio *bio)
{
complete(bio->bi_private);
}

/**
* bio_await - call a function on a bio, and wait until it completes
* @bio: the bio which describes the I/O
* @submit: function called to submit the bio
* @priv: private data passed to @submit
*
* Wait for the bio as well as any bio chained off it after executing the
* passed in callback @submit. The wait for the bio is set up before calling
* @submit to ensure that the completion is captured. If @submit is %NULL,
* submit_bio() is used instead to submit the bio.
*
* Note: this overrides the bi_private and bi_end_io fields in the bio.
*/
void bio_await(struct bio *bio, void *priv,
void (*submit)(struct bio *bio, void *priv))
{
DECLARE_COMPLETION_ONSTACK_MAP(done,
bio->bi_bdev->bd_disk->lockdep_map);

bio->bi_private = &done;
bio->bi_end_io = bio_wait_end_io;
bio->bi_opf |= REQ_SYNC;
if (submit)
submit(bio, priv);
else
submit_bio(bio);
blk_wait_io(&done);
}
EXPORT_SYMBOL_GPL(bio_await);

/**
* submit_bio_wait - submit a bio, and wait until it completes
* @bio: The &struct bio which describes the I/O
Expand All @@ -1499,19 +1529,30 @@ static void submit_bio_wait_endio(struct bio *bio)
*/
int submit_bio_wait(struct bio *bio)
{
DECLARE_COMPLETION_ONSTACK_MAP(done,
bio->bi_bdev->bd_disk->lockdep_map);

bio->bi_private = &done;
bio->bi_end_io = submit_bio_wait_endio;
bio->bi_opf |= REQ_SYNC;
submit_bio(bio);
blk_wait_io(&done);

bio_await(bio, NULL, NULL);
return blk_status_to_errno(bio->bi_status);
}
EXPORT_SYMBOL(submit_bio_wait);

static void bio_endio_cb(struct bio *bio, void *priv)
{
bio_endio(bio);
}

/*
* Submit @bio synchronously, or call bio_endio on it if the current process
* is being killed.
*/
int bio_submit_or_kill(struct bio *bio, unsigned int flags)
{
if ((flags & BLKDEV_ZERO_KILLABLE) && fatal_signal_pending(current)) {
bio_await(bio, NULL, bio_endio_cb);
return -EINTR;
}

return submit_bio_wait(bio);
}

/**
* bdev_rw_virt - synchronously read into / write from kernel mapping
* @bdev: block device to access
Expand Down Expand Up @@ -1542,26 +1583,6 @@ int bdev_rw_virt(struct block_device *bdev, sector_t sector, void *data,
}
EXPORT_SYMBOL_GPL(bdev_rw_virt);

static void bio_wait_end_io(struct bio *bio)
{
complete(bio->bi_private);
bio_put(bio);
}

/*
* bio_await_chain - ends @bio and waits for every chained bio to complete
*/
void bio_await_chain(struct bio *bio)
{
DECLARE_COMPLETION_ONSTACK_MAP(done,
bio->bi_bdev->bd_disk->lockdep_map);

bio->bi_private = &done;
bio->bi_end_io = bio_wait_end_io;
bio_endio(bio);
blk_wait_io(&done);
}

void __bio_advance(struct bio *bio, unsigned bytes)
{
if (bio_integrity(bio))
Expand Down
16 changes: 2 additions & 14 deletions block/blk-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,7 @@ static int blkdev_issue_write_zeroes(struct block_device *bdev, sector_t sector,
__blkdev_issue_write_zeroes(bdev, sector, nr_sects, gfp, &bio,
flags, limit);
if (bio) {
if ((flags & BLKDEV_ZERO_KILLABLE) &&
fatal_signal_pending(current)) {
bio_await_chain(bio);
blk_finish_plug(&plug);
return -EINTR;
}
ret = submit_bio_wait(bio);
ret = bio_submit_or_kill(bio, flags);
bio_put(bio);
}
blk_finish_plug(&plug);
Expand Down Expand Up @@ -236,13 +230,7 @@ static int blkdev_issue_zero_pages(struct block_device *bdev, sector_t sector,
blk_start_plug(&plug);
__blkdev_issue_zero_pages(bdev, sector, nr_sects, gfp, &bio, flags);
if (bio) {
if ((flags & BLKDEV_ZERO_KILLABLE) &&
fatal_signal_pending(current)) {
bio_await_chain(bio);
blk_finish_plug(&plug);
return -EINTR;
}
ret = submit_bio_wait(bio);
ret = bio_submit_or_kill(bio, flags);
bio_put(bio);
}
blk_finish_plug(&plug);
Expand Down
2 changes: 1 addition & 1 deletion block/blk.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ bool __blk_freeze_queue_start(struct request_queue *q,
struct task_struct *owner);
int __bio_queue_enter(struct request_queue *q, struct bio *bio);
void submit_bio_noacct_nocheck(struct bio *bio, bool split);
void bio_await_chain(struct bio *bio);
int bio_submit_or_kill(struct bio *bio, unsigned int flags);

static inline bool blk_try_enter_queue(struct request_queue *q, bool pm)
{
Expand Down
11 changes: 2 additions & 9 deletions block/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,26 +153,19 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
nr_sects = len >> SECTOR_SHIFT;

blk_start_plug(&plug);
while (1) {
if (fatal_signal_pending(current)) {
if (prev)
bio_await_chain(prev);
err = -EINTR;
goto out_unplug;
}
while (!fatal_signal_pending(current)) {
bio = blk_alloc_discard_bio(bdev, &sector, &nr_sects,
GFP_KERNEL);
if (!bio)
break;
prev = bio_chain_and_submit(prev, bio);
}
if (prev) {
err = submit_bio_wait(prev);
err = bio_submit_or_kill(prev, BLKDEV_ZERO_KILLABLE);
if (err == -EOPNOTSUPP)
err = 0;
bio_put(prev);
}
out_unplug:
blk_finish_plug(&plug);
fail:
filemap_invalidate_unlock(bdev->bd_mapping);
Expand Down
38 changes: 15 additions & 23 deletions fs/xfs/xfs_zone_gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,6 @@ xfs_zone_gc_start_chunk(
struct xfs_inode *ip;
struct bio *bio;
xfs_daddr_t daddr;
unsigned int len;
bool is_seq;

if (xfs_is_shutdown(mp))
Expand All @@ -685,15 +684,16 @@ xfs_zone_gc_start_chunk(
return false;
}

len = XFS_FSB_TO_B(mp, irec.rm_blockcount);
bio = bio_alloc_bioset(bdev,
min(howmany(len, XFS_GC_BUF_SIZE) + 1, XFS_GC_NR_BUFS),
REQ_OP_READ, GFP_NOFS, &data->bio_set);

/*
* Scratch allocation can wrap around to the same buffer again,
* provision an extra bvec for that case.
*/
bio = bio_alloc_bioset(bdev, XFS_GC_NR_BUFS + 1, REQ_OP_READ, GFP_NOFS,
&data->bio_set);
chunk = container_of(bio, struct xfs_gc_bio, bio);
chunk->ip = ip;
chunk->offset = XFS_FSB_TO_B(mp, irec.rm_offset);
chunk->len = len;
chunk->len = XFS_FSB_TO_B(mp, irec.rm_blockcount);
chunk->old_startblock =
xfs_rgbno_to_rtb(iter->victim_rtg, irec.rm_startblock);
chunk->new_daddr = daddr;
Expand All @@ -707,8 +707,9 @@ xfs_zone_gc_start_chunk(
bio->bi_iter.bi_sector = xfs_rtb_to_daddr(mp, chunk->old_startblock);
bio->bi_end_io = xfs_zone_gc_end_io;
xfs_zone_gc_add_data(chunk);
data->scratch_head = (data->scratch_head + len) % data->scratch_size;
data->scratch_available -= len;
data->scratch_head =
(data->scratch_head + chunk->len) % data->scratch_size;
data->scratch_available -= chunk->len;

XFS_STATS_INC(mp, xs_gc_read_calls);

Expand Down Expand Up @@ -899,9 +900,10 @@ xfs_zone_gc_finish_reset(

static void
xfs_submit_zone_reset_bio(
struct xfs_rtgroup *rtg,
struct bio *bio)
struct bio *bio,
void *priv)
{
struct xfs_rtgroup *rtg = priv;
struct xfs_mount *mp = rtg_mount(rtg);

trace_xfs_zone_reset(rtg);
Expand Down Expand Up @@ -933,26 +935,16 @@ xfs_submit_zone_reset_bio(
submit_bio(bio);
}

static void xfs_bio_wait_endio(struct bio *bio)
{
complete(bio->bi_private);
}

int
xfs_zone_gc_reset_sync(
struct xfs_rtgroup *rtg)
{
DECLARE_COMPLETION_ONSTACK(done);
struct bio bio;
int error;

bio_init(&bio, rtg_mount(rtg)->m_rtdev_targp->bt_bdev, NULL, 0,
REQ_OP_ZONE_RESET | REQ_SYNC);
bio.bi_private = &done;
bio.bi_end_io = xfs_bio_wait_endio;
xfs_submit_zone_reset_bio(rtg, &bio);
wait_for_completion_io(&done);

bio_await(&bio, rtg, xfs_submit_zone_reset_bio);
error = blk_status_to_errno(bio.bi_status);
bio_uninit(&bio);
return error;
Expand Down Expand Up @@ -989,7 +981,7 @@ xfs_zone_gc_reset_zones(
chunk->data = data;
WRITE_ONCE(chunk->state, XFS_GC_BIO_NEW);
list_add_tail(&chunk->entry, &data->resetting);
xfs_submit_zone_reset_bio(rtg, bio);
xfs_submit_zone_reset_bio(bio, rtg);
} while (next);
}

Expand Down
2 changes: 2 additions & 0 deletions include/linux/bio.h
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,8 @@ extern void bio_uninit(struct bio *);
void bio_reset(struct bio *bio, struct block_device *bdev, blk_opf_t opf);
void bio_reuse(struct bio *bio, blk_opf_t opf);
void bio_chain(struct bio *, struct bio *);
void bio_await(struct bio *bio, void *priv,
void (*submit)(struct bio *bio, void *priv));

int __must_check bio_add_page(struct bio *bio, struct page *page, unsigned len,
unsigned off);
Expand Down
Loading