From: Tom Yan <tom.t...@gmail.com> sg devices have different major/minor than their corresponding block devices. Using sysfs to get max segments never really worked for them.
Fortunately the sg driver provides an ioctl to get sg_tablesize, which is apparently equivalent to max segments. Signed-off-by: Tom Yan <tom.t...@gmail.com> Signed-off-by: Maxim Levitsky <mlevi...@redhat.com> --- block/file-posix.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/block/file-posix.c b/block/file-posix.c index 226ddbbdad..10ebc4c5b7 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -1181,6 +1181,26 @@ static int sg_get_max_transfer_length(int fd) #endif } +static int sg_get_max_segments(int fd) +{ + /* + * /dev/sg* character devices report 'max_segments' via + * SG_GET_SG_TABLESIZE ioctl + */ + +#ifdef SG_GET_SG_TABLESIZE + long max_segments = 0; + + if (ioctl(fd, SG_GET_SG_TABLESIZE, &max_segments) == 0) { + return max_segments; + } else { + return -errno; + } +#else + return -ENOSYS; +#endif +} + static int get_max_transfer_length(int fd) { #if defined(BLKSECTGET) @@ -1267,7 +1287,7 @@ static void hdev_refresh_limits(BlockDriverState *bs, Error **errp) bs->bl.max_transfer = pow2floor(ret); } - ret = get_max_segments(s->fd); + ret = bs->sg ? sg_get_max_segments(s->fd) : get_max_segments(s->fd); if (ret > 0) { bs->bl.max_transfer = MIN_NON_ZERO(bs->bl.max_transfer, ret * qemu_real_host_page_size); -- 2.26.2