Branch data 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 : 165 : 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 [ - + ]: 165 : if (version >= SPDK_COUNTOF(ops)) { 69 : 0 : return NULL; 70 : : } 71 : : 72 : 165 : 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 : 17 : ftl_superblock_check_magic(struct ftl_superblock *sb) 83 : : { 84 : 17 : union ftl_superblock_ver *sb_ver = (union ftl_superblock_ver *)sb; 85 : 17 : struct sb_ops *ops = sb_get_ops(sb_ver->header.version); 86 : : 87 [ + - - + ]: 17 : if (!ops || !ops->check_magic) { 88 : 0 : ftl_abort(); 89 : : return false; 90 : : } 91 : 17 : return ops->check_magic(sb_ver); 92 : : } 93 : : 94 : : bool 95 : 41 : ftl_superblock_is_blob_area_empty(struct ftl_superblock *sb) 96 : : { 97 : 41 : union ftl_superblock_ver *sb_ver = (union ftl_superblock_ver *)sb; 98 : 41 : struct sb_ops *ops = sb_get_ops(sb_ver->header.version); 99 : : 100 [ + - - + ]: 41 : if (!ops || !ops->blob_is_empty) { 101 : 0 : ftl_abort(); 102 : : return false; 103 : : } 104 : 41 : return ops->blob_is_empty(sb_ver); 105 : : } 106 : : 107 : : bool 108 : 17 : ftl_superblock_validate_blob_area(struct spdk_ftl_dev *dev) 109 : : { 110 : 17 : struct sb_ops *ops = sb_get_ops(dev->sb->header.version); 111 : : 112 [ + - - + ]: 17 : if (!ops || !ops->blob_validate) { 113 : 0 : return true; 114 : : } 115 : 17 : return ops->blob_validate(dev); 116 : : } 117 : : 118 : : int 119 : 22 : ftl_superblock_store_blob_area(struct spdk_ftl_dev *dev) 120 : : { 121 : 22 : struct sb_ops *ops = sb_get_ops(dev->sb->header.version); 122 : : 123 [ + - - + ]: 22 : if (!ops || !ops->blob_store) { 124 : 0 : ftl_abort(); 125 : : return -1; 126 : : } 127 : 22 : return ops->blob_store(dev); 128 : : } 129 : : 130 : : int 131 : 17 : ftl_superblock_load_blob_area(struct spdk_ftl_dev *dev) 132 : : { 133 : 17 : struct sb_ops *ops = sb_get_ops(dev->sb->header.version); 134 : : 135 [ + - - + ]: 17 : if (!ops || !ops->blob_load) { 136 : 0 : ftl_abort(); 137 : : return -1; 138 : : } 139 : 17 : return ops->blob_load(dev); 140 : : } 141 : : 142 : : int 143 : 12 : ftl_superblock_md_layout_upgrade_region(struct spdk_ftl_dev *dev, 144 : : struct ftl_layout_region *reg, uint32_t new_version) 145 : : { 146 : 12 : struct sb_ops *ops = sb_get_ops(dev->sb->header.version); 147 : : 148 [ + - - + ]: 12 : if (!ops || !ops->upgrade_region) { 149 : 0 : ftl_abort(); 150 : : return -1; 151 : : } 152 : 12 : return ops->upgrade_region(dev, reg, new_version); 153 : : } 154 : : 155 : : int 156 : 17 : ftl_superblock_md_layout_apply(struct spdk_ftl_dev *dev) 157 : : { 158 : 17 : struct sb_ops *ops = sb_get_ops(dev->sb->header.version); 159 : : 160 [ + - - + ]: 17 : if (!ops || !ops->layout_apply) { 161 : 0 : return 0; 162 : : } 163 : 17 : return ops->layout_apply(dev); 164 : : } 165 : : 166 : : void 167 : 22 : ftl_superblock_md_layout_dump(struct spdk_ftl_dev *dev) 168 : : { 169 : 22 : struct sb_ops *ops = sb_get_ops(dev->sb->header.version); 170 : : 171 [ + - - + ]: 22 : if (!ops || !ops->layout_dump) { 172 : 0 : ftl_abort(); 173 : : return; 174 : : } 175 : 22 : return ops->layout_dump(dev); 176 : : }