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(¶m, 0, sizeof(param)); 8124efbac6fed75c29d3d5f1b676b932754653a2ac5Valerie Aurora Henson ext2fs_blocks_count_set(¶m, 32768); 813470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 8148f82ef9860339039b54a324be137fbc09b762358Valerie Aurora Henson retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, ¶m, 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