diff mbox

[1/3] mirror: Don't extend the last sub-chunk

Message ID 1461060549-8667-2-git-send-email-famz@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Fam Zheng April 19, 2016, 10:09 a.m. UTC
The last sub-chunk is rounded up to the copy granularity in the target
image, resulting in a larger size than the source.

Add a function to clip the copied sectors to the end.

This undoes the "wrong" changes to tests/qemu-iotests/109.out in
e5b43573e28. The remaining two offset changes are okay.

Reported-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
---
 block/mirror.c             | 10 ++++++++++
 tests/qemu-iotests/109.out | 44 ++++++++++++++++++++++----------------------
 2 files changed, 32 insertions(+), 22 deletions(-)

Comments

Max Reitz April 19, 2016, 8:33 p.m. UTC | #1
On 19.04.2016 12:09, Fam Zheng wrote:
> The last sub-chunk is rounded up to the copy granularity in the target
> image, resulting in a larger size than the source.
> 
> Add a function to clip the copied sectors to the end.
> 
> This undoes the "wrong" changes to tests/qemu-iotests/109.out in
> e5b43573e28. The remaining two offset changes are okay.
> 
> Reported-by: Kevin Wolf <kwolf@redhat.com>
> Signed-off-by: Fam Zheng <famz@redhat.com>
> ---
>  block/mirror.c             | 10 ++++++++++
>  tests/qemu-iotests/109.out | 44 ++++++++++++++++++++++----------------------
>  2 files changed, 32 insertions(+), 22 deletions(-)
> 
> diff --git a/block/mirror.c b/block/mirror.c
> index c2cfc1a..b6387f1 100644
> --- a/block/mirror.c
> +++ b/block/mirror.c
> @@ -205,6 +205,14 @@ static inline void mirror_wait_for_io(MirrorBlockJob *s)
>      s->waiting_for_io = false;
>  }
>  
> +static inline void mirror_clip_sectors(MirrorBlockJob *s,
> +                                       int64_t sector_num,
> +                                       int *nb_sectors)
> +{
> +    *nb_sectors = MIN(*nb_sectors,
> +                      s->bdev_length / BDRV_SECTOR_SIZE - sector_num);
> +}
> +
>  /* Submit async read while handling COW.
>   * Returns: nb_sectors if no alignment is necessary, or
>   *          (new_end - sector_num) if tail is rounded up or down due to
> @@ -240,6 +248,7 @@ static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,
>          mirror_wait_for_io(s);
>      }
>  
> +    mirror_clip_sectors(s, sector_num, &nb_sectors);
>      /* Allocate a MirrorOp that is used as an AIO callback.  */
>      op = g_new(MirrorOp, 1);
>      op->s = s;

I think you want to adjust the ret value, too. It doesn't really matter
in practice (the caller just overshoots the end of the image instead of
getting precisely to its end), but I wouldn't rely on this.

