csum.c revision 39f5659ae3a0d9105ecddddfda2800b7002febc3
1ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos/*
2ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * csum.c --- checksumming of ext3 structures
3ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos *
4ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * Copyright (C) 2006 Cluster File Systems, Inc.
5470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o * Copyright (C) 2006, 2007 by Andreas Dilger <adilger@clusterfs.com>
6ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos *
7ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * %Begin-Header%
8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library
9543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2.
10ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * %End-Header%
11ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos */
12ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
13d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include "config.h"
140eeec8ac61bf1eaa31533b2be825cd75580829c9Theodore Ts'o#if HAVE_SYS_TYPES_H
150eeec8ac61bf1eaa31533b2be825cd75580829c9Theodore Ts'o#include <sys/types.h>
160eeec8ac61bf1eaa31533b2be825cd75580829c9Theodore Ts'o#endif
170eeec8ac61bf1eaa31533b2be825cd75580829c9Theodore Ts'o
18ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#include "ext2_fs.h"
19ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#include "ext2fs.h"
20ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#include "crc16.h"
21ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#include <assert.h>
22ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
23ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#ifndef offsetof
24ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
25ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#endif
26ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
27ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#ifdef DEBUG
28ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#define STATIC
29ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#else
30ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#define STATIC static
31ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#endif
32ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
3339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wongstatic errcode_t ext2fs_ext_attr_block_csum(ext2_filsys fs, ext2_ino_t inum,
3439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong					    blk64_t block,
3539f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong					    struct ext2_ext_attr_header *hdr,
3639f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong					    __u32 *crc)
3739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong{
3839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	errcode_t retval;
3939f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	char *buf = (char *)hdr;
4039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	__u32 gen, old_crc = hdr->h_checksum;
4139f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	struct ext2_inode inode;
4239f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong
4339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	hdr->h_checksum = 0;
4439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	block = ext2fs_cpu_to_le64(block);
4539f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	*crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&block,
4639f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong				sizeof(block));
4739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, fs->blocksize);
4839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	hdr->h_checksum = old_crc;
4939f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong
5039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	return 0;
5139f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong}
5239f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong
5339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wongint ext2fs_ext_attr_block_csum_verify(ext2_filsys fs, ext2_ino_t inum,
5439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong				      blk64_t block,
5539f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong				      struct ext2_ext_attr_header *hdr)
5639f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong{
5739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	__u32 calculated;
5839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	errcode_t retval;
5939f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong
6039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
6139f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
6239f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong		return 1;
6339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong
6439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	retval = ext2fs_ext_attr_block_csum(fs, inum, block, hdr, &calculated);
6539f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	if (retval)
6639f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong		return 0;
6739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong
6839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	return ext2fs_le32_to_cpu(hdr->h_checksum) == calculated;
6939f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong}
7039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong
7139f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wongerrcode_t ext2fs_ext_attr_block_csum_set(ext2_filsys fs, ext2_ino_t inum,
7239f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong					 blk64_t block,
7339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong					 struct ext2_ext_attr_header *hdr)
7439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong{
7539f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	errcode_t retval;
7639f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	__u32 crc;
7739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong
7839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
7939f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong		EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
8039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong		return 0;
8139f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong
8239f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	retval = ext2fs_ext_attr_block_csum(fs, inum, block, hdr, &crc);
8339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	if (retval)
8439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong		return retval;
8539f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	hdr->h_checksum = ext2fs_cpu_to_le32(crc);
8639f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong	return 0;
8739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong}
8839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong
89dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic __u16 do_nothing16(__u16 x)
90dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{
91dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	return x;
92dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong}
93dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
94dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic __u16 disk_to_host16(__u16 x)
95dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{
96dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	return ext2fs_le16_to_cpu(x);
97dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong}
98dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
99dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic errcode_t __get_dx_countlimit(ext2_filsys fs,
100dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong				     struct ext2_dir_entry *dirent,
101dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong				     struct ext2_dx_countlimit **cc,
102dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong				     int *offset,
103dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong				     int need_swab)
104dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{
105dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	struct ext2_dir_entry *dp;
106dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	struct ext2_dx_root_info *root;
107dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	struct ext2_dx_countlimit *c;
108dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	int count_offset, max_sane_entries;
109dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	unsigned int rec_len;
110dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	__u16 (*translate)(__u16) = (need_swab ? disk_to_host16 : do_nothing16);
111dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
112dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	rec_len = translate(dirent->rec_len);
113dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
114dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	if (rec_len == fs->blocksize && translate(dirent->name_len) == 0)
115dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		count_offset = 8;
116dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	else if (rec_len == 12) {
117dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		dp = (struct ext2_dir_entry *)(((void *)dirent) + rec_len);
118dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		rec_len = translate(dp->rec_len);
119dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		if (rec_len != fs->blocksize - 12)
120dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong			return EXT2_ET_DB_NOT_FOUND;
121dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		root = (struct ext2_dx_root_info *)(((void *)dp + 12));
122dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		if (root->reserved_zero ||
123dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		    root->info_length != sizeof(struct ext2_dx_root_info))
124dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong			return EXT2_ET_DB_NOT_FOUND;
125dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		count_offset = 32;
126dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	} else
127dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		return EXT2_ET_DB_NOT_FOUND;
128dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
129dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	c = (struct ext2_dx_countlimit *)(((void *)dirent) + count_offset);
130dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	max_sane_entries = (fs->blocksize - count_offset) /
131dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong			   sizeof(struct ext2_dx_entry);
132dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	if (ext2fs_le16_to_cpu(c->limit) > max_sane_entries ||
133dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	    ext2fs_le16_to_cpu(c->count) > max_sane_entries)
134dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		return EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
135dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
136dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	if (offset)
137dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		*offset = count_offset;
138dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	if (cc)
139dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		*cc = c;
140dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
141dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	return 0;
142dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong}
143dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
144dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongerrcode_t ext2fs_get_dx_countlimit(ext2_filsys fs,
145dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong				   struct ext2_dir_entry *dirent,
146dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong				   struct ext2_dx_countlimit **cc,
147dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong				   int *offset)
148dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{
149dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	return __get_dx_countlimit(fs, dirent, cc, offset, 0);
150dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong}
151dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
15281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongvoid ext2fs_initialize_dirent_tail(ext2_filsys fs,
15381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong				   struct ext2_dir_entry_tail *t)
15481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{
15581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	memset(t, 0, sizeof(struct ext2_dir_entry_tail));
15681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	ext2fs_set_rec_len(fs, sizeof(struct ext2_dir_entry_tail),
15781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong			   (struct ext2_dir_entry *)t);
15881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	t->det_reserved_name_len = EXT2_DIR_NAME_LEN_CSUM;
15981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong}
16081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
16181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongstatic errcode_t __get_dirent_tail(ext2_filsys fs,
16281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong				   struct ext2_dir_entry *dirent,
16381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong				   struct ext2_dir_entry_tail **tt,
16481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong				   int need_swab)
16581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{
16681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	struct ext2_dir_entry *d;
16781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	void *top;
16881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	struct ext2_dir_entry_tail *t;
16981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	unsigned int rec_len;
17081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	errcode_t retval = 0;
17181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	__u16 (*translate)(__u16) = (need_swab ? disk_to_host16 : do_nothing16);
17281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
17381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	d = dirent;
17481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	top = EXT2_DIRENT_TAIL(dirent, fs->blocksize);
17581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
17681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	rec_len = translate(d->rec_len);
17781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	while (rec_len && !(rec_len & 0x3)) {
17881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		d = (struct ext2_dir_entry *)(((void *)d) + rec_len);
17981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		if ((void *)d >= top)
18081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong			break;
18181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		rec_len = translate(d->rec_len);
18281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	}
18381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
18481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	if (d != top)
18581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		return EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
18681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
18781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	t = (struct ext2_dir_entry_tail *)d;
18881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	if (t->det_reserved_zero1 ||
18981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	    translate(t->det_rec_len) != sizeof(struct ext2_dir_entry_tail) ||
19081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	    translate(t->det_reserved_name_len) != EXT2_DIR_NAME_LEN_CSUM)
19181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		return EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
19281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
19381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	if (tt)
19481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		*tt = t;
19581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	return retval;
19681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong}
19781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
19881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongint ext2fs_dirent_has_tail(ext2_filsys fs, struct ext2_dir_entry *dirent)
19981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{
20081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	return __get_dirent_tail(fs, dirent, NULL, 0) == 0;
20181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong}
20281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
20381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongstatic errcode_t ext2fs_dirent_csum(ext2_filsys fs, ext2_ino_t inum,
20481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong				    struct ext2_dir_entry *dirent, __u32 *crc,
20581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong				    int size)
20681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{
20781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	errcode_t retval;
20881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	char *buf = (char *)dirent;
20981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	__u32 gen;
21081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	struct ext2_inode inode;
21181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
21281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	retval = ext2fs_read_inode(fs, inum, &inode);
21381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	if (retval)
21481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		return retval;
21581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
21681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	inum = ext2fs_cpu_to_le32(inum);
21781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	gen = ext2fs_cpu_to_le32(inode.i_generation);
21881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	*crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum,
21981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong				sizeof(inum));
22081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen));
22181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, size);
22281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
22381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	return 0;
22481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong}
22581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
22681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongint ext2fs_dirent_csum_verify(ext2_filsys fs, ext2_ino_t inum,
22781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong			      struct ext2_dir_entry *dirent)
22881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{
22981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	errcode_t retval;
23081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	__u32 calculated;
23181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	struct ext2_dir_entry_tail *t;
23281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
23381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	retval = __get_dirent_tail(fs, dirent, &t, 1);
23481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	if (retval)
23581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		return 1;
23681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
23781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	/*
23881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	 * The checksum field is overlaid with the dirent->name field
23981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	 * so the swapfs.c functions won't change the endianness.
24081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	 */
24181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	retval = ext2fs_dirent_csum(fs, inum, dirent, &calculated,
24281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong				    (void *)t - (void *)dirent);
24381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	if (retval)
24481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		return 0;
24581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	return ext2fs_le32_to_cpu(t->det_checksum) == calculated;
24681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong}
24781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
24881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongstatic errcode_t ext2fs_dirent_csum_set(ext2_filsys fs, ext2_ino_t inum,
24981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong					struct ext2_dir_entry *dirent)
25081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{
25181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	errcode_t retval;
25281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	__u32 crc;
25381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	struct ext2_dir_entry_tail *t;
25481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
25581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	retval = __get_dirent_tail(fs, dirent, &t, 1);
25681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	if (retval)
25781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		return retval;
25881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
25981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	/* swapfs.c functions don't change the checksum endianness */
26081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	retval = ext2fs_dirent_csum(fs, inum, dirent, &crc,
26181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong				    (void *)t - (void *)dirent);
26281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	if (retval)
26381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		return retval;
26481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	t->det_checksum = ext2fs_cpu_to_le32(crc);
26581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	return 0;
26681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong}
26781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
268dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum,
269dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong				struct ext2_dir_entry *dirent,
270dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong				__u32 *crc, int count_offset, int count,
271dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong				struct ext2_dx_tail *t)
272dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{
273dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	errcode_t retval;
274dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	char *buf = (char *)dirent;
275dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	int size;
276dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	__u32 old_csum, gen;
277dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	struct ext2_inode inode;
278dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
279dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	size = count_offset + (count * sizeof(struct ext2_dx_entry));
280dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	old_csum = t->dt_checksum;
281dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	t->dt_checksum = 0;
282dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
283dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	retval = ext2fs_read_inode(fs, inum, &inode);
284dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	if (retval)
285dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		return retval;
286dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
287dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	inum = ext2fs_cpu_to_le32(inum);
288dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	gen = ext2fs_cpu_to_le32(inode.i_generation);
289dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	*crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum,
290dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong				sizeof(inum));
291dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen));
292dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, size);
293dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)t,
294dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong				sizeof(struct ext2_dx_tail));
295dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	t->dt_checksum = old_csum;
296dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
297dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	return 0;
298dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong}
299dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
300dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic int ext2fs_dx_csum_verify(ext2_filsys fs, ext2_ino_t inum,
301dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong				 struct ext2_dir_entry *dirent)
302dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{
303dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	__u32 calculated;
304dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	errcode_t retval;
305dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	struct ext2_dx_countlimit *c;
306dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	struct ext2_dx_tail *t;
307dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	int count_offset, limit, count;
308dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
309dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1);
310dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	if (retval)
311dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		return 1;
312dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	limit = ext2fs_le16_to_cpu(c->limit);
313dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	count = ext2fs_le16_to_cpu(c->count);
314dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	if (count_offset + (limit * sizeof(struct ext2_dx_entry)) >
315dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	    fs->blocksize - sizeof(struct ext2_dx_tail))
316dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		return 0;
317dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	/* htree structs are accessed in LE order */
318dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit);
319dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	retval = ext2fs_dx_csum(fs, inum, dirent, &calculated, count_offset,
320dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong				count, t);
321dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	if (retval)
322dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		return 0;
323dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
324dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	return ext2fs_le32_to_cpu(t->dt_checksum) == calculated;
325dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong}
326dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
327dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic errcode_t ext2fs_dx_csum_set(ext2_filsys fs, ext2_ino_t inum,
328dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong				    struct ext2_dir_entry *dirent)
329dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{
330dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	__u32 crc;
331dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	errcode_t retval = 0;
332dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	struct ext2_dx_countlimit *c;
333dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	struct ext2_dx_tail *t;
334dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	int count_offset, limit, count;
335dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
336dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1);
337dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	if (retval)
338dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		return retval;
339dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	limit = ext2fs_le16_to_cpu(c->limit);
340dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	count = ext2fs_le16_to_cpu(c->count);
341dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	if (count_offset + (limit * sizeof(struct ext2_dx_entry)) >
342dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	    fs->blocksize - sizeof(struct ext2_dx_tail))
343dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		return EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
344dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit);
345dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
346dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	/* htree structs are accessed in LE order */
347dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	retval = ext2fs_dx_csum(fs, inum, dirent, &crc, count_offset, count, t);
348dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	if (retval)
349dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong		return retval;
350dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	t->dt_checksum = ext2fs_cpu_to_le32(crc);
351dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong	return retval;
352dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong}
353dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong
35481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongint ext2fs_dir_block_csum_verify(ext2_filsys fs, ext2_ino_t inum,
35581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong				 struct ext2_dir_entry *dirent)
35681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{
35781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
35881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
35981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		return 1;
36081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
36181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	if (__get_dirent_tail(fs, dirent, NULL, 1) == 0)
36281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		return ext2fs_dirent_csum_verify(fs, inum, dirent);
36381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	if (__get_dx_countlimit(fs, dirent, NULL, NULL, 1) == 0)
36481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		return ext2fs_dx_csum_verify(fs, inum, dirent);
36581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
36681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	return 0;
36781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong}
36881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
36981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongerrcode_t ext2fs_dir_block_csum_set(ext2_filsys fs, ext2_ino_t inum,
37081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong				    struct ext2_dir_entry *dirent)
37181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{
37281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
37381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
37481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		return 0;
37581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
37681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	if (__get_dirent_tail(fs, dirent, NULL, 1) == 0)
37781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		return ext2fs_dirent_csum_set(fs, inum, dirent);
37881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	if (__get_dx_countlimit(fs, dirent, NULL, NULL, 1) == 0)
37981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		return ext2fs_dx_csum_set(fs, inum, dirent);
38081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
38181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	if (fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS)
38281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong		return 0;
38381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong	return EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
38481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong}
38581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong
38641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong#define EXT3_EXTENT_TAIL_OFFSET(hdr)	(sizeof(struct ext3_extent_header) + \
38741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	(sizeof(struct ext3_extent) * ext2fs_le16_to_cpu((hdr)->eh_max)))
38841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong
38941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wongstatic struct ext3_extent_tail *get_extent_tail(struct ext3_extent_header *h)
39041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong{
39141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	return (struct ext3_extent_tail *)(((void *)h) +
39241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong					   EXT3_EXTENT_TAIL_OFFSET(h));
39341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong}
39441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong
39541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wongstatic errcode_t ext2fs_extent_block_csum(ext2_filsys fs, ext2_ino_t inum,
39641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong					  struct ext3_extent_header *eh,
39741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong					  __u32 *crc)
39841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong{
39941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	int size;
40041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	__u32 gen;
40141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	errcode_t retval;
40241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	struct ext2_inode inode;
40341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong
40441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	size = EXT3_EXTENT_TAIL_OFFSET(eh) + offsetof(struct ext3_extent_tail,
40541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong						      et_checksum);
40641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong
40741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	retval = ext2fs_read_inode(fs, inum, &inode);
40841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	if (retval)
40941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong		return retval;
41041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	inum = ext2fs_cpu_to_le32(inum);
41141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	gen = ext2fs_cpu_to_le32(inode.i_generation);
41241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	*crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum,
41341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong				sizeof(inum));
41441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen));
41541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)eh, size);
41641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong
41741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	return 0;
41841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong}
41941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong
42041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wongint ext2fs_extent_block_csum_verify(ext2_filsys fs, ext2_ino_t inum,
42141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong				    struct ext3_extent_header *eh)
42241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong{
42341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	errcode_t retval;
42441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	__u32 provided, calculated;
42541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	struct ext3_extent_tail *t = get_extent_tail(eh);
42641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong
42741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	/*
42841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	 * The extent tree structures are accessed in LE order, so we must
42941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	 * swap the checksum bytes here.
43041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	 */
43141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
43241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
43341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong		return 1;
43441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong
43541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	provided = ext2fs_le32_to_cpu(t->et_checksum);
43641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	retval = ext2fs_extent_block_csum(fs, inum, eh, &calculated);
43741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	if (retval)
43841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong		return 0;
43941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong
44041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	return provided == calculated;
44141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong}
44241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong
44341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wongerrcode_t ext2fs_extent_block_csum_set(ext2_filsys fs, ext2_ino_t inum,
44441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong				       struct ext3_extent_header *eh)
44541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong{
44641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	errcode_t retval;
44741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	__u32 crc;
44841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	struct ext3_extent_tail *t = get_extent_tail(eh);
44941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong
45041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
45141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
45241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong		return 0;
45341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong
45441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	/*
45541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	 * The extent tree structures are accessed in LE order, so we must
45641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	 * swap the checksum bytes here.
45741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	 */
45841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	retval = ext2fs_extent_block_csum(fs, inum, eh, &crc);
45941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	if (retval)
46041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong		return retval;
46141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	t->et_checksum = ext2fs_cpu_to_le32(crc);
46241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong	return retval;
46341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong}
46441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong
465a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wongint ext2fs_inode_bitmap_csum_verify(ext2_filsys fs, dgrp_t group,
466a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong				    char *bitmap, int size)
467a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong{
468a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong	struct ext4_group_desc *gdp = (struct ext4_group_desc *)
469a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong			ext2fs_group_desc(fs, fs->group_desc, group);
470a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong	__u32 provided, calculated;
471a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong
472a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
473a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
474a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong		return 1;
475a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong	provided = gdp->bg_inode_bitmap_csum_lo;
476a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong	calculated = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap,
477a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong				      size);
478a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong	if (fs->super->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
479a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong		provided |= (__u32)gdp->bg_inode_bitmap_csum_hi << 16;
480a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong	else
481a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong		calculated &= 0xFFFF;
482a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong
483a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong	return provided == calculated;
484a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong}
485a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong
486a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wongerrcode_t ext2fs_inode_bitmap_csum_set(ext2_filsys fs, dgrp_t group,
487a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong				       char *bitmap, int size)
488a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong{
489a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong	__u32 crc;
490a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong	struct ext4_group_desc *gdp = (struct ext4_group_desc *)
491a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong			ext2fs_group_desc(fs, fs->group_desc, group);
492a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong
493a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
494a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
495a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong		return 0;
496a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong
497a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong	crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, size);
498a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong	gdp->bg_inode_bitmap_csum_lo = crc & 0xFFFF;
499a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong	if (fs->super->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
500a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong		gdp->bg_inode_bitmap_csum_hi = crc >> 16;
501a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong
502a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong	return 0;
503a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong}
504a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong
505e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wongint ext2fs_block_bitmap_csum_verify(ext2_filsys fs, dgrp_t group,
506e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong				    char *bitmap, int size)
507e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong{
508e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong	struct ext4_group_desc *gdp = (struct ext4_group_desc *)
509e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong			ext2fs_group_desc(fs, fs->group_desc, group);
510e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong	__u32 provided, calculated;
511e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong
512e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
513e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
514e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong		return 1;
515e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong	provided = gdp->bg_block_bitmap_csum_lo;
516e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong	calculated = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap,
517e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong				      size);
518e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong	if (fs->super->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
519e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong		provided |= (__u32)gdp->bg_block_bitmap_csum_hi << 16;
520e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong	else
521e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong		calculated &= 0xFFFF;
522e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong
523e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong	return provided == calculated;
524e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong}
525e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong
526e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wongerrcode_t ext2fs_block_bitmap_csum_set(ext2_filsys fs, dgrp_t group,
527e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong				       char *bitmap, int size)
528e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong{
529e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong	__u32 crc;
530e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong	struct ext4_group_desc *gdp = (struct ext4_group_desc *)
531e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong			ext2fs_group_desc(fs, fs->group_desc, group);
532e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong
533e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
534e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
535e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong		return 0;
536e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong
537e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong	crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, size);
538e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong	gdp->bg_block_bitmap_csum_lo = crc & 0xFFFF;
539e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong	if (fs->super->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
540e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong		gdp->bg_block_bitmap_csum_hi = crc >> 16;
541e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong
542e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong	return 0;
543e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong}
544e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong
54537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wongstatic errcode_t ext2fs_inode_csum(ext2_filsys fs, ext2_ino_t inum,
54637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong			       struct ext2_inode_large *inode,
54737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong			       __u32 *crc, int has_hi)
54837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong{
54937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	__u32 gen;
55037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	struct ext2_inode_large *desc = inode;
55137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	size_t size = fs->super->s_inode_size;
55237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	__u16 old_lo;
55337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	__u16 old_hi = 0;
55437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong
55537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	old_lo = inode->i_checksum_lo;
55637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	inode->i_checksum_lo = 0;
55737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	if (has_hi) {
55837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong		old_hi = inode->i_checksum_hi;
55937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong		inode->i_checksum_hi = 0;
56037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	}
56137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong
56237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	inum = ext2fs_cpu_to_le32(inum);
56337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	gen = inode->i_generation;
56437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	*crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum,
56537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong				sizeof(inum));
56637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen));
56737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)desc, size);
56837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong
56937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	inode->i_checksum_lo = old_lo;
57037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	if (has_hi)
57137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong		inode->i_checksum_hi = old_hi;
57237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	return 0;
57337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong}
57437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong
57537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wongint ext2fs_inode_csum_verify(ext2_filsys fs, ext2_ino_t inum,
57637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong			     struct ext2_inode_large *inode)
57737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong{
57837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	errcode_t retval;
57937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	__u32 provided, calculated;
58037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	int has_hi;
58137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong
58237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	if (fs->super->s_creator_os != EXT2_OS_LINUX ||
58337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	    !EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
58437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
58537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong		return 1;
58637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong
58737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	has_hi = (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE &&
58837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong		  inode->i_extra_isize >= EXT4_INODE_CSUM_HI_EXTRA_END);
58937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong
59037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	provided = ext2fs_le16_to_cpu(inode->i_checksum_lo);
59137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	retval = ext2fs_inode_csum(fs, inum, inode, &calculated, has_hi);
59237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	if (retval)
59337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong		return 0;
59437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	if (has_hi) {
59537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong		__u32 hi = ext2fs_le16_to_cpu(inode->i_checksum_hi);
59637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong		provided |= hi << 16;
59737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	} else
59837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong		calculated &= 0xFFFF;
59937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong
60037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	return provided == calculated;
60137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong}
60237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong
60337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wongerrcode_t ext2fs_inode_csum_set(ext2_filsys fs, ext2_ino_t inum,
60437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong			   struct ext2_inode_large *inode)
60537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong{
60637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	errcode_t retval;
60737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	__u32 crc;
60837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	int has_hi;
60937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong
61037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	if (fs->super->s_creator_os != EXT2_OS_LINUX ||
61137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	    !EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
61237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
61337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong		return 0;
61437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong
61537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	has_hi = (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE &&
61637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong		  inode->i_extra_isize >= EXT4_INODE_CSUM_HI_EXTRA_END);
61737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong
61837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	retval = ext2fs_inode_csum(fs, inum, inode, &crc, has_hi);
61937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	if (retval)
62037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong		return retval;
62137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	inode->i_checksum_lo = ext2fs_cpu_to_le16(crc & 0xFFFF);
62237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	if (has_hi)
62337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong		inode->i_checksum_hi = ext2fs_cpu_to_le16(crc >> 16);
62437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong	return 0;
62537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong}
62637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong
62787141781aabb4dc01359428d2feecdc7f43eeac0Theodore Ts'o__u16 ext2fs_group_desc_csum(ext2_filsys fs, dgrp_t group)
628ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{
629ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	__u16 crc = 0;
630ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	struct ext2_group_desc *desc;
6311d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	size_t size;
6321d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o
6331d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	size = fs->super->s_desc_size;
6341d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	if (size < EXT2_MIN_DESC_SIZE)
6351d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o		size = EXT2_MIN_DESC_SIZE;
6361d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	if (size > sizeof(struct ext4_group_desc)) {
637f3ce48a4b6e6a030fa4481532ba04c1a966173bbTheodore Ts'o		/* This should never happen, but cap it for safety's sake */
6381d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o		size = sizeof(struct ext4_group_desc);
6391d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	}
640ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
641d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson	desc = ext2fs_group_desc(fs, fs->group_desc, group);
642ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
643ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
644d32c915abfb224f6f6659e9cada7e9f759b7e3d2Theodore Ts'o		size_t offset = offsetof(struct ext2_group_desc, bg_checksum);
645ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
646ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#ifdef WORDS_BIGENDIAN
6471d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o		struct ext4_group_desc swabdesc;
648ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
649ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos		/* Have to swab back to little-endian to do the checksum */
6501d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o		memcpy(&swabdesc, desc, size);
6511d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o		ext2fs_swap_group_desc2(fs,
6521d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o					(struct ext2_group_desc *) &swabdesc);
6531d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o		desc = (struct ext2_group_desc *) &swabdesc;
654ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
655ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos		group = ext2fs_swab32(group);
656ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#endif
657c4dcb1c10ae5e3d523823fe0a2c84d0841ca2ea1Theodore Ts'o		crc = ext2fs_crc16(~0, fs->super->s_uuid,
658c4dcb1c10ae5e3d523823fe0a2c84d0841ca2ea1Theodore Ts'o				   sizeof(fs->super->s_uuid));
659c4dcb1c10ae5e3d523823fe0a2c84d0841ca2ea1Theodore Ts'o		crc = ext2fs_crc16(crc, &group, sizeof(group));
660c4dcb1c10ae5e3d523823fe0a2c84d0841ca2ea1Theodore Ts'o		crc = ext2fs_crc16(crc, desc, offset);
661ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos		offset += sizeof(desc->bg_checksum); /* skip checksum */
662ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos		/* for checksum of struct ext4_group_desc do the rest...*/
6631d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o		if (offset < size) {
664c4dcb1c10ae5e3d523823fe0a2c84d0841ca2ea1Theodore Ts'o			crc = ext2fs_crc16(crc, (char *)desc + offset,
6651d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o					   size - offset);
666ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos		}
667ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	}
668ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
669ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	return crc;
670ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos}
671ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
672ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santosint ext2fs_group_desc_csum_verify(ext2_filsys fs, dgrp_t group)
673ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{
6744729455f0a68f2fa0a83ec8460d1d4bccba9dcfaTheodore Ts'o	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
6754729455f0a68f2fa0a83ec8460d1d4bccba9dcfaTheodore Ts'o				       EXT4_FEATURE_RO_COMPAT_GDT_CSUM) &&
676d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson	    (ext2fs_bg_checksum(fs, group) !=
6774729455f0a68f2fa0a83ec8460d1d4bccba9dcfaTheodore Ts'o	     ext2fs_group_desc_csum(fs, group)))
678ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos		return 0;
679ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
680ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	return 1;
681ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos}
682ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
683ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santosvoid ext2fs_group_desc_csum_set(ext2_filsys fs, dgrp_t group)
684ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{
685d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
686d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson					EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
687d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson		return;
688d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson
689d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson	/* ext2fs_bg_checksum_set() sets the actual checksum field but
690d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson	 * does not calculate the checksum itself. */
691d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson	ext2fs_bg_checksum_set(fs, group, ext2fs_group_desc_csum(fs, group));
692ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos}
693ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
694ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santosstatic __u32 find_last_inode_ingrp(ext2fs_inode_bitmap bitmap,
695ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos				   __u32 inodes_per_grp, dgrp_t grp_no)
696ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{
697ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	ext2_ino_t i, start_ino, end_ino;
698ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
699ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	start_ino = grp_no * inodes_per_grp + 1;
700ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	end_ino = start_ino + inodes_per_grp - 1;
701ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
702ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	for (i = end_ino; i >= start_ino; i--) {
7038f82ef9860339039b54a324be137fbc09b762358Valerie Aurora Henson		if (ext2fs_fast_test_inode_bitmap2(bitmap, i))
704ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos			return i - start_ino + 1;
705ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	}
706ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	return inodes_per_grp;
707ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos}
708ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
709ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos/* update the bitmap flags, set the itable high watermark, and calculate
710ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * checksums for the group descriptors */
711f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilgererrcode_t ext2fs_set_gdt_csum(ext2_filsys fs)
712ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{
713ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	struct ext2_super_block *sb = fs->super;
7148895f43a60269464f654e9d87c28768875cd703aTheodore Ts'o	int dirty = 0;
715ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	dgrp_t i;
716ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
717f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilger	if (!fs->inode_map)
718f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilger		return EXT2_ET_NO_INODE_BITMAP;
719f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilger
72016b851cdae98244e117fe91d93b267fcad1102b3Theodore Ts'o	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
72116b851cdae98244e117fe91d93b267fcad1102b3Theodore Ts'o					EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
722f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilger		return 0;
723ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
724d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson	for (i = 0; i < fs->group_desc_count; i++) {
725d32c915abfb224f6f6659e9cada7e9f759b7e3d2Theodore Ts'o		__u32 old_csum = ext2fs_bg_checksum(fs, i);
726d32c915abfb224f6f6659e9cada7e9f759b7e3d2Theodore Ts'o		__u32 old_unused = ext2fs_bg_itable_unused(fs, i);
727d32c915abfb224f6f6659e9cada7e9f759b7e3d2Theodore Ts'o		__u32 old_flags = ext2fs_bg_flags(fs, i);
728d32c915abfb224f6f6659e9cada7e9f759b7e3d2Theodore Ts'o		__u32 old_free_inodes_count = ext2fs_bg_free_inodes_count(fs, i);
729ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
730d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson		if (old_free_inodes_count == sb->s_inodes_per_group) {
731d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson			ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
732d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson			ext2fs_bg_itable_unused_set(fs, i, sb->s_inodes_per_group);
73316b851cdae98244e117fe91d93b267fcad1102b3Theodore Ts'o		} else {
734d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson			int unused =
735d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson				sb->s_inodes_per_group -
736ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos				find_last_inode_ingrp(fs->inode_map,
737d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson						      sb->s_inodes_per_group, i);
738d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson
739d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson			ext2fs_bg_flags_clear(fs, i, EXT2_BG_INODE_UNINIT);
740d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson			ext2fs_bg_itable_unused_set(fs, i, unused);
741ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos		}
742ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos
743ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos		ext2fs_group_desc_csum_set(fs, i);
744d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson		if (old_flags != ext2fs_bg_flags(fs, i))
74580fc4e698a308de22ace6179f45e0bb67befa74bAndreas Dilger			dirty = 1;
746d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson		if (old_unused != ext2fs_bg_itable_unused(fs, i))
74780fc4e698a308de22ace6179f45e0bb67befa74bAndreas Dilger			dirty = 1;
748d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson		if (old_csum != ext2fs_bg_checksum(fs, i))
749ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos			dirty = 1;
750ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	}
751ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos	if (dirty)
752ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos		ext2fs_mark_super_dirty(fs);
753f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilger	return 0;
754ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos}
755470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o
756470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o#ifdef DEBUG
757c816ecb204a32e67788738e050ff2b14a721672bEric Sandeen#include "e2p/e2p.h"
758c816ecb204a32e67788738e050ff2b14a721672bEric Sandeen
759470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'ovoid print_csum(const char *msg, ext2_filsys fs, dgrp_t group)
760470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o{
761470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	__u16 crc1, crc2, crc3;
762470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	dgrp_t swabgroup;
763cf828f1a72ec1eb0c1e819307137879447c909b7Theodore Ts'o 	struct ext2_group_desc *desc = ext2fs_group_desc(fs, fs->group_desc, group);
7641d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	size_t size;
765470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	struct ext2_super_block *sb = fs->super;
7661d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	int offset = offsetof(struct ext2_group_desc, bg_checksum);
767470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o#ifdef WORDS_BIGENDIAN
7681d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	struct ext4_group_desc swabdesc;
7691d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o#endif
770470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o
7711d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	size = fs->super->s_desc_size;
7721d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	if (size < EXT2_MIN_DESC_SIZE)
7731d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o		size = EXT2_MIN_DESC_SIZE;
7741d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	if (size > sizeof(struct ext4_group_desc))
7751d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o		size = sizeof(struct ext4_group_desc);
7761d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o#ifdef WORDS_BIGENDIAN
777470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	/* Have to swab back to little-endian to do the checksum */
7781d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	memcpy(&swabdesc, desc, size);
7791d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	ext2fs_swap_group_desc2(fs, (struct ext2_group_desc *) &swabdesc);
7801d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	desc = (struct ext2_group_desc *) &swabdesc;
781470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o
782470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	swabgroup = ext2fs_swab32(group);
783470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o#else
784470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	swabgroup = group;
785470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o#endif
786470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o
787470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	crc1 = ext2fs_crc16(~0, sb->s_uuid, sizeof(fs->super->s_uuid));
788470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	crc2 = ext2fs_crc16(crc1, &swabgroup, sizeof(swabgroup));
7891d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	crc3 = ext2fs_crc16(crc2, desc, offset);
7901d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	offset += sizeof(desc->bg_checksum); /* skip checksum */
7911d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	/* for checksum of struct ext4_group_desc do the rest...*/
7921d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o	if (offset < size)
7931d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o		crc3 = ext2fs_crc16(crc3, (char *)desc + offset, size - offset);
7941d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o
795c816ecb204a32e67788738e050ff2b14a721672bEric Sandeen	printf("%s: UUID %s(%04x), grp %u(%04x): %04x=%04x\n",
796562f264243f4d4385910b6f06872730214977736Theodore Ts'o	       msg, e2p_uuid2str(sb->s_uuid), crc1, group, crc2, crc3,
797c816ecb204a32e67788738e050ff2b14a721672bEric Sandeen	       ext2fs_group_desc_csum(fs, group));
798470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o}
799470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o
800470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'ounsigned char sb_uuid[16] = { 0x4f, 0x25, 0xe8, 0xcf, 0xe7, 0x97, 0x48, 0x23,
801470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o			      0xbe, 0xfa, 0xa7, 0x88, 0x4b, 0xae, 0xec, 0xdb };
802470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o
803470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'oint main(int argc, char **argv)
804470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o{
805470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	struct ext2_super_block param;
806470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	errcode_t		retval;
807470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	ext2_filsys		fs;
808470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	int			i;
809470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	__u16 csum1, csum2, csum_known = 0xd3a4;
810470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o
811470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	memset(&param, 0, sizeof(param));
8124efbac6fed75c29d3d5f1b676b932754653a2ac5Valerie Aurora Henson	ext2fs_blocks_count_set(&param, 32768);
813470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o
8148f82ef9860339039b54a324be137fbc09b762358Valerie Aurora Henson	retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, &param,
815470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o				   test_io_manager, &fs);
816470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	if (retval) {
817470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		com_err("setup", retval,
818470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o			"While initializing filesystem");
819470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		exit(1);
820470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	}
821470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	memcpy(fs->super->s_uuid, sb_uuid, 16);
822470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	fs->super->s_feature_ro_compat = EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
823470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o
824470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	for (i=0; i < fs->group_desc_count; i++) {
825d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson		ext2fs_block_bitmap_loc_set(fs, i, 124);
826d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson		ext2fs_inode_bitmap_loc_set(fs, i, 125);
827d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson		ext2fs_inode_table_loc_set(fs, i, 126);
828d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson		ext2fs_bg_free_blocks_count_set(fs, i, 31119);
829d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson		ext2fs_bg_free_inodes_count_set(fs, i, 15701);
830d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson		ext2fs_bg_used_dirs_count_set(fs, i, 2);
831e633b58ac75f2f544b7d6572e37d4b63da31e59cEric Sandeen		ext2fs_bg_flags_zap(fs, i);
832470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	};
833470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o
834470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	csum1 = ext2fs_group_desc_csum(fs, 0);
835470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	print_csum("csum0000", fs, 0);
836470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o
837470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	if (csum1 != csum_known) {
838470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		printf("checksum for group 0 should be %04x\n", csum_known);
839470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		exit(1);
840470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	}
841470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	csum2 = ext2fs_group_desc_csum(fs, 1);
842470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	print_csum("csum0001", fs, 1);
843470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	if (csum1 == csum2) {
844470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		printf("checksums for different groups shouldn't match\n");
845470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		exit(1);
846470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	}
847470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	csum2 = ext2fs_group_desc_csum(fs, 2);
848470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	print_csum("csumffff", fs, 2);
849470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	if (csum1 == csum2) {
850470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		printf("checksums for different groups shouldn't match\n");
851470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		exit(1);
852470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	}
853d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson	ext2fs_bg_checksum_set(fs, 0, csum1);
854470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	csum2 = ext2fs_group_desc_csum(fs, 0);
855470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	print_csum("csum_set", fs, 0);
856470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	if (csum1 != csum2) {
857470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		printf("checksums should not depend on checksum field\n");
858470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		exit(1);
859470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	}
860470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	if (!ext2fs_group_desc_csum_verify(fs, 0)) {
861470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		printf("checksums should verify against gd_checksum\n");
862470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		exit(1);
863470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	}
864470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	memset(fs->super->s_uuid, 0x30, sizeof(fs->super->s_uuid));
865470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	print_csum("new_uuid", fs, 0);
866470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	if (ext2fs_group_desc_csum_verify(fs, 0) != 0) {
867470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		printf("checksums for different filesystems shouldn't match\n");
868470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		exit(1);
869470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	}
870d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson	csum1 = ext2fs_group_desc_csum(fs, 0);
871d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson	ext2fs_bg_checksum_set(fs, 0, csum1);
872470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	print_csum("csum_new", fs, 0);
873d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson	ext2fs_bg_free_blocks_count_set(fs, 0, 1);
874470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	csum2 = ext2fs_group_desc_csum(fs, 0);
875470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	print_csum("csum_blk", fs, 0);
876470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	if (csum1 == csum2) {
877470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		printf("checksums for different data shouldn't match\n");
878470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o		exit(1);
879470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	}
880470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o
881470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o	return 0;
882470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o}
883470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o#endif
884