diff options
author | Josef Bacik <jbacik@redhat.com> | 2008-07-24 12:17:14 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:05 -0400 |
commit | 7b1287662304c3cb05cb38f5e3e2d69f386e8f10 (patch) | |
tree | bb589bfc3854f801b4098f2f2140e42a2f9e8071 /fs/btrfs/inode.c | |
parent | 33268eaf0b3db5e2bd12c0ada81a8e8f87a46d68 (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/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 237 |
1 files changed, 234 insertions, 3 deletions
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 | ||
81 | static void btrfs_truncate(struct inode *inode); | ||
82 | |||
81 | int btrfs_check_free_space(struct btrfs_root *root, u64 num_required, | 83 | int 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 | */ | ||
835 | int 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 | */ | ||
864 | int 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 | */ | ||
893 | void 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 | |||
829 | void btrfs_read_locked_inode(struct inode *inode) | 1015 | void 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 | ||
1312 | fail_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); |
1119 | fail: | 1315 | fail: |
@@ -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 | */ |
1135 | static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | 1334 | static 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 | |||
3188 | out: | ||
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) |