xref: /linux/fs/ext4/bitmap.c (revision 26b0d14106954ae46d2f4f7eec3481828a210f7d)
1 /*
2  *  linux/fs/ext4/bitmap.c
3  *
4  * Copyright (C) 1992, 1993, 1994, 1995
5  * Remy Card (card@masi.ibp.fr)
6  * Laboratoire MASI - Institut Blaise Pascal
7  * Universite Pierre et Marie Curie (Paris VI)
8  */
9 
10 #include <linux/buffer_head.h>
11 #include <linux/jbd2.h>
12 #include "ext4.h"
13 
14 #ifdef EXT4FS_DEBUG
15 
16 static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
17 
18 unsigned int ext4_count_free(struct buffer_head *map, unsigned int numchars)
19 {
20 	unsigned int i, sum = 0;
21 
22 	if (!map)
23 		return 0;
24 	for (i = 0; i < numchars; i++)
25 		sum += nibblemap[map->b_data[i] & 0xf] +
26 			nibblemap[(map->b_data[i] >> 4) & 0xf];
27 	return sum;
28 }
29 
30 #endif  /*  EXT4FS_DEBUG  */
31 
32 int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
33 				  struct ext4_group_desc *gdp,
34 				  struct buffer_head *bh, int sz)
35 {
36 	__u32 hi;
37 	__u32 provided, calculated;
38 	struct ext4_sb_info *sbi = EXT4_SB(sb);
39 
40 	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
41 					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
42 		return 1;
43 
44 	provided = le16_to_cpu(gdp->bg_inode_bitmap_csum_lo);
45 	calculated = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
46 	if (sbi->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END) {
47 		hi = le16_to_cpu(gdp->bg_inode_bitmap_csum_hi);
48 		provided |= (hi << 16);
49 	} else
50 		calculated &= 0xFFFF;
51 
52 	return provided == calculated;
53 }
54 
55 void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
56 				struct ext4_group_desc *gdp,
57 				struct buffer_head *bh, int sz)
58 {
59 	__u32 csum;
60 	struct ext4_sb_info *sbi = EXT4_SB(sb);
61 
62 	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
63 					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
64 		return;
65 
66 	csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
67 	gdp->bg_inode_bitmap_csum_lo = cpu_to_le16(csum & 0xFFFF);
68 	if (sbi->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
69 		gdp->bg_inode_bitmap_csum_hi = cpu_to_le16(csum >> 16);
70 }
71 
72 int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
73 				  struct ext4_group_desc *gdp,
74 				  struct buffer_head *bh, int sz)
75 {
76 	__u32 hi;
77 	__u32 provided, calculated;
78 	struct ext4_sb_info *sbi = EXT4_SB(sb);
79 
80 	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
81 					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
82 		return 1;
83 
84 	provided = le16_to_cpu(gdp->bg_block_bitmap_csum_lo);
85 	calculated = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
86 	if (sbi->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_END) {
87 		hi = le16_to_cpu(gdp->bg_block_bitmap_csum_hi);
88 		provided |= (hi << 16);
89 	} else
90 		calculated &= 0xFFFF;
91 
92 	if (provided == calculated)
93 		return 1;
94 
95 	ext4_error(sb, "Bad block bitmap checksum: block_group = %u", group);
96 	return 0;
97 }
98 
99 void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
100 				struct ext4_group_desc *gdp,
101 				struct buffer_head *bh, int sz)
102 {
103 	__u32 csum;
104 	struct ext4_sb_info *sbi = EXT4_SB(sb);
105 
106 	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
107 			EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
108 		return;
109 
110 	csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
111 	gdp->bg_block_bitmap_csum_lo = cpu_to_le16(csum & 0xFFFF);
112 	if (sbi->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_END)
113 		gdp->bg_block_bitmap_csum_hi = cpu_to_le16(csum >> 16);
114 }
115