blobstore: allow xattrs to be set internally only for blobstore
Patch adds internal version of xattr functions to allow operations on internal xattrs, which are not visible to upper layers. When there is at least one internal xattr set, also SPDK_BLOB_INTERNAL_XATTR flag is set in invalid_flags to prevent loading this blob in previous spdk versions. Signed-off-by: Piotr Pelplinski <piotr.pelplinski@intel.com> Change-Id: Iec918ec858f069f7cd9f36d5e8f0495ffa4a42d8 Reviewed-on: https://review.gerrithub.io/395122 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Maciej Szwed <maciej.szwed@intel.com> Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
parent
8f3d0a6413
commit
7ba8c006c5
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user