aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorYan <yanzheng@21cn.com>2008-07-24 12:19:32 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:05 -0400
commit445dceb78f3445b9bcade90e93ca35cae6120172 (patch)
treeb658dfc3c2753c74576864a5e1d0e4510d74e73e /fs/btrfs/inode.c
parent974e35a82d022434efa50fe5f805ae14c542ba8c (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.c22
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 ||