diff mbox series

[v3,2/5] file-posix: add sg_get_max_segments that actually works with sg

Message ID 20201217165612.942849-3-mlevitsk@redhat.com
State New
Headers show
Series SCSI: fix transfer limits for SCSI passthrough | expand

Commit Message

Maxim Levitsky Dec. 17, 2020, 4:56 p.m. UTC
From: Tom Yan <tom.ty89@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.ty89@gmail.com>
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
---
 block/file-posix.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

Comments

Max Reitz Jan. 7, 2021, 12:42 p.m. UTC | #1
On 17.12.20 17:56, Maxim Levitsky wrote:
> From: Tom Yan <tom.ty89@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.ty89@gmail.com>
> Signed-off-by: Maxim Levitsky <mlevitsk@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 cbf1271773..2bf4d095a7 100644
> --- a/block/file-posix.c
> +++ b/block/file-posix.c
> @@ -1179,6 +1179,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) {

As far as I can tell from googling, SG_GET_SG_TABLESIZE takes an int 
pointer.

Apart from that, looks good.

Max

> +        return max_segments;
> +    } else {
> +        return -errno;
> +    }
> +#else
> +    return -ENOSYS;
> +#endif
> +}
> +
>   static int get_max_transfer_length(int fd)
>   {
>   #if defined(BLKSECTGET)
> @@ -1265,7 +1285,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);
>
diff mbox series

Patch

diff --git a/block/file-posix.c b/block/file-posix.c
index cbf1271773..2bf4d095a7 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -1179,6 +1179,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)
@@ -1265,7 +1285,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);