diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index 64b0d60c1..d2b70891a 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -53,6 +53,12 @@ static void _spdk_blob_close_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bser void _spdk_blob_insert_cluster_on_md_thread(struct spdk_blob_data *blob, uint32_t cluster_num, uint64_t cluster, spdk_blob_op_complete cb_fn, void *cb_arg); +static int _spdk_blob_set_xattr(struct spdk_blob_data *blob, const char *name, const void *value, + uint16_t value_len, bool internal); +static int _spdk_blob_get_xattr_value(struct spdk_blob_data *blob, const char *name, + const void **value, size_t *value_len, bool internal); +static int _spdk_blob_remove_xattr(struct spdk_blob_data *blob, const char *name, bool internal); + static inline size_t divide_round_up(size_t num, size_t divisor) { @@ -161,6 +167,7 @@ _spdk_blob_alloc(struct spdk_blob_store *bs, spdk_blob_id id) blob->active.pages[0] = _spdk_bs_blobid_to_page(id); TAILQ_INIT(&blob->xattrs); + TAILQ_INIT(&blob->xattrs_internal); return blob; } @@ -189,6 +196,7 @@ _spdk_blob_free(struct spdk_blob_data *blob) free(blob->clean.pages); _spdk_xattrs_free(&blob->xattrs); + _spdk_xattrs_free(&blob->xattrs_internal); free(blob); } @@ -240,7 +248,7 @@ _spdk_blob_mark_clean(struct spdk_blob_data *blob) static int _spdk_blob_deserialize_xattr(struct spdk_blob_data *blob, - struct spdk_blob_md_descriptor_xattr *desc_xattr) + struct spdk_blob_md_descriptor_xattr *desc_xattr, bool internal) { struct spdk_xattr *xattr; @@ -274,7 +282,8 @@ _spdk_blob_deserialize_xattr(struct spdk_blob_data *blob, (void *)((uintptr_t)desc_xattr->name + desc_xattr->name_length), desc_xattr->value_length); - TAILQ_INSERT_TAIL(&blob->xattrs, xattr, link); + TAILQ_INSERT_TAIL(internal ? &blob->xattrs_internal : &blob->xattrs, xattr, link); + return 0; } @@ -375,7 +384,16 @@ _spdk_blob_parse_page(const struct spdk_blob_md_page *page, struct spdk_blob_dat } else if (desc->type == SPDK_MD_DESCRIPTOR_TYPE_XATTR) { int rc; - rc = _spdk_blob_deserialize_xattr(blob, (struct spdk_blob_md_descriptor_xattr *) desc); + rc = _spdk_blob_deserialize_xattr(blob, + (struct spdk_blob_md_descriptor_xattr *) desc, false); + if (rc != 0) { + return rc; + } + } else if (desc->type == SPDK_MD_DESCRIPTOR_TYPE_XATTR_INTERNAL) { + int rc; + + rc = _spdk_blob_deserialize_xattr(blob, + (struct spdk_blob_md_descriptor_xattr *) desc, true); if (rc != 0) { return rc; } @@ -487,7 +505,7 @@ _spdk_blob_serialize_add_page(const struct spdk_blob_data *blob, static int _spdk_blob_serialize_xattr(const struct spdk_xattr *xattr, uint8_t *buf, size_t buf_sz, - size_t *required_sz) + size_t *required_sz, bool internal) { struct spdk_blob_md_descriptor_xattr *desc; @@ -501,7 +519,7 @@ _spdk_blob_serialize_xattr(const struct spdk_xattr *xattr, desc = (struct spdk_blob_md_descriptor_xattr *)buf; - desc->type = SPDK_MD_DESCRIPTOR_TYPE_XATTR; + desc->type = internal ? SPDK_MD_DESCRIPTOR_TYPE_XATTR_INTERNAL : SPDK_MD_DESCRIPTOR_TYPE_XATTR; desc->length = sizeof(desc->name_length) + sizeof(desc->value_length) + strlen(xattr->name) + @@ -598,7 +616,7 @@ _spdk_blob_serialize_flags(const struct spdk_blob_data *blob, static int _spdk_blob_serialize_xattrs(const struct spdk_blob_data *blob, - const struct spdk_xattr_tailq *xattrs, + const struct spdk_xattr_tailq *xattrs, bool internal, struct spdk_blob_md_page **pages, struct spdk_blob_md_page *cur_page, uint32_t *page_count, uint8_t **buf, @@ -612,7 +630,7 @@ _spdk_blob_serialize_xattrs(const struct spdk_blob_data *blob, rc = _spdk_blob_serialize_xattr(xattr, *buf, *remaining_sz, - &required_sz); + &required_sz, internal); if (rc < 0) { /* Need to add a new page to the chain */ rc = _spdk_blob_serialize_add_page(blob, pages, page_count, @@ -631,7 +649,7 @@ _spdk_blob_serialize_xattrs(const struct spdk_blob_data *blob, required_sz = 0; rc = _spdk_blob_serialize_xattr(xattr, *buf, *remaining_sz, - &required_sz); + &required_sz, internal); if (rc < 0) { spdk_dma_free(*pages); @@ -680,11 +698,19 @@ _spdk_blob_serialize(const struct spdk_blob_data *blob, struct spdk_blob_md_page buf += sizeof(struct spdk_blob_md_descriptor_flags); /* Serialize xattrs */ - rc = _spdk_blob_serialize_xattrs(blob, &blob->xattrs, + rc = _spdk_blob_serialize_xattrs(blob, &blob->xattrs, false, pages, cur_page, page_count, &buf, &remaining_sz); if (rc < 0) { return rc; } + + /* Serialize internal xattrs */ + rc = _spdk_blob_serialize_xattrs(blob, &blob->xattrs_internal, true, + pages, cur_page, page_count, &buf, &remaining_sz); + if (rc < 0) { + return rc; + } + /* Serialize extents */ last_cluster = 0; while (last_cluster < blob->active.num_clusters) { @@ -2353,6 +2379,8 @@ _spdk_bs_load_replay_md_parse_page(const struct spdk_blob_md_page *page, struct } } else if (desc->type == SPDK_MD_DESCRIPTOR_TYPE_XATTR) { /* Skip this item */ + } else if (desc->type == SPDK_MD_DESCRIPTOR_TYPE_XATTR_INTERNAL) { + /* Skip this item */ } else if (desc->type == SPDK_MD_DESCRIPTOR_TYPE_FLAGS) { /* Skip this item */ } else { @@ -3169,7 +3197,8 @@ _spdk_bs_create_blob_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno) } static int -_spdk_blob_set_xattrs(struct spdk_blob *blob, const struct spdk_blob_xattr_opts *xattrs) +_spdk_blob_set_xattrs(struct spdk_blob_data *blob, const struct spdk_blob_xattr_opts *xattrs, + bool internal) { uint64_t i; size_t value_len = 0; @@ -3183,7 +3212,7 @@ _spdk_blob_set_xattrs(struct spdk_blob *blob, const struct spdk_blob_xattr_opts if (value == NULL || value_len == 0) { return -EINVAL; } - rc = spdk_blob_set_xattr(blob, xattrs->names[i], value, value_len); + rc = _spdk_blob_set_xattr(blob, xattrs->names[i], value, value_len, internal); if (rc < 0) { return rc; } @@ -3232,7 +3261,7 @@ void spdk_bs_create_blob_ext(struct spdk_blob_store *bs, const struct spdk_blob_ opts = &opts_default; } - rc = _spdk_blob_set_xattrs(__data_to_blob(blob), &opts->xattrs); + rc = _spdk_blob_set_xattrs(blob, &opts->xattrs, false); if (rc < 0) { _spdk_blob_free(blob); cb_fn(cb_arg, 0, rc); @@ -3817,11 +3846,11 @@ spdk_bs_iter_next(struct spdk_blob_store *bs, struct spdk_blob *b, spdk_blob_close(b, _spdk_bs_iter_close_cpl, ctx); } -int -spdk_blob_set_xattr(struct spdk_blob *_blob, const char *name, const void *value, - uint16_t value_len) +static int +_spdk_blob_set_xattr(struct spdk_blob_data *blob, const char *name, const void *value, + uint16_t value_len, bool internal) { - struct spdk_blob_data *blob = __blob_to_data(_blob); + struct spdk_xattr_tailq *xattrs; struct spdk_xattr *xattr; assert(blob != NULL); @@ -3833,7 +3862,14 @@ spdk_blob_set_xattr(struct spdk_blob *_blob, const char *name, const void *value return -EPERM; } - TAILQ_FOREACH(xattr, &blob->xattrs, link) { + if (internal) { + xattrs = &blob->xattrs_internal; + blob->invalid_flags |= SPDK_BLOB_INTERNAL_XATTR; + } else { + xattrs = &blob->xattrs; + } + + TAILQ_FOREACH(xattr, xattrs, link) { if (!strcmp(name, xattr->name)) { free(xattr->value); xattr->value_len = value_len; @@ -3854,7 +3890,7 @@ spdk_blob_set_xattr(struct spdk_blob *_blob, const char *name, const void *value xattr->value_len = value_len; xattr->value = malloc(value_len); memcpy(xattr->value, value, value_len); - TAILQ_INSERT_TAIL(&blob->xattrs, xattr, link); + TAILQ_INSERT_TAIL(xattrs, xattr, link); blob->state = SPDK_BLOB_STATE_DIRTY; @@ -3862,9 +3898,16 @@ spdk_blob_set_xattr(struct spdk_blob *_blob, const char *name, const void *value } int -spdk_blob_remove_xattr(struct spdk_blob *_blob, const char *name) +spdk_blob_set_xattr(struct spdk_blob *blob, const char *name, const void *value, + uint16_t value_len) { - struct spdk_blob_data *blob = __blob_to_data(_blob); + return _spdk_blob_set_xattr(__blob_to_data(blob), name, value, value_len, false); +} + +static int +_spdk_blob_remove_xattr(struct spdk_blob_data *blob, const char *name, bool internal) +{ + struct spdk_xattr_tailq *xattrs; struct spdk_xattr *xattr; assert(blob != NULL); @@ -3875,14 +3918,18 @@ spdk_blob_remove_xattr(struct spdk_blob *_blob, const char *name) if (blob->md_ro) { return -EPERM; } + xattrs = internal ? &blob->xattrs_internal : &blob->xattrs; - TAILQ_FOREACH(xattr, &blob->xattrs, link) { + TAILQ_FOREACH(xattr, xattrs, link) { if (!strcmp(name, xattr->name)) { - TAILQ_REMOVE(&blob->xattrs, xattr, link); + TAILQ_REMOVE(xattrs, xattr, link); free(xattr->value); free(xattr->name); free(xattr); + if (internal && TAILQ_EMPTY(&blob->xattrs_internal)) { + blob->invalid_flags &= ~SPDK_BLOB_INTERNAL_XATTR; + } blob->state = SPDK_BLOB_STATE_DIRTY; return 0; @@ -3893,36 +3940,49 @@ spdk_blob_remove_xattr(struct spdk_blob *_blob, const char *name) } int -spdk_blob_get_xattr_value(struct spdk_blob *_blob, const char *name, - const void **value, size_t *value_len) +spdk_blob_remove_xattr(struct spdk_blob *blob, const char *name) { - struct spdk_blob_data *blob = __blob_to_data(_blob); - struct spdk_xattr *xattr; + return _spdk_blob_remove_xattr(__blob_to_data(blob), name, false); +} - TAILQ_FOREACH(xattr, &blob->xattrs, link) { +static int +_spdk_blob_get_xattr_value(struct spdk_blob_data *blob, const char *name, + const void **value, size_t *value_len, bool internal) +{ + struct spdk_xattr *xattr; + struct spdk_xattr_tailq *xattrs; + + xattrs = internal ? &blob->xattrs_internal : &blob->xattrs; + + TAILQ_FOREACH(xattr, xattrs, link) { if (!strcmp(name, xattr->name)) { *value = xattr->value; *value_len = xattr->value_len; return 0; } } - return -ENOENT; } +int +spdk_blob_get_xattr_value(struct spdk_blob *blob, const char *name, + const void **value, size_t *value_len) +{ + return _spdk_blob_get_xattr_value(__blob_to_data(blob), name, value, value_len, false); +} + struct spdk_xattr_names { uint32_t count; const char *names[0]; }; -int -spdk_blob_get_xattr_names(struct spdk_blob *_blob, struct spdk_xattr_names **names) +static int +_spdk_blob_get_xattr_names(struct spdk_xattr_tailq *xattrs, struct spdk_xattr_names **names) { - struct spdk_blob_data *blob = __blob_to_data(_blob); struct spdk_xattr *xattr; int count = 0; - TAILQ_FOREACH(xattr, &blob->xattrs, link) { + TAILQ_FOREACH(xattr, xattrs, link) { count++; } @@ -3931,13 +3991,19 @@ spdk_blob_get_xattr_names(struct spdk_blob *_blob, struct spdk_xattr_names **nam return -ENOMEM; } - TAILQ_FOREACH(xattr, &blob->xattrs, link) { + TAILQ_FOREACH(xattr, xattrs, link) { (*names)->names[(*names)->count++] = xattr->name; } return 0; } +int +spdk_blob_get_xattr_names(struct spdk_blob *_blob, struct spdk_xattr_names **names) +{ + return _spdk_blob_get_xattr_names(&__blob_to_data(_blob)->xattrs, names); +} + uint32_t spdk_xattr_names_get_count(struct spdk_xattr_names *names) { diff --git a/lib/blob/blobstore.h b/lib/blob/blobstore.h index c6d98cfcb..7d331af1a 100644 --- a/lib/blob/blobstore.h +++ b/lib/blob/blobstore.h @@ -108,6 +108,8 @@ enum spdk_blob_state { SPDK_BLOB_STATE_SYNCING, }; +TAILQ_HEAD(spdk_xattr_tailq, spdk_xattr); + struct spdk_blob_data { struct spdk_blob_store *bs; @@ -138,7 +140,8 @@ struct spdk_blob_data { /* TODO: The xattrs are mutable, but we don't want to be * copying them unecessarily. Figure this out. */ - TAILQ_HEAD(spdk_xattr_tailq, spdk_xattr) xattrs; + struct spdk_xattr_tailq xattrs; + struct spdk_xattr_tailq xattrs_internal; TAILQ_ENTRY(spdk_blob_data) link; }; @@ -223,6 +226,7 @@ struct spdk_bs_md_mask { #define SPDK_MD_DESCRIPTOR_TYPE_EXTENT 1 #define SPDK_MD_DESCRIPTOR_TYPE_XATTR 2 #define SPDK_MD_DESCRIPTOR_TYPE_FLAGS 3 +#define SPDK_MD_DESCRIPTOR_TYPE_XATTR_INTERNAL 4 struct spdk_blob_md_descriptor_xattr { uint8_t type; @@ -246,7 +250,8 @@ struct spdk_blob_md_descriptor_extent { }; #define SPDK_BLOB_THIN_PROV (1ULL << 0) -#define SPDK_BLOB_INVALID_FLAGS_MASK SPDK_BLOB_THIN_PROV +#define SPDK_BLOB_INTERNAL_XATTR (1ULL << 1) +#define SPDK_BLOB_INVALID_FLAGS_MASK (SPDK_BLOB_THIN_PROV | SPDK_BLOB_INTERNAL_XATTR) #define SPDK_BLOB_READ_ONLY (1ULL << 0) #define SPDK_BLOB_DATA_RO_FLAGS_MASK SPDK_BLOB_READ_ONLY diff --git a/test/unit/lib/blob/blob.c/blob_ut.c b/test/unit/lib/blob/blob.c/blob_ut.c index d1a2113ea..5fb6334a7 100644 --- a/test/unit/lib/blob/blob.c/blob_ut.c +++ b/test/unit/lib/blob/blob.c/blob_ut.c @@ -1294,9 +1294,53 @@ blob_xattr(void) rc = spdk_blob_remove_xattr(blob, "foobar"); CU_ASSERT(rc == -ENOENT); + /* Set internal xattr */ + length = 7898; + rc = _spdk_blob_set_xattr(__blob_to_data(blob), "internal", &length, sizeof(length), true); + CU_ASSERT(rc == 0); + rc = _spdk_blob_get_xattr_value(__blob_to_data(blob), "internal", &value, &value_len, true); + CU_ASSERT(rc == 0); + CU_ASSERT(*(uint64_t *)value == length); + /* try to get public xattr with same name */ + rc = spdk_blob_get_xattr_value(blob, "internal", &value, &value_len); + CU_ASSERT(rc != 0); + rc = _spdk_blob_get_xattr_value(__blob_to_data(blob), "internal", &value, &value_len, false); + CU_ASSERT(rc != 0); + /* Check if SPDK_BLOB_INTERNAL_XATTR is set */ + CU_ASSERT((__blob_to_data(blob)->invalid_flags & SPDK_BLOB_INTERNAL_XATTR) == + SPDK_BLOB_INTERNAL_XATTR) + spdk_blob_close(blob, blob_op_complete, NULL); spdk_bs_unload(g_bs, bs_op_complete, NULL); + + /* Check if xattrs are persisted */ + dev = init_dev(); + + spdk_bs_load(dev, NULL, bs_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + SPDK_CU_ASSERT_FATAL(g_bs != NULL); + + bs = g_bs; + + spdk_bs_open_blob(bs, blobid, blob_op_with_handle_complete, NULL); + CU_ASSERT(g_bserrno == 0); + SPDK_CU_ASSERT_FATAL(g_blob != NULL); + blob = g_blob; + + rc = _spdk_blob_get_xattr_value(__blob_to_data(blob), "internal", &value, &value_len, true); + CU_ASSERT(rc == 0); + CU_ASSERT(*(uint64_t *)value == length); + + /* try to get internal xattr trough public call */ + rc = spdk_blob_get_xattr_value(blob, "internal", &value, &value_len); + CU_ASSERT(rc != 0); + + rc = _spdk_blob_remove_xattr(__blob_to_data(blob), "internal", true); + CU_ASSERT(rc == 0); + + CU_ASSERT((__blob_to_data(blob)->invalid_flags & SPDK_BLOB_INTERNAL_XATTR) == 0); + CU_ASSERT(g_bserrno == 0); g_bs = NULL; }