All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 1/1] parallels: wrong call to bdrv_truncate
@ 2017-03-27 14:38 Denis V. Lunev
  2017-03-28 10:07 ` Stefan Hajnoczi
  2017-03-28 16:26 ` Kevin Wolf
  0 siblings, 2 replies; 9+ messages in thread
From: Denis V. Lunev @ 2017-03-27 14:38 UTC (permalink / raw)
  To: qemu-devel; +Cc: Denis V. Lunev, Stefan Hajnoczi

Parallels driver should not call bdrv_truncate if the image was opened
in the read-only mode. Without the patch
    qemu-img check harddisk.hds
asserts with
    bdrv_truncate: Assertion `child->perm & BLK_PERM_RESIZE' failed.

Parameters used on the write path are not needed if the image is opened
in the read-only mode.

Signed-off-by: Denis V. Lunev <den@openvz.org>
Reported-by: Edgar Kaziahmedov <edos@virtuozzo.mipt.ru>
CC: Stefan Hajnoczi <stefanha@redhat.com>
---
 block/parallels.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/block/parallels.c b/block/parallels.c
index 6bf9375..4173b3f 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -687,7 +687,8 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
     if (local_err != NULL) {
         goto fail_options;
     }
-    if (!bdrv_has_zero_init(bs->file->bs) ||
+
+    if (!(flags & BDRV_O_RESIZE) || !bdrv_has_zero_init(bs->file->bs) ||
             bdrv_truncate(bs->file, bdrv_getlength(bs->file->bs)) != 0) {
         s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
     }
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] parallels: wrong call to bdrv_truncate
  2017-03-27 14:38 [Qemu-devel] [PATCH 1/1] parallels: wrong call to bdrv_truncate Denis V. Lunev
@ 2017-03-28 10:07 ` Stefan Hajnoczi
  2017-03-28 16:26 ` Kevin Wolf
  1 sibling, 0 replies; 9+ messages in thread
From: Stefan Hajnoczi @ 2017-03-28 10:07 UTC (permalink / raw)
  To: Denis V. Lunev; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 752 bytes --]

On Mon, Mar 27, 2017 at 05:38:08PM +0300, Denis V. Lunev wrote:
> Parallels driver should not call bdrv_truncate if the image was opened
> in the read-only mode. Without the patch
>     qemu-img check harddisk.hds
> asserts with
>     bdrv_truncate: Assertion `child->perm & BLK_PERM_RESIZE' failed.
> 
> Parameters used on the write path are not needed if the image is opened
> in the read-only mode.
> 
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> Reported-by: Edgar Kaziahmedov <edos@virtuozzo.mipt.ru>
> CC: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>  block/parallels.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

