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> --- block/file-posix.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/block/file-posix.c b/block/file-posix.c index 411a23cf99..9e37594145 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -1178,6 +1178,21 @@ static int sg_get_max_transfer_length(int fd) #endif } +static int sg_get_max_segments(int fd) +{ +#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) && defined(BLKSSZGET) @@ -1268,7 +1283,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.28.0