linux/fs/ocfs2/blockcheck.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * blockcheck.c
 *
 * Checksum and ECC codes for the OCFS2 userspace library.
 *
 * Copyright (C) 2006, 2008 Oracle.  All rights reserved.
 */

#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/crc32.h>
#include <linux/buffer_head.h>
#include <linux/bitops.h>
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/byteorder.h>

#include <cluster/masklog.h>

#include "ocfs2.h"

#include "blockcheck.h"


/*
 * We use the following conventions:
 *
 * d = # data bits
 * p = # parity bits
 * c = # total code bits (d + p)
 */


/*
 * Calculate the bit offset in the hamming code buffer based on the bit's
 * offset in the data buffer.  Since the hamming code reserves all
 * power-of-two bits for parity, the data bit number and the code bit
 * number are offset by all the parity bits beforehand.
 *
 * Recall that bit numbers in hamming code are 1-based.  This function
 * takes the 0-based data bit from the caller.
 *
 * An example.  Take bit 1 of the data buffer.  1 is a power of two (2^0),
 * so it's a parity bit.  2 is a power of two (2^1), so it's a parity bit.
 * 3 is not a power of two.  So bit 1 of the data buffer ends up as bit 3
 * in the code buffer.
 *
 * The caller can pass in *p if it wants to keep track of the most recent
 * number of parity bits added.  This allows the function to start the
 * calculation at the last place.
 */
static unsigned int calc_code_bit(unsigned int i, unsigned int *p_cache)
{}

/*
 * This is the low level encoder function.  It can be called across
 * multiple hunks just like the crc32 code.  'd' is the number of bits
 * _in_this_hunk_.  nr is the bit offset of this hunk.  So, if you had
 * two 512B buffers, you would do it like so:
 *
 * parity = ocfs2_hamming_encode(0, buf1, 512 * 8, 0);
 * parity = ocfs2_hamming_encode(parity, buf2, 512 * 8, 512 * 8);
 *
 * If you just have one buffer, use ocfs2_hamming_encode_block().
 */
u32 ocfs2_hamming_encode(u32 parity, void *data, unsigned int d, unsigned int nr)
{}

u32 ocfs2_hamming_encode_block(void *data, unsigned int blocksize)
{}

/*
 * Like ocfs2_hamming_encode(), this can handle hunks.  nr is the bit
 * offset of the current hunk.  If bit to be fixed is not part of the
 * current hunk, this does nothing.
 *
 * If you only have one hunk, use ocfs2_hamming_fix_block().
 */
void ocfs2_hamming_fix(void *data, unsigned int d, unsigned int nr,
		       unsigned int fix)
{}

void ocfs2_hamming_fix_block(void *data, unsigned int blocksize,
			     unsigned int fix)
{}


/*
 * Debugfs handling.
 */

#ifdef CONFIG_DEBUG_FS

static int blockcheck_u64_get(void *data, u64 *val)
{}
DEFINE_DEBUGFS_ATTRIBUTE();

static void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats)
{}

static void ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats,
					   struct dentry *parent)
{}
#else
static inline void ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats,
						  struct dentry *parent)
{
}

static inline void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats)
{
}
#endif  /* CONFIG_DEBUG_FS */

/* Always-called wrappers for starting and stopping the debugfs files */
void ocfs2_blockcheck_stats_debugfs_install(struct ocfs2_blockcheck_stats *stats,
					    struct dentry *parent)
{}

void ocfs2_blockcheck_stats_debugfs_remove(struct ocfs2_blockcheck_stats *stats)
{}

static void ocfs2_blockcheck_inc_check(struct ocfs2_blockcheck_stats *stats)
{}

static void ocfs2_blockcheck_inc_failure(struct ocfs2_blockcheck_stats *stats)
{}

static void ocfs2_blockcheck_inc_recover(struct ocfs2_blockcheck_stats *stats)
{}



/*
 * These are the low-level APIs for using the ocfs2_block_check structure.
 */

/*
 * This function generates check information for a block.
 * data is the block to be checked.  bc is a pointer to the
 * ocfs2_block_check structure describing the crc32 and the ecc.
 *
 * bc should be a pointer inside data, as the function will
 * take care of zeroing it before calculating the check information.  If
 * bc does not point inside data, the caller must make sure any inline
 * ocfs2_block_check structures are zeroed.
 *
 * The data buffer must be in on-disk endian (little endian for ocfs2).
 * bc will be filled with little-endian values and will be ready to go to
 * disk.
 */
void ocfs2_block_check_compute(void *data, size_t blocksize,
			       struct ocfs2_block_check *bc)
{}

/*
 * This function validates existing check information.  Like _compute,
 * the function will take care of zeroing bc before calculating check codes.
 * If bc is not a pointer inside data, the caller must have zeroed any
 * inline ocfs2_block_check structures.
 *
 * Again, the data passed in should be the on-disk endian.
 */
int ocfs2_block_check_validate(void *data, size_t blocksize,
			       struct ocfs2_block_check *bc,
			       struct ocfs2_blockcheck_stats *stats)
{}

/*
 * This function generates check information for a list of buffer_heads.
 * bhs is the blocks to be checked.  bc is a pointer to the
 * ocfs2_block_check structure describing the crc32 and the ecc.
 *
 * bc should be a pointer inside data, as the function will
 * take care of zeroing it before calculating the check information.  If
 * bc does not point inside data, the caller must make sure any inline
 * ocfs2_block_check structures are zeroed.
 *
 * The data buffer must be in on-disk endian (little endian for ocfs2).
 * bc will be filled with little-endian values and will be ready to go to
 * disk.
 */
void ocfs2_block_check_compute_bhs(struct buffer_head **bhs, int nr,
				   struct ocfs2_block_check *bc)
{}

/*
 * This function validates existing check information on a list of
 * buffer_heads.  Like _compute_bhs, the function will take care of
 * zeroing bc before calculating check codes.  If bc is not a pointer
 * inside data, the caller must have zeroed any inline
 * ocfs2_block_check structures.
 *
 * Again, the data passed in should be the on-disk endian.
 */
int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
				   struct ocfs2_block_check *bc,
				   struct ocfs2_blockcheck_stats *stats)
{}

/*
 * These are the main API.  They check the superblock flag before
 * calling the underlying operations.
 *
 * They expect the buffer(s) to be in disk format.
 */
void ocfs2_compute_meta_ecc(struct super_block *sb, void *data,
			    struct ocfs2_block_check *bc)
{}

int ocfs2_validate_meta_ecc(struct super_block *sb, void *data,
			    struct ocfs2_block_check *bc)
{}

void ocfs2_compute_meta_ecc_bhs(struct super_block *sb,
				struct buffer_head **bhs, int nr,
				struct ocfs2_block_check *bc)
{}

int ocfs2_validate_meta_ecc_bhs(struct super_block *sb,
				struct buffer_head **bhs, int nr,
				struct ocfs2_block_check *bc)
{}