[PATCH] fix

From: Minchan Kim
Date: Tue Mar 07 2017 - 23:35:29 EST


Not-yet-Signed-off-by: Minchan Kim <minchan@xxxxxxxxxx>
---
drivers/block/zram/zram_drv.c | 40 ++++++++++++++--------------------------
1 file changed, 14 insertions(+), 26 deletions(-)

diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index bcb03bacdded..516c3bd97a28 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -147,8 +147,7 @@ static inline bool valid_io_request(struct zram *zram,

static void update_position(u32 *index, int *offset, struct bio_vec *bvec)
{
- if (*offset + bvec->bv_len >= PAGE_SIZE)
- (*index)++;
+ *index += (*offset + bvec->bv_len) / PAGE_SIZE;
*offset = (*offset + bvec->bv_len) % PAGE_SIZE;
}

@@ -886,7 +885,7 @@ static void __zram_make_request(struct zram *zram, struct bio *bio)
{
int offset;
u32 index;
- struct bio_vec bvec;
+ struct bio_vec bvec, bv;
struct bvec_iter iter;

index = bio->bi_iter.bi_sector >> SECTORS_PER_PAGE_SHIFT;
@@ -900,34 +899,23 @@ static void __zram_make_request(struct zram *zram, struct bio *bio)
}

bio_for_each_segment(bvec, bio, iter) {
- int max_transfer_size = PAGE_SIZE - offset;
+ int remained_size = bvec.bv_len;
+ int transfer_size;

- if (bvec.bv_len > max_transfer_size) {
- /*
- * zram_bvec_rw() can only make operation on a single
- * zram page. Split the bio vector.
- */
- struct bio_vec bv;
-
- bv.bv_page = bvec.bv_page;
- bv.bv_len = max_transfer_size;
- bv.bv_offset = bvec.bv_offset;
+ bv.bv_page = bvec.bv_page;
+ bv.bv_offset = bvec.bv_offset;
+ do {
+ transfer_size = min_t(int, PAGE_SIZE, remained_size);
+ bv.bv_len = transfer_size;

if (zram_bvec_rw(zram, &bv, index, offset,
- op_is_write(bio_op(bio))) < 0)
- goto out;
-
- bv.bv_len = bvec.bv_len - max_transfer_size;
- bv.bv_offset += max_transfer_size;
- if (zram_bvec_rw(zram, &bv, index + 1, 0,
- op_is_write(bio_op(bio))) < 0)
- goto out;
- } else
- if (zram_bvec_rw(zram, &bvec, index, offset,
- op_is_write(bio_op(bio))) < 0)
+ op_is_write(bio_op(bio))) < 0)
goto out;

- update_position(&index, &offset, &bvec);
+ bv.bv_offset += transfer_size;
+ update_position(&index, &offset, &bv);
+ remained_size -= transfer_size;
+ } while (remained_size);
}

bio_endio(bio);
--
2.7.4


>
> >
> > Anyway, to me, it's really subtle at this moment so I doubt it should
> > be stable material. :(
>
> I'm not quite sure, it's at least 4.11 material. See above.

Absolutely agree that it should be 4.11 material but I don't want to
backport it to the stable because it would make regression due to
split bio works.

Anyway, if my patch I attached works for you, I will resend this
with modified descriptions includes more detail.

Thanks for the help!!