18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/* -*- mode: c; c-basic-offset: 8; -*-
38c2ecf20Sopenharmony_ci * vim: noexpandtab sw=8 ts=8 sts=0:
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * blockcheck.c
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Checksum and ECC codes for the OCFS2 userspace library.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Copyright (C) 2006, 2008 Oracle.  All rights reserved.
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/kernel.h>
138c2ecf20Sopenharmony_ci#include <linux/types.h>
148c2ecf20Sopenharmony_ci#include <linux/crc32.h>
158c2ecf20Sopenharmony_ci#include <linux/buffer_head.h>
168c2ecf20Sopenharmony_ci#include <linux/bitops.h>
178c2ecf20Sopenharmony_ci#include <linux/debugfs.h>
188c2ecf20Sopenharmony_ci#include <linux/module.h>
198c2ecf20Sopenharmony_ci#include <linux/fs.h>
208c2ecf20Sopenharmony_ci#include <asm/byteorder.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include <cluster/masklog.h>
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#include "ocfs2.h"
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#include "blockcheck.h"
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci/*
308c2ecf20Sopenharmony_ci * We use the following conventions:
318c2ecf20Sopenharmony_ci *
328c2ecf20Sopenharmony_ci * d = # data bits
338c2ecf20Sopenharmony_ci * p = # parity bits
348c2ecf20Sopenharmony_ci * c = # total code bits (d + p)
358c2ecf20Sopenharmony_ci */
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci/*
398c2ecf20Sopenharmony_ci * Calculate the bit offset in the hamming code buffer based on the bit's
408c2ecf20Sopenharmony_ci * offset in the data buffer.  Since the hamming code reserves all
418c2ecf20Sopenharmony_ci * power-of-two bits for parity, the data bit number and the code bit
428c2ecf20Sopenharmony_ci * number are offset by all the parity bits beforehand.
438c2ecf20Sopenharmony_ci *
448c2ecf20Sopenharmony_ci * Recall that bit numbers in hamming code are 1-based.  This function
458c2ecf20Sopenharmony_ci * takes the 0-based data bit from the caller.
468c2ecf20Sopenharmony_ci *
478c2ecf20Sopenharmony_ci * An example.  Take bit 1 of the data buffer.  1 is a power of two (2^0),
488c2ecf20Sopenharmony_ci * so it's a parity bit.  2 is a power of two (2^1), so it's a parity bit.
498c2ecf20Sopenharmony_ci * 3 is not a power of two.  So bit 1 of the data buffer ends up as bit 3
508c2ecf20Sopenharmony_ci * in the code buffer.
518c2ecf20Sopenharmony_ci *
528c2ecf20Sopenharmony_ci * The caller can pass in *p if it wants to keep track of the most recent
538c2ecf20Sopenharmony_ci * number of parity bits added.  This allows the function to start the
548c2ecf20Sopenharmony_ci * calculation at the last place.
558c2ecf20Sopenharmony_ci */
568c2ecf20Sopenharmony_cistatic unsigned int calc_code_bit(unsigned int i, unsigned int *p_cache)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	unsigned int b, p = 0;
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	/*
618c2ecf20Sopenharmony_ci	 * Data bits are 0-based, but we're talking code bits, which
628c2ecf20Sopenharmony_ci	 * are 1-based.
638c2ecf20Sopenharmony_ci	 */
648c2ecf20Sopenharmony_ci	b = i + 1;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	/* Use the cache if it is there */
678c2ecf20Sopenharmony_ci	if (p_cache)
688c2ecf20Sopenharmony_ci		p = *p_cache;
698c2ecf20Sopenharmony_ci        b += p;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	/*
728c2ecf20Sopenharmony_ci	 * For every power of two below our bit number, bump our bit.
738c2ecf20Sopenharmony_ci	 *
748c2ecf20Sopenharmony_ci	 * We compare with (b + 1) because we have to compare with what b
758c2ecf20Sopenharmony_ci	 * would be _if_ it were bumped up by the parity bit.  Capice?
768c2ecf20Sopenharmony_ci	 *
778c2ecf20Sopenharmony_ci	 * p is set above.
788c2ecf20Sopenharmony_ci	 */
798c2ecf20Sopenharmony_ci	for (; (1 << p) < (b + 1); p++)
808c2ecf20Sopenharmony_ci		b++;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	if (p_cache)
838c2ecf20Sopenharmony_ci		*p_cache = p;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	return b;
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/*
898c2ecf20Sopenharmony_ci * This is the low level encoder function.  It can be called across
908c2ecf20Sopenharmony_ci * multiple hunks just like the crc32 code.  'd' is the number of bits
918c2ecf20Sopenharmony_ci * _in_this_hunk_.  nr is the bit offset of this hunk.  So, if you had
928c2ecf20Sopenharmony_ci * two 512B buffers, you would do it like so:
938c2ecf20Sopenharmony_ci *
948c2ecf20Sopenharmony_ci * parity = ocfs2_hamming_encode(0, buf1, 512 * 8, 0);
958c2ecf20Sopenharmony_ci * parity = ocfs2_hamming_encode(parity, buf2, 512 * 8, 512 * 8);
968c2ecf20Sopenharmony_ci *
978c2ecf20Sopenharmony_ci * If you just have one buffer, use ocfs2_hamming_encode_block().
988c2ecf20Sopenharmony_ci */
998c2ecf20Sopenharmony_ciu32 ocfs2_hamming_encode(u32 parity, void *data, unsigned int d, unsigned int nr)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	unsigned int i, b, p = 0;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	BUG_ON(!d);
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	/*
1068c2ecf20Sopenharmony_ci	 * b is the hamming code bit number.  Hamming code specifies a
1078c2ecf20Sopenharmony_ci	 * 1-based array, but C uses 0-based.  So 'i' is for C, and 'b' is
1088c2ecf20Sopenharmony_ci	 * for the algorithm.
1098c2ecf20Sopenharmony_ci	 *
1108c2ecf20Sopenharmony_ci	 * The i++ in the for loop is so that the start offset passed
1118c2ecf20Sopenharmony_ci	 * to ocfs2_find_next_bit_set() is one greater than the previously
1128c2ecf20Sopenharmony_ci	 * found bit.
1138c2ecf20Sopenharmony_ci	 */
1148c2ecf20Sopenharmony_ci	for (i = 0; (i = ocfs2_find_next_bit(data, d, i)) < d; i++)
1158c2ecf20Sopenharmony_ci	{
1168c2ecf20Sopenharmony_ci		/*
1178c2ecf20Sopenharmony_ci		 * i is the offset in this hunk, nr + i is the total bit
1188c2ecf20Sopenharmony_ci		 * offset.
1198c2ecf20Sopenharmony_ci		 */
1208c2ecf20Sopenharmony_ci		b = calc_code_bit(nr + i, &p);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci		/*
1238c2ecf20Sopenharmony_ci		 * Data bits in the resultant code are checked by
1248c2ecf20Sopenharmony_ci		 * parity bits that are part of the bit number
1258c2ecf20Sopenharmony_ci		 * representation.  Huh?
1268c2ecf20Sopenharmony_ci		 *
1278c2ecf20Sopenharmony_ci		 * <wikipedia href="https://en.wikipedia.org/wiki/Hamming_code">
1288c2ecf20Sopenharmony_ci		 * In other words, the parity bit at position 2^k
1298c2ecf20Sopenharmony_ci		 * checks bits in positions having bit k set in
1308c2ecf20Sopenharmony_ci		 * their binary representation.  Conversely, for
1318c2ecf20Sopenharmony_ci		 * instance, bit 13, i.e. 1101(2), is checked by
1328c2ecf20Sopenharmony_ci		 * bits 1000(2) = 8, 0100(2)=4 and 0001(2) = 1.
1338c2ecf20Sopenharmony_ci		 * </wikipedia>
1348c2ecf20Sopenharmony_ci		 *
1358c2ecf20Sopenharmony_ci		 * Note that 'k' is the _code_ bit number.  'b' in
1368c2ecf20Sopenharmony_ci		 * our loop.
1378c2ecf20Sopenharmony_ci		 */
1388c2ecf20Sopenharmony_ci		parity ^= b;
1398c2ecf20Sopenharmony_ci	}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	/* While the data buffer was treated as little endian, the
1428c2ecf20Sopenharmony_ci	 * return value is in host endian. */
1438c2ecf20Sopenharmony_ci	return parity;
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ciu32 ocfs2_hamming_encode_block(void *data, unsigned int blocksize)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	return ocfs2_hamming_encode(0, data, blocksize * 8, 0);
1498c2ecf20Sopenharmony_ci}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci/*
1528c2ecf20Sopenharmony_ci * Like ocfs2_hamming_encode(), this can handle hunks.  nr is the bit
1538c2ecf20Sopenharmony_ci * offset of the current hunk.  If bit to be fixed is not part of the
1548c2ecf20Sopenharmony_ci * current hunk, this does nothing.
1558c2ecf20Sopenharmony_ci *
1568c2ecf20Sopenharmony_ci * If you only have one hunk, use ocfs2_hamming_fix_block().
1578c2ecf20Sopenharmony_ci */
1588c2ecf20Sopenharmony_civoid ocfs2_hamming_fix(void *data, unsigned int d, unsigned int nr,
1598c2ecf20Sopenharmony_ci		       unsigned int fix)
1608c2ecf20Sopenharmony_ci{
1618c2ecf20Sopenharmony_ci	unsigned int i, b;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	BUG_ON(!d);
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	/*
1668c2ecf20Sopenharmony_ci	 * If the bit to fix has an hweight of 1, it's a parity bit.  One
1678c2ecf20Sopenharmony_ci	 * busted parity bit is its own error.  Nothing to do here.
1688c2ecf20Sopenharmony_ci	 */
1698c2ecf20Sopenharmony_ci	if (hweight32(fix) == 1)
1708c2ecf20Sopenharmony_ci		return;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	/*
1738c2ecf20Sopenharmony_ci	 * nr + d is the bit right past the data hunk we're looking at.
1748c2ecf20Sopenharmony_ci	 * If fix after that, nothing to do
1758c2ecf20Sopenharmony_ci	 */
1768c2ecf20Sopenharmony_ci	if (fix >= calc_code_bit(nr + d, NULL))
1778c2ecf20Sopenharmony_ci		return;
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	/*
1808c2ecf20Sopenharmony_ci	 * nr is the offset in the data hunk we're starting at.  Let's
1818c2ecf20Sopenharmony_ci	 * start b at the offset in the code buffer.  See hamming_encode()
1828c2ecf20Sopenharmony_ci	 * for a more detailed description of 'b'.
1838c2ecf20Sopenharmony_ci	 */
1848c2ecf20Sopenharmony_ci	b = calc_code_bit(nr, NULL);
1858c2ecf20Sopenharmony_ci	/* If the fix is before this hunk, nothing to do */
1868c2ecf20Sopenharmony_ci	if (fix < b)
1878c2ecf20Sopenharmony_ci		return;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	for (i = 0; i < d; i++, b++)
1908c2ecf20Sopenharmony_ci	{
1918c2ecf20Sopenharmony_ci		/* Skip past parity bits */
1928c2ecf20Sopenharmony_ci		while (hweight32(b) == 1)
1938c2ecf20Sopenharmony_ci			b++;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci		/*
1968c2ecf20Sopenharmony_ci		 * i is the offset in this data hunk.
1978c2ecf20Sopenharmony_ci		 * nr + i is the offset in the total data buffer.
1988c2ecf20Sopenharmony_ci		 * b is the offset in the total code buffer.
1998c2ecf20Sopenharmony_ci		 *
2008c2ecf20Sopenharmony_ci		 * Thus, when b == fix, bit i in the current hunk needs
2018c2ecf20Sopenharmony_ci		 * fixing.
2028c2ecf20Sopenharmony_ci		 */
2038c2ecf20Sopenharmony_ci		if (b == fix)
2048c2ecf20Sopenharmony_ci		{
2058c2ecf20Sopenharmony_ci			if (ocfs2_test_bit(i, data))
2068c2ecf20Sopenharmony_ci				ocfs2_clear_bit(i, data);
2078c2ecf20Sopenharmony_ci			else
2088c2ecf20Sopenharmony_ci				ocfs2_set_bit(i, data);
2098c2ecf20Sopenharmony_ci			break;
2108c2ecf20Sopenharmony_ci		}
2118c2ecf20Sopenharmony_ci	}
2128c2ecf20Sopenharmony_ci}
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_civoid ocfs2_hamming_fix_block(void *data, unsigned int blocksize,
2158c2ecf20Sopenharmony_ci			     unsigned int fix)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	ocfs2_hamming_fix(data, blocksize * 8, 0, fix);
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci/*
2228c2ecf20Sopenharmony_ci * Debugfs handling.
2238c2ecf20Sopenharmony_ci */
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_cistatic int blockcheck_u64_get(void *data, u64 *val)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	*val = *(u64 *)data;
2308c2ecf20Sopenharmony_ci	return 0;
2318c2ecf20Sopenharmony_ci}
2328c2ecf20Sopenharmony_ciDEFINE_SIMPLE_ATTRIBUTE(blockcheck_fops, blockcheck_u64_get, NULL, "%llu\n");
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_cistatic void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats)
2358c2ecf20Sopenharmony_ci{
2368c2ecf20Sopenharmony_ci	if (stats) {
2378c2ecf20Sopenharmony_ci		debugfs_remove_recursive(stats->b_debug_dir);
2388c2ecf20Sopenharmony_ci		stats->b_debug_dir = NULL;
2398c2ecf20Sopenharmony_ci	}
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_cistatic void ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats,
2438c2ecf20Sopenharmony_ci					   struct dentry *parent)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci	struct dentry *dir;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	dir = debugfs_create_dir("blockcheck", parent);
2488c2ecf20Sopenharmony_ci	stats->b_debug_dir = dir;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	debugfs_create_file("blocks_checked", S_IFREG | S_IRUSR, dir,
2518c2ecf20Sopenharmony_ci			    &stats->b_check_count, &blockcheck_fops);
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	debugfs_create_file("checksums_failed", S_IFREG | S_IRUSR, dir,
2548c2ecf20Sopenharmony_ci			    &stats->b_failure_count, &blockcheck_fops);
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	debugfs_create_file("ecc_recoveries", S_IFREG | S_IRUSR, dir,
2578c2ecf20Sopenharmony_ci			    &stats->b_recover_count, &blockcheck_fops);
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci}
2608c2ecf20Sopenharmony_ci#else
2618c2ecf20Sopenharmony_cistatic inline void ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats,
2628c2ecf20Sopenharmony_ci						  struct dentry *parent)
2638c2ecf20Sopenharmony_ci{
2648c2ecf20Sopenharmony_ci}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_cistatic inline void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats)
2678c2ecf20Sopenharmony_ci{
2688c2ecf20Sopenharmony_ci}
2698c2ecf20Sopenharmony_ci#endif  /* CONFIG_DEBUG_FS */
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci/* Always-called wrappers for starting and stopping the debugfs files */
2728c2ecf20Sopenharmony_civoid ocfs2_blockcheck_stats_debugfs_install(struct ocfs2_blockcheck_stats *stats,
2738c2ecf20Sopenharmony_ci					    struct dentry *parent)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	ocfs2_blockcheck_debug_install(stats, parent);
2768c2ecf20Sopenharmony_ci}
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_civoid ocfs2_blockcheck_stats_debugfs_remove(struct ocfs2_blockcheck_stats *stats)
2798c2ecf20Sopenharmony_ci{
2808c2ecf20Sopenharmony_ci	ocfs2_blockcheck_debug_remove(stats);
2818c2ecf20Sopenharmony_ci}
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_cistatic void ocfs2_blockcheck_inc_check(struct ocfs2_blockcheck_stats *stats)
2848c2ecf20Sopenharmony_ci{
2858c2ecf20Sopenharmony_ci	u64 new_count;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	if (!stats)
2888c2ecf20Sopenharmony_ci		return;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	spin_lock(&stats->b_lock);
2918c2ecf20Sopenharmony_ci	stats->b_check_count++;
2928c2ecf20Sopenharmony_ci	new_count = stats->b_check_count;
2938c2ecf20Sopenharmony_ci	spin_unlock(&stats->b_lock);
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	if (!new_count)
2968c2ecf20Sopenharmony_ci		mlog(ML_NOTICE, "Block check count has wrapped\n");
2978c2ecf20Sopenharmony_ci}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_cistatic void ocfs2_blockcheck_inc_failure(struct ocfs2_blockcheck_stats *stats)
3008c2ecf20Sopenharmony_ci{
3018c2ecf20Sopenharmony_ci	u64 new_count;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	if (!stats)
3048c2ecf20Sopenharmony_ci		return;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	spin_lock(&stats->b_lock);
3078c2ecf20Sopenharmony_ci	stats->b_failure_count++;
3088c2ecf20Sopenharmony_ci	new_count = stats->b_failure_count;
3098c2ecf20Sopenharmony_ci	spin_unlock(&stats->b_lock);
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	if (!new_count)
3128c2ecf20Sopenharmony_ci		mlog(ML_NOTICE, "Checksum failure count has wrapped\n");
3138c2ecf20Sopenharmony_ci}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistatic void ocfs2_blockcheck_inc_recover(struct ocfs2_blockcheck_stats *stats)
3168c2ecf20Sopenharmony_ci{
3178c2ecf20Sopenharmony_ci	u64 new_count;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	if (!stats)
3208c2ecf20Sopenharmony_ci		return;
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	spin_lock(&stats->b_lock);
3238c2ecf20Sopenharmony_ci	stats->b_recover_count++;
3248c2ecf20Sopenharmony_ci	new_count = stats->b_recover_count;
3258c2ecf20Sopenharmony_ci	spin_unlock(&stats->b_lock);
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	if (!new_count)
3288c2ecf20Sopenharmony_ci		mlog(ML_NOTICE, "ECC recovery count has wrapped\n");
3298c2ecf20Sopenharmony_ci}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci/*
3348c2ecf20Sopenharmony_ci * These are the low-level APIs for using the ocfs2_block_check structure.
3358c2ecf20Sopenharmony_ci */
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci/*
3388c2ecf20Sopenharmony_ci * This function generates check information for a block.
3398c2ecf20Sopenharmony_ci * data is the block to be checked.  bc is a pointer to the
3408c2ecf20Sopenharmony_ci * ocfs2_block_check structure describing the crc32 and the ecc.
3418c2ecf20Sopenharmony_ci *
3428c2ecf20Sopenharmony_ci * bc should be a pointer inside data, as the function will
3438c2ecf20Sopenharmony_ci * take care of zeroing it before calculating the check information.  If
3448c2ecf20Sopenharmony_ci * bc does not point inside data, the caller must make sure any inline
3458c2ecf20Sopenharmony_ci * ocfs2_block_check structures are zeroed.
3468c2ecf20Sopenharmony_ci *
3478c2ecf20Sopenharmony_ci * The data buffer must be in on-disk endian (little endian for ocfs2).
3488c2ecf20Sopenharmony_ci * bc will be filled with little-endian values and will be ready to go to
3498c2ecf20Sopenharmony_ci * disk.
3508c2ecf20Sopenharmony_ci */
3518c2ecf20Sopenharmony_civoid ocfs2_block_check_compute(void *data, size_t blocksize,
3528c2ecf20Sopenharmony_ci			       struct ocfs2_block_check *bc)
3538c2ecf20Sopenharmony_ci{
3548c2ecf20Sopenharmony_ci	u32 crc;
3558c2ecf20Sopenharmony_ci	u32 ecc;
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	memset(bc, 0, sizeof(struct ocfs2_block_check));
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	crc = crc32_le(~0, data, blocksize);
3608c2ecf20Sopenharmony_ci	ecc = ocfs2_hamming_encode_block(data, blocksize);
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	/*
3638c2ecf20Sopenharmony_ci	 * No ecc'd ocfs2 structure is larger than 4K, so ecc will be no
3648c2ecf20Sopenharmony_ci	 * larger than 16 bits.
3658c2ecf20Sopenharmony_ci	 */
3668c2ecf20Sopenharmony_ci	BUG_ON(ecc > USHRT_MAX);
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	bc->bc_crc32e = cpu_to_le32(crc);
3698c2ecf20Sopenharmony_ci	bc->bc_ecc = cpu_to_le16((u16)ecc);
3708c2ecf20Sopenharmony_ci}
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci/*
3738c2ecf20Sopenharmony_ci * This function validates existing check information.  Like _compute,
3748c2ecf20Sopenharmony_ci * the function will take care of zeroing bc before calculating check codes.
3758c2ecf20Sopenharmony_ci * If bc is not a pointer inside data, the caller must have zeroed any
3768c2ecf20Sopenharmony_ci * inline ocfs2_block_check structures.
3778c2ecf20Sopenharmony_ci *
3788c2ecf20Sopenharmony_ci * Again, the data passed in should be the on-disk endian.
3798c2ecf20Sopenharmony_ci */
3808c2ecf20Sopenharmony_ciint ocfs2_block_check_validate(void *data, size_t blocksize,
3818c2ecf20Sopenharmony_ci			       struct ocfs2_block_check *bc,
3828c2ecf20Sopenharmony_ci			       struct ocfs2_blockcheck_stats *stats)
3838c2ecf20Sopenharmony_ci{
3848c2ecf20Sopenharmony_ci	int rc = 0;
3858c2ecf20Sopenharmony_ci	u32 bc_crc32e;
3868c2ecf20Sopenharmony_ci	u16 bc_ecc;
3878c2ecf20Sopenharmony_ci	u32 crc, ecc;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	ocfs2_blockcheck_inc_check(stats);
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	bc_crc32e = le32_to_cpu(bc->bc_crc32e);
3928c2ecf20Sopenharmony_ci	bc_ecc = le16_to_cpu(bc->bc_ecc);
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	memset(bc, 0, sizeof(struct ocfs2_block_check));
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	/* Fast path - if the crc32 validates, we're good to go */
3978c2ecf20Sopenharmony_ci	crc = crc32_le(~0, data, blocksize);
3988c2ecf20Sopenharmony_ci	if (crc == bc_crc32e)
3998c2ecf20Sopenharmony_ci		goto out;
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	ocfs2_blockcheck_inc_failure(stats);
4028c2ecf20Sopenharmony_ci	mlog(ML_ERROR,
4038c2ecf20Sopenharmony_ci	     "CRC32 failed: stored: 0x%x, computed 0x%x. Applying ECC.\n",
4048c2ecf20Sopenharmony_ci	     (unsigned int)bc_crc32e, (unsigned int)crc);
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	/* Ok, try ECC fixups */
4078c2ecf20Sopenharmony_ci	ecc = ocfs2_hamming_encode_block(data, blocksize);
4088c2ecf20Sopenharmony_ci	ocfs2_hamming_fix_block(data, blocksize, ecc ^ bc_ecc);
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	/* And check the crc32 again */
4118c2ecf20Sopenharmony_ci	crc = crc32_le(~0, data, blocksize);
4128c2ecf20Sopenharmony_ci	if (crc == bc_crc32e) {
4138c2ecf20Sopenharmony_ci		ocfs2_blockcheck_inc_recover(stats);
4148c2ecf20Sopenharmony_ci		goto out;
4158c2ecf20Sopenharmony_ci	}
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	mlog(ML_ERROR, "Fixed CRC32 failed: stored: 0x%x, computed 0x%x\n",
4188c2ecf20Sopenharmony_ci	     (unsigned int)bc_crc32e, (unsigned int)crc);
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	rc = -EIO;
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ciout:
4238c2ecf20Sopenharmony_ci	bc->bc_crc32e = cpu_to_le32(bc_crc32e);
4248c2ecf20Sopenharmony_ci	bc->bc_ecc = cpu_to_le16(bc_ecc);
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	return rc;
4278c2ecf20Sopenharmony_ci}
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci/*
4308c2ecf20Sopenharmony_ci * This function generates check information for a list of buffer_heads.
4318c2ecf20Sopenharmony_ci * bhs is the blocks to be checked.  bc is a pointer to the
4328c2ecf20Sopenharmony_ci * ocfs2_block_check structure describing the crc32 and the ecc.
4338c2ecf20Sopenharmony_ci *
4348c2ecf20Sopenharmony_ci * bc should be a pointer inside data, as the function will
4358c2ecf20Sopenharmony_ci * take care of zeroing it before calculating the check information.  If
4368c2ecf20Sopenharmony_ci * bc does not point inside data, the caller must make sure any inline
4378c2ecf20Sopenharmony_ci * ocfs2_block_check structures are zeroed.
4388c2ecf20Sopenharmony_ci *
4398c2ecf20Sopenharmony_ci * The data buffer must be in on-disk endian (little endian for ocfs2).
4408c2ecf20Sopenharmony_ci * bc will be filled with little-endian values and will be ready to go to
4418c2ecf20Sopenharmony_ci * disk.
4428c2ecf20Sopenharmony_ci */
4438c2ecf20Sopenharmony_civoid ocfs2_block_check_compute_bhs(struct buffer_head **bhs, int nr,
4448c2ecf20Sopenharmony_ci				   struct ocfs2_block_check *bc)
4458c2ecf20Sopenharmony_ci{
4468c2ecf20Sopenharmony_ci	int i;
4478c2ecf20Sopenharmony_ci	u32 crc, ecc;
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	BUG_ON(nr < 0);
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	if (!nr)
4528c2ecf20Sopenharmony_ci		return;
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	memset(bc, 0, sizeof(struct ocfs2_block_check));
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	for (i = 0, crc = ~0, ecc = 0; i < nr; i++) {
4578c2ecf20Sopenharmony_ci		crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
4588c2ecf20Sopenharmony_ci		/*
4598c2ecf20Sopenharmony_ci		 * The number of bits in a buffer is obviously b_size*8.
4608c2ecf20Sopenharmony_ci		 * The offset of this buffer is b_size*i, so the bit offset
4618c2ecf20Sopenharmony_ci		 * of this buffer is b_size*8*i.
4628c2ecf20Sopenharmony_ci		 */
4638c2ecf20Sopenharmony_ci		ecc = (u16)ocfs2_hamming_encode(ecc, bhs[i]->b_data,
4648c2ecf20Sopenharmony_ci						bhs[i]->b_size * 8,
4658c2ecf20Sopenharmony_ci						bhs[i]->b_size * 8 * i);
4668c2ecf20Sopenharmony_ci	}
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	/*
4698c2ecf20Sopenharmony_ci	 * No ecc'd ocfs2 structure is larger than 4K, so ecc will be no
4708c2ecf20Sopenharmony_ci	 * larger than 16 bits.
4718c2ecf20Sopenharmony_ci	 */
4728c2ecf20Sopenharmony_ci	BUG_ON(ecc > USHRT_MAX);
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	bc->bc_crc32e = cpu_to_le32(crc);
4758c2ecf20Sopenharmony_ci	bc->bc_ecc = cpu_to_le16((u16)ecc);
4768c2ecf20Sopenharmony_ci}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci/*
4798c2ecf20Sopenharmony_ci * This function validates existing check information on a list of
4808c2ecf20Sopenharmony_ci * buffer_heads.  Like _compute_bhs, the function will take care of
4818c2ecf20Sopenharmony_ci * zeroing bc before calculating check codes.  If bc is not a pointer
4828c2ecf20Sopenharmony_ci * inside data, the caller must have zeroed any inline
4838c2ecf20Sopenharmony_ci * ocfs2_block_check structures.
4848c2ecf20Sopenharmony_ci *
4858c2ecf20Sopenharmony_ci * Again, the data passed in should be the on-disk endian.
4868c2ecf20Sopenharmony_ci */
4878c2ecf20Sopenharmony_ciint ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
4888c2ecf20Sopenharmony_ci				   struct ocfs2_block_check *bc,
4898c2ecf20Sopenharmony_ci				   struct ocfs2_blockcheck_stats *stats)
4908c2ecf20Sopenharmony_ci{
4918c2ecf20Sopenharmony_ci	int i, rc = 0;
4928c2ecf20Sopenharmony_ci	u32 bc_crc32e;
4938c2ecf20Sopenharmony_ci	u16 bc_ecc;
4948c2ecf20Sopenharmony_ci	u32 crc, ecc, fix;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	BUG_ON(nr < 0);
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	if (!nr)
4998c2ecf20Sopenharmony_ci		return 0;
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	ocfs2_blockcheck_inc_check(stats);
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	bc_crc32e = le32_to_cpu(bc->bc_crc32e);
5048c2ecf20Sopenharmony_ci	bc_ecc = le16_to_cpu(bc->bc_ecc);
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	memset(bc, 0, sizeof(struct ocfs2_block_check));
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	/* Fast path - if the crc32 validates, we're good to go */
5098c2ecf20Sopenharmony_ci	for (i = 0, crc = ~0; i < nr; i++)
5108c2ecf20Sopenharmony_ci		crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
5118c2ecf20Sopenharmony_ci	if (crc == bc_crc32e)
5128c2ecf20Sopenharmony_ci		goto out;
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	ocfs2_blockcheck_inc_failure(stats);
5158c2ecf20Sopenharmony_ci	mlog(ML_ERROR,
5168c2ecf20Sopenharmony_ci	     "CRC32 failed: stored: %u, computed %u.  Applying ECC.\n",
5178c2ecf20Sopenharmony_ci	     (unsigned int)bc_crc32e, (unsigned int)crc);
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	/* Ok, try ECC fixups */
5208c2ecf20Sopenharmony_ci	for (i = 0, ecc = 0; i < nr; i++) {
5218c2ecf20Sopenharmony_ci		/*
5228c2ecf20Sopenharmony_ci		 * The number of bits in a buffer is obviously b_size*8.
5238c2ecf20Sopenharmony_ci		 * The offset of this buffer is b_size*i, so the bit offset
5248c2ecf20Sopenharmony_ci		 * of this buffer is b_size*8*i.
5258c2ecf20Sopenharmony_ci		 */
5268c2ecf20Sopenharmony_ci		ecc = (u16)ocfs2_hamming_encode(ecc, bhs[i]->b_data,
5278c2ecf20Sopenharmony_ci						bhs[i]->b_size * 8,
5288c2ecf20Sopenharmony_ci						bhs[i]->b_size * 8 * i);
5298c2ecf20Sopenharmony_ci	}
5308c2ecf20Sopenharmony_ci	fix = ecc ^ bc_ecc;
5318c2ecf20Sopenharmony_ci	for (i = 0; i < nr; i++) {
5328c2ecf20Sopenharmony_ci		/*
5338c2ecf20Sopenharmony_ci		 * Try the fix against each buffer.  It will only affect
5348c2ecf20Sopenharmony_ci		 * one of them.
5358c2ecf20Sopenharmony_ci		 */
5368c2ecf20Sopenharmony_ci		ocfs2_hamming_fix(bhs[i]->b_data, bhs[i]->b_size * 8,
5378c2ecf20Sopenharmony_ci				  bhs[i]->b_size * 8 * i, fix);
5388c2ecf20Sopenharmony_ci	}
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	/* And check the crc32 again */
5418c2ecf20Sopenharmony_ci	for (i = 0, crc = ~0; i < nr; i++)
5428c2ecf20Sopenharmony_ci		crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
5438c2ecf20Sopenharmony_ci	if (crc == bc_crc32e) {
5448c2ecf20Sopenharmony_ci		ocfs2_blockcheck_inc_recover(stats);
5458c2ecf20Sopenharmony_ci		goto out;
5468c2ecf20Sopenharmony_ci	}
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n",
5498c2ecf20Sopenharmony_ci	     (unsigned int)bc_crc32e, (unsigned int)crc);
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	rc = -EIO;
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ciout:
5548c2ecf20Sopenharmony_ci	bc->bc_crc32e = cpu_to_le32(bc_crc32e);
5558c2ecf20Sopenharmony_ci	bc->bc_ecc = cpu_to_le16(bc_ecc);
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	return rc;
5588c2ecf20Sopenharmony_ci}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci/*
5618c2ecf20Sopenharmony_ci * These are the main API.  They check the superblock flag before
5628c2ecf20Sopenharmony_ci * calling the underlying operations.
5638c2ecf20Sopenharmony_ci *
5648c2ecf20Sopenharmony_ci * They expect the buffer(s) to be in disk format.
5658c2ecf20Sopenharmony_ci */
5668c2ecf20Sopenharmony_civoid ocfs2_compute_meta_ecc(struct super_block *sb, void *data,
5678c2ecf20Sopenharmony_ci			    struct ocfs2_block_check *bc)
5688c2ecf20Sopenharmony_ci{
5698c2ecf20Sopenharmony_ci	if (ocfs2_meta_ecc(OCFS2_SB(sb)))
5708c2ecf20Sopenharmony_ci		ocfs2_block_check_compute(data, sb->s_blocksize, bc);
5718c2ecf20Sopenharmony_ci}
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ciint ocfs2_validate_meta_ecc(struct super_block *sb, void *data,
5748c2ecf20Sopenharmony_ci			    struct ocfs2_block_check *bc)
5758c2ecf20Sopenharmony_ci{
5768c2ecf20Sopenharmony_ci	int rc = 0;
5778c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(sb);
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	if (ocfs2_meta_ecc(osb))
5808c2ecf20Sopenharmony_ci		rc = ocfs2_block_check_validate(data, sb->s_blocksize, bc,
5818c2ecf20Sopenharmony_ci						&osb->osb_ecc_stats);
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	return rc;
5848c2ecf20Sopenharmony_ci}
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_civoid ocfs2_compute_meta_ecc_bhs(struct super_block *sb,
5878c2ecf20Sopenharmony_ci				struct buffer_head **bhs, int nr,
5888c2ecf20Sopenharmony_ci				struct ocfs2_block_check *bc)
5898c2ecf20Sopenharmony_ci{
5908c2ecf20Sopenharmony_ci	if (ocfs2_meta_ecc(OCFS2_SB(sb)))
5918c2ecf20Sopenharmony_ci		ocfs2_block_check_compute_bhs(bhs, nr, bc);
5928c2ecf20Sopenharmony_ci}
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ciint ocfs2_validate_meta_ecc_bhs(struct super_block *sb,
5958c2ecf20Sopenharmony_ci				struct buffer_head **bhs, int nr,
5968c2ecf20Sopenharmony_ci				struct ocfs2_block_check *bc)
5978c2ecf20Sopenharmony_ci{
5988c2ecf20Sopenharmony_ci	int rc = 0;
5998c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(sb);
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	if (ocfs2_meta_ecc(osb))
6028c2ecf20Sopenharmony_ci		rc = ocfs2_block_check_validate_bhs(bhs, nr, bc,
6038c2ecf20Sopenharmony_ci						    &osb->osb_ecc_stats);
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	return rc;
6068c2ecf20Sopenharmony_ci}
6078c2ecf20Sopenharmony_ci
608