virtio-blk: split large IO according to size_max
if driver reads data larger than VIRTIO_BLK_F_SIZE_MAX, it will cause some issue to the DMA engine. So when upper software wants to read data larger than VIRTIO_BLK_F_SIZE_MAX, virtio-blk driver split one large request into multiple smaller ones. Signed-off-by: Andy Pei <andy.pei@intel.com> Signed-off-by: Ding Limin <dinglimin@cmss.chinamobile.com> Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
815d749865
commit
a05af290ba
|
@ -24,6 +24,11 @@
|
||||||
#include "virtio-ring.h"
|
#include "virtio-ring.h"
|
||||||
#include "virtio-blk.h"
|
#include "virtio-blk.h"
|
||||||
|
|
||||||
|
#define min(a, b) ({\
|
||||||
|
typeof(a) _a = a;\
|
||||||
|
typeof(b) _b = b;\
|
||||||
|
_a < _b ? _a : _b; })
|
||||||
|
|
||||||
struct virtiodrive_s {
|
struct virtiodrive_s {
|
||||||
struct drive_s drive;
|
struct drive_s drive;
|
||||||
struct vring_virtqueue *vq;
|
struct vring_virtqueue *vq;
|
||||||
|
@ -82,8 +87,36 @@ virtio_blk_op(struct disk_op_s *op, int write)
|
||||||
.length = sizeof(status),
|
.length = sizeof(status),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
u32 max_io_size =
|
||||||
|
vdrive->drive.max_segment_size * vdrive->drive.max_segments;
|
||||||
|
u16 blk_num_max;
|
||||||
|
|
||||||
|
if (vdrive->drive.blksize != 0 && max_io_size != 0)
|
||||||
|
blk_num_max = (u16)max_io_size / vdrive->drive.blksize;
|
||||||
|
else
|
||||||
|
/* default blk_num_max if hardware doesnot advise a proper value */
|
||||||
|
blk_num_max = 8;
|
||||||
|
|
||||||
|
if (op->count <= blk_num_max) {
|
||||||
virtio_blk_op_one_segment(vdrive, write, sg);
|
virtio_blk_op_one_segment(vdrive, write, sg);
|
||||||
|
} else {
|
||||||
|
void *p = op->buf_fl;
|
||||||
|
u16 count = op->count;
|
||||||
|
|
||||||
|
while (count > 0) {
|
||||||
|
u16 blk_num = min(count, blk_num_max);
|
||||||
|
sg[1].length = vdrive->drive.blksize * blk_num;
|
||||||
|
sg[1].addr = p;
|
||||||
|
virtio_blk_op_one_segment(vdrive, write, sg);
|
||||||
|
if (status == VIRTIO_BLK_S_OK) {
|
||||||
|
hdr.sector += blk_num;
|
||||||
|
p += sg[1].length;
|
||||||
|
count -= blk_num;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return status == VIRTIO_BLK_S_OK ? DISK_RET_SUCCESS : DISK_RET_EBADTRACK;
|
return status == VIRTIO_BLK_S_OK ? DISK_RET_SUCCESS : DISK_RET_EBADTRACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue