diff mbox series

[v5,07/10] block: Implement bdrv_{pread, pwrite, pwrite_zeroes}() using generated_co_wrapper

Message ID 20220609152744.3891847-8-afaria@redhat.com
State New
Headers show
Series Implement bdrv_{pread, pwrite, pwrite_sync, pwrite_zeroes}() using generated_co_wrapper | expand

Commit Message

Alberto Faria June 9, 2022, 3:27 p.m. UTC
bdrv_{pread,pwrite}() now return -EIO instead of -EINVAL when 'bytes' is
negative, making them consistent with bdrv_{preadv,pwritev}() and
bdrv_co_{pread,pwrite,preadv,pwritev}().

bdrv_pwrite_zeroes() now also calls trace_bdrv_co_pwrite_zeroes() and
clears the BDRV_REQ_MAY_UNMAP flag when appropriate, which it didn't
previously.

Signed-off-by: Alberto Faria <afaria@redhat.com>
---

I audited all bdrv_{pread,pwrite}() callers to make sure that changing
the -EINVAL return code to -EIO wont't break things. However, there are
about 140 call sites, so the probability of me having missed something
isn't negligible. If someone more accustomed to the code base is able to
double-check this, that would be very much appreciated.

As a precaution, I also dropped Paolo's R-b.

 block/io.c               | 41 ----------------------------------------
 include/block/block-io.h | 15 +++++++++------
 2 files changed, 9 insertions(+), 47 deletions(-)

Comments

Eric Blake June 23, 2022, 9:47 p.m. UTC | #1
On Thu, Jun 09, 2022 at 04:27:41PM +0100, Alberto Faria wrote:
> bdrv_{pread,pwrite}() now return -EIO instead of -EINVAL when 'bytes' is
> negative, making them consistent with bdrv_{preadv,pwritev}() and
> bdrv_co_{pread,pwrite,preadv,pwritev}().
> 
> bdrv_pwrite_zeroes() now also calls trace_bdrv_co_pwrite_zeroes() and
> clears the BDRV_REQ_MAY_UNMAP flag when appropriate, which it didn't
> previously.
> 
> Signed-off-by: Alberto Faria <afaria@redhat.com>
> ---
> 
> I audited all bdrv_{pread,pwrite}() callers to make sure that changing
> the -EINVAL return code to -EIO wont't break things. However, there are
> about 140 call sites, so the probability of me having missed something
> isn't negligible. If someone more accustomed to the code base is able to
> double-check this, that would be very much appreciated.

I did not get through all of the callers (you are right, there ARE a
lot), but the ones I checked, particularly in block/qcow2-*.c, appear
to handle -EIO just fine.

I did notice, however, that qcow2-bitmap.c:free_bitmap_clusters()
returns an int failure, but none of its three callers
(qcow2_co_remove_persistent_dirty_bitmap, and twice in
qcow2_store_persistent_dirty_bitmaps) care about the return value.
That may be worth a separate cleanup patch.

> 
> As a precaution, I also dropped Paolo's R-b.
> 
>  block/io.c               | 41 ----------------------------------------
>  include/block/block-io.h | 15 +++++++++------
>  2 files changed, 9 insertions(+), 47 deletions(-)

Reviewed-by: Eric Blake <eblake@redhat.com>
Alberto Faria July 3, 2022, 10:27 p.m. UTC | #2
On Thu, Jun 23, 2022 at 10:47 PM Eric Blake <eblake@redhat.com> wrote:
> I did not get through all of the callers (you are right, there ARE a
> lot), but the ones I checked, particularly in block/qcow2-*.c, appear
> to handle -EIO just fine.
>
> I did notice, however, that qcow2-bitmap.c:free_bitmap_clusters()
> returns an int failure, but none of its three callers
> (qcow2_co_remove_persistent_dirty_bitmap, and twice in
> qcow2_store_persistent_dirty_bitmaps) care about the return value.
> That may be worth a separate cleanup patch.

Thanks, Eric. I decided to add a check for this kind of thing to the
static analyzer I've been working on, which I sent as an RFC [1].

Alberto

[1] https://lore.kernel.org/qemu-devel/20220702113331.2003820-1-afaria@redhat.com/
Hanna Czenczek July 4, 2022, 12:06 p.m. UTC | #3
On 09.06.22 17:27, Alberto Faria wrote:
> bdrv_{pread,pwrite}() now return -EIO instead of -EINVAL when 'bytes' is
> negative, making them consistent with bdrv_{preadv,pwritev}() and
> bdrv_co_{pread,pwrite,preadv,pwritev}().
>
> bdrv_pwrite_zeroes() now also calls trace_bdrv_co_pwrite_zeroes() and
> clears the BDRV_REQ_MAY_UNMAP flag when appropriate, which it didn't
> previously.
>
> Signed-off-by: Alberto Faria <afaria@redhat.com>
> ---
>
> I audited all bdrv_{pread,pwrite}() callers to make sure that changing
> the -EINVAL return code to -EIO wont't break things. However, there are
> about 140 call sites, so the probability of me having missed something
> isn't negligible. If someone more accustomed to the code base is able to
> double-check this, that would be very much appreciated.

