aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-04-05 10:38:44 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-04-05 10:38:44 -0400
commit5f26f772e5c4e833ffcb0599f54deda466d2a3e5 (patch)
tree2ef0183b42e2bd51feff52c2e6f97570514907b9 /fs
parentbae45de03c4d54a9893dedf8a015beb2608b896a (diff)
Btrfs: more inode indexed directory work
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/dir-item.c18
-rw-r--r--fs/btrfs/extent-tree.c3
-rw-r--r--fs/btrfs/super.c90
4 files changed, 70 insertions, 45 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 87c56222a620..61d7b4738af6 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -921,6 +921,10 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
921int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root 921int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
922 *root, struct btrfs_path *path, u64 dir, 922 *root, struct btrfs_path *path, u64 dir,
923 const char *name, int name_len, int mod); 923 const char *name, int name_len, int mod);
924int btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans,
925 struct btrfs_root *root,
926 struct btrfs_path *path, u64 dir,
927 u64 objectid, int mod);
924int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, 928int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path,
925 const char *name, int name_len); 929 const char *name, int name_len);
926/* inode-map.c */ 930/* inode-map.c */
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index 2a87e23ac9c9..62d0c0916a73 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -80,6 +80,24 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
80 return ret; 80 return ret;
81} 81}
82 82
83int btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans,
84 struct btrfs_root *root,
85 struct btrfs_path *path, u64 dir,
86 u64 objectid, int mod)
87{
88 int ret;
89 struct btrfs_key key;
90 int ins_len = mod < 0 ? -1 : 0;
91 int cow = mod != 0;
92
93 key.objectid = dir;
94 key.flags = 0;
95 btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY);
96 key.offset = objectid;
97 ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
98 return ret;
99}
100
83int btrfs_match_dir_item_name(struct btrfs_root *root, 101int btrfs_match_dir_item_name(struct btrfs_root *root,
84 struct btrfs_path *path, 102 struct btrfs_path *path,
85 const char *name, int name_len) 103 const char *name, int name_len)
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 688aa861a928..7c21f63f1b93 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -224,6 +224,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
224 path = btrfs_alloc_path(); 224 path = btrfs_alloc_path();
225 BUG_ON(!path); 225 BUG_ON(!path);
226 btrfs_init_path(path); 226 btrfs_init_path(path);
227
227 ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1); 228 ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1);
228 if (ret) { 229 if (ret) {
229 printk("failed to find %Lu\n", key.objectid); 230 printk("failed to find %Lu\n", key.objectid);
@@ -363,8 +364,6 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
363 if (root->fs_info->last_insert.objectid > search_start) 364 if (root->fs_info->last_insert.objectid > search_start)
364 search_start = root->fs_info->last_insert.objectid; 365 search_start = root->fs_info->last_insert.objectid;
365 366
366 path = btrfs_alloc_path();
367
368check_failed: 367check_failed:
369 btrfs_init_path(path); 368 btrfs_init_path(path);
370 ins->objectid = search_start; 369 ins->objectid = search_start;
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 4b042460e875..d776b29a1676 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -132,13 +132,20 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans,
132 132
133 ret = btrfs_del_item(trans, root, path); 133 ret = btrfs_del_item(trans, root, path);
134 BUG_ON(ret); 134 BUG_ON(ret);
135
136 btrfs_release_path(root, path);
137 ret = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino,
138 objectid, -1);
139 BUG_ON(ret);
140 ret = btrfs_del_item(trans, root, path);
141 BUG_ON(ret);
135 dentry->d_inode->i_ctime = dir->i_ctime; 142 dentry->d_inode->i_ctime = dir->i_ctime;
136err: 143err:
137 btrfs_release_path(root, path); 144 btrfs_release_path(root, path);
138 btrfs_free_path(path); 145 btrfs_free_path(path);
139 if (ret == 0) { 146 if (ret == 0) {
140 inode_dec_link_count(dentry->d_inode); 147 inode_dec_link_count(dentry->d_inode);
141 dir->i_size -= name_len; 148 dir->i_size -= name_len * 2;
142 mark_inode_dirty(dir); 149 mark_inode_dirty(dir);
143 } 150 }
144 return ret; 151 return ret;
@@ -168,8 +175,10 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
168 struct btrfs_path *path; 175 struct btrfs_path *path;
169 struct btrfs_key key; 176 struct btrfs_key key;
170 struct btrfs_trans_handle *trans; 177 struct btrfs_trans_handle *trans;
171 struct btrfs_disk_key *found_key; 178 struct btrfs_key found_key;
179 int found_type;
172 struct btrfs_leaf *leaf; 180 struct btrfs_leaf *leaf;
181 char *goodnames = "..";
173 182
174 path = btrfs_alloc_path(); 183 path = btrfs_alloc_path();
175 BUG_ON(!path); 184 BUG_ON(!path);
@@ -178,46 +187,42 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
178 trans = btrfs_start_transaction(root, 1); 187 trans = btrfs_start_transaction(root, 1);
179 key.objectid = inode->i_ino; 188 key.objectid = inode->i_ino;
180 key.offset = (u64)-1; 189 key.offset = (u64)-1;
181 key.flags = 0; 190 key.flags = (u32)-1;
182 btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); 191 while(1) {
183 ret = btrfs_search_slot(trans, root, &key, path, -1, 1); 192 ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
184 if (ret < 0) { 193 if (ret < 0) {
185 err = ret; 194 err = ret;
186 goto out; 195 goto out;
187 } 196 }
197 BUG_ON(ret == 0);
198 if (path->slots[0] == 0) {
199 err = -ENOENT;
200 goto out;
201 }
202 path->slots[0]--;
203 leaf = btrfs_buffer_leaf(path->nodes[0]);
204 btrfs_disk_key_to_cpu(&found_key,
205 &leaf->items[path->slots[0]].key);
206 found_type = btrfs_key_type(&found_key);
207 if (found_key.objectid != inode->i_ino) {
208 err = -ENOENT;
209 goto out;
210 }
211 if ((found_type != BTRFS_DIR_ITEM_KEY &&
212 found_type != BTRFS_DIR_INDEX_KEY) ||
213 (!btrfs_match_dir_item_name(root, path, goodnames, 2) &&
214 !btrfs_match_dir_item_name(root, path, goodnames, 1))) {
215 err = -ENOTEMPTY;
216 goto out;
217 }
218 ret = btrfs_del_item(trans, root, path);
219 BUG_ON(ret);
188 220
189 BUG_ON(ret == 0); 221 if (found_type == BTRFS_DIR_ITEM_KEY && found_key.offset == 1)
190 BUG_ON(path->slots[0] == 0); 222 break;
191 path->slots[0]--; 223 btrfs_release_path(root, path);
192 leaf = btrfs_buffer_leaf(path->nodes[0]);
193 found_key = &leaf->items[path->slots[0]].key;
194 if (btrfs_disk_key_objectid(found_key) != inode->i_ino) {
195 err = -ENOENT;
196 goto out;
197 }
198 if (btrfs_disk_key_type(found_key) != BTRFS_DIR_ITEM_KEY ||
199 btrfs_disk_key_offset(found_key) != 2) {
200 err = -ENOTEMPTY;
201 goto out;
202 }
203 ret = btrfs_del_item(trans, root, path);
204 BUG_ON(ret);
205 btrfs_release_path(root, path);
206 key.offset = 1;
207 ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
208 if (ret < 0) {
209 err = ret;
210 goto out;
211 }
212 if (ret > 0) {
213 err = -ENOTEMPTY;
214 goto out;
215 }
216 ret = btrfs_del_item(trans, root, path);
217 if (ret) {
218 err = ret;
219 goto out;
220 } 224 }
225 ret = 0;
221 btrfs_release_path(root, path); 226 btrfs_release_path(root, path);
222 227
223 /* now the directory is empty */ 228 /* now the directory is empty */
@@ -676,7 +681,7 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans,
676 dentry->d_parent->d_inode->i_ino, 681 dentry->d_parent->d_inode->i_ino,
677 inode->i_ino, 0); 682 inode->i_ino, 0);
678 if (ret == 0) { 683 if (ret == 0) {
679 dentry->d_parent->d_inode->i_size += dentry->d_name.len; 684 dentry->d_parent->d_inode->i_size += dentry->d_name.len * 2;
680 ret = btrfs_update_inode(trans, btrfs_sb(inode->i_sb), 685 ret = btrfs_update_inode(trans, btrfs_sb(inode->i_sb),
681 dentry->d_parent->d_inode); 686 dentry->d_parent->d_inode);
682 } 687 }
@@ -754,7 +759,7 @@ static int btrfs_make_empty_dir(struct btrfs_trans_handle *trans,
754 dir->i_ino, 1); 759 dir->i_ino, 1);
755 if (ret) 760 if (ret)
756 goto error; 761 goto error;
757 inode->i_size = 3; 762 inode->i_size = 6;
758 ret = btrfs_update_inode(trans, root, inode); 763 ret = btrfs_update_inode(trans, root, inode);
759error: 764error:
760 return ret; 765 return ret;
@@ -915,7 +920,6 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock,
915 if (create) 920 if (create)
916 trans = btrfs_start_transaction(root, 1); 921 trans = btrfs_start_transaction(root, 1);
917 922
918
919 ret = btrfs_lookup_file_extent(trans, root, path, 923 ret = btrfs_lookup_file_extent(trans, root, path,
920 inode->i_ino, 924 inode->i_ino,
921 iblock << inode->i_blkbits, 0); 925 iblock << inode->i_blkbits, 0);