diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index b9c7bd2db..02e3d2f30 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -637,6 +637,53 @@ _spdk_blob_parse_page(const struct spdk_blob_md_page *page, struct spdk_blob *bl return -EINVAL; } } + } else if (desc->type == SPDK_MD_DESCRIPTOR_TYPE_EXTENT_PAGE) { + struct spdk_blob_md_descriptor_extent_page *desc_extent; + unsigned int i; + unsigned int cluster_count = blob->active.num_clusters; + + if (blob->extent_rle_found) { + /* This means that Extent RLE is present in MD, + * both should never be at the same time. */ + return -EINVAL; + } + + desc_extent = (struct spdk_blob_md_descriptor_extent_page *)desc; + + if (desc_extent->length == 0 || + (desc_extent->length % sizeof(desc_extent->cluster_idx[0]) != 0)) { + return -EINVAL; + } + + for (i = 0; i < desc_extent->length / sizeof(desc_extent->cluster_idx[0]); i++) { + if (desc_extent->cluster_idx[i] != 0) { + if (!spdk_bit_array_get(blob->bs->used_clusters, desc_extent->cluster_idx[i])) { + return -EINVAL; + } + } + cluster_count++; + } + + if (cluster_count == 0) { + return -EINVAL; + } + tmp = realloc(blob->active.clusters, cluster_count * sizeof(*blob->active.clusters)); + if (tmp == NULL) { + return -ENOMEM; + } + blob->active.clusters = tmp; + blob->active.cluster_array_size = cluster_count; + + for (i = 0; i < desc_extent->length / sizeof(desc_extent->cluster_idx[0]); i++) { + if (desc_extent->cluster_idx[i] != 0) { + blob->active.clusters[blob->active.num_clusters++] = _spdk_bs_cluster_to_lba(blob->bs, + desc_extent->cluster_idx[i]); + } else if (spdk_blob_is_thin_provisioned(blob)) { + blob->active.clusters[blob->active.num_clusters++] = 0; + } else { + return -EINVAL; + } + } } else if (desc->type == SPDK_MD_DESCRIPTOR_TYPE_XATTR) { int rc; @@ -3352,6 +3399,8 @@ _spdk_bs_load_replay_md_parse_page(const struct spdk_blob_md_page *page, struct if (cluster_count == 0) { return -EINVAL; } + } else if (desc->type == SPDK_MD_DESCRIPTOR_TYPE_EXTENT_PAGE) { + /* Skip this item */ } else if (desc->type == SPDK_MD_DESCRIPTOR_TYPE_XATTR) { /* Skip this item */ } else if (desc->type == SPDK_MD_DESCRIPTOR_TYPE_XATTR_INTERNAL) { @@ -3384,6 +3433,7 @@ static bool _spdk_bs_load_cur_md_page_valid(struct spdk_bs_load_ctx *ctx) return false; } + /* First page of a sequence should match the blobid. */ if (ctx->page->sequence_num == 0 && _spdk_bs_page_to_blobid(ctx->cur_page) != ctx->page->id) { return false; @@ -3788,6 +3838,21 @@ _spdk_bs_dump_print_md_page(struct spdk_bs_dump_ctx *ctx) fprintf(ctx->fp, " Length: %" PRIu32, desc_extent_rle->extents[i].length); fprintf(ctx->fp, "\n"); } + } else if (desc->type == SPDK_MD_DESCRIPTOR_TYPE_EXTENT_PAGE) { + struct spdk_blob_md_descriptor_extent_page *desc_extent; + unsigned int i; + + desc_extent = (struct spdk_blob_md_descriptor_extent_page *)desc; + + for (i = 0; i < desc_extent->length / sizeof(desc_extent->cluster_idx[0]); i++) { + if (desc_extent->cluster_idx[i] != 0) { + fprintf(ctx->fp, "Allocated Extent - Start: %" PRIu32, + desc_extent->cluster_idx[i]); + } else { + fprintf(ctx->fp, "Unallocated Extent"); + } + fprintf(ctx->fp, "\n"); + } } else if (desc->type == SPDK_MD_DESCRIPTOR_TYPE_XATTR) { struct spdk_blob_md_descriptor_xattr *desc_xattr; uint32_t i; diff --git a/lib/blob/blobstore.h b/lib/blob/blobstore.h index 73107ab30..c8d98b2db 100644 --- a/lib/blob/blobstore.h +++ b/lib/blob/blobstore.h @@ -279,6 +279,11 @@ struct spdk_bs_md_mask { * are run-length encoded, non-zero values are unallocated pages. * It is part of serialized metadata chain for a blob. */ #define SPDK_MD_DESCRIPTOR_TYPE_EXTENT_TABLE 5 +/* EXTENT_PAGE descriptor holds an array of LBAs that point to + * beginning of allocated clusters. The array is run-length encoded, + * with 0's being unallocated clusters. It is NOT part of + * serialized metadata chain for a blob. */ +#define SPDK_MD_DESCRIPTOR_TYPE_EXTENT_PAGE 6 struct spdk_blob_md_descriptor_xattr { uint8_t type; @@ -314,6 +319,14 @@ struct spdk_blob_md_descriptor_extent_table { } extent_page[0]; }; +struct spdk_blob_md_descriptor_extent_page { + uint8_t type; + uint32_t length; + + /* TODO: add indicator for ranges of clusters in this EP */ + uint32_t cluster_idx[0]; +}; + #define SPDK_BLOB_THIN_PROV (1ULL << 0) #define SPDK_BLOB_INTERNAL_XATTR (1ULL << 1) #define SPDK_BLOB_INVALID_FLAGS_MASK (SPDK_BLOB_THIN_PROV | SPDK_BLOB_INTERNAL_XATTR)