diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-05 10:38:44 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-05 10:38:44 -0400 |
commit | 5f26f772e5c4e833ffcb0599f54deda466d2a3e5 (patch) | |
tree | 2ef0183b42e2bd51feff52c2e6f97570514907b9 /fs/btrfs/super.c | |
parent | bae45de03c4d54a9893dedf8a015beb2608b896a (diff) |
Btrfs: more inode indexed directory work
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 90 |
1 files changed, 47 insertions, 43 deletions
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; |
136 | err: | 143 | err: |
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); |
759 | error: | 764 | error: |
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); |