diff --git a/block/bio.c b/block/bio.c index 3d757055305f98e7bb2a381b847cf4000ff5b094..f4ead66b0b6fb16eff93746b93fc4ad9c6f6b8c4 100644 --- a/block/bio.c +++ b/block/bio.c @@ -700,7 +700,7 @@ int bio_add_pc_page(struct request_queue *q, struct bio *bio, struct page return 0; } - if (bio_full(bio)) + if (bio_full(bio, len)) return 0; /* @@ -795,7 +795,7 @@ void __bio_add_page(struct bio *bio, struct page *page, struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt]; WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED)); - WARN_ON_ONCE(bio_full(bio)); + WARN_ON_ONCE(bio_full(bio, len)); bv->bv_page = page; bv->bv_offset = off; @@ -820,7 +820,7 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len, unsigned int offset) { if (!__bio_try_merge_page(bio, page, len, offset)) { - if (bio_full(bio)) + if (bio_full(bio, len)) return 0; __bio_add_page(bio, page, len, offset); } @@ -898,7 +898,7 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter) if (unlikely(ret)) return bio->bi_vcnt > orig_vcnt ? 0 : ret; - } while (iov_iter_count(iter) && !bio_full(bio)); + } while (iov_iter_count(iter) && !bio_full(bio, 0)); return 0; } diff --git a/fs/iomap.c b/fs/iomap.c index 9decd10facc668df08e5fb8be6e88e88d5717d55..6819e9858ea513756c16b25b3abb71371af0c655 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -338,7 +338,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data, if (iop) atomic_inc(&iop->read_count); - if (!ctx->bio || !is_contig || bio_full(ctx->bio)) { + if (!ctx->bio || !is_contig || bio_full(ctx->bio, plen)) { gfp_t gfp = mapping_gfp_constraint(page->mapping, GFP_KERNEL); int nr_vecs = (length + PAGE_SIZE - 1) >> PAGE_SHIFT; diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index b697866946d26e49fe6cbbd0753f24d8c3b46964..3ca43a1f3916e00fdb4a3bab76867ea826ad8385 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -620,7 +620,7 @@ xfs_add_to_ioend( if (!__bio_try_merge_page(wpc->ioend->io_bio, page, len, poff)) { if (iop) atomic_inc(&iop->write_count); - if (bio_full(wpc->ioend->io_bio)) + if (bio_full(wpc->ioend->io_bio, len)) xfs_chain_bio(wpc->ioend, wbc, bdev, sector); __bio_add_page(wpc->ioend->io_bio, page, len, poff); } diff --git a/include/linux/bio.h b/include/linux/bio.h index c7433a20117154359c58f6716c938f5f00680441..8a6f4c73b25c0135b1917af58052210323221ccd 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -127,9 +127,23 @@ static inline void *bio_data(struct bio *bio) return NULL; } -static inline bool bio_full(struct bio *bio) +/** + * bio_full - check if the bio is full + * @bio: bio to check + * @len: length of one segment to be added + * + * Return true if @bio is full and one segment with @len bytes can't be + * added to the bio, otherwise return false + */ +static inline bool bio_full(struct bio *bio, unsigned len) { - return bio->bi_vcnt >= bio->bi_max_vecs; + if (bio->bi_vcnt >= bio->bi_max_vecs) + return true; + + if (bio->bi_iter.bi_size > UINT_MAX - len) + return true; + + return false; } /*