aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@redhat.com>2008-07-24 12:12:38 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:05 -0400
commitaec7477b3b0e8ec93f6d274f25ba40b0665134d4 (patch)
tree2f689681e2f1b48d1c42b2242e21cbf456ec4c55 /fs/btrfs/inode.c
parent3eaa2885276fd6dac7b076a793932428b7168e74 (diff)
Btrfs: Implement new dir index format
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c143
1 files changed, 121 insertions, 22 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 0e90315ea803..8d371d6fe551 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -872,6 +872,8 @@ void btrfs_read_locked_inode(struct inode *inode)
872 inode->i_rdev = 0; 872 inode->i_rdev = 0;
873 rdev = btrfs_inode_rdev(leaf, inode_item); 873 rdev = btrfs_inode_rdev(leaf, inode_item);
874 874
875 BTRFS_I(inode)->index_cnt = (u64)-1;
876
875 alloc_group_block = btrfs_inode_block_group(leaf, inode_item); 877 alloc_group_block = btrfs_inode_block_group(leaf, inode_item);
876 BTRFS_I(inode)->block_group = btrfs_lookup_block_group(root->fs_info, 878 BTRFS_I(inode)->block_group = btrfs_lookup_block_group(root->fs_info,
877 alloc_group_block); 879 alloc_group_block);
@@ -993,6 +995,7 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
993 struct extent_buffer *leaf; 995 struct extent_buffer *leaf;
994 struct btrfs_dir_item *di; 996 struct btrfs_dir_item *di;
995 struct btrfs_key key; 997 struct btrfs_key key;
998 u64 index;
996 999
997 path = btrfs_alloc_path(); 1000 path = btrfs_alloc_path();
998 if (!path) { 1001 if (!path) {
@@ -1017,8 +1020,19 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
1017 goto err; 1020 goto err;
1018 btrfs_release_path(root, path); 1021 btrfs_release_path(root, path);
1019 1022
1023 ret = btrfs_del_inode_ref(trans, root, name, name_len,
1024 dentry->d_inode->i_ino,
1025 dentry->d_parent->d_inode->i_ino, &index);
1026 if (ret) {
1027 printk("failed to delete reference to %.*s, "
1028 "inode %lu parent %lu\n", name_len, name,
1029 dentry->d_inode->i_ino,
1030 dentry->d_parent->d_inode->i_ino);
1031 goto err;
1032 }
1033
1020 di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, 1034 di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino,
1021 key.objectid, name, name_len, -1); 1035 index, name, name_len, -1);
1022 if (IS_ERR(di)) { 1036 if (IS_ERR(di)) {
1023 ret = PTR_ERR(di); 1037 ret = PTR_ERR(di);
1024 goto err; 1038 goto err;
@@ -1031,15 +1045,6 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
1031 btrfs_release_path(root, path); 1045 btrfs_release_path(root, path);
1032 1046
1033 dentry->d_inode->i_ctime = dir->i_ctime; 1047 dentry->d_inode->i_ctime = dir->i_ctime;
1034 ret = btrfs_del_inode_ref(trans, root, name, name_len,
1035 dentry->d_inode->i_ino,
1036 dentry->d_parent->d_inode->i_ino);
1037 if (ret) {
1038 printk("failed to delete reference to %.*s, "
1039 "inode %lu parent %lu\n", name_len, name,
1040 dentry->d_inode->i_ino,
1041 dentry->d_parent->d_inode->i_ino);
1042 }
1043err: 1048err:
1044 btrfs_free_path(path); 1049 btrfs_free_path(path);
1045 if (!ret) { 1050 if (!ret) {
@@ -1625,6 +1630,7 @@ static int btrfs_init_locked_inode(struct inode *inode, void *p)
1625 BTRFS_I(inode)->root = args->root; 1630 BTRFS_I(inode)->root = args->root;
1626 BTRFS_I(inode)->delalloc_bytes = 0; 1631 BTRFS_I(inode)->delalloc_bytes = 0;
1627 BTRFS_I(inode)->disk_i_size = 0; 1632 BTRFS_I(inode)->disk_i_size = 0;
1633 BTRFS_I(inode)->index_cnt = (u64)-1;
1628 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS); 1634 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
1629 extent_io_tree_init(&BTRFS_I(inode)->io_tree, 1635 extent_io_tree_init(&BTRFS_I(inode)->io_tree,
1630 inode->i_mapping, GFP_NOFS); 1636 inode->i_mapping, GFP_NOFS);
@@ -1901,8 +1907,77 @@ void btrfs_dirty_inode(struct inode *inode)
1901 btrfs_end_transaction(trans, root); 1907 btrfs_end_transaction(trans, root);
1902} 1908}
1903 1909
1910static int btrfs_set_inode_index_count(struct inode *inode)
1911{
1912 struct btrfs_root *root = BTRFS_I(inode)->root;
1913 struct btrfs_key key, found_key;
1914 struct btrfs_path *path;
1915 struct extent_buffer *leaf;
1916 int ret;
1917
1918 key.objectid = inode->i_ino;
1919 btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY);
1920 key.offset = (u64)-1;
1921
1922 path = btrfs_alloc_path();
1923 if (!path)
1924 return -ENOMEM;
1925
1926 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
1927 if (ret < 0)
1928 goto out;
1929 /* FIXME: we should be able to handle this */
1930 if (ret == 0)
1931 goto out;
1932 ret = 0;
1933
1934 /*
1935 * MAGIC NUMBER EXPLANATION:
1936 * since we search a directory based on f_pos we have to start at 2
1937 * since '.' and '..' have f_pos of 0 and 1 respectively, so everybody
1938 * else has to start at 2
1939 */
1940 if (path->slots[0] == 0) {
1941 BTRFS_I(inode)->index_cnt = 2;
1942 goto out;
1943 }
1944
1945 path->slots[0]--;
1946
1947 leaf = path->nodes[0];
1948 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
1949
1950 if (found_key.objectid != inode->i_ino ||
1951 btrfs_key_type(&found_key) != BTRFS_DIR_INDEX_KEY) {
1952 BTRFS_I(inode)->index_cnt = 2;
1953 goto out;
1954 }
1955
1956 BTRFS_I(inode)->index_cnt = found_key.offset + 1;
1957out:
1958 btrfs_free_path(path);
1959 return ret;
1960}
1961
1962static int btrfs_set_inode_index(struct inode *dir, struct inode *inode)
1963{
1964 int ret = 0;
1965
1966 if (BTRFS_I(dir)->index_cnt == (u64)-1) {
1967 ret = btrfs_set_inode_index_count(dir);
1968 if (ret)
1969 return ret;
1970 }
1971
1972 BTRFS_I(inode)->index = BTRFS_I(dir)->index_cnt;
1973 BTRFS_I(dir)->index_cnt++;
1974
1975 return ret;
1976}
1977
1904static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, 1978static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
1905 struct btrfs_root *root, 1979 struct btrfs_root *root,
1980 struct inode *dir,
1906 const char *name, int name_len, 1981 const char *name, int name_len,
1907 u64 ref_objectid, 1982 u64 ref_objectid,
1908 u64 objectid, 1983 u64 objectid,
@@ -1928,6 +2003,20 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
1928 if (!inode) 2003 if (!inode)
1929 return ERR_PTR(-ENOMEM); 2004 return ERR_PTR(-ENOMEM);
1930 2005
2006 if (dir) {
2007 ret = btrfs_set_inode_index(dir, inode);
2008 if (ret)
2009 return ERR_PTR(ret);
2010 } else {
2011 BTRFS_I(inode)->index = 0;
2012 }
2013 /*
2014 * index_cnt is ignored for everything but a dir,
2015 * btrfs_get_inode_index_count has an explanation for the magic
2016 * number
2017 */
2018 BTRFS_I(inode)->index_cnt = 2;
2019
1931 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS); 2020 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
1932 extent_io_tree_init(&BTRFS_I(inode)->io_tree, 2021 extent_io_tree_init(&BTRFS_I(inode)->io_tree,
1933 inode->i_mapping, GFP_NOFS); 2022 inode->i_mapping, GFP_NOFS);
@@ -1984,6 +2073,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
1984 ref = btrfs_item_ptr(path->nodes[0], path->slots[0] + 1, 2073 ref = btrfs_item_ptr(path->nodes[0], path->slots[0] + 1,
1985 struct btrfs_inode_ref); 2074 struct btrfs_inode_ref);
1986 btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len); 2075 btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len);
2076 btrfs_set_inode_ref_index(path->nodes[0], ref, BTRFS_I(inode)->index);
1987 ptr = (unsigned long)(ref + 1); 2077 ptr = (unsigned long)(ref + 1);
1988 write_extent_buffer(path->nodes[0], name, ptr, name_len); 2078 write_extent_buffer(path->nodes[0], name, ptr, name_len);
1989 2079
@@ -1998,6 +2088,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
1998 insert_inode_hash(inode); 2088 insert_inode_hash(inode);
1999 return inode; 2089 return inode;
2000fail: 2090fail:
2091 if (dir)
2092 BTRFS_I(dir)->index_cnt--;
2001 btrfs_free_path(path); 2093 btrfs_free_path(path);
2002 return ERR_PTR(ret); 2094 return ERR_PTR(ret);
2003} 2095}
@@ -2014,7 +2106,7 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans,
2014 int ret; 2106 int ret;
2015 struct btrfs_key key; 2107 struct btrfs_key key;
2016 struct btrfs_root *root = BTRFS_I(dentry->d_parent->d_inode)->root; 2108 struct btrfs_root *root = BTRFS_I(dentry->d_parent->d_inode)->root;
2017 struct inode *parent_inode; 2109 struct inode *parent_inode = dentry->d_parent->d_inode;
2018 2110
2019 key.objectid = inode->i_ino; 2111 key.objectid = inode->i_ino;
2020 btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); 2112 btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY);
@@ -2023,16 +2115,17 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans,
2023 ret = btrfs_insert_dir_item(trans, root, 2115 ret = btrfs_insert_dir_item(trans, root,
2024 dentry->d_name.name, dentry->d_name.len, 2116 dentry->d_name.name, dentry->d_name.len,
2025 dentry->d_parent->d_inode->i_ino, 2117 dentry->d_parent->d_inode->i_ino,
2026 &key, btrfs_inode_type(inode)); 2118 &key, btrfs_inode_type(inode),
2119 BTRFS_I(inode)->index);
2027 if (ret == 0) { 2120 if (ret == 0) {
2028 if (add_backref) { 2121 if (add_backref) {
2029 ret = btrfs_insert_inode_ref(trans, root, 2122 ret = btrfs_insert_inode_ref(trans, root,
2030 dentry->d_name.name, 2123 dentry->d_name.name,
2031 dentry->d_name.len, 2124 dentry->d_name.len,
2032 inode->i_ino, 2125 inode->i_ino,
2033 dentry->d_parent->d_inode->i_ino); 2126 parent_inode->i_ino,
2127 BTRFS_I(inode)->index);
2034 } 2128 }
2035 parent_inode = dentry->d_parent->d_inode;
2036 btrfs_i_size_write(parent_inode, parent_inode->i_size + 2129 btrfs_i_size_write(parent_inode, parent_inode->i_size +
2037 dentry->d_name.len * 2); 2130 dentry->d_name.len * 2);
2038 parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME; 2131 parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
@@ -2083,7 +2176,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
2083 goto out_unlock; 2176 goto out_unlock;
2084 } 2177 }
2085 2178
2086 inode = btrfs_new_inode(trans, root, dentry->d_name.name, 2179 inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
2087 dentry->d_name.len, 2180 dentry->d_name.len,
2088 dentry->d_parent->d_inode->i_ino, objectid, 2181 dentry->d_parent->d_inode->i_ino, objectid,
2089 BTRFS_I(dir)->block_group, mode); 2182 BTRFS_I(dir)->block_group, mode);
@@ -2138,7 +2231,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
2138 goto out_unlock; 2231 goto out_unlock;
2139 } 2232 }
2140 2233
2141 inode = btrfs_new_inode(trans, root, dentry->d_name.name, 2234 inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
2142 dentry->d_name.len, 2235 dentry->d_name.len,
2143 dentry->d_parent->d_inode->i_ino, 2236 dentry->d_parent->d_inode->i_ino,
2144 objectid, BTRFS_I(dir)->block_group, mode); 2237 objectid, BTRFS_I(dir)->block_group, mode);
@@ -2203,10 +2296,15 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
2203 err = btrfs_check_free_space(root, 1, 0); 2296 err = btrfs_check_free_space(root, 1, 0);
2204 if (err) 2297 if (err)
2205 goto fail; 2298 goto fail;
2299 err = btrfs_set_inode_index(dir, inode);
2300 if (err)
2301 goto fail;
2302
2206 trans = btrfs_start_transaction(root, 1); 2303 trans = btrfs_start_transaction(root, 1);
2207 2304
2208 btrfs_set_trans_block_group(trans, dir); 2305 btrfs_set_trans_block_group(trans, dir);
2209 atomic_inc(&inode->i_count); 2306 atomic_inc(&inode->i_count);
2307
2210 err = btrfs_add_nondir(trans, dentry, inode, 1); 2308 err = btrfs_add_nondir(trans, dentry, inode, 1);
2211 2309
2212 if (err) 2310 if (err)
@@ -2258,7 +2356,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
2258 goto out_unlock; 2356 goto out_unlock;
2259 } 2357 }
2260 2358
2261 inode = btrfs_new_inode(trans, root, dentry->d_name.name, 2359 inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
2262 dentry->d_name.len, 2360 dentry->d_name.len,
2263 dentry->d_parent->d_inode->i_ino, objectid, 2361 dentry->d_parent->d_inode->i_ino, objectid,
2264 BTRFS_I(dir)->block_group, S_IFDIR | mode); 2362 BTRFS_I(dir)->block_group, S_IFDIR | mode);
@@ -2886,9 +2984,8 @@ int btrfs_create_subvol_root(struct btrfs_root *new_root,
2886 struct btrfs_block_group_cache *block_group) 2984 struct btrfs_block_group_cache *block_group)
2887{ 2985{
2888 struct inode *inode; 2986 struct inode *inode;
2889 int ret;
2890 2987
2891 inode = btrfs_new_inode(trans, new_root, "..", 2, new_dirid, 2988 inode = btrfs_new_inode(trans, new_root, NULL, "..", 2, new_dirid,
2892 new_dirid, block_group, S_IFDIR | 0700); 2989 new_dirid, block_group, S_IFDIR | 0700);
2893 if (IS_ERR(inode)) 2990 if (IS_ERR(inode))
2894 return PTR_ERR(inode); 2991 return PTR_ERR(inode);
@@ -2896,8 +2993,6 @@ int btrfs_create_subvol_root(struct btrfs_root *new_root,
2896 inode->i_fop = &btrfs_dir_file_operations; 2993 inode->i_fop = &btrfs_dir_file_operations;
2897 new_root->inode = inode; 2994 new_root->inode = inode;
2898 2995
2899 ret = btrfs_insert_inode_ref(trans, new_root, "..", 2, new_dirid,
2900 new_dirid);
2901 inode->i_nlink = 1; 2996 inode->i_nlink = 1;
2902 btrfs_i_size_write(inode, 0); 2997 btrfs_i_size_write(inode, 0);
2903 2998
@@ -3078,6 +3173,10 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
3078 if (ret) 3173 if (ret)
3079 goto out_fail; 3174 goto out_fail;
3080 } 3175 }
3176 ret = btrfs_set_inode_index(new_dir, old_inode);
3177 if (ret)
3178 goto out_fail;
3179
3081 ret = btrfs_add_link(trans, new_dentry, old_inode, 1); 3180 ret = btrfs_add_link(trans, new_dentry, old_inode, 1);
3082 if (ret) 3181 if (ret)
3083 goto out_fail; 3182 goto out_fail;
@@ -3123,7 +3222,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
3123 goto out_unlock; 3222 goto out_unlock;
3124 } 3223 }
3125 3224
3126 inode = btrfs_new_inode(trans, root, dentry->d_name.name, 3225 inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
3127 dentry->d_name.len, 3226 dentry->d_name.len,
3128 dentry->d_parent->d_inode->i_ino, objectid, 3227 dentry->d_parent->d_inode->i_ino, objectid,
3129 BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO); 3228 BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO);