Blame SOURCES/kvm-block-dirty-bitmaps-add-block_dirty_bitmap_check-fun.patch

7711c0
From ac4ba4bb4b2118dab2e7f0b7c7e3daec3698d060 Mon Sep 17 00:00:00 2001
7711c0
From: John Snow <jsnow@redhat.com>
7711c0
Date: Wed, 3 Apr 2019 18:18:51 +0200
7711c0
Subject: [PATCH 146/163] block/dirty-bitmaps: add block_dirty_bitmap_check
7711c0
 function
7711c0
7711c0
RH-Author: John Snow <jsnow@redhat.com>
7711c0
Message-id: <20190403181857.9693-16-jsnow@redhat.com>
7711c0
Patchwork-id: 85429
7711c0
O-Subject: [RHEL-7.7 qemu-kvm-rhev PATCH 15/21] block/dirty-bitmaps: add block_dirty_bitmap_check function
7711c0
Bugzilla: 1677073
7711c0
RH-Acked-by: Max Reitz <mreitz@redhat.com>
7711c0
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7711c0
RH-Acked-by: Sergio Lopez Pascual <slp@redhat.com>
7711c0
7711c0
Instead of checking against busy, inconsistent, or read only directly,
7711c0
use a check function with permissions bits that let us streamline the
7711c0
checks without reproducing them in many places.
7711c0
7711c0
Included in this patch are permissions changes that simply add the
7711c0
inconsistent check to existing permissions call spots, without
7711c0
addressing existing bugs.
7711c0
7711c0
In general, this means that busy+readonly checks become BDRV_BITMAP_DEFAULT,
7711c0
which checks against all three conditions. busy-only checks become
7711c0
BDRV_BITMAP_ALLOW_RO.
7711c0
7711c0
Notably, remove allows inconsistent bitmaps, so it doesn't follow the pattern.
7711c0
7711c0
Signed-off-by: John Snow <jsnow@redhat.com>
7711c0
Reviewed-by: Eric Blake <eblake@redhat.com>
7711c0
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7711c0
Message-id: 20190301191545.8728-4-jsnow@redhat.com
7711c0
Signed-off-by: John Snow <jsnow@redhat.com>
7711c0
(cherry picked from commit 3ae96d66840f72ef54902d012dbdf87ef4e9fe0c)
7711c0
Signed-off-by: John Snow <jsnow@redhat.com>
7711c0
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
7711c0
---
7711c0
 block/dirty-bitmap.c           | 42 +++++++++++++++++++++++++-----------
7711c0
 blockdev.c                     | 49 ++++++++----------------------------------
7711c0
 include/block/dirty-bitmap.h   | 13 ++++++++++-
7711c0
 migration/block-dirty-bitmap.c | 13 ++++-------
7711c0
 nbd/server.c                   |  3 +--
7711c0
 5 files changed, 56 insertions(+), 64 deletions(-)
7711c0
7711c0
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
7711c0
index 4a2349d..6170f3a 100644
7711c0
--- a/block/dirty-bitmap.c
7711c0
+++ b/block/dirty-bitmap.c
7711c0
@@ -174,7 +174,7 @@ bool bdrv_dirty_bitmap_has_successor(BdrvDirtyBitmap *bitmap)
7711c0
     return bitmap->successor;
7711c0
 }
7711c0
 
7711c0
-bool bdrv_dirty_bitmap_busy(BdrvDirtyBitmap *bitmap)
7711c0
+static bool bdrv_dirty_bitmap_busy(const BdrvDirtyBitmap *bitmap)
7711c0
 {
7711c0
     return bitmap->busy;
7711c0
 }
7711c0
@@ -236,6 +236,33 @@ static bool bdrv_dirty_bitmap_recording(BdrvDirtyBitmap *bitmap)
7711c0
                                  !bitmap->successor->disabled);
7711c0
 }
7711c0
 
7711c0
+int bdrv_dirty_bitmap_check(const BdrvDirtyBitmap *bitmap, uint32_t flags,
7711c0
+                            Error **errp)
7711c0
+{
7711c0
+    if ((flags & BDRV_BITMAP_BUSY) && bdrv_dirty_bitmap_busy(bitmap)) {
7711c0
+        error_setg(errp, "Bitmap '%s' is currently in use by another"
7711c0
+                   " operation and cannot be used", bitmap->name);
7711c0
+        return -1;
7711c0
+    }
7711c0
+
7711c0
+    if ((flags & BDRV_BITMAP_RO) && bdrv_dirty_bitmap_readonly(bitmap)) {
7711c0
+        error_setg(errp, "Bitmap '%s' is readonly and cannot be modified",
7711c0
+                   bitmap->name);
7711c0
+        return -1;
7711c0
+    }
7711c0
+
7711c0
+    if ((flags & BDRV_BITMAP_INCONSISTENT) &&
7711c0
+        bdrv_dirty_bitmap_inconsistent(bitmap)) {
7711c0
+        error_setg(errp, "Bitmap '%s' is inconsistent and cannot be used",
7711c0
+                   bitmap->name);
7711c0
+        error_append_hint(errp, "Try block-dirty-bitmap-remove to delete"
7711c0
+                          " this bitmap from disk");
7711c0
+        return -1;
7711c0
+    }
7711c0
+
7711c0
+    return 0;
7711c0
+}
7711c0
+
7711c0
 /**
7711c0
  * Create a successor bitmap destined to replace this bitmap after an operation.
7711c0
  * Requires that the bitmap is not marked busy and has no successor.
7711c0
@@ -248,9 +275,7 @@ int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs,
7711c0
     uint64_t granularity;
7711c0
     BdrvDirtyBitmap *child;
7711c0
 
7711c0
-    if (bdrv_dirty_bitmap_busy(bitmap)) {
7711c0
-        error_setg(errp, "Cannot create a successor for a bitmap that is "
7711c0
-                   "in-use by an operation");
7711c0
+    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY, errp)) {
7711c0
         return -1;
7711c0
     }
7711c0
     if (bdrv_dirty_bitmap_has_successor(bitmap)) {
7711c0
@@ -796,17 +821,10 @@ void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
7711c0
 
7711c0
     qemu_mutex_lock(dest->mutex);
7711c0
 
7711c0
-    if (bdrv_dirty_bitmap_busy(dest)) {
7711c0
-        error_setg(errp, "Bitmap '%s' is currently in use by another"
7711c0
-        " operation and cannot be modified", dest->name);
7711c0
+    if (bdrv_dirty_bitmap_check(dest, BDRV_BITMAP_DEFAULT, errp)) {
7711c0
         goto out;
7711c0
     }
7711c0
 
7711c0
-    if (bdrv_dirty_bitmap_readonly(dest)) {
7711c0
-        error_setg(errp, "Bitmap '%s' is readonly and cannot be modified",
7711c0
-                   dest->name);
7711c0
-        goto out;
7711c0
-    }
7711c0
 
7711c0
     if (!hbitmap_can_merge(dest->bitmap, src->bitmap)) {
7711c0
         error_setg(errp, "Bitmaps are incompatible and can't be merged");
7711c0
diff --git a/blockdev.c b/blockdev.c
7711c0
index a9e2e1d..860cea6 100644
7711c0
--- a/blockdev.c
7711c0
+++ b/blockdev.c
7711c0
@@ -2160,11 +2160,7 @@ static void block_dirty_bitmap_clear_prepare(BlkActionState *common,
7711c0
         return;
7711c0
     }
7711c0
 
7711c0
-    if (bdrv_dirty_bitmap_busy(state->bitmap)) {
7711c0
-        error_setg(errp, "Cannot modify a bitmap in use by another operation");
7711c0
-        return;
7711c0
-    } else if (bdrv_dirty_bitmap_readonly(state->bitmap)) {
7711c0
-        error_setg(errp, "Cannot clear a readonly bitmap");
7711c0
+    if (bdrv_dirty_bitmap_check(state->bitmap, BDRV_BITMAP_DEFAULT, errp)) {
7711c0
         return;
7711c0
     }
7711c0
 
7711c0
@@ -2209,10 +2205,7 @@ static void block_dirty_bitmap_enable_prepare(BlkActionState *common,
7711c0
         return;
7711c0
     }
7711c0
 
7711c0
-    if (bdrv_dirty_bitmap_busy(state->bitmap)) {
7711c0
-        error_setg(errp,
7711c0
-                   "Bitmap '%s' is currently in use by another operation"
7711c0
-                   " and cannot be enabled", action->name);
7711c0
+    if (bdrv_dirty_bitmap_check(state->bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
7711c0
         return;
7711c0
     }
7711c0
 
7711c0
@@ -2250,10 +2243,7 @@ static void block_dirty_bitmap_disable_prepare(BlkActionState *common,
7711c0
         return;
7711c0
     }
7711c0
 
7711c0
-    if (bdrv_dirty_bitmap_busy(state->bitmap)) {
7711c0
-        error_setg(errp,
7711c0
-                   "Bitmap '%s' is currently in use by another operation"
7711c0
-                   " and cannot be disabled", action->name);
7711c0
+    if (bdrv_dirty_bitmap_check(state->bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
7711c0
         return;
7711c0
     }
7711c0
 
7711c0
@@ -3044,10 +3034,7 @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
7711c0
         return;
7711c0
     }
7711c0
 
7711c0
-    if (bdrv_dirty_bitmap_busy(bitmap)) {
7711c0
-        error_setg(errp,
7711c0
-                   "Bitmap '%s' is currently in use by another operation and"
7711c0
-                   " cannot be removed", name);
7711c0
+    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY, errp)) {
7711c0
         return;
7711c0
     }
7711c0
 
7711c0
@@ -3083,13 +3070,7 @@ void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
7711c0
         return;
7711c0
     }
7711c0
 
7711c0
-    if (bdrv_dirty_bitmap_busy(bitmap)) {
7711c0
-        error_setg(errp,
7711c0
-                   "Bitmap '%s' is currently in use by another operation"
7711c0
-                   " and cannot be cleared", name);
7711c0
-        return;
7711c0
-    } else if (bdrv_dirty_bitmap_readonly(bitmap)) {
7711c0
-        error_setg(errp, "Bitmap '%s' is readonly and cannot be cleared", name);
7711c0
+    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) {
7711c0
         return;
7711c0
     }
7711c0
 
7711c0
@@ -3107,10 +3088,7 @@ void qmp_block_dirty_bitmap_enable(const char *node, const char *name,
7711c0
         return;
7711c0
     }
7711c0
 
7711c0
-    if (bdrv_dirty_bitmap_busy(bitmap)) {
7711c0
-        error_setg(errp,
7711c0
-                   "Bitmap '%s' is currently in use by another operation"
7711c0
-                   " and cannot be enabled", name);
7711c0
+    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
7711c0
         return;
7711c0
     }
7711c0
 
7711c0
@@ -3128,10 +3106,7 @@ void qmp_block_dirty_bitmap_disable(const char *node, const char *name,
7711c0
         return;
7711c0
     }
7711c0
 
7711c0
-    if (bdrv_dirty_bitmap_busy(bitmap)) {
7711c0
-        error_setg(errp,
7711c0
-                   "Bitmap '%s' is currently in use by another operation"
7711c0
-                   " and cannot be disabled", name);
7711c0
+    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
7711c0
         return;
7711c0
     }
7711c0
 
7711c0
@@ -3709,10 +3684,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
7711c0
             bdrv_unref(target_bs);
7711c0
             goto out;
7711c0
         }
7711c0
-        if (bdrv_dirty_bitmap_busy(bmap)) {
7711c0
-            error_setg(errp,
7711c0
-                       "Bitmap '%s' is currently in use by another operation"
7711c0
-                       " and cannot be used for backup", backup->bitmap);
7711c0
+        if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_ALLOW_RO, errp)) {
7711c0
             goto out;
7711c0
         }
7711c0
     }
7711c0
@@ -3816,10 +3788,7 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
7711c0
             error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
7711c0
             goto out;
7711c0
         }
7711c0
-        if (bdrv_dirty_bitmap_busy(bmap)) {
7711c0
-            error_setg(errp,
7711c0
-                       "Bitmap '%s' is currently in use by another operation"
7711c0
-                       " and cannot be used for backup", backup->bitmap);
7711c0
+        if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_ALLOW_RO, errp)) {
7711c0
             goto out;
7711c0
         }
7711c0
     }
7711c0
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
7711c0
index bd1b647..2a78243 100644
7711c0
--- a/include/block/dirty-bitmap.h
7711c0
+++ b/include/block/dirty-bitmap.h
7711c0
@@ -5,6 +5,16 @@
7711c0
 #include "qapi/qapi-types-block-core.h"
7711c0
 #include "qemu/hbitmap.h"
7711c0
 
7711c0
+typedef enum BitmapCheckFlags {
7711c0
+    BDRV_BITMAP_BUSY = 1,
7711c0
+    BDRV_BITMAP_RO = 2,
7711c0
+    BDRV_BITMAP_INCONSISTENT = 4,
7711c0
+} BitmapCheckFlags;
7711c0
+
7711c0
+#define BDRV_BITMAP_DEFAULT (BDRV_BITMAP_BUSY | BDRV_BITMAP_RO |        \
7711c0
+                             BDRV_BITMAP_INCONSISTENT)
7711c0
+#define BDRV_BITMAP_ALLOW_RO (BDRV_BITMAP_BUSY | BDRV_BITMAP_INCONSISTENT)
7711c0
+
7711c0
 BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
7711c0
                                           uint32_t granularity,
7711c0
                                           const char *name,
7711c0
@@ -24,6 +34,8 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs,
7711c0
 void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap);
7711c0
 BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs,
7711c0
                                         const char *name);
7711c0
+int bdrv_dirty_bitmap_check(const BdrvDirtyBitmap *bitmap, uint32_t flags,
7711c0
+                            Error **errp);
7711c0
 void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap);
7711c0
 void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs);
7711c0
 void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs,
7711c0
@@ -93,7 +105,6 @@ bool bdrv_has_readonly_bitmaps(BlockDriverState *bs);
7711c0
 bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap);
7711c0
 bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap);
7711c0
 bool bdrv_dirty_bitmap_inconsistent(const BdrvDirtyBitmap *bitmap);
7711c0
-bool bdrv_dirty_bitmap_busy(BdrvDirtyBitmap *bitmap);
7711c0
 bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs);
7711c0
 BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs,
7711c0
                                         BdrvDirtyBitmap *bitmap);
7711c0
diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c
7711c0
index 62f2806..06ab58d 100644
7711c0
--- a/migration/block-dirty-bitmap.c
7711c0
+++ b/migration/block-dirty-bitmap.c
7711c0
@@ -274,6 +274,7 @@ static int init_dirty_bitmap_migration(void)
7711c0
     BdrvDirtyBitmap *bitmap;
7711c0
     DirtyBitmapMigBitmapState *dbms;
7711c0
     BdrvNextIterator it;
7711c0
+    Error *local_err = NULL;
7711c0
 
7711c0
     dirty_bitmap_mig_state.bulk_completed = false;
7711c0
     dirty_bitmap_mig_state.prev_bs = NULL;
7711c0
@@ -301,15 +302,9 @@ static int init_dirty_bitmap_migration(void)
7711c0
                 goto fail;
7711c0
             }
7711c0
 
7711c0
-            if (bdrv_dirty_bitmap_busy(bitmap)) {
7711c0
-                error_report("Can't migrate a bitmap that is in use by another operation: '%s'",
7711c0
-                             bdrv_dirty_bitmap_name(bitmap));
7711c0
-                goto fail;
7711c0
-            }
7711c0
-
7711c0
-            if (bdrv_dirty_bitmap_readonly(bitmap)) {
7711c0
-                error_report("Can't migrate read-only dirty bitmap: '%s",
7711c0
-                             bdrv_dirty_bitmap_name(bitmap));
7711c0
+            if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT,
7711c0
+                                        &local_err)) {
7711c0
+                error_report_err(local_err);
7711c0
                 goto fail;
7711c0
             }
7711c0
 
7711c0
diff --git a/nbd/server.c b/nbd/server.c
7711c0
index 02773e2..9b87c7f 100644
7711c0
--- a/nbd/server.c
7711c0
+++ b/nbd/server.c
7711c0
@@ -1510,8 +1510,7 @@ NBDExport *nbd_export_new(BlockDriverState *bs, uint64_t dev_offset,
7711c0
             goto fail;
7711c0
         }
7711c0
 
7711c0
-        if (bdrv_dirty_bitmap_busy(bm)) {
7711c0
-            error_setg(errp, "Bitmap '%s' is in use", bitmap);
7711c0
+        if (bdrv_dirty_bitmap_check(bm, BDRV_BITMAP_ALLOW_RO, errp)) {
7711c0
             goto fail;
7711c0
         }
7711c0
 
7711c0
-- 
7711c0
1.8.3.1
7711c0