Re: [PATCH v6 2/4] copy-on-read: add filter append/drop functions

2020-08-23 Thread Andrey Shinkevich

On 23.08.2020 22:35, Andrey Shinkevich wrote:

On 19.08.2020 13:21, Vladimir Sementsov-Ogievskiy wrote:

19.08.2020 00:24, Andrey Shinkevich wrote:

Provide API for the COR-filter insertion/removal.
Also, drop the filter child permissions for an inactive state when the
filter node is being removed.

Signed-off-by: Andrey Shinkevich 
---
  block/copy-on-read.c | 103 
+++

  block/copy-on-read.h |  36 ++
  2 files changed, 139 insertions(+)
  create mode 100644 block/copy-on-read.h

diff --git a/block/copy-on-read.c b/block/copy-on-read.c
index cb03e0f..150d9b7 100644
--- a/block/copy-on-read.c
+++ b/block/copy-on-read.c
@@ -23,11 +23,21 @@

...

+BlockDriverState *bdrv_cor_filter_append(BlockDriverState *bs,
+ const char *filter_node_name,
+ Error **errp)
+{
+    BlockDriverState *cor_filter_bs;
+    BDRVStateCOR *state;
+    Error *local_err = NULL;
+
+    cor_filter_bs = create_filter_node(bs, filter_node_name, errp);
+    if (cor_filter_bs == NULL) {
+    error_prepend(errp, "Could not create filter node: ");
+    return NULL;
+    }
+
+    if (!filter_node_name) {
+    cor_filter_bs->implicit = true;
+    }
+
+    bdrv_drained_begin(bs);
+    bdrv_replace_node(bs, cor_filter_bs, _err);
+    bdrv_drained_end(bs);
+
+    if (local_err) {
+    bdrv_unref(cor_filter_bs);
+    error_propagate(errp, local_err);
+    return NULL;
+    }
+
+    state = cor_filter_bs->opaque;
+    state->active = true;


hmm stop. it's already active, after create_filter_node, so you don't 
need to set it again, isn't it?



I will remove the extra assignment from the cor_open() for consistancy.

Andrey




No, I won't. It is wrong to do that. COR-operations wouldn't work.

Andrey





+
+    return cor_filter_bs;
+}
+

...



Re: [PATCH v6 2/4] copy-on-read: add filter append/drop functions

2020-08-23 Thread Andrey Shinkevich

On 19.08.2020 13:21, Vladimir Sementsov-Ogievskiy wrote:

19.08.2020 00:24, Andrey Shinkevich wrote:

Provide API for the COR-filter insertion/removal.
Also, drop the filter child permissions for an inactive state when the
filter node is being removed.

Signed-off-by: Andrey Shinkevich 
---
  block/copy-on-read.c | 103 
+++

  block/copy-on-read.h |  36 ++
  2 files changed, 139 insertions(+)
  create mode 100644 block/copy-on-read.h

diff --git a/block/copy-on-read.c b/block/copy-on-read.c
index cb03e0f..150d9b7 100644
--- a/block/copy-on-read.c
+++ b/block/copy-on-read.c
@@ -23,11 +23,21 @@
  #include "qemu/osdep.h"
  #include "block/block_int.h"
  #include "qemu/module.h"
