Skip to content

Commit 7de55b7

Browse files
morbidrsaaxboe
authored andcommitted
block: support zone append bvecs
Christoph reported that we'll likely trigger the WARN_ON_ONCE() checking that we're not submitting a bvec with REQ_OP_ZONE_APPEND in bio_iov_iter_get_pages() some time ago using zoned btrfs, but I couldn't reproduce it back then. Now Naohiro was able to trigger the bug as well with xfstests generic/095 on a zoned btrfs. There is nothing that prevents bvec submissions via REQ_OP_ZONE_APPEND if the hardware's zone append limit is met. Reported-by: Naohiro Aota <[email protected]> Reported-by: Christoph Hellwig <[email protected]> Signed-off-by: Johannes Thumshirn <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Link: https://lore.kernel.org/r/10bd414d9326c90cd69029077db63b363854eee5.1616600835.git.johannes.thumshirn@wdc.com Signed-off-by: Jens Axboe <[email protected]>
1 parent a958937 commit 7de55b7

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

block/bio.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,7 @@ void bio_release_pages(struct bio *bio, bool mark_dirty)
949949
}
950950
EXPORT_SYMBOL_GPL(bio_release_pages);
951951

952-
static int bio_iov_bvec_set(struct bio *bio, struct iov_iter *iter)
952+
static void __bio_iov_bvec_set(struct bio *bio, struct iov_iter *iter)
953953
{
954954
WARN_ON_ONCE(bio->bi_max_vecs);
955955

@@ -959,11 +959,26 @@ static int bio_iov_bvec_set(struct bio *bio, struct iov_iter *iter)
959959
bio->bi_iter.bi_size = iter->count;
960960
bio_set_flag(bio, BIO_NO_PAGE_REF);
961961
bio_set_flag(bio, BIO_CLONED);
962+
}
962963

964+
static int bio_iov_bvec_set(struct bio *bio, struct iov_iter *iter)
965+
{
966+
__bio_iov_bvec_set(bio, iter);
963967
iov_iter_advance(iter, iter->count);
964968
return 0;
965969
}
966970

971+
static int bio_iov_bvec_set_append(struct bio *bio, struct iov_iter *iter)
972+
{
973+
struct request_queue *q = bio->bi_bdev->bd_disk->queue;
974+
struct iov_iter i = *iter;
975+
976+
iov_iter_truncate(&i, queue_max_zone_append_sectors(q) << 9);
977+
__bio_iov_bvec_set(bio, &i);
978+
iov_iter_advance(iter, i.count);
979+
return 0;
980+
}
981+
967982
#define PAGE_PTRS_PER_BVEC (sizeof(struct bio_vec) / sizeof(struct page *))
968983

969984
/**
@@ -1094,8 +1109,8 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
10941109
int ret = 0;
10951110

10961111
if (iov_iter_is_bvec(iter)) {
1097-
if (WARN_ON_ONCE(bio_op(bio) == REQ_OP_ZONE_APPEND))
1098-
return -EINVAL;
1112+
if (bio_op(bio) == REQ_OP_ZONE_APPEND)
1113+
return bio_iov_bvec_set_append(bio, iter);
10991114
return bio_iov_bvec_set(bio, iter);
11001115
}
11011116

0 commit comments

Comments
 (0)