Add support for the half-MD4 HTREE hash.

Add HTREE root node tests.
bitmap-optimize
Theodore Ts'o 2002-06-26 16:52:10 -04:00
parent 8fdc9985c1
commit 503f9e7f6e
18 changed files with 375 additions and 47 deletions

View File

@ -1,3 +1,8 @@
2002-06-26 Theodore Ts'o <tytso@mit.edu>
* htree.c (do_dx_hash): Use new ext2fs_dirhash function signature.
Add getopt support so user can specify the hash version.
2002-05-11 <tytso@snap.thunk.org>
* debug_cmds.ct, debugfs.c (do_bmap): Add new command "bmap" which

View File

@ -31,6 +31,7 @@ static FILE *pager;
static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
struct ext2_dx_root_info * root,
blk_t blk, char *buf)
{
errcode_t errcode;
@ -68,7 +69,9 @@ static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino,
(dirent->name_len & 0xFF) : EXT2_NAME_LEN;
strncpy(name, dirent->name, thislen);
name[thislen] = '\0';
errcode = ext2fs_dirhash(0, name, thislen, &hash);
errcode = ext2fs_dirhash(root->hash_version, name, thislen,
fs->super->s_hash_seed,
&hash, 0);
if (errcode)
com_err("htree_dump_leaf_node", errcode,
"while calculating hash");
@ -89,11 +92,13 @@ static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino,
static void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
struct ext2_dx_root_info * root,
blk_t blk, char *buf, int level);
static void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
struct ext2_dx_root_info * root,
struct ext2_dx_entry *ent,
char *buf, int level)
{
@ -115,10 +120,10 @@ static void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino,
fprintf(pager, "Entry #%d: Hash 0x%08x, block %d\n", i,
i ? ent[i].hash : 0, ent[i].block);
if (level)
htree_dump_int_block(fs, ino, inode,
htree_dump_int_block(fs, ino, inode, root,
ent[i].block, buf, level-1);
else
htree_dump_leaf_node(fs, ino, inode,
htree_dump_leaf_node(fs, ino, inode, root,
ent[i].block, buf);
}
@ -127,6 +132,7 @@ static void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino,
static void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
struct ext2_dx_root_info * root,
blk_t blk, char *buf, int level)
{
char *cbuf;
@ -153,7 +159,8 @@ static void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino,
return;
}
htree_dump_int_node(fs, ino, inode, (struct ext2_dx_entry *) (buf+8),
htree_dump_int_node(fs, ino, inode, root,
(struct ext2_dx_entry *) (buf+8),
cbuf, level);
free(cbuf);
}
@ -241,7 +248,7 @@ void do_htree_dump(int argc, char *argv[])
ent = (struct ext2_dx_entry *) (buf + 24 + root->info_length);
limit = (struct ext2_dx_countlimit *) ent;
htree_dump_int_node(current_fs, ino, &inode, ent,
htree_dump_int_node(current_fs, ino, &inode, root, ent,
buf + current_fs->blocksize,
root->indirect_levels);
@ -256,19 +263,36 @@ errout:
*/
void do_dx_hash(int argc, char *argv[])
{
ext2_dirhash_t hash;
ext2_dirhash_t hash, minor_hash;
errcode_t err;
int c;
int hash_version = 0;
__u32 hash_seed[4];
if (argc != 2) {
hash_seed[0] = hash_seed[1] = hash_seed[2] = hash_seed[3] = 0;
optind = 0;
#ifdef HAVE_OPTRESET
optreset = 1; /* Makes BSD getopt happy */
#endif
while ((c = getopt (argc, argv, "h:")) != EOF) {
switch (c) {
case 'h':
hash_version = atoi(optarg);
break;
}
}
if (optind != argc-1) {
com_err(argv[0], 0, "usage: dx_hash filename");
return;
}
err = ext2fs_dirhash(0, argv[1], strlen(argv[1]), &hash);
err = ext2fs_dirhash(hash_version, argv[optind], strlen(argv[optind]),
hash_seed, &hash, &minor_hash);
if (err) {
com_err(argv[0], err, "while caclulating hash");
return;
}
printf("Hash of %s is 0x%0x\n", argv[1], hash);
printf("Hash of %s is 0x%0x (minor 0x%0x)\n", argv[optind],
hash, minor_hash);
}
/*

View File

@ -1,3 +1,23 @@
2002-06-26 Theodore Ts'o <tytso@mit.edu>
* pass1.c (check_blocks): Move htree handling to handle_htree().
Factor out calls to ext2fs_write_inode so that it happens
if dirty_inode is non-zero.
(handle_htree): Add checks for invalid htree root, invalid
hash version, invalid hash version, and htree depth too deep.
* problem.h, problem.c (PR_1_HTREE_NODIR, PR_1_HTREE_BADROOT,
PR_1_HTREE_HASHV, PR_1_HTREE_INCOMPAT, PR_1_HTREE_DEPTH):
Add new problem codes.
* pass2.c (parse_int_node): Fix silly typo.
(check_dir_block): Change to use new ext2fs_dirhash()
function prototype.
(pass2): Fixed two minor bugs discovered by the test case:
Don't stop checking dxdir's after clearing a bad inode.
If there is a bad max hash, make sure the bad_dir flag
is set to make sure we try to clear inode.
2002-06-25 Theodore Ts'o <tytso@mit.edu>
* e2fsck.c (e2fsck_reset_context): Free the dx_dirinfo structure.

View File

@ -1132,6 +1132,57 @@ clear_extattr:
return 0;
}
/* Returns 1 if bad htree, 0 if OK */
static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
ext2_ino_t ino, struct ext2_inode *inode,
char *block_buf)
{
struct ext2_dx_root_info *root;
ext2_filsys fs = ctx->fs;
errcode_t retval;
blk_t blk;
if ((!LINUX_S_ISDIR(inode->i_mode) &&
fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
(!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
fix_problem(ctx, PR_1_HTREE_SET, pctx)))
return 1;
blk = inode->i_block[0];
if (((blk == 0) ||
(blk < fs->super->s_first_data_block) ||
(blk >= fs->super->s_blocks_count)) &&
fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
return 1;
retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
return 1;
/* XXX should check that beginning matches a directory */
root = (struct ext2_dx_root_info *) (block_buf + 24);
if ((root->reserved_zero || root->info_length < 8) &&
fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
return 1;
pctx->num = root->hash_version;
if ((root->hash_version != EXT2_HASH_LEGACY) &&
(root->hash_version != EXT2_HASH_HALF_MD4) &&
fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
return 1;
if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
return 1;
pctx->num = root->indirect_levels;
if ((root->indirect_levels > 1) &&
fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
return 1;
return 0;
}
/*
* This subroutine is called on each inode to account for all of the
@ -1145,6 +1196,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
ext2_ino_t ino = pctx->ino;
struct ext2_inode *inode = pctx->inode;
int bad_size = 0;
int dirty_inode = 0;
__u64 size;
if (!ext2fs_inode_has_valid_blocks(inode))
@ -1172,8 +1224,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
else {
if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
inode->i_flags &= ~EXT2_COMPRBLK_FL;
e2fsck_write_inode(ctx, ino, inode,
"check_blocks");
dirty_inode++;
}
}
}
@ -1182,7 +1233,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
pb.is_dir ? BLOCK_FLAG_HOLE : 0,
block_buf, process_block, &pb);
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
return;
goto out;
end_problem_latch(ctx, PR_LATCH_BLOCK);
end_problem_latch(ctx, PR_LATCH_TOOBIG);
if (pctx->errcode)
@ -1192,11 +1243,10 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
ctx->fs_fragmented++;
if (pb.clear) {
e2fsck_read_inode(ctx, ino, inode, "check_blocks");
inode->i_links_count = 0;
ext2fs_icount_store(ctx->inode_link_info, ino, 0);
inode->i_dtime = time(0);
e2fsck_write_inode(ctx, ino, inode, "check_blocks");
dirty_inode++;
ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
@ -1206,24 +1256,20 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
* restart the pass 1 scan.
*/
ctx->flags |= E2F_FLAG_RESTART;
return;
goto out;
}
if (inode->i_flags & EXT2_INDEX_FL) {
if (fs->super->s_feature_compat &
EXT2_FEATURE_COMPAT_DIR_INDEX) {
if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
inode->i_flags &= ~EXT2_INDEX_FL;
dirty_inode++;
} else {
#ifdef ENABLE_HTREE
e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
#endif
} else {
if (fix_problem(ctx, PR_1_HTREE_SET, pctx)) {
inode->i_flags &= ~EXT2_INDEX_FL;
e2fsck_write_inode(ctx, ino, inode,
"check_blocks");
}
}
}
}
if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
pb.num_blocks++;
@ -1238,7 +1284,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
inode->i_links_count = 0;
ext2fs_icount_store(ctx->inode_link_info, ino, 0);
inode->i_dtime = time(0);
e2fsck_write_inode(ctx, ino, inode, "check_blocks");
dirty_inode++;
ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
@ -1270,7 +1316,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
inode->i_size = pctx->num;
if (LINUX_S_ISREG(inode->i_mode))
inode->i_size_high = pctx->num >> 32;
e2fsck_write_inode(ctx, ino, inode, "check_blocks");
dirty_inode++;
}
pctx->num = 0;
}
@ -1281,10 +1327,13 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
pctx->num = pb.num_blocks;
if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
inode->i_blocks = pb.num_blocks;
e2fsck_write_inode(ctx, ino, inode, "check_blocks");
dirty_inode++;
}
pctx->num = 0;
}
out:
if (dirty_inode)
e2fsck_write_inode(ctx, ino, inode, "check_blocks");
}
#if 0
@ -1422,8 +1471,8 @@ static int process_block(ext2_filsys fs,
p->fragmented = 1;
}
p->previous_block = blk;
if (p->is_dir && blockcnt > 2*1024*1024/fs->blocksize)
if (p->is_dir && blockcnt > (1 << (15 - fs->super->s_log_block_size)))
problem = PR_1_TOOBIG_DIR;
if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
problem = PR_1_TOOBIG_REG;

