drivers/md/dm-vdo/indexer/geometry.c

Source file repositories/reference/linux-study-clean/drivers/md/dm-vdo/indexer/geometry.c

File Facts

System
Linux kernel
Corpus path
drivers/md/dm-vdo/indexer/geometry.c
Extension
.c
Size
8104 bytes
Lines
202
Domain
Driver Families
Bucket
drivers/md
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright 2023 Red Hat
 */

#include "geometry.h"

#include <linux/compiler.h>
#include <linux/log2.h>

#include "errors.h"
#include "logger.h"
#include "memory-alloc.h"
#include "permassert.h"

#include "delta-index.h"
#include "indexer.h"

/*
 * An index volume is divided into a fixed number of fixed-size chapters, each consisting of a
 * fixed number of fixed-size pages. The volume layout is defined by two constants and four
 * parameters. The constants are that index records are 32 bytes long (16-byte block name plus
 * 16-byte metadata) and that open chapter index hash slots are one byte long. The four parameters
 * are the number of bytes in a page, the number of record pages in a chapter, the number of
 * chapters in a volume, and the number of chapters that are sparse. From these parameters, we can
 * derive the rest of the layout and other index properties.
 *
 * The index volume is sized by its maximum memory footprint. For a dense index, the persistent
 * storage is about 10 times the size of the memory footprint. For a sparse index, the persistent
 * storage is about 100 times the size of the memory footprint.
 *
 * For a small index with a memory footprint less than 1GB, there are three possible memory
 * configurations: 0.25GB, 0.5GB and 0.75GB. The default geometry for each is 1024 index records
 * per 32 KB page, 1024 chapters per volume, and either 64, 128, or 192 record pages per chapter
 * (resulting in 6, 13, or 20 index pages per chapter) depending on the memory configuration. For
 * the VDO default of a 0.25 GB index, this yields a deduplication window of 256 GB using about 2.5
 * GB for the persistent storage and 256 MB of RAM.
 *
 * For a larger index with a memory footprint that is a multiple of 1 GB, the geometry is 1024
 * index records per 32 KB page, 256 record pages per chapter, 26 index pages per chapter, and 1024
 * chapters for every GB of memory footprint. For a 1 GB volume, this yields a deduplication window
 * of 1 TB using about 9GB of persistent storage and 1 GB of RAM.
 *
 * The above numbers hold for volumes which have no sparse chapters. A sparse volume has 10 times
 * as many chapters as the corresponding non-sparse volume, which provides 10 times the
 * deduplication window while using 10 times as much persistent storage as the equivalent
 * non-sparse volume with the same memory footprint.
 *
 * If the volume has been converted from a non-lvm format to an lvm volume, the number of chapters
 * per volume will have been reduced by one by eliminating physical chapter 0, and the virtual
 * chapter that formerly mapped to physical chapter 0 may be remapped to another physical chapter.
 * This remapping is expressed by storing which virtual chapter was remapped, and which physical
 * chapter it was moved to.
 */

int uds_make_index_geometry(size_t bytes_per_page, u32 record_pages_per_chapter,
			    u32 chapters_per_volume, u32 sparse_chapters_per_volume,
			    u64 remapped_virtual, u64 remapped_physical,
			    struct index_geometry **geometry_ptr)
{
	int result;
	struct index_geometry *geometry;

	result = vdo_allocate(1, "geometry", &geometry);
	if (result != VDO_SUCCESS)
		return result;

	geometry->bytes_per_page = bytes_per_page;
	geometry->record_pages_per_chapter = record_pages_per_chapter;
	geometry->chapters_per_volume = chapters_per_volume;
	geometry->sparse_chapters_per_volume = sparse_chapters_per_volume;
	geometry->dense_chapters_per_volume = chapters_per_volume - sparse_chapters_per_volume;
	geometry->remapped_virtual = remapped_virtual;
	geometry->remapped_physical = remapped_physical;

	geometry->records_per_page = bytes_per_page / BYTES_PER_RECORD;
	geometry->records_per_chapter = geometry->records_per_page * record_pages_per_chapter;
	geometry->records_per_volume = (u64) geometry->records_per_chapter * chapters_per_volume;

	geometry->chapter_mean_delta = 1 << DEFAULT_CHAPTER_MEAN_DELTA_BITS;
	geometry->chapter_payload_bits = bits_per(record_pages_per_chapter - 1);
	/*
	 * We want 1 delta list for every 64 records in the chapter.
	 * The "| 077" ensures that the chapter_delta_list_bits computation
	 * does not underflow.
	 */
	geometry->chapter_delta_list_bits =
		bits_per((geometry->records_per_chapter - 1) | 077) - 6;
	geometry->delta_lists_per_chapter = 1 << geometry->chapter_delta_list_bits;
	/* We need enough address bits to achieve the desired mean delta. */

Annotation

Implementation Notes