xref: /linux/fs/ext4/bitmap.c (revision a6021aa24f6417416d93318bbfa022ab229c33c8)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  linux/fs/ext4/bitmap.c
4  *
5  * Copyright (C) 1992, 1993, 1994, 1995
6  * Remy Card (card@masi.ibp.fr)
7  * Laboratoire MASI - Institut Blaise Pascal
8  * Universite Pierre et Marie Curie (Paris VI)
9  */
10 
11 #include <linux/buffer_head.h>
12 #include "ext4.h"
13 
14 unsigned int ext4_count_free(char *bitmap, unsigned int numchars)
15 {
16 	return numchars * BITS_PER_BYTE - memweight(bitmap, numchars);
17 }
18 
19 int ext4_inode_bitmap_csum_verify(struct super_block *sb,
20 				  struct ext4_group_desc *gdp,
21 				  struct buffer_head *bh)
22 {
23 	__u32 hi;
24 	__u32 provided, calculated;
25 	struct ext4_sb_info *sbi = EXT4_SB(sb);
26 	int sz;
27 
28 	if (!ext4_has_metadata_csum(sb))
29 		return 1;
30 
31 	sz = EXT4_INODES_PER_GROUP(sb) >> 3;
32 	provided = le16_to_cpu(gdp->bg_inode_bitmap_csum_lo);
33 	calculated = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
34 	if (sbi->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END) {
35 		hi = le16_to_cpu(gdp->bg_inode_bitmap_csum_hi);
36 		provided |= (hi << 16);
37 	} else
38 		calculated &= 0xFFFF;
39 
40 	return provided == calculated;
41 }
42 
43 void ext4_inode_bitmap_csum_set(struct super_block *sb,
44 				struct ext4_group_desc *gdp,
45 				struct buffer_head *bh)
46 {
47 	__u32 csum;
48 	struct ext4_sb_info *sbi = EXT4_SB(sb);
49 	int sz;
50 
51 	if (!ext4_has_metadata_csum(sb))
52 		return;
53 
54 	sz = EXT4_INODES_PER_GROUP(sb) >> 3;
55 	csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
56 	gdp->bg_inode_bitmap_csum_lo = cpu_to_le16(csum & 0xFFFF);
57 	if (sbi->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
58 		gdp->bg_inode_bitmap_csum_hi = cpu_to_le16(csum >> 16);
59 }
60 
61 int ext4_block_bitmap_csum_verify(struct super_block *sb,
62 				  struct ext4_group_desc *gdp,
63 				  struct buffer_head *bh)
64 {
65 	__u32 hi;
66 	__u32 provided, calculated;
67 	struct ext4_sb_info *sbi = EXT4_SB(sb);
68 	int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
69 
70 	if (!ext4_has_metadata_csum(sb))
71 		return 1;
72 
73 	provided = le16_to_cpu(gdp->bg_block_bitmap_csum_lo);
74 	calculated = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
75 	if (sbi->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_END) {
76 		hi = le16_to_cpu(gdp->bg_block_bitmap_csum_hi);
77 		provided |= (hi << 16);
78 	} else
79 		calculated &= 0xFFFF;
80 
81 	return provided == calculated;
82 }
83 
84 void ext4_block_bitmap_csum_set(struct super_block *sb,
85 				struct ext4_group_desc *gdp,
86 				struct buffer_head *bh)
87 {
88 	int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
89 	__u32 csum;
90 	struct ext4_sb_info *sbi = EXT4_SB(sb);
91 
92 	if (!ext4_has_metadata_csum(sb))
93 		return;
94 
95 	csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
96 	gdp->bg_block_bitmap_csum_lo = cpu_to_le16(csum & 0xFFFF);
97 	if (sbi->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_END)
98 		gdp->bg_block_bitmap_csum_hi = cpu_to_le16(csum >> 16);
99 }
100