Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'block-5.5-20200103' of git://git.kernel.dk/linux-block

Pull block fixes from Jens Axboe:
"Three fixes in here:

- Fix for a missing split on default memory boundary mask (4G) (Ming)

- Fix for multi-page read bio truncate (Ming)

- Fix for null_blk zone close request handling (Damien)"

* tag 'block-5.5-20200103' of git://git.kernel.dk/linux-block:
null_blk: Fix REQ_OP_ZONE_CLOSE handling
block: fix splitting segments on boundary masks
block: add bio_truncate to fix guard_bio_eod

+54 -34
+39
block/bio.c
··· 538 538 } 539 539 EXPORT_SYMBOL(zero_fill_bio_iter); 540 540 541 + void bio_truncate(struct bio *bio, unsigned new_size) 542 + { 543 + struct bio_vec bv; 544 + struct bvec_iter iter; 545 + unsigned int done = 0; 546 + bool truncated = false; 547 + 548 + if (new_size >= bio->bi_iter.bi_size) 549 + return; 550 + 551 + if (bio_data_dir(bio) != READ) 552 + goto exit; 553 + 554 + bio_for_each_segment(bv, bio, iter) { 555 + if (done + bv.bv_len > new_size) { 556 + unsigned offset; 557 + 558 + if (!truncated) 559 + offset = new_size - done; 560 + else 561 + offset = 0; 562 + zero_user(bv.bv_page, offset, bv.bv_len - offset); 563 + truncated = true; 564 + } 565 + done += bv.bv_len; 566 + } 567 + 568 + exit: 569 + /* 570 + * Don't touch bvec table here and make it really immutable, since 571 + * fs bio user has to retrieve all pages via bio_for_each_segment_all 572 + * in its .end_bio() callback. 573 + * 574 + * It is enough to truncate bio by updating .bi_size since we can make 575 + * correct bvec with the updated .bi_size for drivers. 576 + */ 577 + bio->bi_iter.bi_size = new_size; 578 + } 579 + 541 580 /** 542 581 * bio_put - release a reference to a bio 543 582 * @bio: bio to release reference to
+9 -9
block/blk-merge.c
··· 157 157 return sectors & (lbs - 1); 158 158 } 159 159 160 - static unsigned get_max_segment_size(const struct request_queue *q, 161 - unsigned offset) 160 + static inline unsigned get_max_segment_size(const struct request_queue *q, 161 + struct page *start_page, 162 + unsigned long offset) 162 163 { 163 164 unsigned long mask = queue_segment_boundary(q); 164 165 165 - /* default segment boundary mask means no boundary limit */ 166 - if (mask == BLK_SEG_BOUNDARY_MASK) 167 - return queue_max_segment_size(q); 168 - 169 - return min_t(unsigned long, mask - (mask & offset) + 1, 166 + offset = mask & (page_to_phys(start_page) + offset); 167 + return min_t(unsigned long, mask - offset + 1, 170 168 queue_max_segment_size(q)); 171 169 } 172 170 ··· 199 201 unsigned seg_size = 0; 200 202 201 203 while (len && *nsegs < max_segs) { 202 - seg_size = get_max_segment_size(q, bv->bv_offset + total_len); 204 + seg_size = get_max_segment_size(q, bv->bv_page, 205 + bv->bv_offset + total_len); 203 206 seg_size = min(seg_size, len); 204 207 205 208 (*nsegs)++; ··· 418 419 419 420 while (nbytes > 0) { 420 421 unsigned offset = bvec->bv_offset + total; 421 - unsigned len = min(get_max_segment_size(q, offset), nbytes); 422 + unsigned len = min(get_max_segment_size(q, bvec->bv_page, 423 + offset), nbytes); 422 424 struct page *page = bvec->bv_page; 423 425 424 426 /*
+4 -1
drivers/block/null_blk_zoned.c
··· 186 186 if (zone->cond == BLK_ZONE_COND_FULL) 187 187 return BLK_STS_IOERR; 188 188 189 - zone->cond = BLK_ZONE_COND_CLOSED; 189 + if (zone->wp == zone->start) 190 + zone->cond = BLK_ZONE_COND_EMPTY; 191 + else 192 + zone->cond = BLK_ZONE_COND_CLOSED; 190 193 break; 191 194 case REQ_OP_ZONE_FINISH: 192 195 if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
+1 -24
fs/buffer.c
··· 3034 3034 void guard_bio_eod(int op, struct bio *bio) 3035 3035 { 3036 3036 sector_t maxsector; 3037 - struct bio_vec *bvec = bio_last_bvec_all(bio); 3038 - unsigned truncated_bytes; 3039 3037 struct hd_struct *part; 3040 3038 3041 3039 rcu_read_lock(); ··· 3059 3061 if (likely((bio->bi_iter.bi_size >> 9) <= maxsector)) 3060 3062 return; 3061 3063 3062 - /* Uhhuh. We've got a bio that straddles the device size! */ 3063 - truncated_bytes = bio->bi_iter.bi_size - (maxsector << 9); 3064 - 3065 - /* 3066 - * The bio contains more than one segment which spans EOD, just return 3067 - * and let IO layer turn it into an EIO 3068 - */ 3069 - if (truncated_bytes > bvec->bv_len) 3070 - return; 3071 - 3072 - /* Truncate the bio.. */ 3073 - bio->bi_iter.bi_size -= truncated_bytes; 3074 - bvec->bv_len -= truncated_bytes; 3075 - 3076 - /* ..and clear the end of the buffer for reads */ 3077 - if (op == REQ_OP_READ) { 3078 - struct bio_vec bv; 3079 - 3080 - mp_bvec_last_segment(bvec, &bv); 3081 - zero_user(bv.bv_page, bv.bv_offset + bv.bv_len, 3082 - truncated_bytes); 3083 - } 3064 + bio_truncate(bio, maxsector << 9); 3084 3065 } 3085 3066 3086 3067 static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
+1
include/linux/bio.h
··· 470 470 gfp_t); 471 471 extern int bio_uncopy_user(struct bio *); 472 472 void zero_fill_bio_iter(struct bio *bio, struct bvec_iter iter); 473 + void bio_truncate(struct bio *bio, unsigned new_size); 473 474 474 475 static inline void zero_fill_bio(struct bio *bio) 475 476 {