diff mbox

[v12,08/17] qmp: add block-dirty-bitmap-clear

Message ID 1423532117-14490-9-git-send-email-jsnow@redhat.com
State New
Headers show

Commit Message

John Snow Feb. 10, 2015, 1:35 a.m. UTC
Add bdrv_clear_dirty_bitmap and a matching QMP command,
qmp_block_dirty_bitmap_clear that enables a user to reset
the bitmap attached to a drive.

This allows us to reset a bitmap in the event of a full
drive backup.

Signed-off-by: John Snow <jsnow@redhat.com>
---
 block.c               |  7 +++++++
 blockdev.c            | 31 +++++++++++++++++++++++++++++++
 include/block/block.h |  1 +
 qapi/block-core.json  | 14 ++++++++++++++
 qmp-commands.hx       | 24 ++++++++++++++++++++++++
 5 files changed, 77 insertions(+)

Comments

Max Reitz Feb. 11, 2015, 6:28 p.m. UTC | #1
On 2015-02-09 at 20:35, John Snow wrote:
> Add bdrv_clear_dirty_bitmap and a matching QMP command,
> qmp_block_dirty_bitmap_clear that enables a user to reset
> the bitmap attached to a drive.
>
> This allows us to reset a bitmap in the event of a full
> drive backup.
>
> Signed-off-by: John Snow <jsnow@redhat.com>
> ---
>   block.c               |  7 +++++++
>   blockdev.c            | 31 +++++++++++++++++++++++++++++++
>   include/block/block.h |  1 +
>   qapi/block-core.json  | 14 ++++++++++++++
>   qmp-commands.hx       | 24 ++++++++++++++++++++++++
>   5 files changed, 77 insertions(+)
>
> diff --git a/block.c b/block.c
> index e93fceb..ad33d96 100644
> --- a/block.c
> +++ b/block.c
> @@ -62,6 +62,7 @@
>   struct BdrvDirtyBitmap {
>       HBitmap *bitmap;
>       BdrvDirtyBitmap *successor;
> +    int64_t size;
>       char *name;
>       bool disabled;
>       QLIST_ENTRY(BdrvDirtyBitmap) list;
> @@ -5422,6 +5423,7 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
>       }
>       bitmap = g_new0(BdrvDirtyBitmap, 1);
>       bitmap->bitmap = hbitmap_alloc(bitmap_size, ffs(sector_granularity) - 1);
> +    bitmap->size = bitmap_size;
>       bitmap->name = g_strdup(name);
>       bitmap->disabled = false;
>       QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
> @@ -5624,6 +5626,11 @@ void bdrv_reset_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
>       hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors);
>   }
>   
> +void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap)
> +{
> +    hbitmap_reset(bitmap->bitmap, 0, bitmap->size);
> +}

Is it fine to use this function on frozen or disabled bitmaps? The QMP 
interface at least suggests the former isn't, but I think the latter 
shouldn't be either (which may be wrong, though).

> +
>   static void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
>                              int nr_sectors)
>   {
> diff --git a/blockdev.c b/blockdev.c
> index 3f41e82..83d0608 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -2116,6 +2116,37 @@ void qmp_block_dirty_bitmap_disable(const char *node, const char *name,
>       aio_context_release(aio_context);
>   }
>   
> +/**
> + * Completely clear a bitmap, for the purposes of synchronizing a bitmap
> + * immediately after a full backup operation.
> + */
> +void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
> +                                  Error **errp)
> +{
> +    AioContext *aio_context;
> +    BdrvDirtyBitmap *bitmap;
> +    BlockDriverState *bs;
> +
> +    bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
> +    if (!bitmap) {
> +        return;
> +    }
> +
> +    aio_context = bdrv_get_aio_context(bs);
> +    aio_context_acquire(aio_context);
> +
> +    if (bdrv_dirty_bitmap_frozen(bitmap)) {
> +        error_setg(errp,
> +                   "Bitmap '%s' is currently frozen and cannot be modified.\n",
> +                   name);
> +        goto out;
> +    }
> +    bdrv_clear_dirty_bitmap(bitmap);
> +
> + out:
> +    aio_context_release(aio_context);
> +}
> +
>   int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
>   {
>       const char *id = qdict_get_str(qdict, "id");
> diff --git a/include/block/block.h b/include/block/block.h
> index 8589e77..8916ecd 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -467,6 +467,7 @@ void bdrv_set_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
>                              int64_t cur_sector, int nr_sectors);
>   void bdrv_reset_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
>                                int64_t cur_sector, int nr_sectors);
> +void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap);
>   void bdrv_dirty_iter_init(BlockDriverState *bs,
>                             BdrvDirtyBitmap *bitmap, struct HBitmapIter *hbi);
>   void bdrv_set_dirty_iter(struct HBitmapIter *hbi, int64_t offset);
> diff --git a/qapi/block-core.json b/qapi/block-core.json
> index 9c5a99c..702b76a 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.json
> @@ -1050,6 +1050,20 @@
>     'data': 'BlockDirtyBitmap' }
>   
>   ##
> +# @block-dirty-bitmap-clear
> +#
> +# Clear (reset) a dirty bitmap on the device
> +#
> +# Returns: nothing on success
> +#          If @node is not a valid block device, DeviceNotFound
> +#          If @name is not found, GenericError with an explanation
> +#
> +# Since 2.3
> +##
> +{ 'command': 'block-dirty-bitmap-clear',
> +  'data': 'BlockDirtyBitmap' }
> +
> +##
>   # @block_set_io_throttle:
>   #
>   # Change I/O throttle limits for a block drive.
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index 5aa3845..e1d96cd 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -1264,6 +1264,11 @@ EQMP
>           .args_type  = "node:B,name:s",
>           .mhandler.cmd_new = qmp_marshal_input_block_dirty_bitmap_disable,
>       },
> +    {
> +        .name       = "block-dirty-bitmap-clear",
> +        .args_type  = "node:B,name:s",
> +        .mhandler.cmd_new = qmp_marshal_input_block_dirty_bitmap_clear,
> +    },
>   
>   SQMP
>   
> @@ -1303,6 +1308,25 @@ Example:
>                                                         "name": "bitmap0" } }
>   <- { "return": {} }
>   
> +block-dirty-bitmap-clear
> +-------------------------

