]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
dm vdo: add super block initialization to encodings.c
authorBruce Johnston <bjohnsto@redhat.com>
Tue, 24 Mar 2026 18:06:45 +0000 (14:06 -0400)
committerMikulas Patocka <mpatocka@redhat.com>
Thu, 26 Mar 2026 17:17:42 +0000 (18:17 +0100)
Add vdo_initialize_component_states() to populate the super block,
computing the space required for the main VDO components on disk.
Those include the slab depot, block map, and recovery journal.

Signed-off-by: Bruce Johnston <bjohnsto@redhat.com>
Reviewed-by: Matthew Sakai <msakai@redhat.com>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
drivers/md/dm-vdo/constants.h
drivers/md/dm-vdo/encodings.c
drivers/md/dm-vdo/encodings.h

index 2a8b03779f878a0c9440f9d723870f520b86c6d0..cc7bc3571ba126502919affdf43bacd6e026f48c 100644 (file)
@@ -44,6 +44,9 @@ enum {
        /* The default size of each slab journal, in blocks */
        DEFAULT_VDO_SLAB_JOURNAL_SIZE = 224,
 
+       /* The recovery journal starting sequence number set at format time */
+       RECOVERY_JOURNAL_STARTING_SEQUENCE_NUMBER = 1,
+
        /*
         * The initial size of lbn_operations and pbn_operations, which is based upon the expected
         * maximum number of outstanding VIOs. This value was chosen to make it highly unlikely
index 9961cb40f8908212bb273441bd81631669e1ded1..441c9aee1749085c5e21dee9b1c5e602b4064d64 100644 (file)
@@ -1488,6 +1488,88 @@ int vdo_decode_super_block(u8 *buffer)
        return ((checksum != saved_checksum) ? VDO_CHECKSUM_MISMATCH : VDO_SUCCESS);
 }
 
+/**
+ * vdo_initialize_component_states() - Initialize the components so they can be written out.
+ * @vdo_config: The config used for component state initialization.
+ * @geometry: The volume geometry used to calculate the data region offset.
+ * @nonce: The nonce to use to identify the vdo.
+ * @states: The component states to initialize.
+ *
+ * Return: VDO_SUCCESS or an error code.
+ */
+int vdo_initialize_component_states(const struct vdo_config *vdo_config,
+                                   const struct volume_geometry *geometry,
+                                   nonce_t nonce,
+                                   struct vdo_component_states *states)
+{
+       int result;
+       struct slab_config slab_config;
+       struct partition *partition;
+
+       states->vdo.config = *vdo_config;
+       states->vdo.nonce = nonce;
+       states->volume_version = VDO_VOLUME_VERSION_67_0;
+
+       states->recovery_journal = (struct recovery_journal_state_7_0) {
+               .journal_start = RECOVERY_JOURNAL_STARTING_SEQUENCE_NUMBER,
+               .logical_blocks_used = 0,
+               .block_map_data_blocks = 0,
+       };
+
+       /*
+        * The layout starts 1 block past the beginning of the data region, as the
+        * data region contains the super block but the layout does not.
+        */
+       result = vdo_initialize_layout(vdo_config->physical_blocks,
+                                      vdo_get_data_region_start(*geometry) + 1,
+                                      DEFAULT_VDO_BLOCK_MAP_TREE_ROOT_COUNT,
+                                      vdo_config->recovery_journal_size,
+                                      VDO_SLAB_SUMMARY_BLOCKS,
+                                      &states->layout);
+       if (result != VDO_SUCCESS)
+               return result;
+
+       result = vdo_configure_slab(vdo_config->slab_size,
+                                   vdo_config->slab_journal_blocks,
+                                   &slab_config);
+       if (result != VDO_SUCCESS) {
+               vdo_uninitialize_layout(&states->layout);
+               return result;
+       }
+
+       result = vdo_get_partition(&states->layout, VDO_SLAB_DEPOT_PARTITION,
+                                  &partition);
+       if (result != VDO_SUCCESS) {
+               vdo_uninitialize_layout(&states->layout);
+               return result;
+       }
+
+       result = vdo_configure_slab_depot(partition, slab_config, 0,
+                                         &states->slab_depot);
+       if (result != VDO_SUCCESS) {
+               vdo_uninitialize_layout(&states->layout);
+               return result;
+       }
+
+       result = vdo_get_partition(&states->layout, VDO_BLOCK_MAP_PARTITION,
+                                  &partition);
+       if (result != VDO_SUCCESS) {
+               vdo_uninitialize_layout(&states->layout);
+               return result;
+       }
+
+       states->block_map = (struct block_map_state_2_0) {
+               .flat_page_origin = VDO_BLOCK_MAP_FLAT_PAGE_ORIGIN,
+               .flat_page_count = 0,
+               .root_origin = partition->offset,
+               .root_count = DEFAULT_VDO_BLOCK_MAP_TREE_ROOT_COUNT,
+       };
+
+       states->vdo.state = VDO_NEW;
+
+       return VDO_SUCCESS;
+}
+
 /**
  * vdo_compute_index_blocks() - Compute the number of blocks that the indexer will use.
  * @config: The index config from which the blocks are calculated.
index 0bc5ae696a6a343365a63b93e6fcca4411d077c2..3cfbe4771a1cd82a7c7772b10378db5ad2d28277 100644 (file)
@@ -1268,6 +1268,11 @@ int __must_check vdo_validate_component_states(struct vdo_component_states *stat
 void vdo_encode_super_block(u8 *buffer, struct vdo_component_states *states);
 int __must_check vdo_decode_super_block(u8 *buffer);
 
+int vdo_initialize_component_states(const struct vdo_config *vdo_config,
+                                   const struct volume_geometry *geometry,
+                                   nonce_t nonce,
+                                   struct vdo_component_states *states);
+
 /* We start with 0L and postcondition with ~0L to match our historical usage in userspace. */
 static inline u32 vdo_crc32(const void *buf, unsigned long len)
 {