diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-03-25 13:44:56 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-03-25 13:44:56 -0400 |
commit | 134e97313491c3a3d6bc3eca3b7c9c64408cbd08 (patch) | |
tree | b886139f45eaee59f0f46e65952cac99b05c7db2 /fs/btrfs/super.c | |
parent | 78fae27ebf5bd35fb9b2e4213e486635eacfc0ad (diff) |
Btrfs: unlink and delete_inode
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 117 |
1 files changed, 114 insertions, 3 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 094a66c267b4..f96bd92155cc 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -187,6 +187,104 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
187 | return; | 187 | return; |
188 | } | 188 | } |
189 | 189 | ||
190 | static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | ||
191 | { | ||
192 | struct btrfs_path path; | ||
193 | struct btrfs_root *root; | ||
194 | struct btrfs_trans_handle *trans; | ||
195 | const char *name = dentry->d_name.name; | ||
196 | int name_len = dentry->d_name.len; | ||
197 | int ret; | ||
198 | u64 objectid; | ||
199 | struct btrfs_dir_item *di; | ||
200 | |||
201 | btrfs_init_path(&path); | ||
202 | root = btrfs_sb(dir->i_sb); | ||
203 | mutex_lock(&root->fs_info->fs_mutex); | ||
204 | trans = btrfs_start_transaction(root, 1); | ||
205 | |||
206 | ret = btrfs_lookup_dir_item(trans, root, &path, dir->i_ino, | ||
207 | name, name_len, -1); | ||
208 | if (ret < 0) | ||
209 | goto err; | ||
210 | if (ret > 0) { | ||
211 | ret = -ENOENT; | ||
212 | goto err; | ||
213 | } | ||
214 | di = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], | ||
215 | struct btrfs_dir_item); | ||
216 | objectid = btrfs_dir_objectid(di); | ||
217 | |||
218 | ret = btrfs_del_item(trans, root, &path); | ||
219 | BUG_ON(ret); | ||
220 | dentry->d_inode->i_ctime = dir->i_ctime; | ||
221 | err: | ||
222 | btrfs_release_path(root, &path); | ||
223 | btrfs_end_transaction(trans, root); | ||
224 | mutex_unlock(&root->fs_info->fs_mutex); | ||
225 | if (ret == 0) | ||
226 | inode_dec_link_count(dentry->d_inode); | ||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | static int btrfs_free_inode(struct btrfs_trans_handle *trans, | ||
231 | struct btrfs_root *root, | ||
232 | struct inode *inode) | ||
233 | { | ||
234 | u64 objectid = inode->i_ino; | ||
235 | struct btrfs_path path; | ||
236 | struct btrfs_inode_map_item *map; | ||
237 | struct btrfs_key stat_data_key; | ||
238 | int ret; | ||
239 | clear_inode(inode); | ||
240 | btrfs_init_path(&path); | ||
241 | ret = btrfs_lookup_inode_map(trans, root, &path, objectid, -1); | ||
242 | if (ret) { | ||
243 | if (ret > 0) | ||
244 | ret = -ENOENT; | ||
245 | btrfs_release_path(root, &path); | ||
246 | goto error; | ||
247 | } | ||
248 | map = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], | ||
249 | struct btrfs_inode_map_item); | ||
250 | btrfs_disk_key_to_cpu(&stat_data_key, &map->key); | ||
251 | ret = btrfs_del_item(trans, root->fs_info->inode_root, &path); | ||
252 | BUG_ON(ret); | ||
253 | btrfs_release_path(root, &path); | ||
254 | btrfs_init_path(&path); | ||
255 | |||
256 | ret = btrfs_lookup_inode(trans, root, &path, objectid, -1); | ||
257 | BUG_ON(ret); | ||
258 | ret = btrfs_del_item(trans, root, &path); | ||
259 | BUG_ON(ret); | ||
260 | btrfs_release_path(root, &path); | ||
261 | error: | ||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | static void btrfs_delete_inode(struct inode *inode) | ||
266 | { | ||
267 | struct btrfs_trans_handle *trans; | ||
268 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | ||
269 | truncate_inode_pages(&inode->i_data, 0); | ||
270 | if (is_bad_inode(inode)) { | ||
271 | goto no_delete; | ||
272 | } | ||
273 | inode->i_size = 0; | ||
274 | if (inode->i_blocks) | ||
275 | WARN_ON(1); | ||
276 | |||
277 | mutex_lock(&root->fs_info->fs_mutex); | ||
278 | trans = btrfs_start_transaction(root, 1); | ||
279 | btrfs_free_inode(trans, root, inode); | ||
280 | btrfs_end_transaction(trans, root); | ||
281 | mutex_unlock(&root->fs_info->fs_mutex); | ||
282 | return; | ||
283 | no_delete: | ||
284 | clear_inode(inode); | ||
285 | } | ||
286 | |||
287 | |||
190 | static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, | 288 | static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, |
191 | ino_t *ino) | 289 | ino_t *ino) |
192 | { | 290 | { |
@@ -272,6 +370,13 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
272 | leaf = btrfs_buffer_leaf(path.nodes[0]); | 370 | leaf = btrfs_buffer_leaf(path.nodes[0]); |
273 | nritems = btrfs_header_nritems(&leaf->header); | 371 | nritems = btrfs_header_nritems(&leaf->header); |
274 | slot = path.slots[0]; | 372 | slot = path.slots[0]; |
373 | #if 0 | ||
374 | page_cache_readahead( | ||
375 | inode->i_sb->s_bdev->bd_inode->i_mapping, | ||
376 | &filp->f_ra, filp, | ||
377 | path.nodes[0]->b_blocknr >> | ||
378 | (PAGE_CACHE_SHIFT - inode->i_blkbits), 1); | ||
379 | #endif | ||
275 | } else { | 380 | } else { |
276 | slot++; | 381 | slot++; |
277 | path.slots[0]++; | 382 | path.slots[0]++; |
@@ -441,8 +546,6 @@ static int btrfs_add_nondir(struct btrfs_trans_handle *trans, | |||
441 | d_instantiate(dentry, inode); | 546 | d_instantiate(dentry, inode); |
442 | return 0; | 547 | return 0; |
443 | } | 548 | } |
444 | inode_dec_link_count(inode); | ||
445 | iput(inode); | ||
446 | return err; | 549 | return err; |
447 | } | 550 | } |
448 | 551 | ||
@@ -453,6 +556,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
453 | struct btrfs_root *root = btrfs_sb(dir->i_sb); | 556 | struct btrfs_root *root = btrfs_sb(dir->i_sb); |
454 | struct inode *inode; | 557 | struct inode *inode; |
455 | int err; | 558 | int err; |
559 | int drop_inode = 0; | ||
456 | 560 | ||
457 | mutex_lock(&root->fs_info->fs_mutex); | 561 | mutex_lock(&root->fs_info->fs_mutex); |
458 | trans = btrfs_start_transaction(root, 1); | 562 | trans = btrfs_start_transaction(root, 1); |
@@ -462,10 +566,16 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
462 | goto out_unlock; | 566 | goto out_unlock; |
463 | // FIXME mark the inode dirty | 567 | // FIXME mark the inode dirty |
464 | err = btrfs_add_nondir(trans, dentry, inode); | 568 | err = btrfs_add_nondir(trans, dentry, inode); |
569 | if (err) | ||
570 | drop_inode = 1; | ||
465 | dir->i_sb->s_dirt = 1; | 571 | dir->i_sb->s_dirt = 1; |
466 | btrfs_end_transaction(trans, root); | 572 | btrfs_end_transaction(trans, root); |
467 | out_unlock: | 573 | out_unlock: |
468 | mutex_unlock(&root->fs_info->fs_mutex); | 574 | mutex_unlock(&root->fs_info->fs_mutex); |
575 | if (drop_inode) { | ||
576 | inode_dec_link_count(inode); | ||
577 | iput(inode); | ||
578 | } | ||
469 | return err; | 579 | return err; |
470 | } | 580 | } |
471 | 581 | ||
@@ -516,7 +626,7 @@ static struct file_system_type btrfs_fs_type = { | |||
516 | 626 | ||
517 | static struct super_operations btrfs_super_ops = { | 627 | static struct super_operations btrfs_super_ops = { |
518 | .statfs = simple_statfs, | 628 | .statfs = simple_statfs, |
519 | .drop_inode = generic_delete_inode, | 629 | .delete_inode = btrfs_delete_inode, |
520 | .put_super = btrfs_put_super, | 630 | .put_super = btrfs_put_super, |
521 | .read_inode = btrfs_read_locked_inode, | 631 | .read_inode = btrfs_read_locked_inode, |
522 | .write_super = btrfs_write_super, | 632 | .write_super = btrfs_write_super, |
@@ -526,6 +636,7 @@ static struct super_operations btrfs_super_ops = { | |||
526 | static struct inode_operations btrfs_dir_inode_operations = { | 636 | static struct inode_operations btrfs_dir_inode_operations = { |
527 | .lookup = btrfs_lookup, | 637 | .lookup = btrfs_lookup, |
528 | .create = btrfs_create, | 638 | .create = btrfs_create, |
639 | .unlink = btrfs_unlink, | ||
529 | }; | 640 | }; |
530 | 641 | ||
531 | static struct file_operations btrfs_dir_file_operations = { | 642 | static struct file_operations btrfs_dir_file_operations = { |