* [Qemu-devel] [PATCH v3 0/3] raw-posix: Fix raw_co_get_block_status() @ 2014-10-22 15:57 Max Reitz 2014-10-22 15:57 ` [Qemu-devel] [PATCH v3 1/3] raw-posix: Fix raw_co_get_block_status() after EOF Max Reitz ` (2 more replies) 0 siblings, 3 replies; 13+ messages in thread From: Max Reitz @ 2014-10-22 15:57 UTC (permalink / raw) To: qemu-devel; +Cc: Kevin Wolf, Benoît Canet, Stefan Hajnoczi, Max Reitz raw_co_get_block_status() should return 0 and set *pnum to 0 after the EOF; currently it does this merely by accident, so implement it directly. Also, nb_sectors should be clamped against the image end. While doing that, centralize the generation of raw_co_get_block_status()'s return value along the way. v3: - Patch 1: - Remove the whole ENXIO assert(), just return -errno. ENXIO is not a very useful message for the user, but it's better than a broken assertion for sure (and there is no good way of returning 0 and setting *pnum to 0 as well, because this would mean acknowledging the new size of the file and we'd have to update its length in the BDS, etc. pp.; just return ENXIO and be done with it) [Kevin] - bdrv_getlength() may fail [Kevin] - Patch 2: Remove the pnum parameter from try_fiemap() and try_seek_hole(), it isn't used anyway - Patch 3: Added. git-backport-diff against v2: Key: [----] : patches are identical [####] : number of functional differences between upstream/downstream patch [down] : patch is downstream-only The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively 001/3:[0008] [FC] 'raw-posix: Fix raw_co_get_block_status() after EOF' 002/3:[0008] [FC] 'raw-posix: raw_co_get_block_status() return value' 003/3:[down] 'iotests: Add test for external image truncation' Max Reitz (3): raw-posix: Fix raw_co_get_block_status() after EOF raw-posix: raw_co_get_block_status() return value iotests: Add test for external image truncation block/raw-posix.c | 42 ++++++++++++++++++++++++------------------ tests/qemu-iotests/102 | 15 +++++++++++++++ tests/qemu-iotests/102.out | 9 +++++++++ 3 files changed, 48 insertions(+), 18 deletions(-) -- 1.9.3 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v3 1/3] raw-posix: Fix raw_co_get_block_status() after EOF 2014-10-22 15:57 [Qemu-devel] [PATCH v3 0/3] raw-posix: Fix raw_co_get_block_status() Max Reitz @ 2014-10-22 15:57 ` Max Reitz 2014-10-22 16:57 ` Eric Blake 2014-10-22 15:57 ` [Qemu-devel] [PATCH v3 2/3] raw-posix: raw_co_get_block_status() return value Max Reitz 2014-10-22 15:57 ` [Qemu-devel] [PATCH v3 3/3] iotests: Add test for external image truncation Max Reitz 2 siblings, 1 reply; 13+ messages in thread From: Max Reitz @ 2014-10-22 15:57 UTC (permalink / raw) To: qemu-devel; +Cc: Kevin Wolf, Benoît Canet, Stefan Hajnoczi, Max Reitz As its comment states, raw_co_get_block_status() should unconditionally return 0 and set *pnum to 0 for after EOF. An assertion after lseek(..., SEEK_HOLE) tried to catch this case by asserting that errno != -ENXIO (which would indicate a position after the EOF); but it should be errno != ENXIO instead. Regardless of that, there should be no such assertion at all. If bdrv_getlength() returned an outdated value and the image has been resized outside of qemu, lseek() will return with errno == ENXIO. Just return that value as an error then. Setting *pnum to 0 and returning 0 should not be done here, as in that case we should update the device length as well. So, from qemu's perspective, the file has not been resized; it's just that there was an error querying sectors beyond a certain point (the actual file size). Additionally, nb_sectors should be clamped against the image end. This was probably not an issue if FIEMAP or SEEK_HOLE/SEEK_DATA worked, but the fallback did not take this case into account. Reported-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Max Reitz <mreitz@redhat.com> --- block/raw-posix.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index ee4ca3c..bd21fff 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -1519,10 +1519,6 @@ static int64_t try_seek_hole(BlockDriverState *bs, off_t start, off_t *data, *hole = lseek(s->fd, start, SEEK_HOLE); if (*hole == -1) { - /* -ENXIO indicates that sector_num was past the end of the file. - * There is a virtual hole there. */ - assert(errno != -ENXIO); - return -errno; } @@ -1562,6 +1558,7 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, int nb_sectors, int *pnum) { off_t start, data = 0, hole = 0; + int64_t total_size; int64_t ret; ret = fd_open(bs); @@ -1570,6 +1567,15 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, } start = sector_num * BDRV_SECTOR_SIZE; + total_size = bdrv_getlength(bs); + if (total_size < 0) { + return total_size; + } else if (start >= total_size) { + *pnum = 0; + return 0; + } else if (start + nb_sectors * BDRV_SECTOR_SIZE > total_size) { + nb_sectors = (total_size - start) / BDRV_SECTOR_SIZE; + } ret = try_seek_hole(bs, start, &data, &hole, pnum); if (ret < 0) { -- 1.9.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v3 1/3] raw-posix: Fix raw_co_get_block_status() after EOF 2014-10-22 15:57 ` [Qemu-devel] [PATCH v3 1/3] raw-posix: Fix raw_co_get_block_status() after EOF Max Reitz @ 2014-10-22 16:57 ` Eric Blake 2014-10-23 7:27 ` Max Reitz 0 siblings, 1 reply; 13+ messages in thread From: Eric Blake @ 2014-10-22 16:57 UTC (permalink / raw) To: Max Reitz, qemu-devel; +Cc: Kevin Wolf, Benoît Canet, Stefan Hajnoczi [-- Attachment #1: Type: text/plain, Size: 1990 bytes --] On 10/22/2014 09:57 AM, Max Reitz wrote: > As its comment states, raw_co_get_block_status() should unconditionally > return 0 and set *pnum to 0 for after EOF. > > An assertion after lseek(..., SEEK_HOLE) tried to catch this case by > asserting that errno != -ENXIO (which would indicate a position after > the EOF); but it should be errno != ENXIO instead. Regardless of that, > there should be no such assertion at all. If bdrv_getlength() returned > an outdated value and the image has been resized outside of qemu, > lseek() will return with errno == ENXIO. Just return that value as an > error then. > > Setting *pnum to 0 and returning 0 should not be done here, as in that > case we should update the device length as well. So, from qemu's > perspective, the file has not been resized; it's just that there was an > error querying sectors beyond a certain point (the actual file size). > > Additionally, nb_sectors should be clamped against the image end. This > was probably not an issue if FIEMAP or SEEK_HOLE/SEEK_DATA worked, but > the fallback did not take this case into account. > > Reported-by: Kevin Wolf <kwolf@redhat.com> > Signed-off-by: Max Reitz <mreitz@redhat.com> > --- > block/raw-posix.c | 14 ++++++++++---- > 1 file changed, 10 insertions(+), 4 deletions(-) Reviewed-by: Eric Blake <eblake@redhat.com> > + if (total_size < 0) { > + return total_size; > + } else if (start >= total_size) { > + *pnum = 0; > + return 0; > + } else if (start + nb_sectors * BDRV_SECTOR_SIZE > total_size) { > + nb_sectors = (total_size - start) / BDRV_SECTOR_SIZE; Should this round up instead of truncate? But it would only matter for a file size that is not a multiple of sectors, where we probably have other issues, and where reporting just the full sectors also seems reasonable. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 539 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v3 1/3] raw-posix: Fix raw_co_get_block_status() after EOF 2014-10-22 16:57 ` Eric Blake @ 2014-10-23 7:27 ` Max Reitz 2014-10-23 7:28 ` Max Reitz 0 siblings, 1 reply; 13+ messages in thread From: Max Reitz @ 2014-10-23 7:27 UTC (permalink / raw) To: Eric Blake, qemu-devel; +Cc: Kevin Wolf, Benoît Canet, Stefan Hajnoczi On 2014-10-22 at 18:57, Eric Blake wrote: > On 10/22/2014 09:57 AM, Max Reitz wrote: >> As its comment states, raw_co_get_block_status() should unconditionally >> return 0 and set *pnum to 0 for after EOF. >> >> An assertion after lseek(..., SEEK_HOLE) tried to catch this case by >> asserting that errno != -ENXIO (which would indicate a position after >> the EOF); but it should be errno != ENXIO instead. Regardless of that, >> there should be no such assertion at all. If bdrv_getlength() returned >> an outdated value and the image has been resized outside of qemu, >> lseek() will return with errno == ENXIO. Just return that value as an >> error then. >> >> Setting *pnum to 0 and returning 0 should not be done here, as in that >> case we should update the device length as well. So, from qemu's >> perspective, the file has not been resized; it's just that there was an >> error querying sectors beyond a certain point (the actual file size). >> >> Additionally, nb_sectors should be clamped against the image end. This >> was probably not an issue if FIEMAP or SEEK_HOLE/SEEK_DATA worked, but >> the fallback did not take this case into account. >> >> Reported-by: Kevin Wolf <kwolf@redhat.com> >> Signed-off-by: Max Reitz <mreitz@redhat.com> >> --- >> block/raw-posix.c | 14 ++++++++++---- >> 1 file changed, 10 insertions(+), 4 deletions(-) > Reviewed-by: Eric Blake <eblake@redhat.com> > >> + if (total_size < 0) { >> + return total_size; >> + } else if (start >= total_size) { >> + *pnum = 0; >> + return 0; >> + } else if (start + nb_sectors * BDRV_SECTOR_SIZE > total_size) { >> + nb_sectors = (total_size - start) / BDRV_SECTOR_SIZE; > Should this round up instead of truncate? But it would only matter for > a file size that is not a multiple of sectors, where we probably have > other issues, and where reporting just the full sectors also seems > reasonable. There already was a series (as far as I remember) that somehow tried to make all or at least some block drivers compatible with sizes which are not a multiple of the sector size, so I shouldn't be nullifying that work. Will use ROUND_UP(). Max ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v3 1/3] raw-posix: Fix raw_co_get_block_status() after EOF 2014-10-23 7:27 ` Max Reitz @ 2014-10-23 7:28 ` Max Reitz 0 siblings, 0 replies; 13+ messages in thread From: Max Reitz @ 2014-10-23 7:28 UTC (permalink / raw) To: Eric Blake, qemu-devel; +Cc: Kevin Wolf, Benoît Canet, Stefan Hajnoczi On 2014-10-23 at 09:27, Max Reitz wrote: > On 2014-10-22 at 18:57, Eric Blake wrote: >> On 10/22/2014 09:57 AM, Max Reitz wrote: >>> As its comment states, raw_co_get_block_status() should unconditionally >>> return 0 and set *pnum to 0 for after EOF. >>> >>> An assertion after lseek(..., SEEK_HOLE) tried to catch this case by >>> asserting that errno != -ENXIO (which would indicate a position after >>> the EOF); but it should be errno != ENXIO instead. Regardless of that, >>> there should be no such assertion at all. If bdrv_getlength() returned >>> an outdated value and the image has been resized outside of qemu, >>> lseek() will return with errno == ENXIO. Just return that value as an >>> error then. >>> >>> Setting *pnum to 0 and returning 0 should not be done here, as in that >>> case we should update the device length as well. So, from qemu's >>> perspective, the file has not been resized; it's just that there was an >>> error querying sectors beyond a certain point (the actual file size). >>> >>> Additionally, nb_sectors should be clamped against the image end. This >>> was probably not an issue if FIEMAP or SEEK_HOLE/SEEK_DATA worked, but >>> the fallback did not take this case into account. >>> >>> Reported-by: Kevin Wolf <kwolf@redhat.com> >>> Signed-off-by: Max Reitz <mreitz@redhat.com> >>> --- >>> block/raw-posix.c | 14 ++++++++++---- >>> 1 file changed, 10 insertions(+), 4 deletions(-) >> Reviewed-by: Eric Blake <eblake@redhat.com> >> >>> + if (total_size < 0) { >>> + return total_size; >>> + } else if (start >= total_size) { >>> + *pnum = 0; >>> + return 0; >>> + } else if (start + nb_sectors * BDRV_SECTOR_SIZE > total_size) { >>> + nb_sectors = (total_size - start) / BDRV_SECTOR_SIZE; >> Should this round up instead of truncate? But it would only matter for >> a file size that is not a multiple of sectors, where we probably have >> other issues, and where reporting just the full sectors also seems >> reasonable. > > There already was a series (as far as I remember) that somehow tried > to make all or at least some block drivers compatible with sizes which > are not a multiple of the sector size, so I shouldn't be nullifying > that work. Will use ROUND_UP(). Sorry, DIV_ROUND_UP(), of course. Max ^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v3 2/3] raw-posix: raw_co_get_block_status() return value 2014-10-22 15:57 [Qemu-devel] [PATCH v3 0/3] raw-posix: Fix raw_co_get_block_status() Max Reitz 2014-10-22 15:57 ` [Qemu-devel] [PATCH v3 1/3] raw-posix: Fix raw_co_get_block_status() after EOF Max Reitz @ 2014-10-22 15:57 ` Max Reitz 2014-10-22 17:00 ` Eric Blake 2014-10-22 15:57 ` [Qemu-devel] [PATCH v3 3/3] iotests: Add test for external image truncation Max Reitz 2 siblings, 1 reply; 13+ messages in thread From: Max Reitz @ 2014-10-22 15:57 UTC (permalink / raw) To: qemu-devel; +Cc: Kevin Wolf, Benoît Canet, Stefan Hajnoczi, Max Reitz Instead of generating the full return value thrice in try_fiemap(), try_seek_hole() and as a fall-back in raw_co_get_block_status() itself, generate the value only in raw_co_get_block_status(). While at it, also remove the pnum parameter from try_fiemap() and try_seek_hole(). Suggested-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Max Reitz <mreitz@redhat.com> --- block/raw-posix.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index bd21fff..0058678 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -1465,12 +1465,12 @@ out: return result; } -static int64_t try_fiemap(BlockDriverState *bs, off_t start, off_t *data, - off_t *hole, int nb_sectors, int *pnum) +static int try_fiemap(BlockDriverState *bs, off_t start, off_t *data, + off_t *hole, int nb_sectors) { #ifdef CONFIG_FIEMAP BDRVRawState *s = bs->opaque; - int64_t ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start; + int ret = 0; struct { struct fiemap fm; struct fiemap_extent fe; @@ -1511,8 +1511,8 @@ static int64_t try_fiemap(BlockDriverState *bs, off_t start, off_t *data, #endif } -static int64_t try_seek_hole(BlockDriverState *bs, off_t start, off_t *data, - off_t *hole, int *pnum) +static int try_seek_hole(BlockDriverState *bs, off_t start, off_t *data, + off_t *hole) { #if defined SEEK_HOLE && defined SEEK_DATA BDRVRawState *s = bs->opaque; @@ -1532,7 +1532,7 @@ static int64_t try_seek_hole(BlockDriverState *bs, off_t start, off_t *data, } } - return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start; + return 0; #else return -ENOTSUP; #endif @@ -1559,7 +1559,7 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, { off_t start, data = 0, hole = 0; int64_t total_size; - int64_t ret; + int ret; ret = fd_open(bs); if (ret < 0) { @@ -1577,28 +1577,28 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, nb_sectors = (total_size - start) / BDRV_SECTOR_SIZE; } - ret = try_seek_hole(bs, start, &data, &hole, pnum); + ret = try_seek_hole(bs, start, &data, &hole); if (ret < 0) { - ret = try_fiemap(bs, start, &data, &hole, nb_sectors, pnum); + ret = try_fiemap(bs, start, &data, &hole, nb_sectors); if (ret < 0) { /* Assume everything is allocated. */ data = 0; hole = start + nb_sectors * BDRV_SECTOR_SIZE; - ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start; + ret = 0; } } + assert(ret >= 0); + if (data <= start) { /* On a data extent, compute sectors to the end of the extent. */ *pnum = MIN(nb_sectors, (hole - start) / BDRV_SECTOR_SIZE); + return ret | BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start; } else { /* On a hole, compute sectors to the beginning of the next extent. */ *pnum = MIN(nb_sectors, (data - start) / BDRV_SECTOR_SIZE); - ret &= ~BDRV_BLOCK_DATA; - ret |= BDRV_BLOCK_ZERO; + return ret | BDRV_BLOCK_ZERO | BDRV_BLOCK_OFFSET_VALID | start; } - - return ret; } static coroutine_fn BlockAIOCB *raw_aio_discard(BlockDriverState *bs, -- 1.9.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v3 2/3] raw-posix: raw_co_get_block_status() return value 2014-10-22 15:57 ` [Qemu-devel] [PATCH v3 2/3] raw-posix: raw_co_get_block_status() return value Max Reitz @ 2014-10-22 17:00 ` Eric Blake 2014-10-23 7:29 ` Max Reitz 0 siblings, 1 reply; 13+ messages in thread From: Eric Blake @ 2014-10-22 17:00 UTC (permalink / raw) To: Max Reitz, qemu-devel; +Cc: Kevin Wolf, Benoît Canet, Stefan Hajnoczi [-- Attachment #1: Type: text/plain, Size: 1510 bytes --] On 10/22/2014 09:57 AM, Max Reitz wrote: > Instead of generating the full return value thrice in try_fiemap(), > try_seek_hole() and as a fall-back in raw_co_get_block_status() itself, > generate the value only in raw_co_get_block_status(). > > While at it, also remove the pnum parameter from try_fiemap() and > try_seek_hole(). > > Suggested-by: Kevin Wolf <kwolf@redhat.com> > Signed-off-by: Max Reitz <mreitz@redhat.com> > --- > block/raw-posix.c | 28 ++++++++++++++-------------- > 1 file changed, 14 insertions(+), 14 deletions(-) Reviewed-by: Eric Blake <eblake@redhat.com> > - ret = try_seek_hole(bs, start, &data, &hole, pnum); > + ret = try_seek_hole(bs, start, &data, &hole); > if (ret < 0) { > - ret = try_fiemap(bs, start, &data, &hole, nb_sectors, pnum); > + ret = try_fiemap(bs, start, &data, &hole, nb_sectors); > if (ret < 0) { > /* Assume everything is allocated. */ > data = 0; > hole = start + nb_sectors * BDRV_SECTOR_SIZE; > - ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start; > + ret = 0; > } > } > > + assert(ret >= 0); I'm not sure the assertion adds much (the lines above are fairly easy to reason about ret always being set), but it does protect against later code addition, so I'm not opposed to leaving it. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 539 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v3 2/3] raw-posix: raw_co_get_block_status() return value 2014-10-22 17:00 ` Eric Blake @ 2014-10-23 7:29 ` Max Reitz 0 siblings, 0 replies; 13+ messages in thread From: Max Reitz @ 2014-10-23 7:29 UTC (permalink / raw) To: Eric Blake, qemu-devel; +Cc: Kevin Wolf, Benoît Canet, Stefan Hajnoczi On 2014-10-22 at 19:00, Eric Blake wrote: > On 10/22/2014 09:57 AM, Max Reitz wrote: >> Instead of generating the full return value thrice in try_fiemap(), >> try_seek_hole() and as a fall-back in raw_co_get_block_status() itself, >> generate the value only in raw_co_get_block_status(). >> >> While at it, also remove the pnum parameter from try_fiemap() and >> try_seek_hole(). >> >> Suggested-by: Kevin Wolf <kwolf@redhat.com> >> Signed-off-by: Max Reitz <mreitz@redhat.com> >> --- >> block/raw-posix.c | 28 ++++++++++++++-------------- >> 1 file changed, 14 insertions(+), 14 deletions(-) > Reviewed-by: Eric Blake <eblake@redhat.com> > >> - ret = try_seek_hole(bs, start, &data, &hole, pnum); >> + ret = try_seek_hole(bs, start, &data, &hole); >> if (ret < 0) { >> - ret = try_fiemap(bs, start, &data, &hole, nb_sectors, pnum); >> + ret = try_fiemap(bs, start, &data, &hole, nb_sectors); >> if (ret < 0) { >> /* Assume everything is allocated. */ >> data = 0; >> hole = start + nb_sectors * BDRV_SECTOR_SIZE; >> - ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start; >> + ret = 0; >> } >> } >> >> + assert(ret >= 0); > I'm not sure the assertion adds much (the lines above are fairly easy to > reason about ret always being set), but it does protect against later > code addition, so I'm not opposed to leaving it. I just liked it there to make clear that the previous code always goes into a fallback, so while some parts of it may throw errors, after everything is done, we're fine. The compiler will hopefully optimize it out anyway. Max ^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v3 3/3] iotests: Add test for external image truncation 2014-10-22 15:57 [Qemu-devel] [PATCH v3 0/3] raw-posix: Fix raw_co_get_block_status() Max Reitz 2014-10-22 15:57 ` [Qemu-devel] [PATCH v3 1/3] raw-posix: Fix raw_co_get_block_status() after EOF Max Reitz 2014-10-22 15:57 ` [Qemu-devel] [PATCH v3 2/3] raw-posix: raw_co_get_block_status() return value Max Reitz @ 2014-10-22 15:57 ` Max Reitz 2014-10-22 16:50 ` Eric Blake 2 siblings, 1 reply; 13+ messages in thread From: Max Reitz @ 2014-10-22 15:57 UTC (permalink / raw) To: qemu-devel; +Cc: Kevin Wolf, Benoît Canet, Stefan Hajnoczi, Max Reitz It should not be happening, but it is possible to truncate an image outside of qemu while qemu is running (or any of the qemu tools using the block layer. raw_co_get_block_status() should not break then. Signed-off-by: Max Reitz <mreitz@redhat.com> --- tests/qemu-iotests/102 | 15 +++++++++++++++ tests/qemu-iotests/102.out | 9 +++++++++ 2 files changed, 24 insertions(+) diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102 index 34b363f..027198b 100755 --- a/tests/qemu-iotests/102 +++ b/tests/qemu-iotests/102 @@ -58,6 +58,21 @@ truncate -s $((5 * 64 * 1024)) "$TEST_IMG" $QEMU_IO -c map "$TEST_IMG" $QEMU_IMG map "$TEST_IMG" +echo +echo '=== Testing map on an image file truncated outside of qemu ===' +echo + +# Same as above, only now we concurrently truncate and map the image +_make_test_img $IMG_SIZE +$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io + +(sleep 0.2; $QEMU_IO -c map "$TEST_IMG"; $QEMU_IMG map "$TEST_IMG") & +truncate -s $((5 * 64 * 1024)) "$TEST_IMG" +# To be sure the image has been truncated before $QEMU_IO and $QEMU_IMG run +echo '--- truncated ---' + +sleep 0.3 + # success, all done echo '*** done' rm -f $seq.full diff --git a/tests/qemu-iotests/102.out b/tests/qemu-iotests/102.out index e0e9cdc..96f4a33 100644 --- a/tests/qemu-iotests/102.out +++ b/tests/qemu-iotests/102.out @@ -7,4 +7,13 @@ wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) [ 0] 128/ 128 sectors allocated at offset 0 bytes (1) Offset Length Mapped to File + +=== Testing map on an image file truncated outside of qemu === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536 +wrote 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +--- truncated --- +[ 0] 128/ 128 sectors allocated at offset 0 bytes (1) +Offset Length Mapped to File *** done -- 1.9.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v3 3/3] iotests: Add test for external image truncation 2014-10-22 15:57 ` [Qemu-devel] [PATCH v3 3/3] iotests: Add test for external image truncation Max Reitz @ 2014-10-22 16:50 ` Eric Blake 2014-10-23 7:26 ` Max Reitz 0 siblings, 1 reply; 13+ messages in thread From: Eric Blake @ 2014-10-22 16:50 UTC (permalink / raw) To: Max Reitz, qemu-devel; +Cc: Kevin Wolf, Benoît Canet, Stefan Hajnoczi [-- Attachment #1: Type: text/plain, Size: 2551 bytes --] On 10/22/2014 09:57 AM, Max Reitz wrote: > It should not be happening, but it is possible to truncate an image > outside of qemu while qemu is running (or any of the qemu tools using > the block layer. raw_co_get_block_status() should not break then. > > Signed-off-by: Max Reitz <mreitz@redhat.com> > --- > tests/qemu-iotests/102 | 15 +++++++++++++++ > tests/qemu-iotests/102.out | 9 +++++++++ > 2 files changed, 24 insertions(+) > > diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102 > index 34b363f..027198b 100755 > --- a/tests/qemu-iotests/102 > +++ b/tests/qemu-iotests/102 > @@ -58,6 +58,21 @@ truncate -s $((5 * 64 * 1024)) "$TEST_IMG" > $QEMU_IO -c map "$TEST_IMG" > $QEMU_IMG map "$TEST_IMG" > > +echo > +echo '=== Testing map on an image file truncated outside of qemu ===' > +echo > + > +# Same as above, only now we concurrently truncate and map the image > +_make_test_img $IMG_SIZE > +$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io > + > +(sleep 0.2; $QEMU_IO -c map "$TEST_IMG"; $QEMU_IMG map "$TEST_IMG") & Should you use '&&' instead of ';' between the three operations, to ensure that you can detect failure of the overall background subshell? [1] Fractional sleep is a GNU extension, and won't work on BSD. It adds .8 seconds to make this sleep 1, but the extra portability may be worth it. It also makes the test more robust, and less likely to fail a race in a heavily-loaded tester. Then again, it is not the first use of fractional sleep in the testsuite. Hmm - does the blkdebug driver allow us to pause qemu operation to reliably allow an external action callback, and then resume qemu? That might be less prone to race failure, as well as reducing the need to blindly sleep for a fixed amount of time. > +truncate -s $((5 * 64 * 1024)) "$TEST_IMG" truncate is a GNU program, not necessarily available on all platforms; but this is not the first test using it. > +# To be sure the image has been truncated before $QEMU_IO and $QEMU_IMG run > +echo '--- truncated ---' > + > +sleep 0.3 > + > # success, all done I think you should have a 'wait' here to reap the background child process before declaring this test all done. Particularly if you take my advice above[1] about detecting errors. Looks like a good start, but I'm worried about false positives if you can't guarantee some timing between actions. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 539 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v3 3/3] iotests: Add test for external image truncation 2014-10-22 16:50 ` Eric Blake @ 2014-10-23 7:26 ` Max Reitz 2014-10-23 7:46 ` Kevin Wolf 0 siblings, 1 reply; 13+ messages in thread From: Max Reitz @ 2014-10-23 7:26 UTC (permalink / raw) To: Eric Blake, qemu-devel; +Cc: Kevin Wolf, Benoît Canet, Stefan Hajnoczi On 2014-10-22 at 18:50, Eric Blake wrote: > On 10/22/2014 09:57 AM, Max Reitz wrote: >> It should not be happening, but it is possible to truncate an image >> outside of qemu while qemu is running (or any of the qemu tools using >> the block layer. raw_co_get_block_status() should not break then. >> >> Signed-off-by: Max Reitz <mreitz@redhat.com> >> --- >> tests/qemu-iotests/102 | 15 +++++++++++++++ >> tests/qemu-iotests/102.out | 9 +++++++++ >> 2 files changed, 24 insertions(+) >> >> diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102 >> index 34b363f..027198b 100755 >> --- a/tests/qemu-iotests/102 >> +++ b/tests/qemu-iotests/102 >> @@ -58,6 +58,21 @@ truncate -s $((5 * 64 * 1024)) "$TEST_IMG" >> $QEMU_IO -c map "$TEST_IMG" >> $QEMU_IMG map "$TEST_IMG" >> >> +echo >> +echo '=== Testing map on an image file truncated outside of qemu ===' >> +echo >> + >> +# Same as above, only now we concurrently truncate and map the image >> +_make_test_img $IMG_SIZE >> +$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io >> + >> +(sleep 0.2; $QEMU_IO -c map "$TEST_IMG"; $QEMU_IMG map "$TEST_IMG") & > Should you use '&&' instead of ';' between the three operations, to > ensure that you can detect failure of the overall background subshell? [1] No, I don't think so. The output is compared against the test output and I probably want to have both the output of qemu-io -c map and qemu-img map, even if one fails. > Fractional sleep is a GNU extension, and won't work on BSD. It adds .8 > seconds to make this sleep 1, but the extra portability may be worth it. Probably so, yes. > It also makes the test more robust, and less likely to fail a race in a > heavily-loaded tester. Then again, it is not the first use of > fractional sleep in the testsuite. > > Hmm - does the blkdebug driver allow us to pause qemu operation to > reliably allow an external action callback, and then resume qemu? That > might be less prone to race failure, as well as reducing the need to > blindly sleep for a fixed amount of time. It does not yet. But when you're asking like this, I'm willing to build a time block driver which pauses one second for every sector you're reading from it. Okay, so without kidding, I think to make this right, we could try to keep qemu-io open, do the truncate, and then continue writing commands to qemu-io. I think I can do that by not using qemu-io but qemu directly and then use the common.qemu functions (along with HMP qemu-io). Of course, this makes testing qemu-img map impossible, but using blkdebug would have done the same, probably. Also, just qemu-io -c map should be enough for this case. >> +truncate -s $((5 * 64 * 1024)) "$TEST_IMG" > truncate is a GNU program, not necessarily available on all platforms; > but this is not the first test using it. Well, if it's not the first test, I'm inclined to leave it. But since I'm going to respin anyway and you're asking so kindly, I'll reach deep into my box of tricks and use qemu-img resize "json:{'driver':'raw','file':{'driver':'file','filename':'$TEST_IMG'}}" $((5 * 64 * 1024)). Speaking of resize not taking a format, we should probably at some point in time add an input format parameter to all of the qemu-img subcommands (resize and snapshot don't have one yet). >> +# To be sure the image has been truncated before $QEMU_IO and $QEMU_IMG run >> +echo '--- truncated ---' >> + >> +sleep 0.3 >> + >> # success, all done > I think you should have a 'wait' here to reap the background child > process before declaring this test all done. Particularly if you take > my advice above[1] about detecting errors. Will probably not take the advice (unless I failed to understand you correctly and you can convince me otherwise), but will use `wait` anyway. > Looks like a good start, but I'm worried about false positives if you > can't guarantee some timing between actions. Yes, you're right. Thanks! Max ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v3 3/3] iotests: Add test for external image truncation 2014-10-23 7:26 ` Max Reitz @ 2014-10-23 7:46 ` Kevin Wolf 2014-10-23 7:47 ` Max Reitz 0 siblings, 1 reply; 13+ messages in thread From: Kevin Wolf @ 2014-10-23 7:46 UTC (permalink / raw) To: Max Reitz; +Cc: qemu-devel, Stefan Hajnoczi, Benoît Canet Am 23.10.2014 um 09:26 hat Max Reitz geschrieben: > On 2014-10-22 at 18:50, Eric Blake wrote: > >On 10/22/2014 09:57 AM, Max Reitz wrote: > >>It should not be happening, but it is possible to truncate an image > >>outside of qemu while qemu is running (or any of the qemu tools using > >>the block layer. raw_co_get_block_status() should not break then. > >> > >>Signed-off-by: Max Reitz <mreitz@redhat.com> > >>--- > >> tests/qemu-iotests/102 | 15 +++++++++++++++ > >> tests/qemu-iotests/102.out | 9 +++++++++ > >> 2 files changed, 24 insertions(+) > >> > >>diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102 > >>index 34b363f..027198b 100755 > >>--- a/tests/qemu-iotests/102 > >>+++ b/tests/qemu-iotests/102 > >>@@ -58,6 +58,21 @@ truncate -s $((5 * 64 * 1024)) "$TEST_IMG" > >> $QEMU_IO -c map "$TEST_IMG" > >> $QEMU_IMG map "$TEST_IMG" > >>+echo > >>+echo '=== Testing map on an image file truncated outside of qemu ===' > >>+echo > >>+ > >>+# Same as above, only now we concurrently truncate and map the image > >>+_make_test_img $IMG_SIZE > >>+$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io > >>+ > >>+(sleep 0.2; $QEMU_IO -c map "$TEST_IMG"; $QEMU_IMG map "$TEST_IMG") & > >Should you use '&&' instead of ';' between the three operations, to > >ensure that you can detect failure of the overall background subshell? [1] > > No, I don't think so. The output is compared against the test output > and I probably want to have both the output of qemu-io -c map and > qemu-img map, even if one fails. > > >Fractional sleep is a GNU extension, and won't work on BSD. It adds .8 > >seconds to make this sleep 1, but the extra portability may be worth it. > > Probably so, yes. > > >It also makes the test more robust, and less likely to fail a race in a > >heavily-loaded tester. Then again, it is not the first use of > >fractional sleep in the testsuite. > > > >Hmm - does the blkdebug driver allow us to pause qemu operation to > >reliably allow an external action callback, and then resume qemu? That > >might be less prone to race failure, as well as reducing the need to > >blindly sleep for a fixed amount of time. > > It does not yet. But when you're asking like this, I'm willing to > build a time block driver which pauses one second for every sector > you're reading from it. > > Okay, so without kidding, I think to make this right, we could try > to keep qemu-io open, do the truncate, and then continue writing > commands to qemu-io. I think I can do that by not using qemu-io but > qemu directly and then use the common.qemu functions (along with HMP > qemu-io). Of course, this makes testing qemu-img map impossible, but > using blkdebug would have done the same, probably. Also, just > qemu-io -c map should be enough for this case. It should be possible to stop qemu-img at a good enough place with blkdebug. The problem would just be how to resume... I agree that the qemu-img test doesn't add much here anyway. > >>+truncate -s $((5 * 64 * 1024)) "$TEST_IMG" > >truncate is a GNU program, not necessarily available on all platforms; > >but this is not the first test using it. > > Well, if it's not the first test, I'm inclined to leave it. But > since I'm going to respin anyway and you're asking so kindly, I'll > reach deep into my box of tricks and use qemu-img resize "json:{'driver':'raw','file':{'driver':'file','filename':'$TEST_IMG'}}" > $((5 * 64 * 1024)). What's wrong with 'qemu-img resize -f raw "$TEST_IMG"'? Also doesn't hardcode the protocol. > Speaking of resize not taking a format, we should probably at some > point in time add an input format parameter to all of the qemu-img > subcommands (resize and snapshot don't have one yet). Well, _my_ resize does have one and has been there since resize was introduced in 2010 (commit ae6b0ed6). Kevin ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v3 3/3] iotests: Add test for external image truncation 2014-10-23 7:46 ` Kevin Wolf @ 2014-10-23 7:47 ` Max Reitz 0 siblings, 0 replies; 13+ messages in thread From: Max Reitz @ 2014-10-23 7:47 UTC (permalink / raw) To: Kevin Wolf; +Cc: qemu-devel, Stefan Hajnoczi, Benoît Canet On 2014-10-23 at 09:46, Kevin Wolf wrote: > Am 23.10.2014 um 09:26 hat Max Reitz geschrieben: >> On 2014-10-22 at 18:50, Eric Blake wrote: >>> On 10/22/2014 09:57 AM, Max Reitz wrote: >>>> It should not be happening, but it is possible to truncate an image >>>> outside of qemu while qemu is running (or any of the qemu tools using >>>> the block layer. raw_co_get_block_status() should not break then. >>>> >>>> Signed-off-by: Max Reitz <mreitz@redhat.com> >>>> --- >>>> tests/qemu-iotests/102 | 15 +++++++++++++++ >>>> tests/qemu-iotests/102.out | 9 +++++++++ >>>> 2 files changed, 24 insertions(+) >>>> >>>> diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102 >>>> index 34b363f..027198b 100755 >>>> --- a/tests/qemu-iotests/102 >>>> +++ b/tests/qemu-iotests/102 >>>> @@ -58,6 +58,21 @@ truncate -s $((5 * 64 * 1024)) "$TEST_IMG" >>>> $QEMU_IO -c map "$TEST_IMG" >>>> $QEMU_IMG map "$TEST_IMG" >>>> +echo >>>> +echo '=== Testing map on an image file truncated outside of qemu ===' >>>> +echo >>>> + >>>> +# Same as above, only now we concurrently truncate and map the image >>>> +_make_test_img $IMG_SIZE >>>> +$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io >>>> + >>>> +(sleep 0.2; $QEMU_IO -c map "$TEST_IMG"; $QEMU_IMG map "$TEST_IMG") & >>> Should you use '&&' instead of ';' between the three operations, to >>> ensure that you can detect failure of the overall background subshell? [1] >> No, I don't think so. The output is compared against the test output >> and I probably want to have both the output of qemu-io -c map and >> qemu-img map, even if one fails. >> >>> Fractional sleep is a GNU extension, and won't work on BSD. It adds .8 >>> seconds to make this sleep 1, but the extra portability may be worth it. >> Probably so, yes. >> >>> It also makes the test more robust, and less likely to fail a race in a >>> heavily-loaded tester. Then again, it is not the first use of >>> fractional sleep in the testsuite. >>> >>> Hmm - does the blkdebug driver allow us to pause qemu operation to >>> reliably allow an external action callback, and then resume qemu? That >>> might be less prone to race failure, as well as reducing the need to >>> blindly sleep for a fixed amount of time. >> It does not yet. But when you're asking like this, I'm willing to >> build a time block driver which pauses one second for every sector >> you're reading from it. >> >> Okay, so without kidding, I think to make this right, we could try >> to keep qemu-io open, do the truncate, and then continue writing >> commands to qemu-io. I think I can do that by not using qemu-io but >> qemu directly and then use the common.qemu functions (along with HMP >> qemu-io). Of course, this makes testing qemu-img map impossible, but >> using blkdebug would have done the same, probably. Also, just >> qemu-io -c map should be enough for this case. > It should be possible to stop qemu-img at a good enough place with > blkdebug. The problem would just be how to resume... > > I agree that the qemu-img test doesn't add much here anyway. > >>>> +truncate -s $((5 * 64 * 1024)) "$TEST_IMG" >>> truncate is a GNU program, not necessarily available on all platforms; >>> but this is not the first test using it. >> Well, if it's not the first test, I'm inclined to leave it. But >> since I'm going to respin anyway and you're asking so kindly, I'll >> reach deep into my box of tricks and use qemu-img resize "json:{'driver':'raw','file':{'driver':'file','filename':'$TEST_IMG'}}" >> $((5 * 64 * 1024)). > What's wrong with 'qemu-img resize -f raw "$TEST_IMG"'? Also doesn't > hardcode the protocol. > >> Speaking of resize not taking a format, we should probably at some >> point in time add an input format parameter to all of the qemu-img >> subcommands (resize and snapshot don't have one yet). > Well, _my_ resize does have one and has been there since resize was > introduced in 2010 (commit ae6b0ed6). Tell that to my qemu-img --help. :-P Max ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2014-10-23 7:47 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-10-22 15:57 [Qemu-devel] [PATCH v3 0/3] raw-posix: Fix raw_co_get_block_status() Max Reitz 2014-10-22 15:57 ` [Qemu-devel] [PATCH v3 1/3] raw-posix: Fix raw_co_get_block_status() after EOF Max Reitz 2014-10-22 16:57 ` Eric Blake 2014-10-23 7:27 ` Max Reitz 2014-10-23 7:28 ` Max Reitz 2014-10-22 15:57 ` [Qemu-devel] [PATCH v3 2/3] raw-posix: raw_co_get_block_status() return value Max Reitz 2014-10-22 17:00 ` Eric Blake 2014-10-23 7:29 ` Max Reitz 2014-10-22 15:57 ` [Qemu-devel] [PATCH v3 3/3] iotests: Add test for external image truncation Max Reitz 2014-10-22 16:50 ` Eric Blake 2014-10-23 7:26 ` Max Reitz 2014-10-23 7:46 ` Kevin Wolf 2014-10-23 7:47 ` Max Reitz
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).