FWIW I checked all call sits when reviewing patch 3, and I can’t 
remember any case where the follow-up check was anything but `ret < 0`.  
The only difference should be a couple of error_setg_errno() calls, 
which will change from “Invalid argument” to “I/O error”.

I guess the real problem wouldn’t be checking the immediate call sites, 
but the fact that most call sites just pass the error code to their 
caller in turn, and that’s really something that’s unreasonable to 
check, I believe.

Honestly, I don’t think it really matters (how likely is `bytes < 0`?), 
nor could I imagine a case where EINVAL vs. EIO would cause any 
difference in behavior.  That’s to say, I’d be disappointed if it did.

(Grepping for 'if.*EINVAL' and 'if.*EIO' in block/ only yields one case 
in block/nbd.c where I can’t quickly absolutely rule out it won’t make a 
difference, but I think that check is only for error codes coming from 
handling network requests.)

> As a precaution, I also dropped Paolo's R-b.
>
>   block/io.c               | 41 ----------------------------------------
>   include/block/block-io.h | 15 +++++++++------
>   2 files changed, 9 insertions(+), 47 deletions(-)

Reviewed-by: Hanna Reitz <hreitz@redhat.com>
diff mbox series

Patch

diff --git a/block/io.c b/block/io.c
index 78a289192e..ecd1c2a53c 100644
--- a/block/io.c
+++ b/block/io.c
@@ -1061,14 +1061,6 @@  static int bdrv_check_request32(int64_t offset, int64_t bytes,
     return 0;
 }
 
-int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
-                       int64_t bytes, BdrvRequestFlags flags)
-{
-    IO_CODE();
-    return bdrv_pwritev(child, offset, bytes, NULL,
-                        BDRV_REQ_ZERO_WRITE | flags);
-}
-
 /*
  * Completely zero out a block device with the help of bdrv_pwrite_zeroes.
  * The operation is sped up by checking the block status and only writing
@@ -1111,39 +1103,6 @@  int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
     }
 }
 
-/* See bdrv_pwrite() for the return codes */
-int bdrv_pread(BdrvChild *child, int64_t offset, int64_t bytes, void *buf,
-               BdrvRequestFlags flags)
-{
-    QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
-    IO_CODE();
-
-    if (bytes < 0) {
-        return -EINVAL;
-    }
-
-    return bdrv_preadv(child, offset, bytes, &qiov, flags);
-}
-
-/* Return no. of bytes on success or < 0 on error. Important errors are:
-  -EIO         generic I/O error (may happen for all errors)
-  -ENOMEDIUM   No media inserted.
-  -EINVAL      Invalid offset or number of bytes
-  -EACCES      Trying to write a read-only device
-*/
-int bdrv_pwrite(BdrvChild *child, int64_t offset, int64_t bytes,
-                const void *buf, BdrvRequestFlags flags)
-{
-    QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
-    IO_CODE();
-
-    if (bytes < 0) {
-        return -EINVAL;
-    }
-
-    return bdrv_pwritev(child, offset, bytes, &qiov, flags);
-}
-
 /*
  * Writes to the file and ensures that no writes are reordered across this
  * request (acts as a barrier)
diff --git a/include/block/block-io.h b/include/block/block-io.h
index 879221cebe..c81739ad16 100644
--- a/include/block/block-io.h
+++ b/include/block/block-io.h
@@ -39,13 +39,16 @@ 
  * to catch when they are accidentally called by the wrong API.
  */
 
-int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
-                       int64_t bytes, BdrvRequestFlags flags);
+int generated_co_wrapper bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
+                                            int64_t bytes,
+                                            BdrvRequestFlags flags);
 int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags);
-int bdrv_pread(BdrvChild *child, int64_t offset, int64_t bytes, void *buf,
-               BdrvRequestFlags flags);
-int bdrv_pwrite(BdrvChild *child, int64_t offset, int64_t bytes,
-                const void *buf, BdrvRequestFlags flags);
+int generated_co_wrapper bdrv_pread(BdrvChild *child, int64_t offset,
+                                    int64_t bytes, void *buf,
+                                    BdrvRequestFlags flags);
+int generated_co_wrapper bdrv_pwrite(BdrvChild *child, int64_t offset,
+                                     int64_t bytes, const void *buf,
+                                     BdrvRequestFlags flags);
 int bdrv_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes,
                      const void *buf, BdrvRequestFlags flags);
 /*