diff options
author | Manuel Bentele | 2019-08-07 17:39:05 +0200 |
---|---|---|
committer | Manuel Bentele | 2019-08-21 22:03:49 +0200 |
commit | 4a3ae0eee2cdef31c9548784adc439337d39e421 (patch) | |
tree | 928ead4faff8f19fd88ab63637bb6d44154cfe30 | |
parent | block: loop: add debugfs support for loop devices (diff) | |
download | kernel-qcow2-linux-4a3ae0eee2cdef31c9548784adc439337d39e421.tar.gz kernel-qcow2-linux-4a3ae0eee2cdef31c9548784adc439337d39e421.tar.xz kernel-qcow2-linux-4a3ae0eee2cdef31c9548784adc439337d39e421.zip |
block: loop: file_fmt_qcow: increment read position for each bvec
The read position for a bvec was not incremented after the first reading of
a bvec of a bio in a request. The reading only succeeds if the request consists
only of one bio with corresponding bvec.
This patch fixes this problem by incrementing the read position for each bvec
after reading.
Signed-off-by: Manuel Bentele <development@manuel-bentele.de>
-rw-r--r-- | drivers/block/loop/loop_file_fmt_qcow_main.c | 24 |
1 files changed, 7 insertions, 17 deletions
diff --git a/drivers/block/loop/loop_file_fmt_qcow_main.c b/drivers/block/loop/loop_file_fmt_qcow_main.c index 70436c8fc076..dc2a7b0ee287 100644 --- a/drivers/block/loop/loop_file_fmt_qcow_main.c +++ b/drivers/block/loop/loop_file_fmt_qcow_main.c @@ -781,14 +781,13 @@ out_free_in_buf: static int __qcow_file_fmt_read_bvec(struct loop_file_fmt *lo_fmt, struct bio_vec *bvec, - loff_t pos) + loff_t *ppos) { struct loop_file_fmt_qcow_data *qcow_data = lo_fmt->private_data; struct loop_device *lo = loop_file_fmt_get_lo(lo_fmt); int offset_in_cluster; int ret; unsigned int cur_bytes; /* number of bytes in current iteration */ - u64 offset; u64 bytes; u64 cluster_offset = 0; u64 bytes_done = 0; @@ -797,22 +796,21 @@ static int __qcow_file_fmt_read_bvec(struct loop_file_fmt *lo_fmt, ssize_t len; loff_t pos_read; - offset = pos; bytes = bvec->bv_len; - while (bytes > 0) { + while (bytes != 0) { /* prepare next request */ cur_bytes = bytes; - ret = loop_file_fmt_qcow_cluster_get_offset(lo_fmt, offset, + ret = loop_file_fmt_qcow_cluster_get_offset(lo_fmt, *ppos, &cur_bytes, &cluster_offset); if (ret < 0) { goto fail; } offset_in_cluster = loop_file_fmt_qcow_offset_into_cluster( - qcow_data, offset); + qcow_data, *ppos); switch (ret) { case QCOW_CLUSTER_UNALLOCATED: @@ -826,7 +824,7 @@ static int __qcow_file_fmt_read_bvec(struct loop_file_fmt *lo_fmt, case QCOW_CLUSTER_COMPRESSED: ret = __qcow_file_fmt_read_compressed(lo_fmt, bvec, - cluster_offset, offset, cur_bytes); + cluster_offset, *ppos, cur_bytes); if (ret < 0) { goto fail; } @@ -858,7 +856,7 @@ static int __qcow_file_fmt_read_bvec(struct loop_file_fmt *lo_fmt, } bytes -= cur_bytes; - offset += cur_bytes; + *ppos += cur_bytes; bytes_done += cur_bytes; } @@ -876,18 +874,10 @@ static int qcow_file_fmt_read(struct loop_file_fmt *lo_fmt, loff_t pos; int ret = 0; - u64 cluster_offset; - unsigned int cur_bytes = blk_rq_bytes(rq); - pos = __qcow_file_fmt_rq_get_pos(lo_fmt, rq); - ret = loop_file_fmt_qcow_cluster_get_offset(lo_fmt, pos, &cur_bytes, - &cluster_offset); - - ret = 0; - rq_for_each_segment(bvec, rq, iter) { - ret = __qcow_file_fmt_read_bvec(lo_fmt, &bvec, pos); + ret = __qcow_file_fmt_read_bvec(lo_fmt, &bvec, &pos); if (ret) return ret; |