diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ctree.h | 4 | ||||
-rw-r--r-- | fs/btrfs/dir-item.c | 18 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 3 | ||||
-rw-r--r-- | fs/btrfs/super.c | 90 |
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 | |||
921 | int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | 921 | int 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); |
924 | int 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); | ||
924 | int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, | 928 | int 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 | ||
83 | int 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 | |||
83 | int btrfs_match_dir_item_name(struct btrfs_root *root, | 101 | int 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 | |||
368 | check_failed: | 367 | check_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; |
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); |