One dash too many (critical!).

Max

> +Since 2.3
> +
> +Reset the dirty bitmap associated with a node so that an incremental backup
> +from this point in time forward will only backup clusters modified after this
> +clear operation.
> +
> +Arguments:
> +
> +- "node": device/node on which to remove dirty bitmap (json-string)
> +- "name": name of the dirty bitmap to remove (json-string)
> +
> +Example:
> +
> +-> { "execute": "block-dirty-bitmap-clear", "arguments": { "node": "drive0",
> +                                                           "name": "bitmap0" } }
> +<- { "return": {} }
> +
>   EQMP
>   
>       {
John Snow Feb. 11, 2015, 6:36 p.m. UTC | #2
On 02/11/2015 01:28 PM, Max Reitz wrote:
> On 2015-02-09 at 20:35, John Snow wrote:
>> Add bdrv_clear_dirty_bitmap and a matching QMP command,
>> qmp_block_dirty_bitmap_clear that enables a user to reset
>> the bitmap attached to a drive.
>>
>> This allows us to reset a bitmap in the event of a full
>> drive backup.
>>
>> Signed-off-by: John Snow <jsnow@redhat.com>
>> ---
>>   block.c               |  7 +++++++
>>   blockdev.c            | 31 +++++++++++++++++++++++++++++++
>>   include/block/block.h |  1 +
>>   qapi/block-core.json  | 14 ++++++++++++++
>>   qmp-commands.hx       | 24 ++++++++++++++++++++++++
>>   5 files changed, 77 insertions(+)
>>
>> diff --git a/block.c b/block.c
>> index e93fceb..ad33d96 100644
>> --- a/block.c
>> +++ b/block.c
>> @@ -62,6 +62,7 @@
>>   struct BdrvDirtyBitmap {
>>       HBitmap *bitmap;
>>       BdrvDirtyBitmap *successor;
>> +    int64_t size;
>>       char *name;
>>       bool disabled;
>>       QLIST_ENTRY(BdrvDirtyBitmap) list;
>> @@ -5422,6 +5423,7 @@ BdrvDirtyBitmap
>> *bdrv_create_dirty_bitmap(BlockDriverState *bs,
>>       }
>>       bitmap = g_new0(BdrvDirtyBitmap, 1);
>>       bitmap->bitmap = hbitmap_alloc(bitmap_size,
>> ffs(sector_granularity) - 1);
>> +    bitmap->size = bitmap_size;
>>       bitmap->name = g_strdup(name);
>>       bitmap->disabled = false;
>>       QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
>> @@ -5624,6 +5626,11 @@ void bdrv_reset_dirty_bitmap(BlockDriverState
>> *bs, BdrvDirtyBitmap *bitmap,
>>       hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors);
>>   }
>> +void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap)
>> +{
>> +    hbitmap_reset(bitmap->bitmap, 0, bitmap->size);
>> +}
>
> Is it fine to use this function on frozen or disabled bitmaps? The QMP
> interface at least suggests the former isn't, but I think the latter
> shouldn't be either (which may be wrong, though).
>

Bug. This should be prohibited for frozen or disabled bitmaps, yes.

