diff options
author | Yan <yanzheng@21cn.com> | 2008-07-24 12:19:32 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:05 -0400 |
commit | 445dceb78f3445b9bcade90e93ca35cae6120172 (patch) | |
tree | b658dfc3c2753c74576864a5e1d0e4510d74e73e /fs/btrfs/inode.c | |
parent | 974e35a82d022434efa50fe5f805ae14c542ba8c (diff) |
Btrfs: Fix .. lookup corner case
Inode ref item can be in the next leaf when we find "path->slots[0] ==
btrfs_header_nritems(...)".
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 22 |
1 files changed, 9 insertions, 13 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 8bc981c4f5ef..cf9534b79aba 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1752,21 +1752,18 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, | |||
1752 | if (namelen == 2 && strcmp(name, "..") == 0) { | 1752 | if (namelen == 2 && strcmp(name, "..") == 0) { |
1753 | struct btrfs_key key; | 1753 | struct btrfs_key key; |
1754 | struct extent_buffer *leaf; | 1754 | struct extent_buffer *leaf; |
1755 | u32 nritems; | ||
1756 | int slot; | 1755 | int slot; |
1757 | 1756 | ||
1758 | key.objectid = dir->i_ino; | 1757 | key.objectid = dir->i_ino; |
1758 | key.offset = (u64)-1; | ||
1759 | btrfs_set_key_type(&key, BTRFS_INODE_REF_KEY); | 1759 | btrfs_set_key_type(&key, BTRFS_INODE_REF_KEY); |
1760 | key.offset = 0; | 1760 | if (ret < 0 || path->slots[0] == 0) |
1761 | goto out_err; | ||
1761 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 1762 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
1762 | BUG_ON(ret == 0); | 1763 | BUG_ON(ret == 0); |
1763 | ret = 0; | 1764 | ret = 0; |
1764 | |||
1765 | leaf = path->nodes[0]; | 1765 | leaf = path->nodes[0]; |
1766 | slot = path->slots[0]; | 1766 | slot = path->slots[0] - 1; |
1767 | nritems = btrfs_header_nritems(leaf); | ||
1768 | if (slot >= nritems) | ||
1769 | goto out_err; | ||
1770 | 1767 | ||
1771 | btrfs_item_key_to_cpu(leaf, &key, slot); | 1768 | btrfs_item_key_to_cpu(leaf, &key, slot); |
1772 | if (key.objectid != dir->i_ino || | 1769 | if (key.objectid != dir->i_ino || |
@@ -1980,16 +1977,15 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
1980 | /* special case for .., just use the back ref */ | 1977 | /* special case for .., just use the back ref */ |
1981 | if (filp->f_pos == 1) { | 1978 | if (filp->f_pos == 1) { |
1982 | btrfs_set_key_type(&key, BTRFS_INODE_REF_KEY); | 1979 | btrfs_set_key_type(&key, BTRFS_INODE_REF_KEY); |
1983 | key.offset = 0; | 1980 | key.offset = (u64)-1; |
1984 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 1981 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
1985 | BUG_ON(ret == 0); | 1982 | if (ret < 0 || path->slots[0] == 0) { |
1986 | leaf = path->nodes[0]; | ||
1987 | slot = path->slots[0]; | ||
1988 | nritems = btrfs_header_nritems(leaf); | ||
1989 | if (slot >= nritems) { | ||
1990 | btrfs_release_path(root, path); | 1983 | btrfs_release_path(root, path); |
1991 | goto read_dir_items; | 1984 | goto read_dir_items; |
1992 | } | 1985 | } |
1986 | BUG_ON(ret == 0); | ||
1987 | leaf = path->nodes[0]; | ||
1988 | slot = path->slots[0] - 1; | ||
1993 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | 1989 | btrfs_item_key_to_cpu(leaf, &found_key, slot); |
1994 | btrfs_release_path(root, path); | 1990 | btrfs_release_path(root, path); |
1995 | if (found_key.objectid != key.objectid || | 1991 | if (found_key.objectid != key.objectid || |