Thanks, applied to my block tree:
https://github.com/stefanha/qemu/commits/block

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] parallels: wrong call to bdrv_truncate
  2017-03-27 14:38 [Qemu-devel] [PATCH 1/1] parallels: wrong call to bdrv_truncate Denis V. Lunev
  2017-03-28 10:07 ` Stefan Hajnoczi
@ 2017-03-28 16:26 ` Kevin Wolf
  2017-03-28 17:12   ` Denis V. Lunev
  1 sibling, 1 reply; 9+ messages in thread
From: Kevin Wolf @ 2017-03-28 16:26 UTC (permalink / raw)
  To: Denis V. Lunev; +Cc: qemu-devel, Stefan Hajnoczi, qemu-block

[ Cc: qemu-block ]

Am 27.03.2017 um 16:38 hat Denis V. Lunev geschrieben:
> Parallels driver should not call bdrv_truncate if the image was opened
> in the read-only mode. Without the patch
>     qemu-img check harddisk.hds
> asserts with
>     bdrv_truncate: Assertion `child->perm & BLK_PERM_RESIZE' failed.
> 
> Parameters used on the write path are not needed if the image is opened
> in the read-only mode.
> 
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> Reported-by: Edgar Kaziahmedov <edos@virtuozzo.mipt.ru>
> CC: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>  block/parallels.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/block/parallels.c b/block/parallels.c
> index 6bf9375..4173b3f 100644
> --- a/block/parallels.c
> +++ b/block/parallels.c
> @@ -687,7 +687,8 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
>      if (local_err != NULL) {
>          goto fail_options;
>      }
> -    if (!bdrv_has_zero_init(bs->file->bs) ||
> +
> +    if (!(flags & BDRV_O_RESIZE) || !bdrv_has_zero_init(bs->file->bs) ||
>              bdrv_truncate(bs->file, bdrv_getlength(bs->file->bs)) != 0) {
>          s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
>      }

Relying on BDRV_O_RESIZE in block drivers is wrong. It is set in some
paths (specifically the users of blk_new_open), but not in others. We
should probably have filtered out the flag before passing it to the
drivers.

As a concrete example, if you're using -blockdev, the bdrv_truncate()
call won't be executed after applying this patch.

I think the correct way would be to check bdrv_is_read_only() instead.

Kevin

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] parallels: wrong call to bdrv_truncate
  2017-03-28 16:26 ` Kevin Wolf
@ 2017-03-28 17:12   ` Denis V. Lunev
  2017-03-29 10:41     ` Kevin Wolf
  0 siblings, 1 reply; 9+ messages in thread
From: Denis V. Lunev @ 2017-03-28 17:12 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel, Stefan Hajnoczi, qemu-block

On 03/28/2017 07:26 PM, Kevin Wolf wrote:
> [ Cc: qemu-block ]
>
> Am 27.03.2017 um 16:38 hat Denis V. Lunev geschrieben:
>> Parallels driver should not call bdrv_truncate if the image was opened
>> in the read-only mode. Without the patch
>>     qemu-img check harddisk.hds
>> asserts with
>>     bdrv_truncate: Assertion `child->perm & BLK_PERM_RESIZE' failed.
>>
>> Parameters used on the write path are not needed if the image is opened
>> in the read-only mode.
>>
>> Signed-off-by: Denis V. Lunev <den@openvz.org>
>> Reported-by: Edgar Kaziahmedov <edos@virtuozzo.mipt.ru>
>> CC: Stefan Hajnoczi <stefanha@redhat.com>
>> ---
>>  block/parallels.c | 3 ++-
>>  1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/block/parallels.c b/block/parallels.c
>> index 6bf9375..4173b3f 100644
>> --- a/block/parallels.c
>> +++ b/block/parallels.c
>> @@ -687,7 +687,8 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
>>      if (local_err != NULL) {
>>          goto fail_options;
>>      }
>> -    if (!bdrv_has_zero_init(bs->file->bs) ||
>> +
>> +    if (!(flags & BDRV_O_RESIZE) || !bdrv_has_zero_init(bs->file->bs) ||
>>              bdrv_truncate(bs->file, bdrv_getlength(bs->file->bs)) != 0) {
>>          s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
>>      }
> Relying on BDRV_O_RESIZE in block drivers is wrong. It is set in some
> paths (specifically the users of blk_new_open), but not in others. We
> should probably have filtered out the flag before passing it to the
> drivers.
>
> As a concrete example, if you're using -blockdev, the bdrv_truncate()
> call won't be executed after applying this patch.
>
> I think the correct way would be to check bdrv_is_read_only() instead.
>
> Kevin
hmmm. But why do we have

int bdrv_truncate(BdrvChild *child, int64_t offset)
{
    BlockDriverState *bs = child->bs;
    BlockDriver *drv = bs->drv;
    int ret;

    assert(child->perm & BLK_PERM_RESIZE);

    if (!drv)
        return -ENOMEDIUM;
    if (!drv->bdrv_truncate)
        return -ENOTSUP;
    if (bs->read_only)
        return -EACCES;

    ret = drv->bdrv_truncate(bs, offset);

instead of

int bdrv_truncate(BdrvChild *child, int64_t offset)
{
    BlockDriverState *bs = child->bs;
    BlockDriver *drv = bs->drv;
    int ret;

    if (!drv)
        return -ENOMEDIUM;
    if (!drv->bdrv_truncate)
        return -ENOTSUP;
    if (bs->read_only)
        return -EACCES;

    assert(child->perm & BLK_PERM_RESIZE);
    ret = drv->bdrv_truncate(bs, offset);

technically this will work properly for my case and calling of
bdrv_truncate could be valid.

Another thing, should we add assert like added into bdrv_co_pwritev,
namely
    assert(!(bs->open_flags & BDRV_O_INACTIVE));
in the same place below access check.

Technically, the requested change is not a problem it looks a bit
strange and not consistent to me.

Den

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] parallels: wrong call to bdrv_truncate
  2017-03-28 17:12   ` Denis V. Lunev
@ 2017-03-29 10:41     ` Kevin Wolf
  2017-03-29 13:53       ` Denis V. Lunev
  0 siblings, 1 reply; 9+ messages in thread
From: Kevin Wolf @ 2017-03-29 10:41 UTC (permalink / raw)
  To: Denis V. Lunev; +Cc: qemu-devel, Stefan Hajnoczi, qemu-block

Am 28.03.2017 um 19:12 hat Denis V. Lunev geschrieben:
> On 03/28/2017 07:26 PM, Kevin Wolf wrote:
> > [ Cc: qemu-block ]
> >
> > Am 27.03.2017 um 16:38 hat Denis V. Lunev geschrieben:
> >> Parallels driver should not call bdrv_truncate if the image was opened
> >> in the read-only mode. Without the patch
> >>     qemu-img check harddisk.hds
> >> asserts with
> >>     bdrv_truncate: Assertion `child->perm & BLK_PERM_RESIZE' failed.
> >>
> >> Parameters used on the write path are not needed if the image is opened
> >> in the read-only mode.
> >>
> >> Signed-off-by: Denis V. Lunev <den@openvz.org>
> >> Reported-by: Edgar Kaziahmedov <edos@virtuozzo.mipt.ru>
> >> CC: Stefan Hajnoczi <stefanha@redhat.com>
> >> ---
> >>  block/parallels.c | 3 ++-
> >>  1 file changed, 2 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/block/parallels.c b/block/parallels.c
> >> index 6bf9375..4173b3f 100644
> >> --- a/block/parallels.c
> >> +++ b/block/parallels.c
> >> @@ -687,7 +687,8 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
> >>      if (local_err != NULL) {
> >>          goto fail_options;
> >>      }
> >> -    if (!bdrv_has_zero_init(bs->file->bs) ||
> >> +
> >> +    if (!(flags & BDRV_O_RESIZE) || !bdrv_has_zero_init(bs->file->bs) ||
> >>              bdrv_truncate(bs->file, bdrv_getlength(bs->file->bs)) != 0) {
> >>          s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
> >>      }
> > Relying on BDRV_O_RESIZE in block drivers is wrong. It is set in some
> > paths (specifically the users of blk_new_open), but not in others. We
> > should probably have filtered out the flag before passing it to the
> > drivers.
> >
> > As a concrete example, if you're using -blockdev, the bdrv_truncate()
> > call won't be executed after applying this patch.
> >
> > I think the correct way would be to check bdrv_is_read_only() instead.
> >
> > Kevin
> hmmm. But why do we have
> 
> int bdrv_truncate(BdrvChild *child, int64_t offset)
> {
>     BlockDriverState *bs = child->bs;
>     BlockDriver *drv = bs->drv;
>     int ret;
> 
>     assert(child->perm & BLK_PERM_RESIZE);
> 
>     if (!drv)
>         return -ENOMEDIUM;
>     if (!drv->bdrv_truncate)
>         return -ENOTSUP;
>     if (bs->read_only)
>         return -EACCES;
> 
>     ret = drv->bdrv_truncate(bs, offset);
> 
> instead of
> 
> int bdrv_truncate(BdrvChild *child, int64_t offset)
> {
>     BlockDriverState *bs = child->bs;
>     BlockDriver *drv = bs->drv;
>     int ret;
> 
>     if (!drv)
>         return -ENOMEDIUM;
>     if (!drv->bdrv_truncate)
>         return -ENOTSUP;
>     if (bs->read_only)
>         return -EACCES;
> 
>     assert(child->perm & BLK_PERM_RESIZE);
>     ret = drv->bdrv_truncate(bs, offset);
> 
> technically this will work properly for my case and calling of
> bdrv_truncate could be valid.

The question is what the contract of bdrv_truncate() is. I think "you
can only call this when you got resize permissions" is the clearest
interface, and the current code enforces it.

Your proposal would change it into "you can only call this when you get
resize permissions, except when it would fail anyway because the image
is closed, the driver doesn't support resizing or the node is
read-only". I wouldn't make such exceptions unless there is a good
reason to have them, e.g. if it made the life of the callers
substantially easier. But it don't think it does in this case.

> Another thing, should we add assert like added into bdrv_co_pwritev,
> namely
>     assert(!(bs->open_flags & BDRV_O_INACTIVE));
> in the same place below access check.

You mean asserting that we have write permission? We already do that in
bdrv_aligned_pwritev(), which is called by bdrv_co_pwritev().

> Technically, the requested change is not a problem it looks a bit
> strange and not consistent to me.

Hm, okay? Why do you think so? To me, it feels correct that
bdrv_truncate() can only be called for writable images.

It's the current code in the parallels driver that calls it for
read-only images and implicitly expects an error return on the normal
code path (without even having a comment about this) that feels somewhat
unclean to me.

Kevin

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] parallels: wrong call to bdrv_truncate
  2017-03-29 10:41     ` Kevin Wolf
@ 2017-03-29 13:53       ` Denis V. Lunev
  2017-03-29 14:11         ` Kevin Wolf
  0 siblings, 1 reply; 9+ messages in thread
From: Denis V. Lunev @ 2017-03-29 13:53 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel, Stefan Hajnoczi, qemu-block

On 03/29/2017 01:41 PM, Kevin Wolf wrote:
> Am 28.03.2017 um 19:12 hat Denis V. Lunev geschrieben:
>> On 03/28/2017 07:26 PM, Kevin Wolf wrote:
>>> [ Cc: qemu-block ]
>>>
>>> Am 27.03.2017 um 16:38 hat Denis V. Lunev geschrieben:
>>>> Parallels driver should not call bdrv_truncate if the image was opened
>>>> in the read-only mode. Without the patch
>>>>     qemu-img check harddisk.hds
>>>> asserts with
>>>>     bdrv_truncate: Assertion `child->perm & BLK_PERM_RESIZE' failed.
>>>>
>>>> Parameters used on the write path are not needed if the image is opened
>>>> in the read-only mode.
>>>>
>>>> Signed-off-by: Denis V. Lunev <den@openvz.org>
>>>> Reported-by: Edgar Kaziahmedov <edos@virtuozzo.mipt.ru>
>>>> CC: Stefan Hajnoczi <stefanha@redhat.com>
>>>> ---
>>>>  block/parallels.c | 3 ++-
>>>>  1 file changed, 2 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/block/parallels.c b/block/parallels.c
>>>> index 6bf9375..4173b3f 100644
>>>> --- a/block/parallels.c
>>>> +++ b/block/parallels.c
>>>> @@ -687,7 +687,8 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
>>>>      if (local_err != NULL) {
>>>>          goto fail_options;
>>>>      }
>>>> -    if (!bdrv_has_zero_init(bs->file->bs) ||
>>>> +
>>>> +    if (!(flags & BDRV_O_RESIZE) || !bdrv_has_zero_init(bs->file->bs) ||
>>>>              bdrv_truncate(bs->file, bdrv_getlength(bs->file->bs)) != 0) {
>>>>          s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
>>>>      }
>>> Relying on BDRV_O_RESIZE in block drivers is wrong. It is set in some
>>> paths (specifically the users of blk_new_open), but not in others. We
>>> should probably have filtered out the flag before passing it to the
>>> drivers.
>>>
>>> As a concrete example, if you're using -blockdev, the bdrv_truncate()
>>> call won't be executed after applying this patch.
>>>
>>> I think the correct way would be to check bdrv_is_read_only() instead.
>>>
>>> Kevin
>> hmmm. But why do we have
>>
>> int bdrv_truncate(BdrvChild *child, int64_t offset)
>> {
>>     BlockDriverState *bs = child->bs;
>>     BlockDriver *drv = bs->drv;
>>     int ret;
>>
>>     assert(child->perm & BLK_PERM_RESIZE);
>>
>>     if (!drv)
>>         return -ENOMEDIUM;
>>     if (!drv->bdrv_truncate)
>>         return -ENOTSUP;
>>     if (bs->read_only)
>>         return -EACCES;
>>
>>     ret = drv->bdrv_truncate(bs, offset);
>>
>> instead of
>>
>> int bdrv_truncate(BdrvChild *child, int64_t offset)
>> {
>>     BlockDriverState *bs = child->bs;
>>     BlockDriver *drv = bs->drv;
>>     int ret;
>>
>>     if (!drv)
>>         return -ENOMEDIUM;
>>     if (!drv->bdrv_truncate)
>>         return -ENOTSUP;
>>     if (bs->read_only)
>>         return -EACCES;
>>
>>     assert(child->perm & BLK_PERM_RESIZE);
>>     ret = drv->bdrv_truncate(bs, offset);
>>
>> technically this will work properly for my case and calling of
>> bdrv_truncate could be valid.
> The question is what the contract of bdrv_truncate() is. I think "you
> can only call this when you got resize permissions" is the clearest
> interface, and the current code enforces it.
but in the original patch I have made check exactly over this simple
condition and you says that it was not accurate. If this is wrong, I'll be
rejected later on with EACCESS and will still be on the safe side.
Original patch just avoids the assert().

> Your proposal would change it into "you can only call this when you get
> resize permissions, except when it would fail anyway because the image
> is closed, the driver doesn't support resizing or the node is
> read-only". I wouldn't make such exceptions unless there is a good
> reason to have them, e.g. if it made the life of the callers
> substantially easier. But it don't think it does in this case.
Actually we have had an error condition as the image was really read-only
and all was safe. Right now we have an assert even if the image is
read-only.
This looks the same to me as to raise an assert in write for read-only
image. Is there any difference?


>> Another thing, should we add assert like added into bdrv_co_pwritev,
>> namely
>>     assert(!(bs->open_flags & BDRV_O_INACTIVE));
>> in the same place below access check.
> You mean asserting that we have write permission? We already do that in
> bdrv_aligned_pwritev(), which is called by bdrv_co_pwritev().
I mean that we should disallow image change if it is disallowed
by the contract. Current contract says that we can not change
image content once BDRV_O_INACTIVE is set. Should we
Do we have implicit rule that (child->perm & BLK_PERM_RESIZE)
is set only when INACTIVE is not set?

>> Technically, the requested change is not a problem it looks a bit
>> strange and not consistent to me.
> Hm, okay? Why do you think so? To me, it feels correct that
> bdrv_truncate() can only be called for writable images.
I was unclear here. I have trying to say that "the change requested by you
is not a problem, I'll do that once we will agree". Sorry :(

> It's the current code in the parallels driver that calls it for
> read-only images and implicitly expects an error return on the normal
> code path (without even having a comment about this) that feels somewhat
> unclean to me.
Actually I tend to drop this truncate at all. It was set for a state of
insurance and should not be actually used.

Den

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] parallels: wrong call to bdrv_truncate
  2017-03-29 13:53       ` Denis V. Lunev
@ 2017-03-29 14:11         ` Kevin Wolf
  2017-03-29 14:18           ` Denis V. Lunev
  0 siblings, 1 reply; 9+ messages in thread
From: Kevin Wolf @ 2017-03-29 14:11 UTC (permalink / raw)
  To: Denis V. Lunev; +Cc: qemu-devel, Stefan Hajnoczi, qemu-block

Am 29.03.2017 um 15:53 hat Denis V. Lunev geschrieben:
> On 03/29/2017 01:41 PM, Kevin Wolf wrote:
> > Am 28.03.2017 um 19:12 hat Denis V. Lunev geschrieben:
> >> On 03/28/2017 07:26 PM, Kevin Wolf wrote:
> >>> [ Cc: qemu-block ]
> >>>
> >>> Am 27.03.2017 um 16:38 hat Denis V. Lunev geschrieben:
> >>>> Parallels driver should not call bdrv_truncate if the image was opened
> >>>> in the read-only mode. Without the patch
> >>>>     qemu-img check harddisk.hds
> >>>> asserts with
> >>>>     bdrv_truncate: Assertion `child->perm & BLK_PERM_RESIZE' failed.
> >>>>
> >>>> Parameters used on the write path are not needed if the image is opened
> >>>> in the read-only mode.
> >>>>
> >>>> Signed-off-by: Denis V. Lunev <den@openvz.org>
> >>>> Reported-by: Edgar Kaziahmedov <edos@virtuozzo.mipt.ru>
> >>>> CC: Stefan Hajnoczi <stefanha@redhat.com>
> >>>> ---
> >>>>  block/parallels.c | 3 ++-
> >>>>  1 file changed, 2 insertions(+), 1 deletion(-)
> >>>>
> >>>> diff --git a/block/parallels.c b/block/parallels.c
> >>>> index 6bf9375..4173b3f 100644
> >>>> --- a/block/parallels.c
> >>>> +++ b/block/parallels.c
> >>>> @@ -687,7 +687,8 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
> >>>>      if (local_err != NULL) {
> >>>>          goto fail_options;
> >>>>      }
> >>>> -    if (!bdrv_has_zero_init(bs->file->bs) ||
> >>>> +
> >>>> +    if (!(flags & BDRV_O_RESIZE) || !bdrv_has_zero_init(bs->file->bs) ||
> >>>>              bdrv_truncate(bs->file, bdrv_getlength(bs->file->bs)) != 0) {
> >>>>          s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
> >>>>      }
> >>> Relying on BDRV_O_RESIZE in block drivers is wrong. It is set in some
> >>> paths (specifically the users of blk_new_open), but not in others. We
> >>> should probably have filtered out the flag before passing it to the
> >>> drivers.
> >>>
> >>> As a concrete example, if you're using -blockdev, the bdrv_truncate()
> >>> call won't be executed after applying this patch.
> >>>
> >>> I think the correct way would be to check bdrv_is_read_only() instead.
> >>>
> >>> Kevin
> >> hmmm. But why do we have
> >>
> >> int bdrv_truncate(BdrvChild *child, int64_t offset)
> >> {
> >>     BlockDriverState *bs = child->bs;
> >>     BlockDriver *drv = bs->drv;
> >>     int ret;
> >>
> >>     assert(child->perm & BLK_PERM_RESIZE);
> >>
> >>     if (!drv)
> >>         return -ENOMEDIUM;
> >>     if (!drv->bdrv_truncate)
> >>         return -ENOTSUP;
> >>     if (bs->read_only)
> >>         return -EACCES;
> >>
> >>     ret = drv->bdrv_truncate(bs, offset);
> >>
> >> instead of
> >>
> >> int bdrv_truncate(BdrvChild *child, int64_t offset)
> >> {
> >>     BlockDriverState *bs = child->bs;
> >>     BlockDriver *drv = bs->drv;
> >>     int ret;
> >>
> >>     if (!drv)
> >>         return -ENOMEDIUM;
> >>     if (!drv->bdrv_truncate)
> >>         return -ENOTSUP;
> >>     if (bs->read_only)
> >>         return -EACCES;
> >>
> >>     assert(child->perm & BLK_PERM_RESIZE);
> >>     ret = drv->bdrv_truncate(bs, offset);
> >>
> >> technically this will work properly for my case and calling of
> >> bdrv_truncate could be valid.
> > The question is what the contract of bdrv_truncate() is. I think "you
> > can only call this when you got resize permissions" is the clearest
> > interface, and the current code enforces it.
> but in the original patch I have made check exactly over this simple
> condition and you says that it was not accurate. If this is wrong, I'll be
> rejected later on with EACCESS and will still be on the safe side.
> Original patch just avoids the assert().

No, you checked BDRV_O_RESIZE in bs->open_flags, not BLK_PERM_RESIZE in
child->perm. If you checked for BLK_PERM_RESIZE, that would work (though
I still think that checking for read-only gets closer to the actual
intent).

> > Your proposal would change it into "you can only call this when you get
> > resize permissions, except when it would fail anyway because the image
> > is closed, the driver doesn't support resizing or the node is
> > read-only". I wouldn't make such exceptions unless there is a good
> > reason to have them, e.g. if it made the life of the callers
> > substantially easier. But it don't think it does in this case.
> Actually we have had an error condition as the image was really read-only
> and all was safe. Right now we have an assert even if the image is
> read-only.
> This looks the same to me as to raise an assert in write for read-only
> image. Is there any difference?

Hm, no, not really. You're right that we're inconsistent there. Not sure
which one we should change, but you do have a point there.

> >> Another thing, should we add assert like added into bdrv_co_pwritev,
> >> namely
> >>     assert(!(bs->open_flags & BDRV_O_INACTIVE));
> >> in the same place below access check.
> > You mean asserting that we have write permission? We already do that in
> > bdrv_aligned_pwritev(), which is called by bdrv_co_pwritev().
> I mean that we should disallow image change if it is disallowed
> by the contract. Current contract says that we can not change
> image content once BDRV_O_INACTIVE is set. Should we
> Do we have implicit rule that (child->perm & BLK_PERM_RESIZE)
> is set only when INACTIVE is not set?

Ah, you want to assert cleared BDRV_O_INACTIVE in bdrv_truncate()?
That sounds like a good idea to me.

> >> Technically, the requested change is not a problem it looks a bit
> >> strange and not consistent to me.
> > Hm, okay? Why do you think so? To me, it feels correct that
> > bdrv_truncate() can only be called for writable images.
> I was unclear here. I have trying to say that "the change requested by you
> is not a problem, I'll do that once we will agree". Sorry :(
> 
> > It's the current code in the parallels driver that calls it for
> > read-only images and implicitly expects an error return on the normal
> > code path (without even having a comment about this) that feels somewhat
> > unclean to me.
> Actually I tend to drop this truncate at all. It was set for a state of
> insurance and should not be actually used.

Well, that's the best solution then for this specific case. :-)

Kevin

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] parallels: wrong call to bdrv_truncate
  2017-03-29 14:11         ` Kevin Wolf
@ 2017-03-29 14:18           ` Denis V. Lunev
  2017-03-29 14:32             ` Kevin Wolf
  0 siblings, 1 reply; 9+ messages in thread
From: Denis V. Lunev @ 2017-03-29 14:18 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel, Stefan Hajnoczi, qemu-block

On 03/29/2017 05:11 PM, Kevin Wolf wrote:
> Am 29.03.2017 um 15:53 hat Denis V. Lunev geschrieben:
>> On 03/29/2017 01:41 PM, Kevin Wolf wrote:
>>> Am 28.03.2017 um 19:12 hat Denis V. Lunev geschrieben:
>>>> On 03/28/2017 07:26 PM, Kevin Wolf wrote:
>>>>> [ Cc: qemu-block ]
>>>>>
>>>>> Am 27.03.2017 um 16:38 hat Denis V. Lunev geschrieben:
>>>>>> Parallels driver should not call bdrv_truncate if the image was opened
>>>>>> in the read-only mode. Without the patch
>>>>>>     qemu-img check harddisk.hds
>>>>>> asserts with
>>>>>>     bdrv_truncate: Assertion `child->perm & BLK_PERM_RESIZE' failed.
>>>>>>
>>>>>> Parameters used on the write path are not needed if the image is opened
>>>>>> in the read-only mode.
>>>>>>
>>>>>> Signed-off-by: Denis V. Lunev <den@openvz.org>
>>>>>> Reported-by: Edgar Kaziahmedov <edos@virtuozzo.mipt.ru>
>>>>>> CC: Stefan Hajnoczi <stefanha@redhat.com>
>>>>>> ---
>>>>>>  block/parallels.c | 3 ++-
>>>>>>  1 file changed, 2 insertions(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/block/parallels.c b/block/parallels.c
>>>>>> index 6bf9375..4173b3f 100644
>>>>>> --- a/block/parallels.c
>>>>>> +++ b/block/parallels.c
>>>>>> @@ -687,7 +687,8 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
>>>>>>      if (local_err != NULL) {
>>>>>>          goto fail_options;
>>>>>>      }
>>>>>> -    if (!bdrv_has_zero_init(bs->file->bs) ||
>>>>>> +
>>>>>> +    if (!(flags & BDRV_O_RESIZE) || !bdrv_has_zero_init(bs->file->bs) ||
>>>>>>              bdrv_truncate(bs->file, bdrv_getlength(bs->file->bs)) != 0) {
>>>>>>          s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
>>>>>>      }
>>>>> Relying on BDRV_O_RESIZE in block drivers is wrong. It is set in some
>>>>> paths (specifically the users of blk_new_open), but not in others. We
>>>>> should probably have filtered out the flag before passing it to the
>>>>> drivers.
>>>>>
>>>>> As a concrete example, if you're using -blockdev, the bdrv_truncate()
>>>>> call won't be executed after applying this patch.
>>>>>
>>>>> I think the correct way would be to check bdrv_is_read_only() instead.
>>>>>
>>>>> Kevin
>>>> hmmm. But why do we have
>>>>
>>>> int bdrv_truncate(BdrvChild *child, int64_t offset)
>>>> {
>>>>     BlockDriverState *bs = child->bs;
>>>>     BlockDriver *drv = bs->drv;
>>>>     int ret;
>>>>
>>>>     assert(child->perm & BLK_PERM_RESIZE);
>>>>
>>>>     if (!drv)
>>>>         return -ENOMEDIUM;
>>>>     if (!drv->bdrv_truncate)
>>>>         return -ENOTSUP;
>>>>     if (bs->read_only)
>>>>         return -EACCES;
>>>>
>>>>     ret = drv->bdrv_truncate(bs, offset);
>>>>
>>>> instead of
>>>>
>>>> int bdrv_truncate(BdrvChild *child, int64_t offset)
>>>> {
>>>>     BlockDriverState *bs = child->bs;
>>>>     BlockDriver *drv = bs->drv;
>>>>     int ret;
>>>>
>>>>     if (!drv)
>>>>         return -ENOMEDIUM;
>>>>     if (!drv->bdrv_truncate)
>>>>         return -ENOTSUP;
>>>>     if (bs->read_only)
>>>>         return -EACCES;
>>>>
>>>>     assert(child->perm & BLK_PERM_RESIZE);
>>>>     ret = drv->bdrv_truncate(bs, offset);
>>>>
>>>> technically this will work properly for my case and calling of
>>>> bdrv_truncate could be valid.
>>> The question is what the contract of bdrv_truncate() is. I think "you
>>> can only call this when you got resize permissions" is the clearest
>>> interface, and the current code enforces it.
>> but in the original patch I have made check exactly over this simple
>> condition and you says that it was not accurate. If this is wrong, I'll be
>> rejected later on with EACCESS and will still be on the safe side.
>> Original patch just avoids the assert().
> No, you checked BDRV_O_RESIZE in bs->open_flags, not BLK_PERM_RESIZE in
> child->perm. If you checked for BLK_PERM_RESIZE, that would work (though
> I still think that checking for read-only gets closer to the actual
> intent).
OK. That is clear now, I'll send a fixup.
Thank you for the explanation.


>
>>> Your proposal would change it into "you can only call this when you get
>>> resize permissions, except when it would fail anyway because the image
>>> is closed, the driver doesn't support resizing or the node is
>>> read-only". I wouldn't make such exceptions unless there is a good
>>> reason to have them, e.g. if it made the life of the callers
>>> substantially easier. But it don't think it does in this case.
>> Actually we have had an error condition as the image was really read-only
>> and all was safe. Right now we have an assert even if the image is
>> read-only.
>> This looks the same to me as to raise an assert in write for read-only
>> image. Is there any difference?
> Hm, no, not really. You're right that we're inconsistent there. Not sure
> which one we should change, but you do have a point there.
>
>>>> Another thing, should we add assert like added into bdrv_co_pwritev,
>>>> namely
>>>>     assert(!(bs->open_flags & BDRV_O_INACTIVE));
>>>> in the same place below access check.
>>> You mean asserting that we have write permission? We already do that in
>>> bdrv_aligned_pwritev(), which is called by bdrv_co_pwritev().
>> I mean that we should disallow image change if it is disallowed
>> by the contract. Current contract says that we can not change
>> image content once BDRV_O_INACTIVE is set. Should we
>> Do we have implicit rule that (child->perm & BLK_PERM_RESIZE)
>> is set only when INACTIVE is not set?
> Ah, you want to assert cleared BDRV_O_INACTIVE in bdrv_truncate()?
> That sounds like a good idea to me.
but this is for 2.10. I think it is too late to do that right now.

>>>> Technically, the requested change is not a problem it looks a bit
>>>> strange and not consistent to me.
>>> Hm, okay? Why do you think so? To me, it feels correct that
>>> bdrv_truncate() can only be called for writable images.
>> I was unclear here. I have trying to say that "the change requested by you
>> is not a problem, I'll do that once we will agree". Sorry :(
>>
>>> It's the current code in the parallels driver that calls it for
>>> read-only images and implicitly expects an error return on the normal
>>> code path (without even having a comment about this) that feels somewhat
>>> unclean to me.
>> Actually I tend to drop this truncate at all. It was set for a state of
>> insurance and should not be actually used.
> Well, that's the best solution then for this specific case. :-)
>
> Kevin
;)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] parallels: wrong call to bdrv_truncate
  2017-03-29 14:18           ` Denis V. Lunev
@ 2017-03-29 14:32             ` Kevin Wolf
  0 siblings, 0 replies; 9+ messages in thread
From: Kevin Wolf @ 2017-03-29 14:32 UTC (permalink / raw)
  To: Denis V. Lunev; +Cc: qemu-devel, Stefan Hajnoczi, qemu-block

Am 29.03.2017 um 16:18 hat Denis V. Lunev geschrieben:
> On 03/29/2017 05:11 PM, Kevin Wolf wrote:
> > Am 29.03.2017 um 15:53 hat Denis V. Lunev geschrieben:
> >> On 03/29/2017 01:41 PM, Kevin Wolf wrote:
> >>> The question is what the contract of bdrv_truncate() is. I think "you
> >>> can only call this when you got resize permissions" is the clearest
> >>> interface, and the current code enforces it.
> >> but in the original patch I have made check exactly over this simple
> >> condition and you says that it was not accurate. If this is wrong, I'll be
> >> rejected later on with EACCESS and will still be on the safe side.
> >> Original patch just avoids the assert().
> > No, you checked BDRV_O_RESIZE in bs->open_flags, not BLK_PERM_RESIZE in
> > child->perm. If you checked for BLK_PERM_RESIZE, that would work (though
> > I still think that checking for read-only gets closer to the actual
> > intent).
> OK. That is clear now, I'll send a fixup.
> Thank you for the explanation.

Ok, thanks.

> >>>> Another thing, should we add assert like added into bdrv_co_pwritev,
> >>>> namely
> >>>>     assert(!(bs->open_flags & BDRV_O_INACTIVE));
> >>>> in the same place below access check.
> >>> You mean asserting that we have write permission? We already do that in
> >>> bdrv_aligned_pwritev(), which is called by bdrv_co_pwritev().
> >> I mean that we should disallow image change if it is disallowed
> >> by the contract. Current contract says that we can not change
> >> image content once BDRV_O_INACTIVE is set. Should we
> >> Do we have implicit rule that (child->perm & BLK_PERM_RESIZE)
> >> is set only when INACTIVE is not set?
> > Ah, you want to assert cleared BDRV_O_INACTIVE in bdrv_truncate()?
> > That sounds like a good idea to me.
> but this is for 2.10. I think it is too late to do that right now.

Yes, definitely for 2.10. If you like, you can already send a patch
anyway, I always have a block-next queue while we're in freeze.

Kevin

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2017-03-29 15:53 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-27 14:38 [Qemu-devel] [PATCH 1/1] parallels: wrong call to bdrv_truncate Denis V. Lunev
2017-03-28 10:07 ` Stefan Hajnoczi
2017-03-28 16:26 ` Kevin Wolf
2017-03-28 17:12   ` Denis V. Lunev
2017-03-29 10:41     ` Kevin Wolf
2017-03-29 13:53       ` Denis V. Lunev
2017-03-29 14:11         ` Kevin Wolf
2017-03-29 14:18           ` Denis V. Lunev
2017-03-29 14:32             ` Kevin Wolf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.