From: Dmitry Fomichev <dmitry.fomichev@wdc.com> To: "Kevin Wolf" <kwolf@redhat.com>, "Max Reitz" <mreitz@redhat.com>, "Paolo Bonzini" <pbonzini@redhat.com>, "Fam Zheng" <famz@redhat.com>, "Maxim Levitsky" <mlevitsky@redhat.com>, "Philippe Mathieu-Daudé" <philmd@redhat.com> Cc: Dmitry Fomichev <dmitry.fomichev@wdc.com>, Damien Le Moal <damien.lemoal@wdc.com>, Alistair Francis <alistair.francis@wdc.com>, qemu-devel@nongnu.org, qemu-block@nongnu.org Subject: [PATCH 1/2] file-posix: Correctly read max_segments of SG nodes Date: Wed, 12 Aug 2020 07:51:21 +0900 Message-ID: <20200811225122.17342-2-dmitry.fomichev@wdc.com> (raw) In-Reply-To: <20200811225122.17342-1-dmitry.fomichev@wdc.com> If scsi-generic driver is in use, an SG node can be specified in the command line in place of a regular SCSI device. In this case, sg_get_max_segments() fails to open max_segments entry in sysfs because /dev/sgX is a character device. As the result, the maximum transfer size for the device may be calculated incorrectly, causing I/O errors if the maximum transfer size at the guest ends up to be larger compared to the host. Check system device type in sg_get_max_segments() and read the max_segments value differently if it is a character device. Reported-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Fixes: 9103f1ceb46614b150bcbc3c9a4fbc72b47fedcc Signed-off-by: Dmitry Fomichev <dmitry.fomichev@wdc.com> --- block/file-posix.c | 55 +++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/block/file-posix.c b/block/file-posix.c index 094e3b0212..f9e2424e8f 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -1108,6 +1108,7 @@ static int sg_get_max_segments(int fd) int ret; int sysfd = -1; long max_segments; + unsigned int max_segs; struct stat st; if (fstat(fd, &st)) { @@ -1115,30 +1116,38 @@ static int sg_get_max_segments(int fd) goto out; } - sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/max_segments", - major(st.st_rdev), minor(st.st_rdev)); - sysfd = open(sysfspath, O_RDONLY); - if (sysfd == -1) { - ret = -errno; - goto out; + if (S_ISBLK(st.st_mode)) { + sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/max_segments", + major(st.st_rdev), minor(st.st_rdev)); + sysfd = open(sysfspath, O_RDONLY); + if (sysfd == -1) { + ret = -errno; + goto out; + } + do { + ret = read(sysfd, buf, sizeof(buf) - 1); + } while (ret == -1 && errno == EINTR); + if (ret < 0) { + ret = -errno; + goto out; + } else if (ret == 0) { + ret = -EIO; + goto out; + } + buf[ret] = 0; + /* The file is ended with '\n', pass 'end' to accept that. */ + ret = qemu_strtol(buf, &end, 10, &max_segments); + if (ret == 0 && end && *end == '\n') { + ret = max_segments; + } + } else { + ret = ioctl(fd, SG_GET_SG_TABLESIZE, &max_segs); + if (ret != 0) { + ret = -errno; + goto out; + } + ret = max_segs; } - do { - ret = read(sysfd, buf, sizeof(buf) - 1); - } while (ret == -1 && errno == EINTR); - if (ret < 0) { - ret = -errno; - goto out; - } else if (ret == 0) { - ret = -EIO; - goto out; - } - buf[ret] = 0; - /* The file is ended with '\n', pass 'end' to accept that. */ - ret = qemu_strtol(buf, &end, 10, &max_segments); - if (ret == 0 && end && *end == '\n') { - ret = max_segments; - } - out: if (sysfd != -1) { close(sysfd); -- 2.21.0
next prev parent reply index Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-08-11 22:51 [PATCH 0/2] block;scsi-generic: Fix max transfer size calculation Dmitry Fomichev 2020-08-11 22:51 ` Dmitry Fomichev [this message] 2020-09-17 13:16 ` [PATCH 1/2] file-posix: Correctly read max_segments of SG nodes Max Reitz 2020-09-17 13:22 ` Maxim Levitsky 2020-09-17 13:24 ` Maxim Levitsky 2020-09-17 16:44 ` Dmitry Fomichev 2020-09-19 15:18 ` Paolo Bonzini 2020-09-19 15:15 ` Paolo Bonzini 2020-08-11 22:51 ` [PATCH 2/2] scsi-generic: Fix HM-zoned device scan Dmitry Fomichev 2020-08-17 15:58 ` Alistair Francis 2020-08-17 16:38 ` [PATCH 0/2] block; scsi-generic: Fix max transfer size calculation Paolo Bonzini
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200811225122.17342-2-dmitry.fomichev@wdc.com \ --to=dmitry.fomichev@wdc.com \ --cc=alistair.francis@wdc.com \ --cc=damien.lemoal@wdc.com \ --cc=famz@redhat.com \ --cc=kwolf@redhat.com \ --cc=mlevitsky@redhat.com \ --cc=mreitz@redhat.com \ --cc=pbonzini@redhat.com \ --cc=philmd@redhat.com \ --cc=qemu-block@nongnu.org \ --cc=qemu-devel@nongnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
QEMU-Devel Archive on lore.kernel.org Archives are clonable: git clone --mirror https://lore.kernel.org/qemu-devel/0 qemu-devel/git/0.git git clone --mirror https://lore.kernel.org/qemu-devel/1 qemu-devel/git/1.git git clone --mirror https://lore.kernel.org/qemu-devel/2 qemu-devel/git/2.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 qemu-devel qemu-devel/ https://lore.kernel.org/qemu-devel \ qemu-devel@nongnu.org public-inbox-index qemu-devel Example config snippet for mirrors Newsgroup available over NNTP: nntp://nntp.lore.kernel.org/org.nongnu.qemu-devel AGPL code for this site: git clone https://public-inbox.org/public-inbox.git