xref: /linux/fs/ext4/bitmap.c (revision ca55b2fef3a9373fcfc30f82fd26bc7fccbda732)
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 "ext4.h"
12 
13 unsigned int ext4_count_free(char *bitmap, unsigned int numchars)
14 {
15 	return numchars * BITS_PER_BYTE - memweight(bitmap, numchars);
16 }
17 
18 int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
19 				  struct ext4_group_desc *gdp,
20 				  struct buffer_head *bh, int sz)
21 {
22 	__u32 hi;
23 	__u32 provided, calculated;
24 	struct ext4_sb_info *sbi = EXT4_SB(sb);
25 
26 	if (!ext4_has_metadata_csum(sb))
27 		return 1;
28 
29 	provided = le16_to_cpu(gdp->bg_inode_bitmap_csum_lo);
30 	calculated = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
31 	if (sbi->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END) {
32 		hi = le16_to_cpu(gdp->bg_inode_bitmap_csum_hi);
33 		provided |= (hi << 16);
34 	} else
35 		calculated &= 0xFFFF;
36 
37 	return provided == calculated;
38 }
39 
40 void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
41 				struct ext4_group_desc *gdp,
42 				struct buffer_head *bh, int sz)
43 {
44 	__u32 csum;
45 	struct ext4_sb_info *sbi = EXT4_SB(sb);
46 
47 	if (!ext4_has_metadata_csum(sb))
48 		return;
49 
50 	csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
51 	gdp->bg_inode_bitmap_csum_lo = cpu_to_le16(csum & 0xFFFF);
52 	if (sbi->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
53 		gdp->bg_inode_bitmap_csum_hi = cpu_to_le16(csum >> 16);
54 }
55 
56 int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
57 				  struct ext4_group_desc *gdp,
58 				  struct buffer_head *bh)
59 {
60 	__u32 hi;
61 	__u32 provided, calculated;
62 	struct ext4_sb_info *sbi = EXT4_SB(sb);
63 	int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
64 
65 	if (!ext4_has_metadata_csum(sb))
66 		return 1;
67 
68 	provided = le16_to_cpu(gdp->bg_block_bitmap_csum_lo);
69 	calculated = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
70 	if (sbi->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_END) {
71 		hi = le16_to_cpu(gdp->bg_block_bitmap_csum_hi);
72 		provided |= (hi << 16);
73 	} else
74 		calculated &= 0xFFFF;
75 
76 	if (provided == calculated)
77 		return 1;
78 
79 	return 0;
80 }
81 
82 void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
83 				struct ext4_group_desc *gdp,
84 				struct buffer_head *bh)
85 {
86 	int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
87 	__u32 csum;
88 	struct ext4_sb_info *sbi = EXT4_SB(sb);
89 
90 	if (!ext4_has_metadata_csum(sb))
91 		return;
92 
93 	csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
94 	gdp->bg_block_bitmap_csum_lo = cpu_to_le16(csum & 0xFFFF);
95 	if (sbi->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_END)
96 		gdp->bg_block_bitmap_csum_hi = cpu_to_le16(csum >> 16);
97 }
98