Commit 721695e1 authored by Paul Luse's avatar Paul Luse Committed by Daniel Verkamp
Browse files

blob: fix issue with blobid handling



Fixes github issue #29.

Because of how we handle the blobid and pagenum in blobstore,
it was possible to have blobstore inadvertently open the wrong
blob if open is provided a blobid where the lower 32 bits match
an existing blob but the upper 32 are clear.

Patch does the following:
- removes assert() that caught this on MD load and replace with
an error given that this condition can be induced via the API
- cleanup of pagenum and blobid conversion/handling to make it
clearer how they're related and converted
- new UTs that would have failed w/o the new check in place

Change-Id: I2b49b237922b3b8cfc4df296f5bc20195e41dc41
Signed-off-by: default avatarPaul Luse <paul.e.luse@intel.com>
Reviewed-on: https://review.gerrithub.io/380872


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 6f227249
Loading
Loading
Loading
Loading
+18 −7
Original line number Diff line number Diff line
@@ -270,9 +270,17 @@ _spdk_blob_parse(const struct spdk_blob_md_page *pages, uint32_t page_count,
	assert(blob != NULL);
	assert(blob->state == SPDK_BLOB_STATE_LOADING);
	assert(blob->active.clusters == NULL);
	assert(blob->id == pages[0].id);
	assert(blob->state == SPDK_BLOB_STATE_LOADING);

	/* The blobid provided doesn't match what's in the MD, this can
	 * happen for example if a bogus blobid is passed in through open.
	 */
	if (blob->id != pages[0].id) {
		SPDK_ERRLOG("Blobid (%lu) doesn't match what's in metadata (%lu)\n",
			    blob->id, pages[0].id);
		return -ENOENT;
	}

	for (i = 0; i < page_count; i++) {
		page = &pages[i];

@@ -579,6 +587,13 @@ _spdk_blob_load_cpl(spdk_bs_sequence_t *seq, void *cb_arg, int bserrno)

	/* Parse the pages */
	rc = _spdk_blob_parse(ctx->pages, ctx->num_pages, blob);
	if (rc) {
		_spdk_blob_free(blob);
		ctx->cb_fn(seq, NULL, rc);
		spdk_dma_free(ctx->pages);
		free(ctx);
		return;
	}

	_spdk_blob_mark_clean(blob);

@@ -2131,11 +2146,7 @@ void spdk_bs_md_create_blob(struct spdk_blob_store *bs,
	}
	spdk_bit_array_set(bs->used_md_pages, page_idx);

	/* The blob id is a 64 bit number. The lower 32 bits are the page_idx. The upper
	 * 32 bits are not currently used. Stick a 1 there just to catch bugs where the
	 * code assumes blob id == page_idx.
	 */
	id = (1ULL << 32) | page_idx;
	id = _spdk_bs_page_to_blobid(page_idx);

	SPDK_DEBUGLOG(SPDK_TRACE_BLOB, "Creating blob with id %lu at page %u\n", id, page_idx);

@@ -2496,7 +2507,7 @@ _spdk_bs_iter_cpl(void *cb_arg, struct spdk_blob *blob, int bserrno)
		return;
	}

	id = (1ULL << 32) | ctx->page_num;
	id = _spdk_bs_page_to_blobid(ctx->page_num);

	blob = _spdk_blob_lookup(bs, id);
	if (blob) {
+11 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@
#define SPDK_BLOB_OPTS_NUM_MD_PAGES UINT32_MAX
#define SPDK_BLOB_OPTS_MAX_MD_OPS 32
#define SPDK_BLOB_OPTS_MAX_CHANNEL_OPS 512
#define SPDK_BLOB_BLOBID_HIGH_BIT (1ULL << 32)

struct spdk_xattr {
	/* TODO: reorder for best packing */
@@ -350,6 +351,16 @@ _spdk_bs_blobid_to_page(spdk_blob_id id)
	return id & 0xFFFFFFFF;
}

/* The blob id is a 64 bit number. The lower 32 bits are the page_idx. The upper
 * 32 bits are not currently used. Stick a 1 there just to catch bugs where the
 * code assumes blob id == page_idx.
 */
static inline spdk_blob_id
_spdk_bs_page_to_blobid(uint32_t page_idx)
{
	return SPDK_BLOB_BLOBID_HIGH_BIT | page_idx;
}

/* Given a page offset into a blob, look up the LBA for the
 * start of that page.
 */
+10 −0
Original line number Diff line number Diff line
@@ -855,6 +855,11 @@ bs_load(void)
	CU_ASSERT(g_bserrno == 0);
	SPDK_CU_ASSERT_FATAL(g_bs != NULL);

	/* Try to open a blobid that does not exist */
	spdk_bs_md_open_blob(g_bs, 0, blob_op_with_handle_complete, NULL);
	CU_ASSERT(g_bserrno == -ENOENT);
	CU_ASSERT(g_blob == NULL);

	/* Create a blob */
	spdk_bs_md_create_blob(g_bs, blob_op_with_id_complete, NULL);
	CU_ASSERT(g_bserrno == 0);
@@ -866,6 +871,11 @@ bs_load(void)
	CU_ASSERT(g_blob != NULL);
	blob = g_blob;

	/* Try again to open valid blob but without the upper bit set */
	spdk_bs_md_open_blob(g_bs, blobid & 0xFFFFFFFF, blob_op_with_handle_complete, NULL);
	CU_ASSERT(g_bserrno == -ENOENT);
	CU_ASSERT(g_blob == NULL);

	/* Set some xattrs */
	rc = spdk_blob_md_set_xattr(blob, "name", "log.txt", strlen("log.txt") + 1);
	CU_ASSERT(rc == 0);