diff options
| -rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 3 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 15 | ||||
| -rw-r--r-- | fs/btrfs/tests/inode-tests.c | 197 |
4 files changed, 217 insertions, 1 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index a0c90a324f53..5bd721a1516e 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -3910,6 +3910,9 @@ int btrfs_prealloc_file_range_trans(struct inode *inode, | |||
| 3910 | loff_t actual_len, u64 *alloc_hint); | 3910 | loff_t actual_len, u64 *alloc_hint); |
| 3911 | int btrfs_inode_check_errors(struct inode *inode); | 3911 | int btrfs_inode_check_errors(struct inode *inode); |
| 3912 | extern const struct dentry_operations btrfs_dentry_operations; | 3912 | extern const struct dentry_operations btrfs_dentry_operations; |
| 3913 | #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS | ||
| 3914 | void btrfs_test_inode_set_ops(struct inode *inode); | ||
| 3915 | #endif | ||
| 3913 | 3916 | ||
| 3914 | /* ioctl.c */ | 3917 | /* ioctl.c */ |
| 3915 | long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | 3918 | long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 3ac3fefb1625..d1ca86ea9993 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -5285,6 +5285,9 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes) | |||
| 5285 | if (dropped > 0) | 5285 | if (dropped > 0) |
| 5286 | to_free += btrfs_calc_trans_metadata_size(root, dropped); | 5286 | to_free += btrfs_calc_trans_metadata_size(root, dropped); |
| 5287 | 5287 | ||
| 5288 | if (btrfs_test_is_dummy_root(root)) | ||
| 5289 | return; | ||
| 5290 | |||
| 5288 | trace_btrfs_space_reservation(root->fs_info, "delalloc", | 5291 | trace_btrfs_space_reservation(root->fs_info, "delalloc", |
| 5289 | btrfs_ino(inode), to_free, 0); | 5292 | btrfs_ino(inode), to_free, 0); |
| 5290 | if (root->fs_info->quota_enabled) { | 5293 | if (root->fs_info->quota_enabled) { |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index bb74a4181075..3717b3d4c2ce 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -108,6 +108,13 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start, | |||
| 108 | 108 | ||
| 109 | static int btrfs_dirty_inode(struct inode *inode); | 109 | static int btrfs_dirty_inode(struct inode *inode); |
| 110 | 110 | ||
| 111 | #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS | ||
| 112 | void btrfs_test_inode_set_ops(struct inode *inode) | ||
| 113 | { | ||
| 114 | BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; | ||
| 115 | } | ||
| 116 | #endif | ||
| 117 | |||
| 111 | static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, | 118 | static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, |
| 112 | struct inode *inode, struct inode *dir, | 119 | struct inode *inode, struct inode *dir, |
| 113 | const struct qstr *qstr) | 120 | const struct qstr *qstr) |
| @@ -1694,6 +1701,10 @@ static void btrfs_set_bit_hook(struct inode *inode, | |||
| 1694 | spin_unlock(&BTRFS_I(inode)->lock); | 1701 | spin_unlock(&BTRFS_I(inode)->lock); |
| 1695 | } | 1702 | } |
| 1696 | 1703 | ||
| 1704 | /* For sanity tests */ | ||
| 1705 | if (btrfs_test_is_dummy_root(root)) | ||
| 1706 | return; | ||
| 1707 | |||
| 1697 | __percpu_counter_add(&root->fs_info->delalloc_bytes, len, | 1708 | __percpu_counter_add(&root->fs_info->delalloc_bytes, len, |
| 1698 | root->fs_info->delalloc_batch); | 1709 | root->fs_info->delalloc_batch); |
| 1699 | spin_lock(&BTRFS_I(inode)->lock); | 1710 | spin_lock(&BTRFS_I(inode)->lock); |
| @@ -1749,6 +1760,10 @@ static void btrfs_clear_bit_hook(struct inode *inode, | |||
| 1749 | root != root->fs_info->tree_root) | 1760 | root != root->fs_info->tree_root) |
| 1750 | btrfs_delalloc_release_metadata(inode, len); | 1761 | btrfs_delalloc_release_metadata(inode, len); |
| 1751 | 1762 | ||
| 1763 | /* For sanity tests. */ | ||
| 1764 | if (btrfs_test_is_dummy_root(root)) | ||
| 1765 | return; | ||
| 1766 | |||
| 1752 | if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID | 1767 | if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID |
| 1753 | && do_list && !(state->state & EXTENT_NORESERVE)) | 1768 | && do_list && !(state->state & EXTENT_NORESERVE)) |
| 1754 | btrfs_free_reserved_data_space(inode, len); | 1769 | btrfs_free_reserved_data_space(inode, len); |
diff --git a/fs/btrfs/tests/inode-tests.c b/fs/btrfs/tests/inode-tests.c index a116b55ce788..054fc0d97131 100644 --- a/fs/btrfs/tests/inode-tests.c +++ b/fs/btrfs/tests/inode-tests.c | |||
| @@ -911,6 +911,197 @@ out: | |||
| 911 | return ret; | 911 | return ret; |
| 912 | } | 912 | } |
| 913 | 913 | ||
| 914 | static int test_extent_accounting(void) | ||
| 915 | { | ||
| 916 | struct inode *inode = NULL; | ||
| 917 | struct btrfs_root *root = NULL; | ||
| 918 | int ret = -ENOMEM; | ||
| 919 | |||
| 920 | inode = btrfs_new_test_inode(); | ||
| 921 | if (!inode) { | ||
| 922 | test_msg("Couldn't allocate inode\n"); | ||
| 923 | return ret; | ||
| 924 | } | ||
| 925 | |||
| 926 | root = btrfs_alloc_dummy_root(); | ||
| 927 | if (IS_ERR(root)) { | ||
| 928 | test_msg("Couldn't allocate root\n"); | ||
| 929 | goto out; | ||
| 930 | } | ||
| 931 | |||
| 932 | root->fs_info = btrfs_alloc_dummy_fs_info(); | ||
| 933 | if (!root->fs_info) { | ||
| 934 | test_msg("Couldn't allocate dummy fs info\n"); | ||
| 935 | goto out; | ||
| 936 | } | ||
| 937 | |||
| 938 | BTRFS_I(inode)->root = root; | ||
| 939 | btrfs_test_inode_set_ops(inode); | ||
| 940 | |||
| 941 | /* [BTRFS_MAX_EXTENT_SIZE] */ | ||
| 942 | BTRFS_I(inode)->outstanding_extents++; | ||
| 943 | ret = btrfs_set_extent_delalloc(inode, 0, BTRFS_MAX_EXTENT_SIZE - 1, | ||
| 944 | NULL); | ||
| 945 | if (ret) { | ||
| 946 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); | ||
| 947 | goto out; | ||
| 948 | } | ||
| 949 | if (BTRFS_I(inode)->outstanding_extents != 1) { | ||
| 950 | ret = -EINVAL; | ||
| 951 | test_msg("Miscount, wanted 1, got %u\n", | ||
| 952 | BTRFS_I(inode)->outstanding_extents); | ||
| 953 | goto out; | ||
| 954 | } | ||
| 955 | |||
| 956 | /* [BTRFS_MAX_EXTENT_SIZE][4k] */ | ||
| 957 | BTRFS_I(inode)->outstanding_extents++; | ||
| 958 | ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE, | ||
| 959 | BTRFS_MAX_EXTENT_SIZE + 4095, NULL); | ||
| 960 | if (ret) { | ||
| 961 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); | ||
| 962 | goto out; | ||
| 963 | } | ||
| 964 | if (BTRFS_I(inode)->outstanding_extents != 2) { | ||
| 965 | ret = -EINVAL; | ||
| 966 | test_msg("Miscount, wanted 2, got %u\n", | ||
| 967 | BTRFS_I(inode)->outstanding_extents); | ||
| 968 | goto out; | ||
| 969 | } | ||
| 970 | |||
| 971 | /* [BTRFS_MAX_EXTENT_SIZE/2][4K HOLE][the rest] */ | ||
| 972 | ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, | ||
| 973 | BTRFS_MAX_EXTENT_SIZE >> 1, | ||
| 974 | (BTRFS_MAX_EXTENT_SIZE >> 1) + 4095, | ||
| 975 | EXTENT_DELALLOC | EXTENT_DIRTY | | ||
| 976 | EXTENT_UPTODATE | EXTENT_DO_ACCOUNTING, 0, 0, | ||
| 977 | NULL, GFP_NOFS); | ||
| 978 | if (ret) { | ||
| 979 | test_msg("clear_extent_bit returned %d\n", ret); | ||
| 980 | goto out; | ||
| 981 | } | ||
| 982 | if (BTRFS_I(inode)->outstanding_extents != 2) { | ||
| 983 | ret = -EINVAL; | ||
| 984 | test_msg("Miscount, wanted 2, got %u\n", | ||
| 985 | BTRFS_I(inode)->outstanding_extents); | ||
| 986 | goto out; | ||
| 987 | } | ||
| 988 | |||
| 989 | /* [BTRFS_MAX_EXTENT_SIZE][4K] */ | ||
| 990 | BTRFS_I(inode)->outstanding_extents++; | ||
| 991 | ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE >> 1, | ||
| 992 | (BTRFS_MAX_EXTENT_SIZE >> 1) + 4095, | ||
| 993 | NULL); | ||
| 994 | if (ret) { | ||
| 995 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); | ||
| 996 | goto out; | ||
| 997 | } | ||
| 998 | if (BTRFS_I(inode)->outstanding_extents != 2) { | ||
| 999 | ret = -EINVAL; | ||
| 1000 | test_msg("Miscount, wanted 2, got %u\n", | ||
| 1001 | BTRFS_I(inode)->outstanding_extents); | ||
| 1002 | goto out; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | /* | ||
| 1006 | * [BTRFS_MAX_EXTENT_SIZE+4K][4K HOLE][BTRFS_MAX_EXTENT_SIZE+4K] | ||
| 1007 | * | ||
| 1008 | * I'm artificially adding 2 to outstanding_extents because in the | ||
| 1009 | * buffered IO case we'd add things up as we go, but I don't feel like | ||
| 1010 | * doing that here, this isn't the interesting case we want to test. | ||
| 1011 | */ | ||
| 1012 | BTRFS_I(inode)->outstanding_extents += 2; | ||
| 1013 | ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE + 8192, | ||
| 1014 | (BTRFS_MAX_EXTENT_SIZE << 1) + 12287, | ||
| 1015 | NULL); | ||
| 1016 | if (ret) { | ||
| 1017 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); | ||
| 1018 | goto out; | ||
| 1019 | } | ||
| 1020 | if (BTRFS_I(inode)->outstanding_extents != 4) { | ||
| 1021 | ret = -EINVAL; | ||
| 1022 | test_msg("Miscount, wanted 4, got %u\n", | ||
| 1023 | BTRFS_I(inode)->outstanding_extents); | ||
| 1024 | goto out; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | /* [BTRFS_MAX_EXTENT_SIZE+4k][4k][BTRFS_MAX_EXTENT_SIZE+4k] */ | ||
| 1028 | BTRFS_I(inode)->outstanding_extents++; | ||
| 1029 | ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE+4096, | ||
| 1030 | BTRFS_MAX_EXTENT_SIZE+8191, NULL); | ||
| 1031 | if (ret) { | ||
| 1032 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); | ||
| 1033 | goto out; | ||
| 1034 | } | ||
| 1035 | if (BTRFS_I(inode)->outstanding_extents != 3) { | ||
| 1036 | ret = -EINVAL; | ||
| 1037 | test_msg("Miscount, wanted 3, got %u\n", | ||
| 1038 | BTRFS_I(inode)->outstanding_extents); | ||
| 1039 | goto out; | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | /* [BTRFS_MAX_EXTENT_SIZE+4k][4K HOLE][BTRFS_MAX_EXTENT_SIZE+4k] */ | ||
| 1043 | ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, | ||
| 1044 | BTRFS_MAX_EXTENT_SIZE+4096, | ||
| 1045 | BTRFS_MAX_EXTENT_SIZE+8191, | ||
| 1046 | EXTENT_DIRTY | EXTENT_DELALLOC | | ||
| 1047 | EXTENT_DO_ACCOUNTING | EXTENT_UPTODATE, 0, 0, | ||
| 1048 | NULL, GFP_NOFS); | ||
| 1049 | if (ret) { | ||
| 1050 | test_msg("clear_extent_bit returned %d\n", ret); | ||
| 1051 | goto out; | ||
| 1052 | } | ||
| 1053 | if (BTRFS_I(inode)->outstanding_extents != 4) { | ||
| 1054 | ret = -EINVAL; | ||
| 1055 | test_msg("Miscount, wanted 4, got %u\n", | ||
| 1056 | BTRFS_I(inode)->outstanding_extents); | ||
| 1057 | goto out; | ||
| 1058 | } | ||
| 1059 | |||
| 1060 | /* | ||
| 1061 | * Refill the hole again just for good measure, because I thought it | ||
| 1062 | * might fail and I'd rather satisfy my paranoia at this point. | ||
| 1063 | */ | ||
| 1064 | BTRFS_I(inode)->outstanding_extents++; | ||
| 1065 | ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE+4096, | ||
| 1066 | BTRFS_MAX_EXTENT_SIZE+8191, NULL); | ||
| 1067 | if (ret) { | ||
| 1068 | test_msg("btrfs_set_extent_delalloc returned %d\n", ret); | ||
| 1069 | goto out; | ||
| 1070 | } | ||
| 1071 | if (BTRFS_I(inode)->outstanding_extents != 3) { | ||
| 1072 | ret = -EINVAL; | ||
| 1073 | test_msg("Miscount, wanted 3, got %u\n", | ||
| 1074 | BTRFS_I(inode)->outstanding_extents); | ||
| 1075 | goto out; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | /* Empty */ | ||
| 1079 | ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1, | ||
| 1080 | EXTENT_DIRTY | EXTENT_DELALLOC | | ||
| 1081 | EXTENT_DO_ACCOUNTING | EXTENT_UPTODATE, 0, 0, | ||
| 1082 | NULL, GFP_NOFS); | ||
| 1083 | if (ret) { | ||
| 1084 | test_msg("clear_extent_bit returned %d\n", ret); | ||
| 1085 | goto out; | ||
| 1086 | } | ||
| 1087 | if (BTRFS_I(inode)->outstanding_extents) { | ||
| 1088 | ret = -EINVAL; | ||
| 1089 | test_msg("Miscount, wanted 0, got %u\n", | ||
| 1090 | BTRFS_I(inode)->outstanding_extents); | ||
| 1091 | goto out; | ||
| 1092 | } | ||
| 1093 | ret = 0; | ||
| 1094 | out: | ||
| 1095 | if (ret) | ||
| 1096 | clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, (u64)-1, | ||
| 1097 | EXTENT_DIRTY | EXTENT_DELALLOC | | ||
| 1098 | EXTENT_DO_ACCOUNTING | EXTENT_UPTODATE, 0, 0, | ||
| 1099 | NULL, GFP_NOFS); | ||
| 1100 | iput(inode); | ||
| 1101 | btrfs_free_dummy_root(root); | ||
| 1102 | return ret; | ||
| 1103 | } | ||
| 1104 | |||
| 914 | int btrfs_test_inodes(void) | 1105 | int btrfs_test_inodes(void) |
| 915 | { | 1106 | { |
| 916 | int ret; | 1107 | int ret; |
| @@ -924,5 +1115,9 @@ int btrfs_test_inodes(void) | |||
| 924 | if (ret) | 1115 | if (ret) |
| 925 | return ret; | 1116 | return ret; |
| 926 | test_msg("Running hole first btrfs_get_extent test\n"); | 1117 | test_msg("Running hole first btrfs_get_extent test\n"); |
| 927 | return test_hole_first(); | 1118 | ret = test_hole_first(); |
| 1119 | if (ret) | ||
| 1120 | return ret; | ||
| 1121 | test_msg("Running outstanding_extents tests\n"); | ||
| 1122 | return test_extent_accounting(); | ||
| 928 | } | 1123 | } |
