drivers/md/persistent-data/dm-array.c

Source file repositories/reference/linux-study-clean/drivers/md/persistent-data/dm-array.c

File Facts

System
Linux kernel
Corpus path
drivers/md/persistent-data/dm-array.c
Extension
.c
Size
24625 bytes
Lines
1022
Domain
Driver Families
Bucket
drivers/md
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

struct array_block {
	__le32 csum;
	__le32 max_entries;
	__le32 nr_entries;
	__le32 value_size;
	__le64 blocknr; /* Block this node is supposed to live in. */
} __packed;

/*----------------------------------------------------------------*/

/*
 * Validator methods.  As usual we calculate a checksum, and also write the
 * block location into the header (paranoia about ssds remapping areas by
 * mistake).
 */
#define CSUM_XOR 595846735

static void array_block_prepare_for_write(const struct dm_block_validator *v,
					  struct dm_block *b,
					  size_t size_of_block)
{
	struct array_block *bh_le = dm_block_data(b);

	bh_le->blocknr = cpu_to_le64(dm_block_location(b));
	bh_le->csum = cpu_to_le32(dm_bm_checksum(&bh_le->max_entries,
						 size_of_block - sizeof(__le32),
						 CSUM_XOR));
}

static int array_block_check(const struct dm_block_validator *v,
			     struct dm_block *b,
			     size_t size_of_block)
{
	struct array_block *bh_le = dm_block_data(b);
	__le32 csum_disk;

	if (dm_block_location(b) != le64_to_cpu(bh_le->blocknr)) {
		DMERR_LIMIT("%s failed: blocknr %llu != wanted %llu", __func__,
			    (unsigned long long) le64_to_cpu(bh_le->blocknr),
			    (unsigned long long) dm_block_location(b));
		return -ENOTBLK;
	}

	csum_disk = cpu_to_le32(dm_bm_checksum(&bh_le->max_entries,
					       size_of_block - sizeof(__le32),
					       CSUM_XOR));
	if (csum_disk != bh_le->csum) {
		DMERR_LIMIT("%s failed: csum %u != wanted %u", __func__,
			    (unsigned int) le32_to_cpu(csum_disk),
			    (unsigned int) le32_to_cpu(bh_le->csum));
		return -EILSEQ;
	}

	return 0;
}

static const struct dm_block_validator array_validator = {
	.name = "array",
	.prepare_for_write = array_block_prepare_for_write,
	.check = array_block_check
};

/*----------------------------------------------------------------*/

/*
 * Functions for manipulating the array blocks.
 */

/*
 * Returns a pointer to a value within an array block.
 *
 * index - The index into _this_ specific block.
 */
static void *element_at(struct dm_array_info *info, struct array_block *ab,
			unsigned int index)
{
	unsigned char *entry = (unsigned char *) (ab + 1);

	entry += index * info->value_type.size;

	return entry;
}

/*
 * Utility function that calls one of the value_type methods on every value
 * in an array block.
 */
static void on_entries(struct dm_array_info *info, struct array_block *ab,
		       void (*fn)(void *, const void *, unsigned int))
{

Annotation

Implementation Notes