In commit 867eccfed84f96b54f4a432c510a02c2ce03b430, Levitsky appears to have assumed that the only "SCSI Passthrough" is `-device scsi-generic`, while the fact is there's also `-device scsi-block` (passthrough without the sg driver). Unlike `-device scsi-hd`, getting max_sectors is necessary to it (more precisely, hw_max_sectors might what matters, but BLKSECTGET reports max_sectors, so).
I'm unsure about how qemu-nbd works, but the commit clearly wasn't the right approach to fix the original issue it addresses. (It should for example ignore the max_transfer if it will never matter in to it, or overrides it in certain cases; when I glimpsed over https://bugzilla.redhat.com/show_bug.cgi?id=1647104, I don't see how it could be file-posix problem when it is reporting the right thing, regardless of whether "removing" the code helps.) I don't think we want to "mark" `-device scsi-block` as sg either. It will probably bring even more unexpected problems, because they are literally different sets of things behind the scene / in the kernel. On Fri, 4 Sep 2020 at 10:09, Tom Yan <tom.t...@gmail.com> wrote: > > 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 >