]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
dm vdo: add geometry block encoding
authorBruce Johnston <bjohnsto@redhat.com>
Tue, 24 Mar 2026 18:06:48 +0000 (14:06 -0400)
committerMikulas Patocka <mpatocka@redhat.com>
Thu, 26 Mar 2026 17:18:42 +0000 (18:18 +0100)
Add vdo_encode_volume_geometry() to write the geometry block into a
buffer so that it can be written to disk. The corresponding decode
path already exists.

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/encodings.c
drivers/md/dm-vdo/encodings.h

index 3ceba010f4e6d0015c703b61f6203301e271b7e7..d75e023df63734a4b56739be5d81ff563f6beb3d 100644 (file)
@@ -287,6 +287,62 @@ static void decode_volume_geometry(u8 *buffer, size_t *offset,
        };
 }
 
+/**
+ * vdo_encode_volume_geometry() - Encode the on-disk representation of a volume geometry into a buffer.
+ * @buffer: A buffer to store the encoding.
+ * @geometry: The geometry to encode.
+ * @version: The geometry block version to encode.
+ *
+ * Return: VDO_SUCCESS or an error.
+ */
+int vdo_encode_volume_geometry(u8 *buffer, const struct volume_geometry *geometry,
+                              u32 version)
+{
+       int result;
+       enum volume_region_id id;
+       u32 checksum;
+       size_t offset = 0;
+       const struct header *header;
+
+       memcpy(buffer, VDO_GEOMETRY_MAGIC_NUMBER, VDO_GEOMETRY_MAGIC_NUMBER_SIZE);
+       offset += VDO_GEOMETRY_MAGIC_NUMBER_SIZE;
+
+       header = (version > 4) ? &GEOMETRY_BLOCK_HEADER_5_0 : &GEOMETRY_BLOCK_HEADER_4_0;
+       vdo_encode_header(buffer, &offset, header);
+
+       /* This is for backwards compatibility */
+       encode_u32_le(buffer, &offset, geometry->unused);
+       encode_u64_le(buffer, &offset, geometry->nonce);
+       memcpy(buffer + offset, (unsigned char *) &geometry->uuid, sizeof(uuid_t));
+       offset += sizeof(uuid_t);
+
+       if (version > 4)
+               encode_u64_le(buffer, &offset, geometry->bio_offset);
+
+       for (id = 0; id < VDO_VOLUME_REGION_COUNT; id++) {
+               encode_u32_le(buffer, &offset, geometry->regions[id].id);
+               encode_u64_le(buffer, &offset, geometry->regions[id].start_block);
+       }
+
+       encode_u32_le(buffer, &offset, geometry->index_config.mem);
+       encode_u32_le(buffer, &offset, 0);
+
+       if (geometry->index_config.sparse)
+               buffer[offset++] = 1;
+       else
+               buffer[offset++] = 0;
+
+       result = VDO_ASSERT(header->size == offset + sizeof(u32),
+                           "should have encoded up to the geometry checksum");
+       if (result != VDO_SUCCESS)
+               return result;
+
+       checksum = vdo_crc32(buffer, offset);
+       encode_u32_le(buffer, &offset, checksum);
+
+       return VDO_SUCCESS;
+}
+
 /**
  * vdo_parse_geometry_block() - Decode and validate an encoded geometry block.
  * @block: The encoded geometry block.
index 0393936c8aeb7b8588520d936501eddfb3ffb323..67ff0ff2ffdaaa057601d590f530294e3a73cbb3 100644 (file)
@@ -813,6 +813,8 @@ int vdo_initialize_volume_geometry(nonce_t nonce, uuid_t *uuid,
                                   const struct index_config *index_config,
                                   struct volume_geometry *geometry);
 
+int vdo_encode_volume_geometry(u8 *buffer, const struct volume_geometry *geometry,
+                              u32 version);
 int __must_check vdo_parse_geometry_block(unsigned char *block,
                                          struct volume_geometry *geometry);