>> +
>>   static void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
>>                              int nr_sectors)
>>   {
>> diff --git a/blockdev.c b/blockdev.c
>> index 3f41e82..83d0608 100644
>> --- a/blockdev.c
>> +++ b/blockdev.c
>> @@ -2116,6 +2116,37 @@ void qmp_block_dirty_bitmap_disable(const char
>> *node, const char *name,
>>       aio_context_release(aio_context);
>>   }
>> +/**
>> + * Completely clear a bitmap, for the purposes of synchronizing a bitmap
>> + * immediately after a full backup operation.
>> + */
>> +void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
>> +                                  Error **errp)
>> +{
>> +    AioContext *aio_context;
>> +    BdrvDirtyBitmap *bitmap;
>> +    BlockDriverState *bs;
>> +
>> +    bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
>> +    if (!bitmap) {
>> +        return;
>> +    }
>> +
>> +    aio_context = bdrv_get_aio_context(bs);
>> +    aio_context_acquire(aio_context);
>> +
>> +    if (bdrv_dirty_bitmap_frozen(bitmap)) {
>> +        error_setg(errp,
>> +                   "Bitmap '%s' is currently frozen and cannot be
>> modified.\n",
>> +                   name);
>> +        goto out;
>> +    }
>> +    bdrv_clear_dirty_bitmap(bitmap);
>> +
>> + out:
>> +    aio_context_release(aio_context);
>> +}
>> +
>>   int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
>>   {
>>       const char *id = qdict_get_str(qdict, "id");
>> diff --git a/include/block/block.h b/include/block/block.h
>> index 8589e77..8916ecd 100644
>> --- a/include/block/block.h
>> +++ b/include/block/block.h
>> @@ -467,6 +467,7 @@ void bdrv_set_dirty_bitmap(BlockDriverState *bs,
>> BdrvDirtyBitmap *bitmap,
>>                              int64_t cur_sector, int nr_sectors);
>>   void bdrv_reset_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap
>> *bitmap,
>>                                int64_t cur_sector, int nr_sectors);
>> +void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap);
>>   void bdrv_dirty_iter_init(BlockDriverState *bs,
>>                             BdrvDirtyBitmap *bitmap, struct
>> HBitmapIter *hbi);
>>   void bdrv_set_dirty_iter(struct HBitmapIter *hbi, int64_t offset);
>> diff --git a/qapi/block-core.json b/qapi/block-core.json
>> index 9c5a99c..702b76a 100644
>> --- a/qapi/block-core.json
>> +++ b/qapi/block-core.json
>> @@ -1050,6 +1050,20 @@
>>     'data': 'BlockDirtyBitmap' }
>>   ##
>> +# @block-dirty-bitmap-clear
>> +#
>> +# Clear (reset) a dirty bitmap on the device
>> +#
>> +# Returns: nothing on success
>> +#          If @node is not a valid block device, DeviceNotFound
>> +#          If @name is not found, GenericError with an explanation
>> +#
>> +# Since 2.3
>> +##
>> +{ 'command': 'block-dirty-bitmap-clear',
>> +  'data': 'BlockDirtyBitmap' }
>> +
>> +##
>>   # @block_set_io_throttle:
>>   #
>>   # Change I/O throttle limits for a block drive.
>> diff --git a/qmp-commands.hx b/qmp-commands.hx
>> index 5aa3845..e1d96cd 100644
>> --- a/qmp-commands.hx
>> +++ b/qmp-commands.hx
>> @@ -1264,6 +1264,11 @@ EQMP
>>           .args_type  = "node:B,name:s",
>>           .mhandler.cmd_new =
>> qmp_marshal_input_block_dirty_bitmap_disable,
>>       },
>> +    {
>> +        .name       = "block-dirty-bitmap-clear",
>> +        .args_type  = "node:B,name:s",
>> +        .mhandler.cmd_new = qmp_marshal_input_block_dirty_bitmap_clear,
>> +    },
>>   SQMP
>> @@ -1303,6 +1308,25 @@ Example:
>>                                                         "name":
>> "bitmap0" } }
>>   <- { "return": {} }
>> +block-dirty-bitmap-clear
>> +-------------------------
>
> One dash too many (critical!).
>
> Max
>

Yes.

