drivers/md/dm-vdo/indexer/index-page-map.c

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

File Facts

System
Linux kernel
Corpus path
drivers/md/dm-vdo/indexer/index-page-map.c
Extension
.c
Size
4851 bytes
Lines
174
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 "index-page-map.h"

#include "errors.h"
#include "logger.h"
#include "memory-alloc.h"
#include "numeric.h"
#include "permassert.h"
#include "string-utils.h"
#include "thread-utils.h"

#include "hash-utils.h"
#include "indexer.h"

/*
 * The index page map is conceptually a two-dimensional array indexed by chapter number and index
 * page number within the chapter. Each entry contains the number of the last delta list on that
 * index page. In order to save memory, the information for the last page in each chapter is not
 * recorded, as it is known from the geometry.
 */

static const u8 PAGE_MAP_MAGIC[] = "ALBIPM02";

#define PAGE_MAP_MAGIC_LENGTH (sizeof(PAGE_MAP_MAGIC) - 1)

static inline u32 get_entry_count(const struct index_geometry *geometry)
{
	return geometry->chapters_per_volume * (geometry->index_pages_per_chapter - 1);
}

int uds_make_index_page_map(const struct index_geometry *geometry,
			    struct index_page_map **map_ptr)
{
	int result;
	struct index_page_map *map;

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

	map->geometry = geometry;
	map->entries_per_chapter = geometry->index_pages_per_chapter - 1;
	result = vdo_allocate(get_entry_count(geometry), "Index Page Map Entries",
			      &map->entries);
	if (result != VDO_SUCCESS) {
		uds_free_index_page_map(map);
		return result;
	}

	*map_ptr = map;
	return UDS_SUCCESS;
}

void uds_free_index_page_map(struct index_page_map *map)
{
	if (map != NULL) {
		vdo_free(map->entries);
		vdo_free(map);
	}
}

void uds_update_index_page_map(struct index_page_map *map, u64 virtual_chapter_number,
			       u32 chapter_number, u32 index_page_number,
			       u32 delta_list_number)
{
	size_t slot;

	map->last_update = virtual_chapter_number;
	if (index_page_number == map->entries_per_chapter)
		return;

	slot = (chapter_number * map->entries_per_chapter) + index_page_number;
	map->entries[slot] = delta_list_number;
}

u32 uds_find_index_page_number(const struct index_page_map *map,
			       const struct uds_record_name *name, u32 chapter_number)
{
	u32 delta_list_number = uds_hash_to_chapter_delta_list(name, map->geometry);
	u32 slot = chapter_number * map->entries_per_chapter;
	u32 page;

	for (page = 0; page < map->entries_per_chapter; page++) {
		if (delta_list_number <= map->entries[slot + page])
			break;
	}

Annotation

Implementation Notes