aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-05-23 15:44:28 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-05-23 15:44:28 -0400
commite06afa839e726959be2166bec4cb85c117e213f1 (patch)
treef2acae733ce4c4368e3368cf912b1c76462aa0f7
parentf9f3c6b666f717510b67036c314ec915b9059eaa (diff)
Btrfs: rename
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/TODO1
-rw-r--r--fs/btrfs/ctree.h1
-rw-r--r--fs/btrfs/dir-item.c27
-rw-r--r--fs/btrfs/super.c132
4 files changed, 143 insertions, 18 deletions
diff --git a/fs/btrfs/TODO b/fs/btrfs/TODO
index f6df246f26c3..861e34ae0979 100644
--- a/fs/btrfs/TODO
+++ b/fs/btrfs/TODO
@@ -8,6 +8,7 @@
8* Add generation number to key pointer in nodes 8* Add generation number to key pointer in nodes
9* Add generation number to inode 9* Add generation number to inode
10* Add ability to switch a block group from data to metadata or vice versa 10* Add ability to switch a block group from data to metadata or vice versa
11* forbid cross subvolume renames and hardlinks
11* Release 12* Release
12* Do real tree locking 13* Do real tree locking
13* Add extent mirroring (backup copies of blocks) 14* Add extent mirroring (backup copies of blocks)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index da12d8275817..3330004af1a6 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -32,6 +32,7 @@ extern struct kmem_cache *btrfs_path_cachep;
32#define BTRFS_CSUM_SIZE 32 32#define BTRFS_CSUM_SIZE 32
33/* four bytes for CRC32 */ 33/* four bytes for CRC32 */
34#define BTRFS_CRC32_SIZE 4 34#define BTRFS_CRC32_SIZE 4
35#define BTRFS_EMPTY_DIR_SIZE 6
35 36
36/* 37/*
37 * the key defines the order in the tree, and so it also defines (optimal) 38 * the key defines the order in the tree, and so it also defines (optimal)
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index 00a28d90fea6..b408a3d20c7b 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -9,7 +9,9 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
9 struct btrfs_root *root, 9 struct btrfs_root *root,
10 struct btrfs_path *path, 10 struct btrfs_path *path,
11 struct btrfs_key *cpu_key, 11 struct btrfs_key *cpu_key,
12 u32 data_size) 12 u32 data_size,
13 const char *name,
14 int name_len)
13{ 15{
14 int ret; 16 int ret;
15 char *ptr; 17 char *ptr;
@@ -18,6 +20,10 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
18 20
19 ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); 21 ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
20 if (ret == -EEXIST) { 22 if (ret == -EEXIST) {
23 struct btrfs_dir_item *di;
24 di = btrfs_match_dir_item_name(root, path, name, name_len);
25 if (di)
26 return ERR_PTR(-EEXIST);
21 ret = btrfs_extend_item(trans, root, path, data_size); 27 ret = btrfs_extend_item(trans, root, path, data_size);
22 WARN_ON(ret > 0); 28 WARN_ON(ret > 0);
23 if (ret) 29 if (ret)
@@ -37,6 +43,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
37 struct btrfs_key *location, u8 type) 43 struct btrfs_key *location, u8 type)
38{ 44{
39 int ret = 0; 45 int ret = 0;
46 int ret2 = 0;
40 struct btrfs_path *path; 47 struct btrfs_path *path;
41 struct btrfs_dir_item *dir_item; 48 struct btrfs_dir_item *dir_item;
42 char *name_ptr; 49 char *name_ptr;
@@ -51,9 +58,12 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
51 path = btrfs_alloc_path(); 58 path = btrfs_alloc_path();
52 btrfs_init_path(path); 59 btrfs_init_path(path);
53 data_size = sizeof(*dir_item) + name_len; 60 data_size = sizeof(*dir_item) + name_len;
54 dir_item = insert_with_overflow(trans, root, path, &key, data_size); 61 dir_item = insert_with_overflow(trans, root, path, &key, data_size,
62 name, name_len);
55 if (IS_ERR(dir_item)) { 63 if (IS_ERR(dir_item)) {
56 ret = PTR_ERR(dir_item); 64 ret = PTR_ERR(dir_item);
65 if (ret == -EEXIST)
66 goto second_insert;
57 goto out; 67 goto out;
58 } 68 }
59 69
@@ -66,19 +76,20 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
66 btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); 76 btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len);
67 btrfs_mark_buffer_dirty(path->nodes[0]); 77 btrfs_mark_buffer_dirty(path->nodes[0]);
68 78
79second_insert:
69 /* FIXME, use some real flag for selecting the extra index */ 80 /* FIXME, use some real flag for selecting the extra index */
70 if (root == root->fs_info->tree_root) { 81 if (root == root->fs_info->tree_root) {
71 ret = 0; 82 ret = 0;
72 goto out; 83 goto out;
73 } 84 }
74
75 btrfs_release_path(root, path); 85 btrfs_release_path(root, path);
76 86
77 btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); 87 btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY);
78 key.offset = location->objectid; 88 key.offset = location->objectid;
79 dir_item = insert_with_overflow(trans, root, path, &key, data_size); 89 dir_item = insert_with_overflow(trans, root, path, &key, data_size,
90 name, name_len);
80 if (IS_ERR(dir_item)) { 91 if (IS_ERR(dir_item)) {
81 ret = PTR_ERR(dir_item); 92 ret2 = PTR_ERR(dir_item);
82 goto out; 93 goto out;
83 } 94 }
84 btrfs_cpu_key_to_disk(&dir_item->location, location); 95 btrfs_cpu_key_to_disk(&dir_item->location, location);
@@ -90,7 +101,11 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
90 btrfs_mark_buffer_dirty(path->nodes[0]); 101 btrfs_mark_buffer_dirty(path->nodes[0]);
91out: 102out:
92 btrfs_free_path(path); 103 btrfs_free_path(path);
93 return ret; 104 if (ret)
105 return ret;
106 if (ret2)
107 return ret2;
108 return 0;
94} 109}
95 110
96struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, 111struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 0220c82841ad..f49cad603ee8 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -375,6 +375,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
375 struct btrfs_path *path; 375 struct btrfs_path *path;
376 struct btrfs_key key; 376 struct btrfs_key key;
377 struct btrfs_disk_key *found_key; 377 struct btrfs_disk_key *found_key;
378 u32 found_type;
378 struct btrfs_leaf *leaf; 379 struct btrfs_leaf *leaf;
379 struct btrfs_file_extent_item *fi = NULL; 380 struct btrfs_file_extent_item *fi = NULL;
380 u64 extent_start = 0; 381 u64 extent_start = 0;
@@ -386,12 +387,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
386 /* FIXME, add redo link to tree so we don't leak on crash */ 387 /* FIXME, add redo link to tree so we don't leak on crash */
387 key.objectid = inode->i_ino; 388 key.objectid = inode->i_ino;
388 key.offset = (u64)-1; 389 key.offset = (u64)-1;
389 key.flags = 0; 390 key.flags = (u32)-1;
390 /*
391 * use BTRFS_CSUM_ITEM_KEY because it is larger than inline keys
392 * or extent data
393 */
394 btrfs_set_key_type(&key, BTRFS_CSUM_ITEM_KEY);
395 while(1) { 391 while(1) {
396 btrfs_init_path(path); 392 btrfs_init_path(path);
397 ret = btrfs_search_slot(trans, root, &key, path, -1, 1); 393 ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
@@ -405,10 +401,13 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
405 reada_truncate(root, path, inode->i_ino); 401 reada_truncate(root, path, inode->i_ino);
406 leaf = btrfs_buffer_leaf(path->nodes[0]); 402 leaf = btrfs_buffer_leaf(path->nodes[0]);
407 found_key = &leaf->items[path->slots[0]].key; 403 found_key = &leaf->items[path->slots[0]].key;
404 found_type = btrfs_disk_key_type(found_key);
408 if (btrfs_disk_key_objectid(found_key) != inode->i_ino) 405 if (btrfs_disk_key_objectid(found_key) != inode->i_ino)
409 break; 406 break;
410 if (btrfs_disk_key_type(found_key) != BTRFS_CSUM_ITEM_KEY && 407 if (found_type != BTRFS_CSUM_ITEM_KEY &&
411 btrfs_disk_key_type(found_key) != BTRFS_EXTENT_DATA_KEY) 408 found_type != BTRFS_DIR_ITEM_KEY &&
409 found_type != BTRFS_DIR_INDEX_KEY &&
410 found_type != BTRFS_EXTENT_DATA_KEY)
412 break; 411 break;
413 if (btrfs_disk_key_offset(found_key) < inode->i_size) 412 if (btrfs_disk_key_offset(found_key) < inode->i_size)
414 break; 413 break;
@@ -460,10 +459,8 @@ static void btrfs_delete_inode(struct inode *inode)
460 mutex_lock(&root->fs_info->fs_mutex); 459 mutex_lock(&root->fs_info->fs_mutex);
461 trans = btrfs_start_transaction(root, 1); 460 trans = btrfs_start_transaction(root, 1);
462 btrfs_set_trans_block_group(trans, inode); 461 btrfs_set_trans_block_group(trans, inode);
463 if (S_ISREG(inode->i_mode)) { 462 ret = btrfs_truncate_in_trans(trans, root, inode);
464 ret = btrfs_truncate_in_trans(trans, root, inode); 463 BUG_ON(ret);
465 BUG_ON(ret);
466 }
467 btrfs_free_inode(trans, root, inode); 464 btrfs_free_inode(trans, root, inode);
468 btrfs_end_transaction(trans, root); 465 btrfs_end_transaction(trans, root);
469 mutex_unlock(&root->fs_info->fs_mutex); 466 mutex_unlock(&root->fs_info->fs_mutex);
@@ -2504,6 +2501,116 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
2504 return 0; 2501 return 0;
2505} 2502}
2506 2503
2504static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
2505 struct inode * new_dir,struct dentry *new_dentry)
2506{
2507 struct btrfs_trans_handle *trans;
2508 struct btrfs_root *root = BTRFS_I(old_dir)->root;
2509 struct inode *new_inode = new_dentry->d_inode;
2510 struct inode *old_inode = old_dentry->d_inode;
2511 struct timespec ctime = CURRENT_TIME;
2512 struct btrfs_path *path;
2513 struct btrfs_dir_item *di;
2514 int ret;
2515
2516 if (S_ISDIR(old_inode->i_mode) && new_inode &&
2517 new_inode->i_size > BTRFS_EMPTY_DIR_SIZE) {
2518 return -ENOTEMPTY;
2519 }
2520 mutex_lock(&root->fs_info->fs_mutex);
2521 trans = btrfs_start_transaction(root, 1);
2522 btrfs_set_trans_block_group(trans, new_dir);
2523 path = btrfs_alloc_path();
2524 if (!path) {
2525 ret = -ENOMEM;
2526 goto out_fail;
2527 }
2528
2529 old_dentry->d_inode->i_nlink++;
2530 old_dir->i_ctime = old_dir->i_mtime = ctime;
2531 new_dir->i_ctime = new_dir->i_mtime = ctime;
2532 old_inode->i_ctime = ctime;
2533 if (S_ISDIR(old_inode->i_mode) && old_dir != new_dir) {
2534 struct btrfs_key *location = &BTRFS_I(new_dir)->location;
2535 u64 old_parent_oid;
2536 di = btrfs_lookup_dir_item(trans, root, path, old_inode->i_ino,
2537 "..", 2, -1);
2538 if (IS_ERR(di)) {
2539 ret = PTR_ERR(di);
2540 goto out_fail;
2541 }
2542 if (!di) {
2543 ret = -ENOENT;
2544 goto out_fail;
2545 }
2546 old_parent_oid = btrfs_disk_key_objectid(&di->location);
2547 ret = btrfs_del_item(trans, root, path);
2548 if (ret) {
2549 ret = -EIO;
2550 goto out_fail;
2551 }
2552 btrfs_release_path(root, path);
2553
2554 di = btrfs_lookup_dir_index_item(trans, root, path,
2555 old_inode->i_ino,
2556 old_parent_oid,
2557 "..", 2, -1);
2558 if (IS_ERR(di)) {
2559 ret = PTR_ERR(di);
2560 goto out_fail;
2561 }
2562 if (!di) {
2563 ret = -ENOENT;
2564 goto out_fail;
2565 }
2566 ret = btrfs_del_item(trans, root, path);
2567 if (ret) {
2568 ret = -EIO;
2569 goto out_fail;
2570 }
2571 btrfs_release_path(root, path);
2572
2573 ret = btrfs_insert_dir_item(trans, root, "..", 2,
2574 old_inode->i_ino, location, 0);
2575 if (ret)
2576 goto out_fail;
2577 }
2578
2579
2580 ret = btrfs_add_link(trans, new_dentry, old_inode);
2581 if (ret == -EEXIST && new_inode)
2582 ret = 0;
2583 else if (ret)
2584 goto out_fail;
2585
2586 ret = btrfs_unlink_trans(trans, root, old_dir, old_dentry);
2587 if (ret)
2588 goto out_fail;
2589
2590 if (new_inode) {
2591 new_inode->i_ctime = CURRENT_TIME;
2592 di = btrfs_lookup_dir_index_item(trans, root, path,
2593 new_dir->i_ino,
2594 new_inode->i_ino,
2595 new_dentry->d_name.name,
2596 new_dentry->d_name.len, -1);
2597 if (di && !IS_ERR(di)) {
2598 btrfs_del_item(trans, root, path);
2599 btrfs_release_path(root, path);
2600 }
2601 if (S_ISDIR(new_inode->i_mode))
2602 clear_nlink(new_inode);
2603 else
2604 drop_nlink(new_inode);
2605 btrfs_update_inode(trans, root, new_inode);
2606 }
2607out_fail:
2608 btrfs_free_path(path);
2609 btrfs_end_transaction(trans, root);
2610 mutex_unlock(&root->fs_info->fs_mutex);
2611 return ret;
2612}
2613
2507static struct file_system_type btrfs_fs_type = { 2614static struct file_system_type btrfs_fs_type = {
2508 .owner = THIS_MODULE, 2615 .owner = THIS_MODULE,
2509 .name = "btrfs", 2616 .name = "btrfs",
@@ -2531,6 +2638,7 @@ static struct inode_operations btrfs_dir_inode_operations = {
2531 .unlink = btrfs_unlink, 2638 .unlink = btrfs_unlink,
2532 .mkdir = btrfs_mkdir, 2639 .mkdir = btrfs_mkdir,
2533 .rmdir = btrfs_rmdir, 2640 .rmdir = btrfs_rmdir,
2641 .rename = btrfs_rename,
2534}; 2642};
2535 2643
2536static struct inode_operations btrfs_dir_ro_inode_operations = { 2644static struct inode_operations btrfs_dir_ro_inode_operations = {