FTL: Move base device sb to LBA 0

Moving the superblock of the base device to sector 0, in order to
prevent other bdevs (e.g. GPT or blobstore) from potentially hijacking
the base device during startup (if their metadata by 'luck' manages to
find itself at sector 0 of band 0, which depending on the order of
operations could be very likely).

Signed-off-by: Kozlowski Mateusz <mateusz.kozlowski@intel.com>
Change-Id: I8a6eb3c89a229f443ef23d975a8ff0880ba65b08
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14143
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Kozlowski Mateusz 2022-08-19 14:12:46 +02:00 committed by Jim Harris
parent 759e176927
commit c332181331
6 changed files with 43 additions and 23 deletions

View File

@ -225,6 +225,12 @@ ftl_band_user_blocks(const struct ftl_band *band)
ftl_tail_md_num_blocks(band->dev);
}
static inline uint64_t
ftl_addr_get_band(const struct spdk_ftl_dev *dev, ftl_addr addr)
{
return (addr - dev->bands->start_addr) / ftl_get_num_blocks_in_band(dev);
}
struct ftl_band *
ftl_band_from_addr(struct spdk_ftl_dev *dev, ftl_addr addr)
{
@ -238,7 +244,7 @@ uint64_t
ftl_band_block_offset_from_addr(struct ftl_band *band, ftl_addr addr)
{
assert(ftl_addr_get_band(band->dev, addr) == band->id);
return addr % ftl_get_num_blocks_in_band(band->dev);
return addr - band->start_addr;
}
ftl_addr
@ -285,7 +291,7 @@ ftl_band_addr_from_block_offset(struct ftl_band *band, uint64_t block_off)
{
ftl_addr addr;
addr = block_off + band->id * ftl_get_num_blocks_in_band(band->dev);
addr = block_off + band->start_addr;
return addr;
}

View File

@ -220,12 +220,6 @@ ftl_get_num_blocks_in_band(const struct spdk_ftl_dev *dev)
return dev->num_blocks_in_band;
}
static inline uint64_t
ftl_addr_get_band(const struct spdk_ftl_dev *dev, ftl_addr addr)
{
return addr / ftl_get_num_blocks_in_band(dev);
}
static inline uint32_t
ftl_get_write_unit_size(struct spdk_bdev *bdev)
{

View File

@ -344,30 +344,33 @@ setup_layout_base(struct spdk_ftl_dev *dev)
uint64_t left, offset;
struct ftl_layout *layout = &dev->layout;
struct ftl_layout_region *region;
uint64_t data_base_alignment = 8 * ftl_bitmap_buffer_alignment;
/* Allocating a ftl_bitmap requires a 8B input buffer alignment, since we're reusing the global valid map md buffer
* this means that each band starting address needs to be aligned too - each device sector takes 1b in the valid map,
* so 64 sectors (8*8) is the needed alignment
*/
layout->base.num_usable_blocks = ftl_get_num_blocks_in_band(dev);
layout->base.user_blocks = ftl_band_user_blocks(dev->bands);
/* Base device layout is following:
* - data
* - superblock
* - data
* - valid map
*
* Superblock has been already configured, its offset marks the end of the data region
*/
offset = layout->region[FTL_LAYOUT_REGION_TYPE_SB_BASE].current.offset;
offset = layout->region[FTL_LAYOUT_REGION_TYPE_SB_BASE].current.blocks;
offset = SPDK_ALIGN_CEIL(offset, data_base_alignment);
/* Setup data region on base device */
region = &layout->region[FTL_LAYOUT_REGION_TYPE_DATA_BASE];
region->type = FTL_LAYOUT_REGION_TYPE_DATA_BASE;
region->name = "data_btm";
region->current.version = region->prev.version = 0;
region->current.offset = 0;
region->current.blocks = offset;
region->current.offset = offset;
region->current.blocks = layout_base_offset(dev);
set_region_bdev_btm(region, dev);
/* Move offset after base superblock */
offset += layout->region[FTL_LAYOUT_REGION_TYPE_SB_BASE].current.blocks;
offset += region->current.blocks;
/* Setup validity map */
region = &layout->region[FTL_LAYOUT_REGION_TYPE_VALID_MAP];
@ -529,10 +532,7 @@ ftl_layout_setup_superblock(struct spdk_ftl_dev *dev)
region->name = "sb_mirror";
region->current.version = FTL_SB_VERSION_CURRENT;
region->prev.version = FTL_SB_VERSION_CURRENT;
/* TODO: This should really be at offset 0 - think how best to upgrade between the two layouts
* This is an issue if some other metadata appears at block 0 of base device (most likely GPT or blobstore)
*/
region->current.offset = layout_base_offset(dev);
region->current.offset = 0;
region->current.blocks = blocks_region(FTL_SUPERBLOCK_SIZE);
set_region_bdev_btm(region, dev);

View File

@ -26,7 +26,7 @@ ftl_band_init_md(struct ftl_band *band)
band_valid_map_bytes = band_num_blocks / 8;
p2l_map->valid = ftl_bitmap_create(ftl_md_get_buffer(valid_map_md) +
band_valid_map_bytes * band->id, band_valid_map_bytes);
band->start_addr / 8, band_valid_map_bytes);
if (!p2l_map->valid) {
return -ENOMEM;
}
@ -170,8 +170,6 @@ decorate_bands(struct spdk_ftl_dev *dev)
i = 0;
while (i < ftl_get_num_bands(dev) - num_to_drop) {
band = &dev->bands[i];
band->start_addr = i * dev->num_blocks_in_band;
band->tail_md_addr = ftl_band_tail_md_addr(band);
band->phys_id = phys_id;
i++;
@ -199,6 +197,22 @@ ftl_mngt_decorate_bands(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
ftl_mngt_next_step(mngt);
}
void
ftl_mngt_initialize_band_address(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
{
struct ftl_band *band;
struct ftl_md *data_md = dev->layout.md[FTL_LAYOUT_REGION_TYPE_DATA_BASE];
uint64_t i;
for (i = 0; i < ftl_get_num_bands(dev); i++) {
band = &dev->bands[i];
band->start_addr = data_md->region->current.offset + i * dev->num_blocks_in_band;
band->tail_md_addr = ftl_band_tail_md_addr(band);
}
ftl_mngt_next_step(mngt);
}
void
ftl_recover_max_seq(struct spdk_ftl_dev *dev)
{

View File

@ -104,6 +104,10 @@ static const struct ftl_mngt_process_desc desc_startup = {
.action = ftl_mngt_init_md,
.cleanup = ftl_mngt_deinit_md
},
{
.name = "Initialize band addresses",
.action = ftl_mngt_initialize_band_address
},
{
.name = "Initialize NV cache",
.action = ftl_mngt_init_nv_cache,

View File

@ -50,6 +50,8 @@ void ftl_mngt_deinit_io_channel(struct spdk_ftl_dev *dev, struct ftl_mngt_proces
void ftl_mngt_decorate_bands(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);
void ftl_mngt_initialize_band_address(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);
void ftl_mngt_init_reloc(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);
void ftl_mngt_deinit_reloc(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt);