|
@@ -856,6 +856,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
|
|
|
struct buffer_head *bh_use[NAMEI_RA_SIZE];
|
|
|
struct buffer_head *bh, *ret = NULL;
|
|
|
ext4_lblk_t start, block, b;
|
|
|
+ const u8 *name = d_name->name;
|
|
|
int ra_max = 0; /* Number of bh's in the readahead
|
|
|
buffer, bh_use[] */
|
|
|
int ra_ptr = 0; /* Current index into readahead
|
|
@@ -870,6 +871,16 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
|
|
|
namelen = d_name->len;
|
|
|
if (namelen > EXT4_NAME_LEN)
|
|
|
return NULL;
|
|
|
+ if ((namelen <= 2) && (name[0] == '.') &&
|
|
|
+ (name[1] == '.' || name[1] == '0')) {
|
|
|
+ /*
|
|
|
+ * "." or ".." will only be in the first block
|
|
|
+ * NFS may look up ".."; "." should be handled by the VFS
|
|
|
+ */
|
|
|
+ block = start = 0;
|
|
|
+ nblocks = 1;
|
|
|
+ goto restart;
|
|
|
+ }
|
|
|
if (is_dx(dir)) {
|
|
|
bh = ext4_dx_find_entry(dir, d_name, res_dir, &err);
|
|
|
/*
|
|
@@ -960,9 +971,8 @@ cleanup_and_exit:
|
|
|
static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct qstr *d_name,
|
|
|
struct ext4_dir_entry_2 **res_dir, int *err)
|
|
|
{
|
|
|
- struct super_block * sb;
|
|
|
+ struct super_block * sb = dir->i_sb;
|
|
|
struct dx_hash_info hinfo;
|
|
|
- u32 hash;
|
|
|
struct dx_frame frames[2], *frame;
|
|
|
struct ext4_dir_entry_2 *de, *top;
|
|
|
struct buffer_head *bh;
|
|
@@ -971,18 +981,8 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
|
|
|
int namelen = d_name->len;
|
|
|
const u8 *name = d_name->name;
|
|
|
|
|
|
- sb = dir->i_sb;
|
|
|
- /* NFS may look up ".." - look at dx_root directory block */
|
|
|
- if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){
|
|
|
- if (!(frame = dx_probe(d_name, dir, &hinfo, frames, err)))
|
|
|
- return NULL;
|
|
|
- } else {
|
|
|
- frame = frames;
|
|
|
- frame->bh = NULL; /* for dx_release() */
|
|
|
- frame->at = (struct dx_entry *)frames; /* hack for zero entry*/
|
|
|
- dx_set_block(frame->at, 0); /* dx_root block is 0 */
|
|
|
- }
|
|
|
- hash = hinfo.hash;
|
|
|
+ if (!(frame = dx_probe(d_name, dir, &hinfo, frames, err)))
|
|
|
+ return NULL;
|
|
|
do {
|
|
|
block = dx_get_block(frame->at);
|
|
|
if (!(bh = ext4_bread (NULL,dir, block, 0, err)))
|
|
@@ -1008,7 +1008,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
|
|
|
}
|
|
|
brelse(bh);
|
|
|
/* Check to see if we should continue to search */
|
|
|
- retval = ext4_htree_next_block(dir, hash, frame,
|
|
|
+ retval = ext4_htree_next_block(dir, hinfo.hash, frame,
|
|
|
frames, NULL);
|
|
|
if (retval < 0) {
|
|
|
ext4_warning(sb,
|