mirror of https://gitee.com/openkylin/linux.git
ext4: convert dx_probe() to use the ERR_PTR convention
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
parent
1c2150283c
commit
dd73b5d5cb
|
@ -253,8 +253,7 @@ static unsigned dx_node_limit(struct inode *dir);
|
||||||
static struct dx_frame *dx_probe(const struct qstr *d_name,
|
static struct dx_frame *dx_probe(const struct qstr *d_name,
|
||||||
struct inode *dir,
|
struct inode *dir,
|
||||||
struct dx_hash_info *hinfo,
|
struct dx_hash_info *hinfo,
|
||||||
struct dx_frame *frame,
|
struct dx_frame *frame);
|
||||||
int *err);
|
|
||||||
static void dx_release(struct dx_frame *frames);
|
static void dx_release(struct dx_frame *frames);
|
||||||
static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize,
|
static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize,
|
||||||
struct dx_hash_info *hinfo, struct dx_map_entry map[]);
|
struct dx_hash_info *hinfo, struct dx_map_entry map[]);
|
||||||
|
@ -670,29 +669,25 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
|
||||||
*/
|
*/
|
||||||
static struct dx_frame *
|
static struct dx_frame *
|
||||||
dx_probe(const struct qstr *d_name, struct inode *dir,
|
dx_probe(const struct qstr *d_name, struct inode *dir,
|
||||||
struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err)
|
struct dx_hash_info *hinfo, struct dx_frame *frame_in)
|
||||||
{
|
{
|
||||||
unsigned count, indirect;
|
unsigned count, indirect;
|
||||||
struct dx_entry *at, *entries, *p, *q, *m;
|
struct dx_entry *at, *entries, *p, *q, *m;
|
||||||
struct dx_root *root;
|
struct dx_root *root;
|
||||||
struct buffer_head *bh;
|
|
||||||
struct dx_frame *frame = frame_in;
|
struct dx_frame *frame = frame_in;
|
||||||
|
struct dx_frame *ret_err = ERR_PTR(ERR_BAD_DX_DIR);
|
||||||
u32 hash;
|
u32 hash;
|
||||||
|
|
||||||
frame->bh = NULL;
|
frame->bh = ext4_read_dirblock(dir, 0, INDEX);
|
||||||
bh = ext4_read_dirblock(dir, 0, INDEX);
|
if (IS_ERR(frame->bh))
|
||||||
if (IS_ERR(bh)) {
|
return (struct dx_frame *) frame->bh;
|
||||||
*err = PTR_ERR(bh);
|
|
||||||
goto fail;
|
root = (struct dx_root *) frame->bh->b_data;
|
||||||
}
|
|
||||||
root = (struct dx_root *) bh->b_data;
|
|
||||||
if (root->info.hash_version != DX_HASH_TEA &&
|
if (root->info.hash_version != DX_HASH_TEA &&
|
||||||
root->info.hash_version != DX_HASH_HALF_MD4 &&
|
root->info.hash_version != DX_HASH_HALF_MD4 &&
|
||||||
root->info.hash_version != DX_HASH_LEGACY) {
|
root->info.hash_version != DX_HASH_LEGACY) {
|
||||||
ext4_warning(dir->i_sb, "Unrecognised inode hash code %d",
|
ext4_warning(dir->i_sb, "Unrecognised inode hash code %d",
|
||||||
root->info.hash_version);
|
root->info.hash_version);
|
||||||
brelse(bh);
|
|
||||||
*err = ERR_BAD_DX_DIR;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
hinfo->hash_version = root->info.hash_version;
|
hinfo->hash_version = root->info.hash_version;
|
||||||
|
@ -706,16 +701,12 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
|
||||||
if (root->info.unused_flags & 1) {
|
if (root->info.unused_flags & 1) {
|
||||||
ext4_warning(dir->i_sb, "Unimplemented inode hash flags: %#06x",
|
ext4_warning(dir->i_sb, "Unimplemented inode hash flags: %#06x",
|
||||||
root->info.unused_flags);
|
root->info.unused_flags);
|
||||||
brelse(bh);
|
|
||||||
*err = ERR_BAD_DX_DIR;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((indirect = root->info.indirect_levels) > 1) {
|
if ((indirect = root->info.indirect_levels) > 1) {
|
||||||
ext4_warning(dir->i_sb, "Unimplemented inode hash depth: %#06x",
|
ext4_warning(dir->i_sb, "Unimplemented inode hash depth: %#06x",
|
||||||
root->info.indirect_levels);
|
root->info.indirect_levels);
|
||||||
brelse(bh);
|
|
||||||
*err = ERR_BAD_DX_DIR;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,27 +716,21 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
|
||||||
if (dx_get_limit(entries) != dx_root_limit(dir,
|
if (dx_get_limit(entries) != dx_root_limit(dir,
|
||||||
root->info.info_length)) {
|
root->info.info_length)) {
|
||||||
ext4_warning(dir->i_sb, "dx entry: limit != root limit");
|
ext4_warning(dir->i_sb, "dx entry: limit != root limit");
|
||||||
brelse(bh);
|
|
||||||
*err = ERR_BAD_DX_DIR;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
dxtrace(printk("Look up %x", hash));
|
dxtrace(printk("Look up %x", hash));
|
||||||
while (1)
|
while (1) {
|
||||||
{
|
|
||||||
count = dx_get_count(entries);
|
count = dx_get_count(entries);
|
||||||
if (!count || count > dx_get_limit(entries)) {
|
if (!count || count > dx_get_limit(entries)) {
|
||||||
ext4_warning(dir->i_sb,
|
ext4_warning(dir->i_sb,
|
||||||
"dx entry: no count or count > limit");
|
"dx entry: no count or count > limit");
|
||||||
brelse(bh);
|
goto fail;
|
||||||
*err = ERR_BAD_DX_DIR;
|
|
||||||
goto fail2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p = entries + 1;
|
p = entries + 1;
|
||||||
q = entries + count - 1;
|
q = entries + count - 1;
|
||||||
while (p <= q)
|
while (p <= q) {
|
||||||
{
|
|
||||||
m = p + (q - p)/2;
|
m = p + (q - p)/2;
|
||||||
dxtrace(printk("."));
|
dxtrace(printk("."));
|
||||||
if (dx_get_hash(m) > hash)
|
if (dx_get_hash(m) > hash)
|
||||||
|
@ -754,8 +739,7 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
|
||||||
p = m + 1;
|
p = m + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0) // linear search cross check
|
if (0) { // linear search cross check
|
||||||
{
|
|
||||||
unsigned n = count - 1;
|
unsigned n = count - 1;
|
||||||
at = entries;
|
at = entries;
|
||||||
while (n--)
|
while (n--)
|
||||||
|
@ -772,38 +756,35 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
|
||||||
|
|
||||||
at = p - 1;
|
at = p - 1;
|
||||||
dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
|
dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
|
||||||
frame->bh = bh;
|
|
||||||
frame->entries = entries;
|
frame->entries = entries;
|
||||||
frame->at = at;
|
frame->at = at;
|
||||||
if (!indirect--) return frame;
|
if (!indirect--)
|
||||||
bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX);
|
return frame;
|
||||||
if (IS_ERR(bh)) {
|
frame++;
|
||||||
*err = PTR_ERR(bh);
|
frame->bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX);
|
||||||
goto fail2;
|
if (IS_ERR(frame->bh)) {
|
||||||
|
ret_err = (struct dx_frame *) frame->bh;
|
||||||
|
frame->bh = NULL;
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
entries = ((struct dx_node *) bh->b_data)->entries;
|
entries = ((struct dx_node *) frame->bh->b_data)->entries;
|
||||||
|
|
||||||
if (dx_get_limit(entries) != dx_node_limit (dir)) {
|
if (dx_get_limit(entries) != dx_node_limit (dir)) {
|
||||||
ext4_warning(dir->i_sb,
|
ext4_warning(dir->i_sb,
|
||||||
"dx entry: limit != node limit");
|
"dx entry: limit != node limit");
|
||||||
brelse(bh);
|
goto fail;
|
||||||
*err = ERR_BAD_DX_DIR;
|
|
||||||
goto fail2;
|
|
||||||
}
|
}
|
||||||
frame++;
|
|
||||||
frame->bh = NULL;
|
|
||||||
}
|
}
|
||||||
fail2:
|
fail:
|
||||||
while (frame >= frame_in) {
|
while (frame >= frame_in) {
|
||||||
brelse(frame->bh);
|
brelse(frame->bh);
|
||||||
frame--;
|
frame--;
|
||||||
}
|
}
|
||||||
fail:
|
if (ret_err == ERR_PTR(ERR_BAD_DX_DIR))
|
||||||
if (*err == ERR_BAD_DX_DIR)
|
|
||||||
ext4_warning(dir->i_sb,
|
ext4_warning(dir->i_sb,
|
||||||
"Corrupt dir inode %lu, running e2fsck is "
|
"Corrupt dir inode %lu, running e2fsck is "
|
||||||
"recommended.", dir->i_ino);
|
"recommended.", dir->i_ino);
|
||||||
return NULL;
|
return ret_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dx_release (struct dx_frame *frames)
|
static void dx_release (struct dx_frame *frames)
|
||||||
|
@ -989,9 +970,9 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
|
||||||
}
|
}
|
||||||
hinfo.hash = start_hash;
|
hinfo.hash = start_hash;
|
||||||
hinfo.minor_hash = 0;
|
hinfo.minor_hash = 0;
|
||||||
frame = dx_probe(NULL, dir, &hinfo, frames, &err);
|
frame = dx_probe(NULL, dir, &hinfo, frames);
|
||||||
if (!frame)
|
if (IS_ERR(frame))
|
||||||
return err;
|
return PTR_ERR(frame);
|
||||||
|
|
||||||
/* Add '.' and '..' from the htree header */
|
/* Add '.' and '..' from the htree header */
|
||||||
if (!start_hash && !start_minor_hash) {
|
if (!start_hash && !start_minor_hash) {
|
||||||
|
@ -1369,11 +1350,11 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
|
||||||
struct dx_frame frames[2], *frame;
|
struct dx_frame frames[2], *frame;
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
ext4_lblk_t block;
|
ext4_lblk_t block;
|
||||||
int err = 0, retval;
|
int retval;
|
||||||
|
|
||||||
frame = dx_probe(d_name, dir, &hinfo, frames, &err);
|
frame = dx_probe(d_name, dir, &hinfo, frames);
|
||||||
if (err)
|
if (IS_ERR(frame))
|
||||||
return ERR_PTR(err);
|
return (struct buffer_head *) frame;
|
||||||
do {
|
do {
|
||||||
block = dx_get_block(frame->at);
|
block = dx_get_block(frame->at);
|
||||||
bh = ext4_read_dirblock(dir, block, DIRENT);
|
bh = ext4_read_dirblock(dir, block, DIRENT);
|
||||||
|
@ -1977,9 +1958,9 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
|
||||||
struct ext4_dir_entry_2 *de;
|
struct ext4_dir_entry_2 *de;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
frame = dx_probe(&dentry->d_name, dir, &hinfo, frames, &err);
|
frame = dx_probe(&dentry->d_name, dir, &hinfo, frames);
|
||||||
if (!frame)
|
if (IS_ERR(frame))
|
||||||
return err;
|
return PTR_ERR(frame);
|
||||||
entries = frame->entries;
|
entries = frame->entries;
|
||||||
at = frame->at;
|
at = frame->at;
|
||||||
bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT);
|
bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT);
|
||||||
|
|
Loading…
Reference in New Issue