Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause 2 : * Copyright 2023 Solidigm All Rights Reserved 3 : * Copyright (C) 2022 Intel Corporation. 4 : * All rights reserved. 5 : */ 6 : 7 : #include "ftl_sb.h" 8 : #include "ftl_core.h" 9 : #include "ftl_layout.h" 10 : #include "upgrade/ftl_sb_upgrade.h" 11 : #include "upgrade/ftl_sb_v3.h" 12 : #include "upgrade/ftl_sb_v5.h" 13 : 14 : static bool ftl_superblock_v2_check_magic(union ftl_superblock_ver *sb_ver); 15 : 16 : struct sb_ops { 17 : bool (*check_magic)(union ftl_superblock_ver *sb_ver); 18 : 19 : bool (*blob_is_empty)(union ftl_superblock_ver *sb_ver); 20 : bool (*blob_validate)(struct spdk_ftl_dev *dev); 21 : int (*blob_store)(struct spdk_ftl_dev *dev); 22 : int (*blob_load)(struct spdk_ftl_dev *dev); 23 : 24 : int (*upgrade_region)(struct spdk_ftl_dev *dev, struct ftl_layout_region *reg, 25 : uint32_t new_version); 26 : 27 : int (*layout_apply)(struct spdk_ftl_dev *dev); 28 : void (*layout_dump)(struct spdk_ftl_dev *dev); 29 : }; 30 : 31 : static struct sb_ops * 32 9 : sb_get_ops(uint64_t version) 33 : { 34 : static struct sb_ops ops[] = { 35 : [FTL_SB_VERSION_0] = { 36 : .check_magic = ftl_superblock_v2_check_magic, 37 : }, 38 : [FTL_SB_VERSION_1] = { 39 : .check_magic = ftl_superblock_v2_check_magic, 40 : }, 41 : [FTL_SB_VERSION_2] = { 42 : .check_magic = ftl_superblock_v2_check_magic, 43 : }, 44 : [FTL_SB_VERSION_3] = { 45 : .check_magic = ftl_superblock_v3_check_magic, 46 : .blob_is_empty = ftl_superblock_v3_md_layout_is_empty, 47 : .blob_load = ftl_superblock_v3_md_layout_load_all, 48 : .layout_dump = ftl_superblock_v3_md_layout_dump, 49 : }, 50 : [FTL_SB_VERSION_4] = { 51 : .check_magic = ftl_superblock_v3_check_magic, 52 : .blob_is_empty = ftl_superblock_v3_md_layout_is_empty, 53 : .blob_load = ftl_superblock_v3_md_layout_load_all, 54 : .layout_dump = ftl_superblock_v3_md_layout_dump, 55 : }, 56 : [FTL_SB_VERSION_5] = { 57 : .check_magic = ftl_superblock_v3_check_magic, 58 : .blob_is_empty = ftl_superblock_v5_is_blob_area_empty, 59 : .blob_validate = ftl_superblock_v5_validate_blob_area, 60 : .blob_store = ftl_superblock_v5_store_blob_area, 61 : .blob_load = ftl_superblock_v5_load_blob_area, 62 : .upgrade_region = ftl_superblock_v5_md_layout_upgrade_region, 63 : .layout_apply = ftl_superblock_v5_md_layout_apply, 64 : .layout_dump = ftl_superblock_v5_md_layout_dump, 65 : }, 66 : }; 67 : 68 9 : if (version >= SPDK_COUNTOF(ops)) { 69 0 : return NULL; 70 : } 71 : 72 9 : return &ops[version]; 73 : } 74 : 75 : static bool 76 0 : ftl_superblock_v2_check_magic(union ftl_superblock_ver *sb_ver) 77 : { 78 0 : return sb_ver->header.magic == FTL_SUPERBLOCK_MAGIC_V2; 79 : } 80 : 81 : bool 82 0 : ftl_superblock_check_magic(struct ftl_superblock *sb) 83 : { 84 0 : union ftl_superblock_ver *sb_ver = (union ftl_superblock_ver *)sb; 85 0 : struct sb_ops *ops = sb_get_ops(sb_ver->header.version); 86 : 87 0 : if (!ops || !ops->check_magic) { 88 0 : ftl_abort(); 89 : return false; 90 : } 91 0 : return ops->check_magic(sb_ver); 92 : } 93 : 94 : bool 95 6 : ftl_superblock_is_blob_area_empty(struct ftl_superblock *sb) 96 : { 97 6 : union ftl_superblock_ver *sb_ver = (union ftl_superblock_ver *)sb; 98 6 : struct sb_ops *ops = sb_get_ops(sb_ver->header.version); 99 : 100 6 : if (!ops || !ops->blob_is_empty) { 101 0 : ftl_abort(); 102 : return false; 103 : } 104 6 : return ops->blob_is_empty(sb_ver); 105 : } 106 : 107 : bool 108 0 : ftl_superblock_validate_blob_area(struct spdk_ftl_dev *dev) 109 : { 110 0 : struct sb_ops *ops = sb_get_ops(dev->sb->header.version); 111 : 112 0 : if (!ops || !ops->blob_validate) { 113 0 : return true; 114 : } 115 0 : return ops->blob_validate(dev); 116 : } 117 : 118 : int 119 0 : ftl_superblock_store_blob_area(struct spdk_ftl_dev *dev) 120 : { 121 0 : struct sb_ops *ops = sb_get_ops(dev->sb->header.version); 122 : 123 0 : if (!ops || !ops->blob_store) { 124 0 : ftl_abort(); 125 : return -1; 126 : } 127 0 : return ops->blob_store(dev); 128 : } 129 : 130 : int 131 0 : ftl_superblock_load_blob_area(struct spdk_ftl_dev *dev) 132 : { 133 0 : struct sb_ops *ops = sb_get_ops(dev->sb->header.version); 134 : 135 0 : if (!ops || !ops->blob_load) { 136 0 : ftl_abort(); 137 : return -1; 138 : } 139 0 : return ops->blob_load(dev); 140 : } 141 : 142 : int 143 3 : ftl_superblock_md_layout_upgrade_region(struct spdk_ftl_dev *dev, 144 : struct ftl_layout_region *reg, uint32_t new_version) 145 : { 146 3 : struct sb_ops *ops = sb_get_ops(dev->sb->header.version); 147 : 148 3 : if (!ops || !ops->upgrade_region) { 149 0 : ftl_abort(); 150 : return -1; 151 : } 152 3 : return ops->upgrade_region(dev, reg, new_version); 153 : } 154 : 155 : int 156 0 : ftl_superblock_md_layout_apply(struct spdk_ftl_dev *dev) 157 : { 158 0 : struct sb_ops *ops = sb_get_ops(dev->sb->header.version); 159 : 160 0 : if (!ops || !ops->layout_apply) { 161 0 : return 0; 162 : } 163 0 : return ops->layout_apply(dev); 164 : } 165 : 166 : void 167 0 : ftl_superblock_md_layout_dump(struct spdk_ftl_dev *dev) 168 : { 169 0 : struct sb_ops *ops = sb_get_ops(dev->sb->header.version); 170 : 171 0 : if (!ops || !ops->layout_dump) { 172 0 : ftl_abort(); 173 : return; 174 : } 175 0 : return ops->layout_dump(dev); 176 : }