From 42e50f66d00e7598e0c8249321f4a31542fc97dc Mon Sep 17 00:00:00 2001 From: Mike Gerdts Date: Thu, 6 Apr 2023 08:55:38 -0500 Subject: [PATCH] blob: add spdk_blob_is_degraded() In preparation for supporting degraded lvols, spdk_blob_is_degraded() is added. To support this, bs_dev gains an optional is_degraded() callback. spdk_blob_is_degraded() returns false so long as no bs_dev that the blob depends on is degraded. Depended upon bs_devs include the blobstore's device and the blob's back_bs_dev. Signed-off-by: Mike Gerdts Change-Id: Ib02227f5735b00038ed30923813e1d5b57deb1ab Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/17516 Tested-by: SPDK CI Jenkins Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- include/spdk/blob.h | 11 +++++ lib/blob/blobstore.c | 13 ++++++ lib/blob/spdk_blob.map | 1 + test/unit/lib/blob/blob.c/blob_ut.c | 71 +++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+) diff --git a/include/spdk/blob.h b/include/spdk/blob.h index a6d87007c..2f6ef0c39 100644 --- a/include/spdk/blob.h +++ b/include/spdk/blob.h @@ -244,6 +244,8 @@ struct spdk_bs_dev { uint64_t dst_lba, uint64_t src_lba, uint64_t lba_count, struct spdk_bs_dev_cb_args *cb_args); + bool (*is_degraded)(struct spdk_bs_dev *dev); + uint64_t blockcnt; uint32_t blocklen; /* In bytes */ }; @@ -1143,6 +1145,15 @@ void spdk_blob_set_esnap_bs_dev(struct spdk_blob *blob, struct spdk_bs_dev *back */ struct spdk_bs_dev *spdk_blob_get_esnap_bs_dev(const struct spdk_blob *blob); +/** + * Determine if the blob is degraded. A degraded blob cannot perform IO. + * + * \param blob A blob + * + * \return true if the blob or any snapshots upon which it depends are degraded, else false. + */ +bool spdk_blob_is_degraded(const struct spdk_blob *blob); + #ifdef __cplusplus } #endif diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index f8a2676ab..065beebb7 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -9115,5 +9115,18 @@ spdk_blob_get_esnap_bs_dev(const struct spdk_blob *blob) return blob->back_bs_dev; } +bool +spdk_blob_is_degraded(const struct spdk_blob *blob) +{ + if (blob->bs->dev->is_degraded != NULL && blob->bs->dev->is_degraded(blob->bs->dev)) { + return true; + } + if (blob->back_bs_dev == NULL || blob->back_bs_dev->is_degraded == NULL) { + return false; + } + + return blob->back_bs_dev->is_degraded(blob->back_bs_dev); +} + SPDK_LOG_REGISTER_COMPONENT(blob) SPDK_LOG_REGISTER_COMPONENT(blob_esnap) diff --git a/lib/blob/spdk_blob.map b/lib/blob/spdk_blob.map index 175f5cdc8..cb4f60639 100644 --- a/lib/blob/spdk_blob.map +++ b/lib/blob/spdk_blob.map @@ -68,6 +68,7 @@ spdk_bs_set_bstype; spdk_blob_get_esnap_bs_dev; spdk_blob_set_esnap_bs_dev; + spdk_blob_is_degraded; local: *; }; diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index bc26a487a..0fa8debeb 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -8506,6 +8506,76 @@ blob_esnap_hotplug(void) CU_ASSERT(g_bserrno == 0); } +static bool g_blob_is_degraded; +static int g_blob_is_degraded_called; + +static bool +_blob_is_degraded(struct spdk_bs_dev *dev) +{ + g_blob_is_degraded_called++; + return g_blob_is_degraded; +} + +static void +blob_is_degraded(void) +{ + struct spdk_bs_dev bs_is_degraded_null = { 0 }; + struct spdk_bs_dev bs_is_degraded = { .is_degraded = _blob_is_degraded }; + + /* No back_bs_dev, no bs->dev->is_degraded */ + g_blob_is_degraded_called = 0; + CU_ASSERT(!spdk_blob_is_degraded(g_blob)); + CU_ASSERT(g_blob_is_degraded_called == 0); + + /* No back_bs_dev, blobstore device degraded */ + g_bs->dev->is_degraded = _blob_is_degraded; + g_blob_is_degraded_called = 0; + g_blob_is_degraded = true; + CU_ASSERT(spdk_blob_is_degraded(g_blob)); + CU_ASSERT(g_blob_is_degraded_called == 1); + + /* No back_bs_dev, blobstore device not degraded */ + g_bs->dev->is_degraded = _blob_is_degraded; + g_blob_is_degraded_called = 0; + g_blob_is_degraded = false; + CU_ASSERT(!spdk_blob_is_degraded(g_blob)); + CU_ASSERT(g_blob_is_degraded_called == 1); + + /* back_bs_dev does not define is_degraded, no bs->dev->is_degraded */ + g_bs->dev->is_degraded = NULL; + g_blob->back_bs_dev = &bs_is_degraded_null; + g_blob_is_degraded_called = 0; + g_blob_is_degraded = false; + CU_ASSERT(!spdk_blob_is_degraded(g_blob)); + CU_ASSERT(g_blob_is_degraded_called == 0); + + /* back_bs_dev is not degraded, no bs->dev->is_degraded */ + g_bs->dev->is_degraded = NULL; + g_blob->back_bs_dev = &bs_is_degraded; + g_blob_is_degraded_called = 0; + g_blob_is_degraded = false; + CU_ASSERT(!spdk_blob_is_degraded(g_blob)); + CU_ASSERT(g_blob_is_degraded_called == 1); + + /* back_bs_dev is degraded, no bs->dev->is_degraded */ + g_bs->dev->is_degraded = NULL; + g_blob->back_bs_dev = &bs_is_degraded; + g_blob_is_degraded_called = 0; + g_blob_is_degraded = true; + CU_ASSERT(spdk_blob_is_degraded(g_blob)); + CU_ASSERT(g_blob_is_degraded_called == 1); + + /* back_bs_dev is not degraded, blobstore device is not degraded */ + g_bs->dev->is_degraded = _blob_is_degraded; + g_blob->back_bs_dev = &bs_is_degraded; + g_blob_is_degraded_called = 0; + g_blob_is_degraded = false; + CU_ASSERT(!spdk_blob_is_degraded(g_blob)); + CU_ASSERT(g_blob_is_degraded_called == 2); + + g_blob->back_bs_dev = NULL; +} + static void suite_bs_setup(void) { @@ -8717,6 +8787,7 @@ main(int argc, char **argv) CU_ADD_TEST(suite_esnap_bs, blob_esnap_clone_decouple); CU_ADD_TEST(suite_esnap_bs, blob_esnap_clone_reload); CU_ADD_TEST(suite_esnap_bs, blob_esnap_hotplug); + CU_ADD_TEST(suite_blob, blob_is_degraded); allocate_threads(2); set_thread(0);