+#include "qapi/error.h"
+#include "qapi/qmp/qdict.h"
+#include "block/copy-on-read.h"
+
+
+typedef struct BDRVStateCOR {
+    bool active;
+} BDRVStateCOR;
      static int cor_open(BlockDriverState *bs, QDict *options, int 
flags,

  Error **errp)
  {
+    BDRVStateCOR *state = bs->opaque;
+
  bs->file = bdrv_open_child(NULL, options, "file", bs, 
_of_bds,
 BDRV_CHILD_FILTERED | 
BDRV_CHILD_PRIMARY,

 false, errp);
@@ -42,6 +52,8 @@ static int cor_open(BlockDriverState *bs, QDict 
*options, int flags,

  ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
  bs->file->bs->supported_zero_flags);
  +    state->active = true;


We don't need to call bdrv_child_refresh_perms() here, as permissions 
will be

updated soon, when the filter node get its parent, yes?

Let's add at least a comment on this.


+
  return 0;
  }
  @@ -57,6 +69,17 @@ static void cor_child_perm(BlockDriverState *bs, 
BdrvChild *c,

 uint64_t perm, uint64_t shared,
 uint64_t *nperm, uint64_t *nshared)
  {
+    BDRVStateCOR *s = bs->opaque;
+
+    if (!s->active) {
+    /*
+ * While the filter is being removed
+ */
+    *nperm = 0;
+    *nshared = BLK_PERM_ALL;
+    return;
+    }
+
  *nperm = perm & PERM_PASSTHROUGH;
  *nshared = (shared & PERM_PASSTHROUGH) | PERM_UNCHANGED;
  @@ -135,6 +158,7 @@ static void cor_lock_medium(BlockDriverState 
*bs, bool locked)

    static BlockDriver bdrv_copy_on_read = {
  .format_name    = "copy-on-read",
+    .instance_size  = sizeof(BDRVStateCOR),
    .bdrv_open  = cor_open,
  .bdrv_child_perm    = cor_child_perm,
@@ -159,4 +183,83 @@ static void bdrv_copy_on_read_init(void)
  bdrv_register(_copy_on_read);
  }
  +
+static BlockDriverState *create_filter_node(BlockDriverState *bs,
+    const char 
*filter_node_name,

+    Error **errp)
+{
+    QDict *opts = qdict_new();
+
+    qdict_put_str(opts, "driver", "copy-on-read");
+    qdict_put_str(opts, "file", bdrv_get_node_name(bs));
+    if (filter_node_name) {
+    qdict_put_str(opts, "node-name", filter_node_name);
+    }
+
+    return bdrv_open(NULL, NULL, opts, BDRV_O_RDWR, errp);
+}
+
+
+BlockDriverState *bdrv_cor_filter_append(BlockDriverState *bs,
+ const char *filter_node_name,
+ Error **errp)
+{
+    BlockDriverState *cor_filter_bs;
+    BDRVStateCOR *state;
+    Error *local_err = NULL;
+
+    cor_filter_bs = create_filter_node(bs, filter_node_name, errp);
+    if (cor_filter_bs == NULL) {
+    error_prepend(errp, "Could not create filter node: ");
+    return NULL;
+    }
+
+    if (!filter_node_name) {
+    cor_filter_bs->implicit = true;
+    }
+
+    bdrv_drained_begin(bs);
+    bdrv_replace_node(bs, cor_filter_bs, _err);
+    bdrv_drained_end(bs);
+
+    if (local_err) {
+    bdrv_unref(cor_filter_bs);
+    error_propagate(errp, local_err);
+    return NULL;
+    }
+
+    state = cor_filter_bs->opaque;
+    state->active = true;


hmm stop. it's already active, after create_filter_node, so you don't 
need to set it again, isn't it?



I will remove the extra assignment from the cor_open() for consistancy.

Andrey





+
+    return cor_filter_bs;
+}
+
+
+void bdrv_cor_filter_drop(BlockDriverState *cor_filter_bs)
+{
+    BdrvChild *child;
+    BlockDriverState *bs;
+    BDRVStateCOR *s = cor_filter_bs->opaque;
+
+    child = bdrv_filter_child(cor_filter_bs);
+    if (!child) {
+    return;
+    }
+    bs = child->bs;
+
+    /* Retain the BDS until we complete the graph change. */
+    bdrv_ref(bs);
+    /* Hold a guest back from writing while permissions are being 
reset. */

+    bdrv_drained_begin(bs);
+    /* Drop permissions before the graph change. */
+    s->active = false;
+    bdrv_child_refresh_perms(cor_filter_bs, child, _abort);
+    bdrv_replace_node(cor_filter_bs, bs, _abort);
+
+    

Re: [PATCH v6 2/4] copy-on-read: add filter append/drop functions

2020-08-19 Thread Vladimir Sementsov-Ogievskiy

19.08.2020 00:24, Andrey Shinkevich wrote:

Provide API for the COR-filter insertion/removal.
Also, drop the filter child permissions for an inactive state when the
filter node is being removed.

Signed-off-by: Andrey Shinkevich 
---
  block/copy-on-read.c | 103 +++
  block/copy-on-read.h |  36 ++
  2 files changed, 139 insertions(+)
  create mode 100644 block/copy-on-read.h

diff --git a/block/copy-on-read.c b/block/copy-on-read.c
index cb03e0f..150d9b7 100644
--- a/block/copy-on-read.c
+++ b/block/copy-on-read.c
@@ -23,11 +23,21 @@
  #include "qemu/osdep.h"
  #include "block/block_int.h"
  #include "qemu/module.h"
+#include "qapi/error.h"
+#include "qapi/qmp/qdict.h"
+#include "block/copy-on-read.h"
+
+
+typedef struct BDRVStateCOR {
+bool active;
+} BDRVStateCOR;
  
  
  static int cor_open(BlockDriverState *bs, QDict *options, int flags,

  Error **errp)
  {
+BDRVStateCOR *state = bs->opaque;
+
  bs->file = bdrv_open_child(NULL, options, "file", bs, _of_bds,
 BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
 false, errp);
@@ -42,6 +52,8 @@ static int cor_open(BlockDriverState *bs, QDict *options, int 
flags,
  ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
  bs->file->bs->supported_zero_flags);
  
+state->active = true;


We don't need to call bdrv_child_refresh_perms() here, as permissions will be
updated soon, when the filter node get its parent, yes?

Let's add at least a comment on this.


+
  return 0;
  }
  
@@ -57,6 +69,17 @@ static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,

 uint64_t perm, uint64_t shared,
 uint64_t *nperm, uint64_t *nshared)
  {
+BDRVStateCOR *s = bs->opaque;
+
+if (!s->active) {
+/*
+ * While the filter is being removed
+ */
+*nperm = 0;
+*nshared = BLK_PERM_ALL;
+return;
+}
+
  *nperm = perm & PERM_PASSTHROUGH;
  *nshared = (shared & PERM_PASSTHROUGH) | PERM_UNCHANGED;
  
@@ -135,6 +158,7 @@ static void cor_lock_medium(BlockDriverState *bs, bool locked)
  
  static BlockDriver bdrv_copy_on_read = {

  .format_name= "copy-on-read",
+.instance_size  = sizeof(BDRVStateCOR),
  
  .bdrv_open  = cor_open,

  .bdrv_child_perm= cor_child_perm,
@@ -159,4 +183,83 @@ static void bdrv_copy_on_read_init(void)
  bdrv_register(_copy_on_read);
  }
  
+

+static BlockDriverState *create_filter_node(BlockDriverState *bs,
+const char *filter_node_name,
+Error **errp)
+{
+QDict *opts = qdict_new();
+
+qdict_put_str(opts, "driver", "copy-on-read");
+qdict_put_str(opts, "file", bdrv_get_node_name(bs));
+if (filter_node_name) {
+qdict_put_str(opts, "node-name", filter_node_name);
+}
+
+return bdrv_open(NULL, NULL, opts, BDRV_O_RDWR, errp);
+}
+
+
+BlockDriverState *bdrv_cor_filter_append(BlockDriverState *bs,
+ const char *filter_node_name,
+ Error **errp)
+{
+BlockDriverState *cor_filter_bs;
+BDRVStateCOR *state;
+Error *local_err = NULL;
+
+cor_filter_bs = create_filter_node(bs, filter_node_name, errp);
+if (cor_filter_bs == NULL) {
+error_prepend(errp, "Could not create filter node: ");
+return NULL;
+}
+
+if (!filter_node_name) {
+cor_filter_bs->implicit = true;
+}
+
+bdrv_drained_begin(bs);
+bdrv_replace_node(bs, cor_filter_bs, _err);
+bdrv_drained_end(bs);
+
+if (local_err) {
+bdrv_unref(cor_filter_bs);
+error_propagate(errp, local_err);
+return NULL;
+}
+
+state = cor_filter_bs->opaque;
+state->active = true;


hmm stop. it's already active, after create_filter_node, so you don't need to 
set it again, isn't it?


+
+return cor_filter_bs;
+}
+
+
+void bdrv_cor_filter_drop(BlockDriverState *cor_filter_bs)
+{
+BdrvChild *child;
+BlockDriverState *bs;
+BDRVStateCOR *s = cor_filter_bs->opaque;
+
+child = bdrv_filter_child(cor_filter_bs);
+if (!child) {
+return;
+}
+bs = child->bs;
+
+/* Retain the BDS until we complete the graph change. */
+bdrv_ref(bs);
+/* Hold a guest back from writing while permissions are being reset. */
+bdrv_drained_begin(bs);
+/* Drop permissions before the graph change. */
+s->active = false;
+bdrv_child_refresh_perms(cor_filter_bs, child, _abort);
+bdrv_replace_node(cor_filter_bs, bs, _abort);
+
+bdrv_drained_end(bs);
+bdrv_unref(bs);
+bdrv_unref(cor_filter_bs);
+}
+
+
  block_init(bdrv_copy_on_read_init);
diff --git a/block/copy-on-read.h