View File

@ -205,6 +205,7 @@ void e2fsck_pass2(e2fsck_t ctx)
pctx.blk2 = dx_db->node_max_hash;
code = PR_2_HTREE_MAX_HASH;
fix_problem(ctx, code, &pctx);
bad_dir++;
}
if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
code = PR_2_HTREE_NOTREF;
@ -221,7 +222,6 @@ void e2fsck_pass2(e2fsck_t ctx)
if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
clear_htree(ctx, dx_dir->ino);
dx_dir->ino = 0;
break;
}
#ifdef ENABLE_HTREE_CLEAR
if (dx_dir->ino) {
@ -501,7 +501,7 @@ static void parse_int_node(ext2_filsys fs,
/* Check to make sure the block is valid */
if (blk > dx_dir->numblocks) {
if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
cd->pctx)) {
&cd->pctx)) {
clear_htree(cd->ctx, cd->pctx.ino);
dx_dir->ino = 0;
return;
@ -781,7 +781,8 @@ static int check_dir_block(ext2_filsys fs,
#ifdef ENABLE_HTREE
if (dx_db) {
ext2fs_dirhash(dx_dir->hashversion, dirent->name,
(dirent->name_len & 0xFF), &hash);
(dirent->name_len & 0xFF),
fs->super->s_hash_seed, &hash, 0);
if (hash < dx_db->min_hash)
dx_db->min_hash = hash;
if (hash > dx_db->max_hash)

View File

@ -38,7 +38,8 @@
#define PROMPT_DELETE 15
#define PROMPT_SUPPRESS 16
#define PROMPT_UNLINK 17
#define PROMPT_NULL 18
#define PROMPT_CLEAR_HTREE 18
#define PROMPT_NULL 19
/*
* These are the prompts which are used to ask the user if they want
@ -63,7 +64,8 @@ static const char *prompt[] = {
N_("Delete file"), /* 15 */
N_("Suppress messages"),/* 16 */
N_("Unlink"), /* 17 */
"", /* 18 */
N_("Clear HTree index"),/* 18 */
"", /* 19 */
};
/*
@ -89,7 +91,8 @@ static const char *preen_msg[] = {
N_("FILE DELETED"), /* 15 */
N_("SUPPRESSED"), /* 16 */
N_("UNLINKED"), /* 17 */
"", /* 18 */
N_("HTREE INDEX CLEARED"),/* 18 */
"", /* 19 */
};
static const struct e2fsck_problem problem_table[] = {
@ -668,8 +671,33 @@ static const struct e2fsck_problem problem_table[] = {
/* INDEX_FL flag set on a non-HTREE filesystem */
{ PR_1_HTREE_SET,
N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
PROMPT_CLEAR, 0 },
PROMPT_CLEAR_HTREE, 0 },
/* INDEX_FL flag set on a non-directory */
{ PR_1_HTREE_NODIR,
N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
PROMPT_CLEAR_HTREE, 0 },
/* Invalid root node in HTREE directory */
{ PR_1_HTREE_BADROOT,
N_("@h %i has an invalid root node.\n"),
PROMPT_CLEAR_HTREE, 0 },
/* Unsupported hash version in HTREE directory */
{ PR_1_HTREE_HASHV,
N_("@h %i has an unsupported hash version (%N)\n"),
PROMPT_CLEAR_HTREE, 0 },
/* Incompatible flag in HTREE root node */
{ PR_1_HTREE_INCOMPAT,
N_("@h %i uses an incompatible htree root node flag.\n"),
PROMPT_CLEAR_HTREE, 0 },
/* HTREE too deep */
{ PR_1_HTREE_DEPTH,
N_("@h %i has a tree depth (%N) which is too big\n"),
PROMPT_CLEAR_HTREE, 0 },
/* Pass 1b errors */
/* Pass 1B: Rescan for duplicate/bad blocks */
@ -1021,7 +1049,7 @@ static const struct e2fsck_problem problem_table[] = {
/* Bad block in htree interior node */
{ PR_2_HTREE_BADBLK,
N_("@p @h %d (%q): bad @b number %B.\n"),
PROMPT_CLEAR, 0 },
PROMPT_CLEAR_HTREE, 0 },
/* Pass 3 errors */

View File

@ -388,6 +388,21 @@ struct problem_context {
/* INDEX_FL flag set on a non-HTREE filesystem */
#define PR_1_HTREE_SET 0x010047
/* INDEX_FL flag set on a non-directory */
#define PR_1_HTREE_NODIR 0x010048
/* Invalid root node in HTREE directory */
#define PR_1_HTREE_BADROOT 0x010049
/* Unsupported hash version in HTREE directory */
#define PR_1_HTREE_HASHV 0x01004A
/* Incompatible flag in HTREE root node */
#define PR_1_HTREE_INCOMPAT 0x01004B
/* HTREE too deep */
#define PR_1_HTREE_DEPTH 0x01004C
/*
* Pass 1b errors
*/

View File

@ -1,3 +1,10 @@
2002-06-26 Theodore Ts'o <tytso@mit.edu>
* dirhash.c (ext2fs_dirhash): Change function signature to support
a hash seed, and to return the minor hash (for 64-bit hash
support). Add support for the half MD4, half MD4 with
seed, and half MD4 with seed and 64 bits.
2002-06-15 Theodore Ts'o <tytso@mit.edu>
* ext2_fs.h (EXT2_DIRSYNC_FL): Add new file.

View File

@ -16,6 +16,78 @@
#include "ext2_fs.h"
#include "ext2fs.h"
/* F, G and H are basic MD4 functions: selection, majority, parity */
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
/*
* The generic round function. The application is so specific that
* we don't bother protecting all the arguments with parens, as is generally
* good macro practice, in favor of extra legibility.
* Rotation is separate from addition to prevent recomputation
*/
#define ROUND(f, a, b, c, d, x, s) \
(a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))
#define K1 0
#define K2 013240474631UL
#define K3 015666365641UL
/*
* Basic cut-down MD4 transform. Returns only 32 bits of result.
*/
static __u32 halfMD4Transform (__u32 buf[4], __u32 const in[])
{
__u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
/* Round 1 */
ROUND(F, a, b, c, d, in[0] + K1, 3);
ROUND(F, d, a, b, c, in[1] + K1, 7);
ROUND(F, c, d, a, b, in[2] + K1, 11);
ROUND(F, b, c, d, a, in[3] + K1, 19);
ROUND(F, a, b, c, d, in[4] + K1, 3);
ROUND(F, d, a, b, c, in[5] + K1, 7);
ROUND(F, c, d, a, b, in[6] + K1, 11);
ROUND(F, b, c, d, a, in[7] + K1, 19);
/* Round 2 */
ROUND(G, a, b, c, d, in[1] + K2, 3);
ROUND(G, d, a, b, c, in[3] + K2, 5);
ROUND(G, c, d, a, b, in[5] + K2, 9);
ROUND(G, b, c, d, a, in[7] + K2, 13);
ROUND(G, a, b, c, d, in[0] + K2, 3);
ROUND(G, d, a, b, c, in[2] + K2, 5);
ROUND(G, c, d, a, b, in[4] + K2, 9);
ROUND(G, b, c, d, a, in[6] + K2, 13);
/* Round 3 */
ROUND(H, a, b, c, d, in[3] + K3, 3);
ROUND(H, d, a, b, c, in[7] + K3, 9);
ROUND(H, c, d, a, b, in[2] + K3, 11);
ROUND(H, b, c, d, a, in[6] + K3, 15);
ROUND(H, a, b, c, d, in[1] + K3, 3);
ROUND(H, d, a, b, c, in[5] + K3, 9);
ROUND(H, c, d, a, b, in[0] + K3, 11);
ROUND(H, b, c, d, a, in[4] + K3, 15);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
return buf[1]; /* "most hashed" word */
/* Alternative: return sum of all words? */
}
#undef ROUND
#undef F
#undef G
#undef H
#undef K1
#undef K2
#undef K3
/* The old legacy hash */
static ext2_dirhash_t dx_hack_hash (const char *name, int len)
{
__u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
@ -33,19 +105,69 @@ static ext2_dirhash_t dx_hack_hash (const char *name, int len)
* Returns the hash of a filename. If len is 0 and name is NULL, then
* this function can be used to test whether or not a hash version is
* supported.
*
* The seed is an 4 longword (32 bits) "secret" which can be used to
* uniquify a hash. If the seed is all zero's, then some default seed
* may be used.
*
* A particular hash version specifies whether or not the seed is
* represented, and whether or not the returned hash is 32 bits or 64
* bits. 32 bit hashes will return 0 for the minor hash.
*/
errcode_t ext2fs_dirhash(int version, const char *name, int len,
ext2_dirhash_t *ret_hash)
const __u32 seed[4],
ext2_dirhash_t *ret_hash,
ext2_dirhash_t *ret_minor_hash)
{
__u32 hash;
__u32 minor_hash = 0;
char *p;
int i;
if (version == 0)
/* Check to see if the seed is all zero's */
for (i=0; i < 4; i++) {
if (seed[i])
break;
}
if (version == EXT2_HASH_LEGACY)
hash = dx_hack_hash(name, len);
else {
else if ((version == EXT2_HASH_HALF_MD4) ||
(version == EXT2_HASH_HALF_MD4_SEED) ||
(version == EXT2_HASH_HALF_MD4_64)) {
char in[32];
__u32 buf[4];
if ((i == 4) || (version == EXT2_HASH_HALF_MD4)) {
buf[0] = 0x67452301;
buf[1] = 0xefcdab89;
buf[2] = 0x98badcfe;
buf[3] = 0x10325476;
} else
memcpy(buf, in, sizeof(buf));
while (len) {
if (len < 32) {
memcpy(in, name, len);
memset(in+len, 0, 32-len);
hash = halfMD4Transform(buf, (__u32 *) in);
break;
}
hash = halfMD4Transform(buf, (__u32 *) p);
len -= 32;
p += 32;
}
if (version == EXT2_HASH_HALF_MD4_64)
minor_hash = buf[2];
} else {
*ret_hash = 0;
return EXT2_ET_DIRHASH_UNSUPP;
}
*ret_hash = hash;
if (ret_minor_hash)
*ret_minor_hash = minor_hash;
return 0;
}

View File

@ -167,6 +167,13 @@ struct ext2_dx_root_info {
__u8 unused_flags;
};
#define EXT2_HASH_LEGACY 0
#define EXT2_HASH_HALF_MD4 1
#define EXT2_HASH_HALF_MD4_SEED 2
#define EXT2_HASH_HALF_MD4_64 3 /* SEED & 64 */
#define EXT2_HASH_FLAG_INCOMPAT 0x1
struct ext2_dx_entry {
__u32 hash;
__u32 block;
@ -428,8 +435,8 @@ struct ext2_super_block {
__u32 s_journal_inum; /* inode number of journal file */
__u32 s_journal_dev; /* device number of journal file */
__u32 s_last_orphan; /* start of list of inodes to delete */
__u32 s_reserved[197]; /* Padding to the end of the block */
__u32 s_hash_seed[4]; /* HTREE hash */
__u32 s_reserved[193]; /* Padding to the end of the block */
};
/*

View File

@ -612,7 +612,9 @@ extern errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
/* dirhash.c */
extern errcode_t ext2fs_dirhash(int version, const char *name, int len,
ext2_dirhash_t *ret_hash);
const __u32 seed[4],
ext2_dirhash_t *ret_hash,
ext2_dirhash_t *ret_minor_hash);
/* dir_iterate.c */

View File

@ -1,3 +1,7 @@
2002-06-26 Theodore Ts'o <tytso@mit.edu>
* f_h_badroot: New test cases to test bogus HTREE node values
2002-06-25 Theodore Ts'o <tytso@mit.edu>
* Makefile.in (test_script): Add pass in the state of

View File

@ -0,0 +1,33 @@
Pass 1: Checking inodes, blocks, and sizes
HTREE directory inode 13345 has an invalid root node.
Clear HTree index? yes
HTREE directory inode 26689 has an unsupported hash version (240)
Clear HTree index? yes
HTREE directory inode 40033 has an invalid root node.
Clear HTree index? yes
HTREE directory inode 53377 has a tree depth (8) which is too big
Clear HTree index? yes
HTREE directory inode 66721 uses an incompatible htree root node flag.
Clear HTree index? yes
Pass 2: Checking directory structure
Problem in HTREE directory inode 73393: node (1) has bad min hash
Problem in HTREE directory inode 73393: node (2) has bad max hash
Invalid HTREE directory inode 73393 (/test6). Clear? yes
Problem in HTREE directory inode 80065: node (2) has bad max hash
Problem in HTREE directory inode 80065: node (7) has bad max hash
Problem in HTREE directory inode 80065: node (21) has bad max hash
Invalid HTREE directory inode 80065 (/test7). Clear? yes
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 1719/100080 files (0.0% non-contiguous), 12611/15361 blocks
Exit status is 1

View File

@ -0,0 +1,7 @@
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
test_filesys: 1719/100080 files (0.0% non-contiguous), 12611/15361 blocks
Exit status is 0

BIN
tests/f_h_badroot/image.gz Normal file

Binary file not shown.

1
tests/f_h_badroot/name Normal file
View File

@ -0,0 +1 @@
bad htree root nodes

6
tests/f_h_badroot/script Normal file
View File

@ -0,0 +1,6 @@
if test "$HTREE"x = yx -a "$HTREE_CLR"x = x; then
. $cmd_dir/run_e2fsck
else
rm -f $test_name.ok $test_name.failed
echo "skipped"
fi

View File

@ -1,3 +0,0 @@
if test "$HTREE"x = yx ; then
. $cmd_dir/run_e2fsck
fi