// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2011 Red Hat, Inc.
*
* This file is released under the GPL.
*/
#include "dm-space-map-common.h"
#include "dm-transaction-manager.h"
#include "dm-btree-internal.h"
#include "dm-persistent-data-internal.h"
#include <linux/bitops.h>
#include <linux/device-mapper.h>
#define DM_MSG_PREFIX "space map common"
/*----------------------------------------------------------------*/
/*
* Index validator.
*/
#define INDEX_CSUM_XOR 160478
static void index_prepare_for_write(const struct dm_block_validator *v,
struct dm_block *b,
size_t block_size)
{
struct disk_metadata_index *mi_le = dm_block_data(b);
mi_le->blocknr = cpu_to_le64(dm_block_location(b));
mi_le->csum = cpu_to_le32(dm_bm_checksum(&mi_le->padding,
block_size - sizeof(__le32),
INDEX_CSUM_XOR));
}
static int index_check(const struct dm_block_validator *v,
struct dm_block *b,
size_t block_size)
{
struct disk_metadata_index *mi_le = dm_block_data(b);
__le32 csum_disk;
if (dm_block_location(b) != le64_to_cpu(mi_le->blocknr)) {
DMERR_LIMIT("%s failed: blocknr %llu != wanted %llu", __func__,
le64_to_cpu(mi_le->blocknr), dm_block_location(b));
return -ENOTBLK;
}
csum_disk = cpu_to_le32(dm_bm_checksum(&mi_le->padding,
block_size - sizeof(__le32),
INDEX_CSUM_XOR));
if (csum_disk != mi_le->csum) {
DMERR_LIMIT("i%s failed: csum %u != wanted %u", __func__,
le32_to_cpu(csum_disk), le32_to_cpu(mi_le->csum));
return -EILSEQ;
}
return 0;
}
static const struct dm_block_validator index_validator = {
.name = "index",
.prepare_for_write = index_prepare_for_write,
.check = index_check
};
/*----------------------------------------------------------------*/
/*
* Bitmap validator
*/
#define BITMAP_CSUM_XOR 240779
static void dm_bitmap_prepare_for_write(const struct dm_block_validator *v,
struct dm_block *b,
size_t block_size)
{
struct disk_bitmap_header *disk_header = dm_block_data(b);
disk_header->blocknr = cpu_to_le64(dm_block_location(b));
disk_header->csum = cpu_to_le32(dm_bm_checksum(&disk_header->not_used,
block_size - sizeof(__le32),
BITMAP_CSUM_XOR));
}
static int dm_bitmap_check(const struct dm_block_validator *v,
struct dm_block *b,
size_t block_size)
{
struct disk_bitmap_header *disk_header = dm_block_data(b);
__le32 csum_disk;
if (dm_block_location(b) != le64_to_cpu(disk_header->blocknr)) {
DMERR_LIMIT("bitmap check failed: blocknr %llu != wanted %llu",
le64_to_cpu(disk_header->blocknr), dm_block_location(b));
return -ENOTBLK;
}
csum_disk = cpu_to_le32(dm_bm_checksum(&disk_header->not_used,
block_size - sizeof(__le32),
BITMAP_CSUM_XOR));
if (csum_disk != disk_header->csum) {
DMERR_LIMIT("bitmap check failed: csum %u != wanted %u",
le32_to_cpu(csum_disk), le32_to_cpu(disk_header->csum));
return -EILSEQ;
}
return 0;
}
static const struct dm_block_validator dm_sm_bitmap_validator = {
.name = "sm_bitmap",