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:
Piotr Pelplinski 2018-01-29 10:25:44 +01:00 committed by Jim Harris
parent 8f3d0a6413
commit 7ba8c006c5
3 changed files with 150 additions and 35 deletions

View File

@ -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)
{

View File

@ -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

View File

@ -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;
}