aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@redhat.com>2008-07-24 12:17:14 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:05 -0400
commit7b1287662304c3cb05cb38f5e3e2d69f386e8f10 (patch)
treebb589bfc3854f801b4098f2f2140e42a2f9e8071 /fs
parent33268eaf0b3db5e2bd12c0ada81a8e8f87a46d68 (diff)
Btrfs: Create orphan inode records to prevent lost files after a crash
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/Makefile2
-rw-r--r--fs/btrfs/btrfs_inode.h3
-rw-r--r--fs/btrfs/ctree.c2
-rw-r--r--fs/btrfs/ctree.h14
-rw-r--r--fs/btrfs/disk-io.c2
-rw-r--r--fs/btrfs/inode.c237
-rw-r--r--fs/btrfs/orphan.c67
7 files changed, 322 insertions, 5 deletions
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile
index f8a38b0da7fb..5a0fd7b0e3e7 100644
--- a/fs/btrfs/Makefile
+++ b/fs/btrfs/Makefile
@@ -6,7 +6,7 @@ btrfs-y := super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
6 hash.o file-item.o inode-item.o inode-map.o disk-io.o \ 6 hash.o file-item.o inode-item.o inode-map.o disk-io.o \
7 transaction.o bit-radix.o inode.o file.o tree-defrag.o \ 7 transaction.o bit-radix.o inode.o file.o tree-defrag.o \
8 extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \ 8 extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \
9 extent_io.o volumes.o async-thread.o ioctl.o locking.o 9 extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o
10 10
11btrfs-$(CONFIG_FS_POSIX_ACL) += acl.o 11btrfs-$(CONFIG_FS_POSIX_ACL) += acl.o
12else 12else
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index 9f2a4ef944a7..df624fd735c1 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -39,6 +39,9 @@ struct btrfs_inode {
39 struct posix_acl *i_acl; 39 struct posix_acl *i_acl;
40 struct posix_acl *i_default_acl; 40 struct posix_acl *i_default_acl;
41 41
42 /* for keeping track of orphaned inodes */
43 struct list_head i_orphan;
44
42 /* 45 /*
43 * transid of the trans_handle that last modified this inode 46 * transid of the trans_handle that last modified this inode
44 */ 47 */
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index cdc713062b03..f2a94999c371 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -2622,7 +2622,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
2622 total_data += data_size[i]; 2622 total_data += data_size[i];
2623 } 2623 }
2624 2624
2625 total_size = total_data + (nr - 1) * sizeof(struct btrfs_item); 2625 total_size = total_data + (nr * sizeof(struct btrfs_item));
2626 ret = btrfs_search_slot(trans, root, cpu_key, path, total_size, 1); 2626 ret = btrfs_search_slot(trans, root, cpu_key, path, total_size, 1);
2627 if (ret == 0) { 2627 if (ret == 0) {
2628 return -EEXIST; 2628 return -EEXIST;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index f87d7263f2d7..012ad529cb18 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -74,6 +74,9 @@ struct btrfs_ordered_sum;
74/* directory objectid inside the root tree */ 74/* directory objectid inside the root tree */
75#define BTRFS_ROOT_TREE_DIR_OBJECTID 6ULL 75#define BTRFS_ROOT_TREE_DIR_OBJECTID 6ULL
76 76
77/* orhpan objectid for tracking unlinked/truncated files */
78#define BTRFS_ORPHAN_OBJECTID -5ULL
79
77/* 80/*
78 * All files have objectids higher than this. 81 * All files have objectids higher than this.
79 */ 82 */
@@ -646,6 +649,9 @@ struct btrfs_root {
646 649
647 /* the dirty list is only used by non-reference counted roots */ 650 /* the dirty list is only used by non-reference counted roots */
648 struct list_head dirty_list; 651 struct list_head dirty_list;
652
653 spinlock_t orphan_lock;
654 struct list_head orphan_list;
649}; 655};
650 656
651/* 657/*
@@ -657,6 +663,7 @@ struct btrfs_root {
657#define BTRFS_INODE_ITEM_KEY 1 663#define BTRFS_INODE_ITEM_KEY 1
658#define BTRFS_INODE_REF_KEY 2 664#define BTRFS_INODE_REF_KEY 2
659#define BTRFS_XATTR_ITEM_KEY 8 665#define BTRFS_XATTR_ITEM_KEY 8
666#define BTRFS_ORPHAN_ITEM_KEY 9
660/* reserve 2-15 close to the inode for later flexibility */ 667/* reserve 2-15 close to the inode for later flexibility */
661 668
662/* 669/*
@@ -1560,6 +1567,13 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
1560 struct btrfs_path *path, u64 dir, 1567 struct btrfs_path *path, u64 dir,
1561 const char *name, u16 name_len, 1568 const char *name, u16 name_len,
1562 int mod); 1569 int mod);
1570
1571/* orphan.c */
1572int btrfs_insert_orphan_item(struct btrfs_trans_handle *trans,
1573 struct btrfs_root *root, u64 offset);
1574int btrfs_del_orphan_item(struct btrfs_trans_handle *trans,
1575 struct btrfs_root *root, u64 offset);
1576
1563/* inode-map.c */ 1577/* inode-map.c */
1564int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, 1578int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
1565 struct btrfs_root *fs_root, 1579 struct btrfs_root *fs_root,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index ec01062eb41d..d60923967347 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -732,7 +732,9 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
732 root->in_sysfs = 0; 732 root->in_sysfs = 0;
733 733
734 INIT_LIST_HEAD(&root->dirty_list); 734 INIT_LIST_HEAD(&root->dirty_list);
735 INIT_LIST_HEAD(&root->orphan_list);
735 spin_lock_init(&root->node_lock); 736 spin_lock_init(&root->node_lock);
737 spin_lock_init(&root->orphan_lock);
736 mutex_init(&root->objectid_mutex); 738 mutex_init(&root->objectid_mutex);
737 memset(&root->root_key, 0, sizeof(root->root_key)); 739 memset(&root->root_key, 0, sizeof(root->root_key));
738 memset(&root->root_item, 0, sizeof(root->root_item)); 740 memset(&root->root_item, 0, sizeof(root->root_item));
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 2d8853543a71..0c9ec8aa304a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -78,6 +78,8 @@ static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = {
78 [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK, 78 [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK,
79}; 79};
80 80
81static void btrfs_truncate(struct inode *inode);
82
81int btrfs_check_free_space(struct btrfs_root *root, u64 num_required, 83int btrfs_check_free_space(struct btrfs_root *root, u64 num_required,
82 int for_del) 84 int for_del)
83{ 85{
@@ -826,6 +828,190 @@ zeroit:
826 return -EIO; 828 return -EIO;
827} 829}
828 830
831/*
832 * This creates an orphan entry for the given inode in case something goes
833 * wrong in the middle of an unlink/truncate.
834 */
835int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode)
836{
837 struct btrfs_root *root = BTRFS_I(inode)->root;
838 int ret = 0;
839
840 spin_lock(&root->orphan_lock);
841
842 /* already on the orphan list, we're good */
843 if (!list_empty(&BTRFS_I(inode)->i_orphan)) {
844 spin_unlock(&root->orphan_lock);
845 return 0;
846 }
847
848 list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list);
849
850 spin_unlock(&root->orphan_lock);
851
852 /*
853 * insert an orphan item to track this unlinked/truncated file
854 */
855 ret = btrfs_insert_orphan_item(trans, root, inode->i_ino);
856
857 return ret;
858}
859
860/*
861 * We have done the truncate/delete so we can go ahead and remove the orphan
862 * item for this particular inode.
863 */
864int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode)
865{
866 struct btrfs_root *root = BTRFS_I(inode)->root;
867 int ret = 0;
868
869 spin_lock(&root->orphan_lock);
870
871 if (list_empty(&BTRFS_I(inode)->i_orphan)) {
872 spin_unlock(&root->orphan_lock);
873 return 0;
874 }
875
876 list_del_init(&BTRFS_I(inode)->i_orphan);
877 if (!trans) {
878 spin_unlock(&root->orphan_lock);
879 return 0;
880 }
881
882 spin_unlock(&root->orphan_lock);
883
884 ret = btrfs_del_orphan_item(trans, root, inode->i_ino);
885
886 return ret;
887}
888
889/*
890 * this cleans up any orphans that may be left on the list from the last use
891 * of this root.
892 */
893void btrfs_orphan_cleanup(struct btrfs_root *root)
894{
895 struct btrfs_path *path;
896 struct extent_buffer *leaf;
897 struct btrfs_item *item;
898 struct btrfs_key key, found_key;
899 struct btrfs_trans_handle *trans;
900 struct inode *inode;
901 int ret = 0, nr_unlink = 0, nr_truncate = 0;
902
903 /* don't do orphan cleanup if the fs is readonly. */
904 if (root->inode->i_sb->s_flags & MS_RDONLY)
905 return;
906
907 path = btrfs_alloc_path();
908 if (!path)
909 return;
910 path->reada = -1;
911
912 key.objectid = BTRFS_ORPHAN_OBJECTID;
913 btrfs_set_key_type(&key, BTRFS_ORPHAN_ITEM_KEY);
914 key.offset = (u64)-1;
915
916 trans = btrfs_start_transaction(root, 1);
917 btrfs_set_trans_block_group(trans, root->inode);
918
919 while (1) {
920 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
921 if (ret < 0) {
922 printk(KERN_ERR "Error searching slot for orphan: %d"
923 "\n", ret);
924 break;
925 }
926
927 /*
928 * if ret == 0 means we found what we were searching for, which
929 * is weird, but possible, so only screw with path if we didnt
930 * find the key and see if we have stuff that matches
931 */
932 if (ret > 0) {
933 if (path->slots[0] == 0)
934 break;
935 path->slots[0]--;
936 }
937
938 /* pull out the item */
939 leaf = path->nodes[0];
940 item = btrfs_item_nr(leaf, path->slots[0]);
941 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
942
943 /* make sure the item matches what we want */
944 if (found_key.objectid != BTRFS_ORPHAN_OBJECTID)
945 break;
946 if (btrfs_key_type(&found_key) != BTRFS_ORPHAN_ITEM_KEY)
947 break;
948
949 /* release the path since we're done with it */
950 btrfs_release_path(root, path);
951
952 /*
953 * this is where we are basically btrfs_lookup, without the
954 * crossing root thing. we store the inode number in the
955 * offset of the orphan item.
956 */
957 inode = btrfs_iget_locked(root->inode->i_sb,
958 found_key.offset, root);
959 if (!inode)
960 break;
961
962 if (inode->i_state & I_NEW) {
963 BTRFS_I(inode)->root = root;
964
965 /* have to set the location manually */
966 BTRFS_I(inode)->location.objectid = inode->i_ino;
967 BTRFS_I(inode)->location.type = BTRFS_INODE_ITEM_KEY;
968 BTRFS_I(inode)->location.offset = 0;
969
970 btrfs_read_locked_inode(inode);
971 unlock_new_inode(inode);
972 }
973
974 /*
975 * add this inode to the orphan list so btrfs_orphan_del does
976 * the proper thing when we hit it
977 */
978 spin_lock(&root->orphan_lock);
979 list_add(&BTRFS_I(inode)->i_orphan, &root->orphan_list);
980 spin_unlock(&root->orphan_lock);
981
982 /*
983 * if this is a bad inode, means we actually succeeded in
984 * removing the inode, but not the orphan record, which means
985 * we need to manually delete the orphan since iput will just
986 * do a destroy_inode
987 */
988 if (is_bad_inode(inode)) {
989 btrfs_orphan_del(trans, inode);
990 iput(inode);
991 continue;
992 }
993
994 /* if we have links, this was a truncate, lets do that */
995 if (inode->i_nlink) {
996 nr_truncate++;
997 btrfs_truncate(inode);
998 } else {
999 nr_unlink++;
1000 }
1001
1002 /* this will do delete_inode and everything for us */
1003 iput(inode);
1004 }
1005
1006 if (nr_unlink)
1007 printk(KERN_INFO "btrfs: unlinked %d orphans\n", nr_unlink);
1008 if (nr_truncate)
1009 printk(KERN_INFO "btrfs: truncated %d orphans\n", nr_truncate);
1010
1011 btrfs_free_path(path);
1012 btrfs_end_transaction(trans, root);
1013}
1014
829void btrfs_read_locked_inode(struct inode *inode) 1015void btrfs_read_locked_inode(struct inode *inode)
830{ 1016{
831 struct btrfs_path *path; 1017 struct btrfs_path *path;
@@ -1067,6 +1253,7 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
1067{ 1253{
1068 struct btrfs_root *root; 1254 struct btrfs_root *root;
1069 struct btrfs_trans_handle *trans; 1255 struct btrfs_trans_handle *trans;
1256 struct inode *inode = dentry->d_inode;
1070 int ret; 1257 int ret;
1071 unsigned long nr = 0; 1258 unsigned long nr = 0;
1072 1259
@@ -1080,6 +1267,10 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
1080 1267
1081 btrfs_set_trans_block_group(trans, dir); 1268 btrfs_set_trans_block_group(trans, dir);
1082 ret = btrfs_unlink_trans(trans, root, dir, dentry); 1269 ret = btrfs_unlink_trans(trans, root, dir, dentry);
1270
1271 if (inode->i_nlink == 0)
1272 ret = btrfs_orphan_add(trans, inode);
1273
1083 nr = trans->blocks_used; 1274 nr = trans->blocks_used;
1084 1275
1085 btrfs_end_transaction_throttle(trans, root); 1276 btrfs_end_transaction_throttle(trans, root);
@@ -1108,12 +1299,17 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
1108 trans = btrfs_start_transaction(root, 1); 1299 trans = btrfs_start_transaction(root, 1);
1109 btrfs_set_trans_block_group(trans, dir); 1300 btrfs_set_trans_block_group(trans, dir);
1110 1301
1302 err = btrfs_orphan_add(trans, inode);
1303 if (err)
1304 goto fail_trans;
1305
1111 /* now the directory is empty */ 1306 /* now the directory is empty */
1112 err = btrfs_unlink_trans(trans, root, dir, dentry); 1307 err = btrfs_unlink_trans(trans, root, dir, dentry);
1113 if (!err) { 1308 if (!err) {
1114 btrfs_i_size_write(inode, 0); 1309 btrfs_i_size_write(inode, 0);
1115 } 1310 }
1116 1311
1312fail_trans:
1117 nr = trans->blocks_used; 1313 nr = trans->blocks_used;
1118 ret = btrfs_end_transaction_throttle(trans, root); 1314 ret = btrfs_end_transaction_throttle(trans, root);
1119fail: 1315fail:
@@ -1131,6 +1327,9 @@ fail:
1131 * 1327 *
1132 * csum items that cross the new i_size are truncated to the new size 1328 * csum items that cross the new i_size are truncated to the new size
1133 * as well. 1329 * as well.
1330 *
1331 * min_type is the minimum key type to truncate down to. If set to 0, this
1332 * will kill all the items on this inode, including the INODE_ITEM_KEY.
1134 */ 1333 */
1135static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, 1334static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
1136 struct btrfs_root *root, 1335 struct btrfs_root *root,
@@ -1495,6 +1694,7 @@ void btrfs_delete_inode(struct inode *inode)
1495 1694
1496 truncate_inode_pages(&inode->i_data, 0); 1695 truncate_inode_pages(&inode->i_data, 0);
1497 if (is_bad_inode(inode)) { 1696 if (is_bad_inode(inode)) {
1697 btrfs_orphan_del(NULL, inode);
1498 goto no_delete; 1698 goto no_delete;
1499 } 1699 }
1500 btrfs_wait_ordered_range(inode, 0, (u64)-1); 1700 btrfs_wait_ordered_range(inode, 0, (u64)-1);
@@ -1504,8 +1704,12 @@ void btrfs_delete_inode(struct inode *inode)
1504 1704
1505 btrfs_set_trans_block_group(trans, inode); 1705 btrfs_set_trans_block_group(trans, inode);
1506 ret = btrfs_truncate_in_trans(trans, root, inode, 0); 1706 ret = btrfs_truncate_in_trans(trans, root, inode, 0);
1507 if (ret) 1707 if (ret) {
1708 btrfs_orphan_del(NULL, inode);
1508 goto no_delete_lock; 1709 goto no_delete_lock;
1710 }
1711
1712 btrfs_orphan_del(trans, inode);
1509 1713
1510 nr = trans->blocks_used; 1714 nr = trans->blocks_used;
1511 clear_inode(inode); 1715 clear_inode(inode);
@@ -1688,7 +1892,7 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
1688 struct btrfs_root *root = bi->root; 1892 struct btrfs_root *root = bi->root;
1689 struct btrfs_root *sub_root = root; 1893 struct btrfs_root *sub_root = root;
1690 struct btrfs_key location; 1894 struct btrfs_key location;
1691 int ret; 1895 int ret, do_orphan = 0;
1692 1896
1693 if (dentry->d_name.len > BTRFS_NAME_LEN) 1897 if (dentry->d_name.len > BTRFS_NAME_LEN)
1694 return ERR_PTR(-ENAMETOOLONG); 1898 return ERR_PTR(-ENAMETOOLONG);
@@ -1706,6 +1910,7 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
1706 return ERR_PTR(ret); 1910 return ERR_PTR(ret);
1707 if (ret > 0) 1911 if (ret > 0)
1708 return ERR_PTR(-ENOENT); 1912 return ERR_PTR(-ENOENT);
1913
1709 inode = btrfs_iget_locked(dir->i_sb, location.objectid, 1914 inode = btrfs_iget_locked(dir->i_sb, location.objectid,
1710 sub_root); 1915 sub_root);
1711 if (!inode) 1916 if (!inode)
@@ -1715,6 +1920,7 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
1715 if (sub_root != root) { 1920 if (sub_root != root) {
1716 igrab(inode); 1921 igrab(inode);
1717 sub_root->inode = inode; 1922 sub_root->inode = inode;
1923 do_orphan = 1;
1718 } 1924 }
1719 BTRFS_I(inode)->root = sub_root; 1925 BTRFS_I(inode)->root = sub_root;
1720 memcpy(&BTRFS_I(inode)->location, &location, 1926 memcpy(&BTRFS_I(inode)->location, &location,
@@ -1723,6 +1929,10 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
1723 unlock_new_inode(inode); 1929 unlock_new_inode(inode);
1724 } 1930 }
1725 } 1931 }
1932
1933 if (unlikely(do_orphan))
1934 btrfs_orphan_cleanup(sub_root);
1935
1726 return d_splice_alias(inode, dentry); 1936 return d_splice_alias(inode, dentry);
1727} 1937}
1728 1938
@@ -2964,12 +3174,19 @@ static void btrfs_truncate(struct inode *inode)
2964 btrfs_set_trans_block_group(trans, inode); 3174 btrfs_set_trans_block_group(trans, inode);
2965 btrfs_i_size_write(inode, inode->i_size); 3175 btrfs_i_size_write(inode, inode->i_size);
2966 3176
3177 ret = btrfs_orphan_add(trans, inode);
3178 if (ret)
3179 goto out;
2967 /* FIXME, add redo link to tree so we don't leak on crash */ 3180 /* FIXME, add redo link to tree so we don't leak on crash */
2968 ret = btrfs_truncate_in_trans(trans, root, inode, 3181 ret = btrfs_truncate_in_trans(trans, root, inode,
2969 BTRFS_EXTENT_DATA_KEY); 3182 BTRFS_EXTENT_DATA_KEY);
2970 btrfs_update_inode(trans, root, inode); 3183 btrfs_update_inode(trans, root, inode);
2971 nr = trans->blocks_used;
2972 3184
3185 ret = btrfs_orphan_del(trans, inode);
3186 BUG_ON(ret);
3187
3188out:
3189 nr = trans->blocks_used;
2973 ret = btrfs_end_transaction_throttle(trans, root); 3190 ret = btrfs_end_transaction_throttle(trans, root);
2974 BUG_ON(ret); 3191 BUG_ON(ret);
2975 btrfs_btree_balance_dirty(root, nr); 3192 btrfs_btree_balance_dirty(root, nr);
@@ -3046,6 +3263,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
3046 btrfs_ordered_inode_tree_init(&ei->ordered_tree); 3263 btrfs_ordered_inode_tree_init(&ei->ordered_tree);
3047 ei->i_acl = BTRFS_ACL_NOT_CACHED; 3264 ei->i_acl = BTRFS_ACL_NOT_CACHED;
3048 ei->i_default_acl = BTRFS_ACL_NOT_CACHED; 3265 ei->i_default_acl = BTRFS_ACL_NOT_CACHED;
3266 INIT_LIST_HEAD(&ei->i_orphan);
3049 return &ei->vfs_inode; 3267 return &ei->vfs_inode;
3050} 3268}
3051 3269
@@ -3062,6 +3280,14 @@ void btrfs_destroy_inode(struct inode *inode)
3062 BTRFS_I(inode)->i_default_acl != BTRFS_ACL_NOT_CACHED) 3280 BTRFS_I(inode)->i_default_acl != BTRFS_ACL_NOT_CACHED)
3063 posix_acl_release(BTRFS_I(inode)->i_default_acl); 3281 posix_acl_release(BTRFS_I(inode)->i_default_acl);
3064 3282
3283 spin_lock(&BTRFS_I(inode)->root->orphan_lock);
3284 if (!list_empty(&BTRFS_I(inode)->i_orphan)) {
3285 printk(KERN_ERR "BTRFS: inode %lu: inode still on the orphan"
3286 " list\n", inode->i_ino);
3287 dump_stack();
3288 }
3289 spin_unlock(&BTRFS_I(inode)->root->orphan_lock);
3290
3065 while(1) { 3291 while(1) {
3066 ordered = btrfs_lookup_first_ordered_extent(inode, (u64)-1); 3292 ordered = btrfs_lookup_first_ordered_extent(inode, (u64)-1);
3067 if (!ordered) 3293 if (!ordered)
@@ -3202,6 +3428,11 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
3202 ret = btrfs_unlink_trans(trans, root, new_dir, new_dentry); 3428 ret = btrfs_unlink_trans(trans, root, new_dir, new_dentry);
3203 if (ret) 3429 if (ret)
3204 goto out_fail; 3430 goto out_fail;
3431 if (new_inode->i_nlink == 0) {
3432 ret = btrfs_orphan_add(trans, new_inode);
3433 if (ret)
3434 goto out_fail;
3435 }
3205 } 3436 }
3206 ret = btrfs_set_inode_index(new_dir, old_inode); 3437 ret = btrfs_set_inode_index(new_dir, old_inode);
3207 if (ret) 3438 if (ret)
diff --git a/fs/btrfs/orphan.c b/fs/btrfs/orphan.c
new file mode 100644
index 000000000000..3c0d52af4f80
--- /dev/null
+++ b/fs/btrfs/orphan.c
@@ -0,0 +1,67 @@
1/*
2 * Copyright (C) 2008 Red Hat. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
17 */
18
19#include "ctree.h"
20#include "disk-io.h"
21
22int btrfs_insert_orphan_item(struct btrfs_trans_handle *trans,
23 struct btrfs_root *root, u64 offset)
24{
25 struct btrfs_path *path;
26 struct btrfs_key key;
27 int ret = 0;
28
29 key.objectid = BTRFS_ORPHAN_OBJECTID;
30 btrfs_set_key_type(&key, BTRFS_ORPHAN_ITEM_KEY);
31 key.offset = offset;
32
33 path = btrfs_alloc_path();
34 if (!path)
35 return -ENOMEM;
36
37 ret = btrfs_insert_empty_item(trans, root, path, &key, 0);
38
39 btrfs_free_path(path);
40 return ret;
41}
42
43int btrfs_del_orphan_item(struct btrfs_trans_handle *trans,
44 struct btrfs_root *root, u64 offset)
45{
46 struct btrfs_path *path;
47 struct btrfs_key key;
48 int ret = 0;
49
50 key.objectid = BTRFS_ORPHAN_OBJECTID;
51 btrfs_set_key_type(&key, BTRFS_ORPHAN_ITEM_KEY);
52 key.offset = offset;
53
54 path = btrfs_alloc_path();
55 if (!path)
56 return -ENOMEM;
57
58 ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
59 if (ret)
60 goto out;
61
62 ret = btrfs_del_item(trans, root, path);
63
64out:
65 btrfs_free_path(path);
66 return ret;
67}