Skip to content

Commit f8664dd

Browse files
authored
Merge pull request #7 from WaberZhuang/master
[bugfix] htree: continue to search if the next block starts with same hash value
2 parents 5c1a477 + f8d323b commit f8664dd

File tree

1 file changed

+87
-34
lines changed

1 file changed

+87
-34
lines changed

lib/ext2fs/lookup.c

Lines changed: 87 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
#include "ext2fsP.h"
2222

2323
struct lookup_struct {
24-
const char *name;
25-
int len;
26-
ext2_ino_t *inode;
27-
int found;
24+
const char *name;
25+
int len;
26+
ext2_ino_t *inode;
27+
int found;
2828
};
2929

3030
#ifdef __TURBOC__
@@ -33,14 +33,14 @@ struct lookup_struct {
3333
static int lookup_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
3434
int entru EXT2FS_ATTR((unused)),
3535
struct ext2_dir_entry *dirent,
36-
int offset EXT2FS_ATTR((unused)),
37-
int blocksize EXT2FS_ATTR((unused)),
38-
char *buf EXT2FS_ATTR((unused)),
39-
void *priv_data)
36+
int offset EXT2FS_ATTR((unused)),
37+
int blocksize EXT2FS_ATTR((unused)),
38+
char *buf EXT2FS_ATTR((unused)),
39+
void *priv_data)
4040
{
4141
struct lookup_struct *ls = (struct lookup_struct *) priv_data;
4242

43-
if (dirent->inode == 0)
43+
if (dirent->inode == 0 /* useless? */)
4444
return 0;
4545
if (ls->len != ext2fs_dirent_name_len(dirent))
4646
return 0;
@@ -51,6 +51,54 @@ static int lookup_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
5151
return DIRENT_ABORT;
5252
}
5353

54+
/**
55+
* @return 0 if the caller should continue to search, or errcode
56+
*/
57+
static int htree_next_block(ext2_filsys fs, ext2_ino_t dir, struct ext2_inode *diri, struct dx_lookup_info *info) {
58+
errcode_t retval = 0;
59+
struct dx_frame *p;
60+
int num_frames = 0;
61+
62+
p = &(info->frames[info->levels - 1]);
63+
/*
64+
* Find the next leaf page by incrementing the frame pointer.
65+
* If we run out of entries in the interior node, loop around and
66+
* increment pointer in the parent node. When we break out of
67+
* this loop, num_frames indicates the number of interior
68+
* nodes need to be read.
69+
*/
70+
while (1) {
71+
int count = ext2fs_le16_to_cpu(p->head->count);
72+
if (++(p->at) < p->entries + count) break;
73+
if (p == info->frames) return EXT2_ET_FILE_NOT_FOUND;
74+
num_frames++;
75+
p--;
76+
}
77+
78+
__u32 next_hash = ext2fs_le32_to_cpu(p->at->hash);
79+
if ((info->hash & 1) == 0 /* useless? */ && (next_hash & ~1) != info->hash) {
80+
return EXT2_ET_FILE_NOT_FOUND;
81+
}
82+
83+
while (num_frames--) {
84+
e2_blkcnt_t blockcnt = ext2fs_le32_to_cpu(info->frames[info->levels-1].at->block) & 0x0fffffff;
85+
p++;
86+
if ((retval = load_logical_dir_block(fs, dir, diri, blockcnt, &(p->pblock), p->buf)) != 0) {
87+
return retval;
88+
}
89+
if ((retval = ext2fs_get_dx_countlimit(fs, p->buf, &(p->head), NULL)) != 0) {
90+
return retval;
91+
}
92+
int count = ext2fs_le16_to_cpu(p->head->count);
93+
int limit = ext2fs_le16_to_cpu(p->head->limit);
94+
if (!count || count > limit) {
95+
return EXT2_ET_DIR_CORRUPTED;
96+
}
97+
p->at = p->entries = (struct ext2_dx_entry *) (p->head);
98+
}
99+
return 0;
100+
}
101+
54102
static errcode_t dx_namei(ext2_filsys fs, ext2_ino_t dir, struct ext2_inode *diri, const char *name, int namelen, char *buf, ext2_ino_t *res_inode) {
55103
struct dx_lookup_info dx_info;
56104
errcode_t retval = 0;
@@ -68,43 +116,48 @@ static errcode_t dx_namei(ext2_filsys fs, ext2_ino_t dir, struct ext2_inode *dir
68116
if ((retval = dx_lookup(fs, dir, diri, &dx_info)) != 0)
69117
goto cleanup;
70118

71-
e2_blkcnt_t blockcnt = ext2fs_le32_to_cpu(dx_info.frames[dx_info.levels-1].at->block) & 0x0fffffff;
72-
if ((retval = load_logical_dir_block(fs, dir, diri, blockcnt, &leaf_pblk, buf)) != 0)
73-
goto cleanup;
74-
75-
struct dir_context ctx;
76-
struct lookup_struct ls;
77-
ctx.errcode = 0;
78-
ctx.func = lookup_proc;
79-
ctx.dir = dir;
80-
ctx.flags = DIRENT_FLAG_INCLUDE_EMPTY;
81-
ctx.buf = buf;
82-
ctx.priv_data = &ls;
119+
do {
120+
e2_blkcnt_t blockcnt = ext2fs_le32_to_cpu(dx_info.frames[dx_info.levels-1].at->block) & 0x0fffffff;
83121

84-
ls.name = name;
85-
ls.len = namelen;
86-
ls.inode = res_inode;
87-
ls.found = 0;
122+
if ((retval = load_logical_dir_block(fs, dir, diri, blockcnt, &leaf_pblk, buf)) != 0)
123+
goto cleanup;
88124

89-
ext2fs_process_dir_block(fs, &leaf_pblk, blockcnt, 0, 0, &ctx);
90-
dx_release(&dx_info);
91-
if (ctx.errcode) {
92-
retval = ctx.errcode;
93-
goto cleanup;
94-
}
125+
struct dir_context ctx;
126+
struct lookup_struct ls;
127+
ctx.errcode = 0;
128+
ctx.func = lookup_proc;
129+
ctx.dir = dir;
130+
ctx.flags = 0;
131+
ctx.buf = buf;
132+
ctx.priv_data = &ls;
133+
134+
ls.name = name;
135+
ls.len = namelen;
136+
ls.inode = res_inode;
137+
ls.found = 0;
138+
139+
ext2fs_process_dir_block(fs, &leaf_pblk, blockcnt, 0, 0, &ctx);
140+
if (ctx.errcode) {
141+
retval = ctx.errcode;
142+
goto cleanup;
143+
}
144+
if (ls.found) {
145+
break;
146+
}
147+
retval = htree_next_block(fs, dir, diri, &dx_info);
148+
} while (retval == 0);
95149

96-
if (!ls.found)
97-
retval = EXT2_ET_FILE_NOT_FOUND;
98150
cleanup:
99151
if (block_buf) {
100152
ext2fs_free_mem(&block_buf);
101153
}
154+
dx_release(&dx_info);
102155

103156
return retval;
104157
}
105158

106159
errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
107-
int namelen, char *buf, ext2_ino_t *inode)
160+
int namelen, char *buf, ext2_ino_t *inode)
108161
{
109162
errcode_t retval;
110163
struct lookup_struct ls;

0 commit comments

Comments
 (0)