> @@ -276,6 +285,7 @@ static void mirror_do_zero_or_discard(MirrorBlockJob *s,
>  {
>      MirrorOp *op;
>  
> +    mirror_clip_sectors(s, sector_num, &nb_sectors);
>      /* Allocate a MirrorOp that is used as an AIO callback. The qiov is zeroed
>       * so the freeing in mirror_iteration_done is nop. */
>      op = g_new0(MirrorOp, 1);

I think it would be best to just pull out the mirror_clip_sectors() from
these functions and put it above the "switch (mirror_method)" in
mirror_iteration().

We'd just have to make sure that mirror_cow_align() will not increase
nb_sectors such that it points beyond the image end. It can do that,
because and image's size does not need to be aligned to its cluster
size. But just putting a mirror_clip_sectors() below the
bdrv_round_to_clusters() call in mirror_cow_align() should fix that.

Then you wouldn't need to worry about fixing the ret value in
mirror_do_read().

Max
Fam Zheng April 20, 2016, 1:13 a.m. UTC | #2
On Tue, 04/19 22:33, Max Reitz wrote:
> On 19.04.2016 12:09, Fam Zheng wrote:
> > The last sub-chunk is rounded up to the copy granularity in the target
> > image, resulting in a larger size than the source.
> > 
> > Add a function to clip the copied sectors to the end.
> > 
> > This undoes the "wrong" changes to tests/qemu-iotests/109.out in
> > e5b43573e28. The remaining two offset changes are okay.
> > 
> > Reported-by: Kevin Wolf <kwolf@redhat.com>
> > Signed-off-by: Fam Zheng <famz@redhat.com>
> > ---
> >  block/mirror.c             | 10 ++++++++++
> >  tests/qemu-iotests/109.out | 44 ++++++++++++++++++++++----------------------
> >  2 files changed, 32 insertions(+), 22 deletions(-)
> > 
> > diff --git a/block/mirror.c b/block/mirror.c
> > index c2cfc1a..b6387f1 100644
> > --- a/block/mirror.c
> > +++ b/block/mirror.c
> > @@ -205,6 +205,14 @@ static inline void mirror_wait_for_io(MirrorBlockJob *s)
> >      s->waiting_for_io = false;
> >  }
> >  
> > +static inline void mirror_clip_sectors(MirrorBlockJob *s,
> > +                                       int64_t sector_num,
> > +                                       int *nb_sectors)
> > +{
> > +    *nb_sectors = MIN(*nb_sectors,
> > +                      s->bdev_length / BDRV_SECTOR_SIZE - sector_num);
> > +}
> > +
> >  /* Submit async read while handling COW.
> >   * Returns: nb_sectors if no alignment is necessary, or
> >   *          (new_end - sector_num) if tail is rounded up or down due to
> > @@ -240,6 +248,7 @@ static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,
> >          mirror_wait_for_io(s);
> >      }
> >  
> > +    mirror_clip_sectors(s, sector_num, &nb_sectors);
> >      /* Allocate a MirrorOp that is used as an AIO callback.  */
> >      op = g_new(MirrorOp, 1);
> >      op->s = s;
> 
> I think you want to adjust the ret value, too. It doesn't really matter
> in practice (the caller just overshoots the end of the image instead of
> getting precisely to its end), but I wouldn't rely on this.
> 
> > @@ -276,6 +285,7 @@ static void mirror_do_zero_or_discard(MirrorBlockJob *s,
> >  {
> >      MirrorOp *op;
> >  
> > +    mirror_clip_sectors(s, sector_num, &nb_sectors);
> >      /* Allocate a MirrorOp that is used as an AIO callback. The qiov is zeroed
> >       * so the freeing in mirror_iteration_done is nop. */
> >      op = g_new0(MirrorOp, 1);
> 
> I think it would be best to just pull out the mirror_clip_sectors() from
> these functions and put it above the "switch (mirror_method)" in
> mirror_iteration().
> 
> We'd just have to make sure that mirror_cow_align() will not increase
> nb_sectors such that it points beyond the image end. It can do that,
> because and image's size does not need to be aligned to its cluster
> size. But just putting a mirror_clip_sectors() below the
> bdrv_round_to_clusters() call in mirror_cow_align() should fix that.
> 
> Then you wouldn't need to worry about fixing the ret value in
> mirror_do_read().

Sounds good, will do this.

Thanks,
Fam
diff mbox

Patch

diff --git a/block/mirror.c b/block/mirror.c
index c2cfc1a..b6387f1 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -205,6 +205,14 @@  static inline void mirror_wait_for_io(MirrorBlockJob *s)
     s->waiting_for_io = false;
 }
 
+static inline void mirror_clip_sectors(MirrorBlockJob *s,
+                                       int64_t sector_num,
+                                       int *nb_sectors)
+{
+    *nb_sectors = MIN(*nb_sectors,
+                      s->bdev_length / BDRV_SECTOR_SIZE - sector_num);
+}
+
 /* Submit async read while handling COW.
  * Returns: nb_sectors if no alignment is necessary, or
  *          (new_end - sector_num) if tail is rounded up or down due to
@@ -240,6 +248,7 @@  static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,
         mirror_wait_for_io(s);
     }
 
+    mirror_clip_sectors(s, sector_num, &nb_sectors);
     /* Allocate a MirrorOp that is used as an AIO callback.  */
     op = g_new(MirrorOp, 1);
     op->s = s;
@@ -276,6 +285,7 @@  static void mirror_do_zero_or_discard(MirrorBlockJob *s,
 {
     MirrorOp *op;
 
+    mirror_clip_sectors(s, sector_num, &nb_sectors);
     /* Allocate a MirrorOp that is used as an AIO callback. The qiov is zeroed
      * so the freeing in mirror_iteration_done is nop. */
     op = g_new0(MirrorOp, 1);
diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out
index b3358de..38bc073 100644
--- a/tests/qemu-iotests/109.out
+++ b/tests/qemu-iotests/109.out
@@ -10,14 +10,14 @@  Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 {"return": {}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 65536, "offset": 65536, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
+{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 1024, "offset": 1024, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
 Warning: Image size mismatch!
 Images are identical.
 
@@ -31,14 +31,14 @@  Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 262144, "offset": 65536, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 197120, "offset": 512, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 {"return": {}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 262144, "offset": 262144, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 262144, "offset": 262144, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}}
+{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 197120, "offset": 197120, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
 Warning: Image size mismatch!
 Images are identical.
 
@@ -73,14 +73,14 @@  Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 {"return": {}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 65536, "offset": 65536, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
+{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 1024, "offset": 1024, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
 Warning: Image size mismatch!
 Images are identical.
 
@@ -115,14 +115,14 @@  Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 {"return": {}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 65536, "offset": 65536, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
+{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 2560, "offset": 2560, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
 Warning: Image size mismatch!
 Images are identical.
 
@@ -135,14 +135,14 @@  Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 {"return": {}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 65536, "offset": 65536, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
+{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 2560, "offset": 2560, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
 Image resized.
 Warning: Image size mismatch!
 Images are identical.
@@ -198,14 +198,14 @@  Automatically detecting the format is dangerous for raw images, write operations
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2048, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
 {"return": []}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 {"return": {}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 65536, "offset": 65536, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}}
+{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 2048, "offset": 2048, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
 Image resized.
 Warning: Image size mismatch!
 Images are identical.
@@ -218,14 +218,14 @@  WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed
 Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
 Specify the 'raw' format explicitly to remove the restrictions.
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 65536, "offset": 65536, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
+{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 512, "offset": 512, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
 Warning: Image size mismatch!
 Images are identical.
 {"return": {}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
-{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 65536, "offset": 65536, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
+{"return": [{"io-status": "ok", "device": "src", "busy": false, "len": 512, "offset": 512, "paused": false, "speed": 0, "ready": true, "type": "mirror"}]}
 Warning: Image size mismatch!
 Images are identical.
 *** done