diff --git a/include/spdk/blob.h b/include/spdk/blob.h index bd8d1acb1da..38137a9d037 100644 --- a/include/spdk/blob.h +++ b/include/spdk/blob.h @@ -727,25 +727,42 @@ int spdk_blob_get_clones(struct spdk_blob_store *bs, spdk_blob_id blobid, spdk_b size_t *count); /** - * Provide table with blob id's of clones are dependent on specified snapshot. + * Get a count of all snapshot clones. * If the clone_attr exists in the blob xattr, then it's a clone. * - * Ids array should be allocated and the count parameter set to the number of - * id's it can store, before calling this function. + * \param bs blobstore. + * \param clone_attr Name of the attribute which denotes a clone. + * \param snap_uuid Uuid of the snapshot. * - * If ids is NULL or count parameter is not sufficient to handle ids of all - * clones, -ENOMEM error is returned and count parameter is updated to the - * total number of clones. + * \return count of all clones from snapshots. + */ +size_t +spdk_blob_count_real_clones(struct spdk_blob_store *bs, const char *clone_attr, + const char *snap_uuid); + +/** + * Callback definition for spdk_bs_blob_clone_iter_cb. * - * \param bs blobstore. - * \param blobid Snapshots blob id. - * \param ids Array of the clone ids or NULL to get required size in count. - * \param count Size of ids. After call it is updated to the number of clones. + * \param lvol An iterated lvol. + * \param cb_arg Opaque context passed to spdk_bs_blob_clone_iter_cb(). + * \param blob_id The blob id of the clone. + */ +typedef void (*spdk_bs_blob_clone_iter_cb)(void *cb_arg, spdk_blob_id blob_id); + +/** + * Iterate all snapshot clones. + * If the clone_attr exists in the blob xattr, then it's a clone. * - * \return -ENOMEM if count is not sufficient to store all clones. + * \param bs blobstore. + * \param clone_attr Name of the attribute which denotes a clone. + * \param snap_uuid Uuid of the snapshot. + * \param cb_fn Callback for each clone. + * \param cb_arg Context for each callback. */ -int spdk_blob_get_real_clones(struct spdk_blob_store *bs, spdk_blob_id blobid, spdk_blob_id *ids, - size_t *count, const char *clone_attr); +void +spdk_blob_get_real_clones(struct spdk_blob_store *bs, const char *clone_attr, + const char *snap_uuid, + spdk_bs_blob_clone_iter_cb cb_fn, void *cb_arg); /** * Get the blob id for the parent snapshot of this blob. diff --git a/include/spdk/lvol.h b/include/spdk/lvol.h index 577897b948c..e042aae28fd 100644 --- a/include/spdk/lvol.h +++ b/include/spdk/lvol.h @@ -387,6 +387,16 @@ void spdk_lvol_close(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void * */ int spdk_lvol_iter_immediate_clones(struct spdk_lvol *lvol, spdk_lvol_iter_cb cb_fn, void *cb_arg); +/** + * Get the lvol that has a particular blob id, from the specified lvolstore. + * + * \param lvs The lvol's lvolstore. + * \param uuid The lvol's blobstore blob id. + * \return A pointer to the requested lvol on success, else NULL. + */ +struct spdk_lvol * +lvs_get_lvol_by_blob_id(struct spdk_lvol_store *lvs, spdk_blob_id blob_id); + /** * Get the lvol that has a particular UUID. * diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index 086074c0d26..7ce57ffa34f 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -9804,7 +9804,8 @@ blob_get_xattr_value(struct spdk_blob *blob, const char *name, } static bool -blob_xattr_exists(struct spdk_blob *blob, const char *name, bool internal) +blob_xattr_matches(struct spdk_blob *blob, const char *name, const char *value, int len, + bool internal) { struct spdk_xattr *xattr; struct spdk_xattr_tailq *xattrs; @@ -9813,7 +9814,11 @@ blob_xattr_exists(struct spdk_blob *blob, const char *name, bool internal) TAILQ_FOREACH(xattr, xattrs, link) { if (!strcmp(name, xattr->name)) { - return true; + if (xattr->value_len != len) { + SPDK_ERRLOG("Invalid xattr->value_len for %s\n", name); + } else if (!strncmp(value, xattr->value, len)) { + return true; + } } } return false; @@ -9986,43 +9991,41 @@ spdk_blob_get_parent_snapshot(struct spdk_blob_store *bs, spdk_blob_id blob_id) return SPDK_BLOBID_INVALID; } -int -spdk_blob_get_real_clones(struct spdk_blob_store *bs, spdk_blob_id blobid, spdk_blob_id *ids, - size_t *count, const char *clone_attr) +void +spdk_blob_get_real_clones(struct spdk_blob_store *bs, const char *clone_attr, const char *snap_uuid, + spdk_bs_blob_clone_iter_cb cb_fn, void *cb_arg) { - struct spdk_blob_list *snapshot_entry, *clone_entry; - size_t n; struct spdk_blob *blob; + int uuid_len = SPDK_UUID_STRING_LEN - 1; - snapshot_entry = bs_get_snapshot_entry(bs, blobid); - if (snapshot_entry == NULL) { - *count = 0; - return 0; - } - - if (ids == NULL || *count < snapshot_entry->clone_count) { - n = 0; - TAILQ_FOREACH(clone_entry, &snapshot_entry->clones, link) { - blob = blob_lookup(bs, clone_entry->id); - if (blob && blob_xattr_exists(blob, clone_attr, false)) { - n++; - } + RB_FOREACH(blob, spdk_blob_tree, &bs->open_blobs) { + if (!spdk_blob_is_clone(blob)) { + continue; + } + if (blob_xattr_matches(blob, clone_attr, snap_uuid, uuid_len, false)) { + cb_fn(cb_arg, blob->id); } - *count = n; - - return -ENOMEM; } - *count = snapshot_entry->clone_count; +} - n = 0; - TAILQ_FOREACH(clone_entry, &snapshot_entry->clones, link) { - blob = blob_lookup(bs, clone_entry->id); - if (blob && blob_xattr_exists(blob, clone_attr, false)) { - ids[n++] = clone_entry->id; +size_t +spdk_blob_count_real_clones(struct spdk_blob_store *bs, const char *clone_attr, + const char *snap_uuid) +{ + size_t count = 0; + struct spdk_blob *blob; + int uuid_len = SPDK_UUID_STRING_LEN - 1; + + RB_FOREACH(blob, spdk_blob_tree, &bs->open_blobs) { + if (!spdk_blob_is_clone(blob)) { + continue; + } + if (blob_xattr_matches(blob, clone_attr, snap_uuid, uuid_len, false)) { + count++; } } - return 0; + return count; } int diff --git a/lib/lvol/lvol.c b/lib/lvol/lvol.c index d3526d72c4a..b397d33dedf 100644 --- a/lib/lvol/lvol.c +++ b/lib/lvol/lvol.c @@ -41,7 +41,6 @@ static inline int lvs_opts_copy(const struct spdk_lvs_opts *src, struct spdk_lvs static int lvs_esnap_bs_dev_create(void *bs_ctx, void *blob_ctx, struct spdk_blob *blob, const void *esnap_id, uint32_t id_len, struct spdk_bs_dev **_bs_dev); -static struct spdk_lvol *lvs_get_lvol_by_blob_id(struct spdk_lvol_store *lvs, spdk_blob_id blob_id); static void lvs_degraded_lvol_set_add(struct spdk_lvs_degraded_lvol_set *degraded_set, struct spdk_lvol *lvol); static void lvs_degraded_lvol_set_remove(struct spdk_lvs_degraded_lvol_set *degraded_set, @@ -2102,7 +2101,7 @@ spdk_lvs_grow(struct spdk_bs_dev *bs_dev, spdk_lvs_op_with_handle_complete cb_fn spdk_bs_grow(bs_dev, &opts, lvs_load_cb, req); } -static struct spdk_lvol * +struct spdk_lvol * lvs_get_lvol_by_blob_id(struct spdk_lvol_store *lvs, spdk_blob_id blob_id) { struct spdk_lvol *lvol;