>> +Since 2.3
>> +
>> +Reset the dirty bitmap associated with a node so that an incremental
>> backup
>> +from this point in time forward will only backup clusters modified
>> after this
>> +clear operation.
>> +
>> +Arguments:
>> +
>> +- "node": device/node on which to remove dirty bitmap (json-string)
>> +- "name": name of the dirty bitmap to remove (json-string)
>> +
>> +Example:
>> +
>> +-> { "execute": "block-dirty-bitmap-clear", "arguments": { "node":
>> "drive0",
>> +                                                           "name":
>> "bitmap0" } }
>> +<- { "return": {} }
>> +
>>   EQMP
>>       {
>
>
diff mbox

Patch

diff --git a/block.c b/block.c
index e93fceb..ad33d96 100644
--- a/block.c
+++ b/block.c
@@ -62,6 +62,7 @@ 
 struct BdrvDirtyBitmap {
     HBitmap *bitmap;
     BdrvDirtyBitmap *successor;
+    int64_t size;
     char *name;
     bool disabled;
     QLIST_ENTRY(BdrvDirtyBitmap) list;
@@ -5422,6 +5423,7 @@  BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
     }
     bitmap = g_new0(BdrvDirtyBitmap, 1);
     bitmap->bitmap = hbitmap_alloc(bitmap_size, ffs(sector_granularity) - 1);
+    bitmap->size = bitmap_size;
     bitmap->name = g_strdup(name);
     bitmap->disabled = false;
     QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list);
@@ -5624,6 +5626,11 @@  void bdrv_reset_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
     hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors);
 }
 
+void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap)
+{
+    hbitmap_reset(bitmap->bitmap, 0, bitmap->size);
+}
+
 static void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector,
                            int nr_sectors)
 {
diff --git a/blockdev.c b/blockdev.c
index 3f41e82..83d0608 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2116,6 +2116,37 @@  void qmp_block_dirty_bitmap_disable(const char *node, const char *name,
     aio_context_release(aio_context);
 }
 
+/**
+ * Completely clear a bitmap, for the purposes of synchronizing a bitmap
+ * immediately after a full backup operation.
+ */
+void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
+                                  Error **errp)
+{
+    AioContext *aio_context;
+    BdrvDirtyBitmap *bitmap;
+    BlockDriverState *bs;
+
+    bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
+    if (!bitmap) {
+        return;
+    }
+
+    aio_context = bdrv_get_aio_context(bs);
+    aio_context_acquire(aio_context);
+
+    if (bdrv_dirty_bitmap_frozen(bitmap)) {
+        error_setg(errp,
+                   "Bitmap '%s' is currently frozen and cannot be modified.\n",
+                   name);
+        goto out;
+    }
+    bdrv_clear_dirty_bitmap(bitmap);
+
+ out:
+    aio_context_release(aio_context);
+}
+
 int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     const char *id = qdict_get_str(qdict, "id");
diff --git a/include/block/block.h b/include/block/block.h
index 8589e77..8916ecd 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -467,6 +467,7 @@  void bdrv_set_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
                            int64_t cur_sector, int nr_sectors);
 void bdrv_reset_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap,
                              int64_t cur_sector, int nr_sectors);
+void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap);
 void bdrv_dirty_iter_init(BlockDriverState *bs,
                           BdrvDirtyBitmap *bitmap, struct HBitmapIter *hbi);
 void bdrv_set_dirty_iter(struct HBitmapIter *hbi, int64_t offset);
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 9c5a99c..702b76a 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1050,6 +1050,20 @@ 
   'data': 'BlockDirtyBitmap' }
 
 ##
+# @block-dirty-bitmap-clear
+#
+# Clear (reset) a dirty bitmap on the device
+#
+# Returns: nothing on success
+#          If @node is not a valid block device, DeviceNotFound
+#          If @name is not found, GenericError with an explanation
+#
+# Since 2.3
+##
+{ 'command': 'block-dirty-bitmap-clear',
+  'data': 'BlockDirtyBitmap' }
+
+##
 # @block_set_io_throttle:
 #
 # Change I/O throttle limits for a block drive.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 5aa3845..e1d96cd 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1264,6 +1264,11 @@  EQMP
         .args_type  = "node:B,name:s",
         .mhandler.cmd_new = qmp_marshal_input_block_dirty_bitmap_disable,
     },
+    {
+        .name       = "block-dirty-bitmap-clear",
+        .args_type  = "node:B,name:s",
+        .mhandler.cmd_new = qmp_marshal_input_block_dirty_bitmap_clear,
+    },
 
 SQMP
 
@@ -1303,6 +1308,25 @@  Example:
                                                       "name": "bitmap0" } }
 <- { "return": {} }
 
+block-dirty-bitmap-clear
+-------------------------
+Since 2.3
+
+Reset the dirty bitmap associated with a node so that an incremental backup
+from this point in time forward will only backup clusters modified after this
+clear operation.
+
+Arguments:
+
+- "node": device/node on which to remove dirty bitmap (json-string)
+- "name": name of the dirty bitmap to remove (json-string)
+
+Example:
+
+-> { "execute": "block-dirty-bitmap-clear", "arguments": { "node": "drive0",
+                                                           "name": "bitmap0" } }
+<- { "return": {} }
+
 EQMP
 
     {