diff options
author | Tao Ma <tao.ma@oracle.com> | 2009-08-11 02:33:14 -0400 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2009-09-22 23:09:33 -0400 |
commit | e73a819db9c2d6c4065b7cab7374709b6939e8f1 (patch) | |
tree | 40968bc5b37d3b55e382267683c9612d4697f036 /fs | |
parent | e2e9f6082b5ff099978774d5c0148e062344c2f9 (diff) |
ocfs2: Add support for incrementing refcount in the tree.
Given a physical cpos and length, increment the refcount
in the tree. If the extent has not been seen before, a refcount
record is created for it. Refcount records may be merged or
split by this operation.
Signed-off-by: Tao Ma <tao.ma@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ocfs2/extent_map.c | 15 | ||||
-rw-r--r-- | fs/ocfs2/extent_map.h | 5 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2_fs.h | 7 | ||||
-rw-r--r-- | fs/ocfs2/refcounttree.c | 1053 |
4 files changed, 1073 insertions, 7 deletions
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index dc9482cb463a..40b51056bb32 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c | |||
@@ -353,11 +353,11 @@ static int ocfs2_search_for_hole_index(struct ocfs2_extent_list *el, | |||
353 | * eb_bh is NULL. Otherwise, eb_bh should point to the extent block | 353 | * eb_bh is NULL. Otherwise, eb_bh should point to the extent block |
354 | * containing el. | 354 | * containing el. |
355 | */ | 355 | */ |
356 | static int ocfs2_figure_hole_clusters(struct inode *inode, | 356 | int ocfs2_figure_hole_clusters(struct ocfs2_caching_info *ci, |
357 | struct ocfs2_extent_list *el, | 357 | struct ocfs2_extent_list *el, |
358 | struct buffer_head *eb_bh, | 358 | struct buffer_head *eb_bh, |
359 | u32 v_cluster, | 359 | u32 v_cluster, |
360 | u32 *num_clusters) | 360 | u32 *num_clusters) |
361 | { | 361 | { |
362 | int ret, i; | 362 | int ret, i; |
363 | struct buffer_head *next_eb_bh = NULL; | 363 | struct buffer_head *next_eb_bh = NULL; |
@@ -375,7 +375,7 @@ static int ocfs2_figure_hole_clusters(struct inode *inode, | |||
375 | if (le64_to_cpu(eb->h_next_leaf_blk) == 0ULL) | 375 | if (le64_to_cpu(eb->h_next_leaf_blk) == 0ULL) |
376 | goto no_more_extents; | 376 | goto no_more_extents; |
377 | 377 | ||
378 | ret = ocfs2_read_extent_block(INODE_CACHE(inode), | 378 | ret = ocfs2_read_extent_block(ci, |
379 | le64_to_cpu(eb->h_next_leaf_blk), | 379 | le64_to_cpu(eb->h_next_leaf_blk), |
380 | &next_eb_bh); | 380 | &next_eb_bh); |
381 | if (ret) { | 381 | if (ret) { |
@@ -456,7 +456,8 @@ static int ocfs2_get_clusters_nocache(struct inode *inode, | |||
456 | * field. | 456 | * field. |
457 | */ | 457 | */ |
458 | if (hole_len) { | 458 | if (hole_len) { |
459 | ret = ocfs2_figure_hole_clusters(inode, el, eb_bh, | 459 | ret = ocfs2_figure_hole_clusters(INODE_CACHE(inode), |
460 | el, eb_bh, | ||
460 | v_cluster, &len); | 461 | v_cluster, &len); |
461 | if (ret) { | 462 | if (ret) { |
462 | mlog_errno(ret); | 463 | mlog_errno(ret); |
diff --git a/fs/ocfs2/extent_map.h b/fs/ocfs2/extent_map.h index b7dd9731b462..9942f47efda7 100644 --- a/fs/ocfs2/extent_map.h +++ b/fs/ocfs2/extent_map.h | |||
@@ -61,6 +61,11 @@ int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr, | |||
61 | struct buffer_head *bhs[], int flags, | 61 | struct buffer_head *bhs[], int flags, |
62 | int (*validate)(struct super_block *sb, | 62 | int (*validate)(struct super_block *sb, |
63 | struct buffer_head *bh)); | 63 | struct buffer_head *bh)); |
64 | int ocfs2_figure_hole_clusters(struct ocfs2_caching_info *ci, | ||
65 | struct ocfs2_extent_list *el, | ||
66 | struct buffer_head *eb_bh, | ||
67 | u32 v_cluster, | ||
68 | u32 *num_clusters); | ||
64 | static inline int ocfs2_read_virt_block(struct inode *inode, u64 v_block, | 69 | static inline int ocfs2_read_virt_block(struct inode *inode, u64 v_block, |
65 | struct buffer_head **bh, | 70 | struct buffer_head **bh, |
66 | int (*validate)(struct super_block *sb, | 71 | int (*validate)(struct super_block *sb, |
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index e4288b446ec0..40072cdef7b6 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h | |||
@@ -916,6 +916,7 @@ struct ocfs2_refcount_rec { | |||
916 | __le32 r_refcount; /* Reference count of this extent */ | 916 | __le32 r_refcount; /* Reference count of this extent */ |
917 | /*10*/ | 917 | /*10*/ |
918 | }; | 918 | }; |
919 | #define OCFS2_32BIT_POS_MASK (0xffffffffULL) | ||
919 | 920 | ||
920 | #define OCFS2_REFCOUNT_LEAF_FL (0x00000001) | 921 | #define OCFS2_REFCOUNT_LEAF_FL (0x00000001) |
921 | #define OCFS2_REFCOUNT_TREE_FL (0x00000002) | 922 | #define OCFS2_REFCOUNT_TREE_FL (0x00000002) |
@@ -1394,6 +1395,12 @@ static inline u16 ocfs2_refcount_recs_per_rb(struct super_block *sb) | |||
1394 | 1395 | ||
1395 | return size / sizeof(struct ocfs2_refcount_rec); | 1396 | return size / sizeof(struct ocfs2_refcount_rec); |
1396 | } | 1397 | } |
1398 | |||
1399 | static inline u32 | ||
1400 | ocfs2_get_ref_rec_low_cpos(const struct ocfs2_refcount_rec *rec) | ||
1401 | { | ||
1402 | return le64_to_cpu(rec->r_cpos) & OCFS2_32BIT_POS_MASK; | ||
1403 | } | ||
1397 | #else | 1404 | #else |
1398 | static inline int ocfs2_fast_symlink_chars(int blocksize) | 1405 | static inline int ocfs2_fast_symlink_chars(int blocksize) |
1399 | { | 1406 | { |
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index d0d6fa312b01..ee0422ce72c4 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * General Public License for more details. | 15 | * General Public License for more details. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/sort.h> | ||
18 | #define MLOG_MASK_PREFIX ML_REFCOUNT | 19 | #define MLOG_MASK_PREFIX ML_REFCOUNT |
19 | #include <cluster/masklog.h> | 20 | #include <cluster/masklog.h> |
20 | #include "ocfs2.h" | 21 | #include "ocfs2.h" |
@@ -29,6 +30,7 @@ | |||
29 | #include "refcounttree.h" | 30 | #include "refcounttree.h" |
30 | #include "sysfile.h" | 31 | #include "sysfile.h" |
31 | #include "dlmglue.h" | 32 | #include "dlmglue.h" |
33 | #include "extent_map.h" | ||
32 | 34 | ||
33 | static inline struct ocfs2_refcount_tree * | 35 | static inline struct ocfs2_refcount_tree * |
34 | cache_info_to_refcount(struct ocfs2_caching_info *ci) | 36 | cache_info_to_refcount(struct ocfs2_caching_info *ci) |
@@ -848,3 +850,1054 @@ out: | |||
848 | 850 | ||
849 | return ret; | 851 | return ret; |
850 | } | 852 | } |
853 | |||
854 | static void ocfs2_find_refcount_rec_in_rl(struct ocfs2_caching_info *ci, | ||
855 | struct buffer_head *ref_leaf_bh, | ||
856 | u64 cpos, unsigned int len, | ||
857 | struct ocfs2_refcount_rec *ret_rec, | ||
858 | int *index) | ||
859 | { | ||
860 | int i = 0; | ||
861 | struct ocfs2_refcount_block *rb = | ||
862 | (struct ocfs2_refcount_block *)ref_leaf_bh->b_data; | ||
863 | struct ocfs2_refcount_rec *rec = NULL; | ||
864 | |||
865 | for (; i < le16_to_cpu(rb->rf_records.rl_used); i++) { | ||
866 | rec = &rb->rf_records.rl_recs[i]; | ||
867 | |||
868 | if (le64_to_cpu(rec->r_cpos) + | ||
869 | le32_to_cpu(rec->r_clusters) <= cpos) | ||
870 | continue; | ||
871 | else if (le64_to_cpu(rec->r_cpos) > cpos) | ||
872 | break; | ||
873 | |||
874 | /* ok, cpos fail in this rec. Just return. */ | ||
875 | if (ret_rec) | ||
876 | *ret_rec = *rec; | ||
877 | goto out; | ||
878 | } | ||
879 | |||
880 | if (ret_rec) { | ||
881 | /* We meet with a hole here, so fake the rec. */ | ||
882 | ret_rec->r_cpos = cpu_to_le64(cpos); | ||
883 | ret_rec->r_refcount = 0; | ||
884 | if (i < le16_to_cpu(rb->rf_records.rl_used) && | ||
885 | le64_to_cpu(rec->r_cpos) < cpos + len) | ||
886 | ret_rec->r_clusters = | ||
887 | cpu_to_le32(le64_to_cpu(rec->r_cpos) - cpos); | ||
888 | else | ||
889 | ret_rec->r_clusters = cpu_to_le32(len); | ||
890 | } | ||
891 | |||
892 | out: | ||
893 | *index = i; | ||
894 | } | ||
895 | |||
896 | /* | ||
897 | * Given a cpos and len, try to find the refcount record which contains cpos. | ||
898 | * 1. If cpos can be found in one refcount record, return the record. | ||
899 | * 2. If cpos can't be found, return a fake record which start from cpos | ||
900 | * and end at a small value between cpos+len and start of the next record. | ||
901 | * This fake record has r_refcount = 0. | ||
902 | */ | ||
903 | static int ocfs2_get_refcount_rec(struct ocfs2_caching_info *ci, | ||
904 | struct buffer_head *ref_root_bh, | ||
905 | u64 cpos, unsigned int len, | ||
906 | struct ocfs2_refcount_rec *ret_rec, | ||
907 | int *index, | ||
908 | struct buffer_head **ret_bh) | ||
909 | { | ||
910 | int ret = 0, i, found; | ||
911 | u32 low_cpos; | ||
912 | struct ocfs2_extent_list *el; | ||
913 | struct ocfs2_extent_rec *tmp, *rec = NULL; | ||
914 | struct ocfs2_extent_block *eb; | ||
915 | struct buffer_head *eb_bh = NULL, *ref_leaf_bh = NULL; | ||
916 | struct super_block *sb = ocfs2_metadata_cache_get_super(ci); | ||
917 | struct ocfs2_refcount_block *rb = | ||
918 | (struct ocfs2_refcount_block *)ref_root_bh->b_data; | ||
919 | |||
920 | if (!(le32_to_cpu(rb->rf_flags) & OCFS2_REFCOUNT_TREE_FL)) { | ||
921 | ocfs2_find_refcount_rec_in_rl(ci, ref_root_bh, cpos, len, | ||
922 | ret_rec, index); | ||
923 | *ret_bh = ref_root_bh; | ||
924 | get_bh(ref_root_bh); | ||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | el = &rb->rf_list; | ||
929 | low_cpos = cpos & OCFS2_32BIT_POS_MASK; | ||
930 | |||
931 | if (el->l_tree_depth) { | ||
932 | ret = ocfs2_find_leaf(ci, el, low_cpos, &eb_bh); | ||
933 | if (ret) { | ||
934 | mlog_errno(ret); | ||
935 | goto out; | ||
936 | } | ||
937 | |||
938 | eb = (struct ocfs2_extent_block *) eb_bh->b_data; | ||
939 | el = &eb->h_list; | ||
940 | |||
941 | if (el->l_tree_depth) { | ||
942 | ocfs2_error(sb, | ||
943 | "refcount tree %llu has non zero tree " | ||
944 | "depth in leaf btree tree block %llu\n", | ||
945 | (unsigned long long)ocfs2_metadata_cache_owner(ci), | ||
946 | (unsigned long long)eb_bh->b_blocknr); | ||
947 | ret = -EROFS; | ||
948 | goto out; | ||
949 | } | ||
950 | } | ||
951 | |||
952 | found = 0; | ||
953 | for (i = le16_to_cpu(el->l_next_free_rec) - 1; i >= 0; i--) { | ||
954 | rec = &el->l_recs[i]; | ||
955 | |||
956 | if (le32_to_cpu(rec->e_cpos) <= low_cpos) { | ||
957 | found = 1; | ||
958 | break; | ||
959 | } | ||
960 | } | ||
961 | |||
962 | /* adjust len when we have ocfs2_extent_rec after it. */ | ||
963 | if (found && i < le16_to_cpu(el->l_next_free_rec) - 1) { | ||
964 | tmp = &el->l_recs[i+1]; | ||
965 | |||
966 | if (le32_to_cpu(tmp->e_cpos) < cpos + len) | ||
967 | len = le32_to_cpu(tmp->e_cpos) - cpos; | ||
968 | } | ||
969 | |||
970 | ret = ocfs2_read_refcount_block(ci, le64_to_cpu(rec->e_blkno), | ||
971 | &ref_leaf_bh); | ||
972 | if (ret) { | ||
973 | mlog_errno(ret); | ||
974 | goto out; | ||
975 | } | ||
976 | |||
977 | ocfs2_find_refcount_rec_in_rl(ci, ref_leaf_bh, cpos, len, | ||
978 | ret_rec, index); | ||
979 | *ret_bh = ref_leaf_bh; | ||
980 | out: | ||
981 | brelse(eb_bh); | ||
982 | return ret; | ||
983 | } | ||
984 | |||
985 | enum ocfs2_ref_rec_contig { | ||
986 | REF_CONTIG_NONE = 0, | ||
987 | REF_CONTIG_LEFT, | ||
988 | REF_CONTIG_RIGHT, | ||
989 | REF_CONTIG_LEFTRIGHT, | ||
990 | }; | ||
991 | |||
992 | static enum ocfs2_ref_rec_contig | ||
993 | ocfs2_refcount_rec_adjacent(struct ocfs2_refcount_block *rb, | ||
994 | int index) | ||
995 | { | ||
996 | if ((rb->rf_records.rl_recs[index].r_refcount == | ||
997 | rb->rf_records.rl_recs[index + 1].r_refcount) && | ||
998 | (le64_to_cpu(rb->rf_records.rl_recs[index].r_cpos) + | ||
999 | le32_to_cpu(rb->rf_records.rl_recs[index].r_clusters) == | ||
1000 | le64_to_cpu(rb->rf_records.rl_recs[index + 1].r_cpos))) | ||
1001 | return REF_CONTIG_RIGHT; | ||
1002 | |||
1003 | return REF_CONTIG_NONE; | ||
1004 | } | ||
1005 | |||
1006 | static enum ocfs2_ref_rec_contig | ||
1007 | ocfs2_refcount_rec_contig(struct ocfs2_refcount_block *rb, | ||
1008 | int index) | ||
1009 | { | ||
1010 | enum ocfs2_ref_rec_contig ret = REF_CONTIG_NONE; | ||
1011 | |||
1012 | if (index < le16_to_cpu(rb->rf_records.rl_used) - 1) | ||
1013 | ret = ocfs2_refcount_rec_adjacent(rb, index); | ||
1014 | |||
1015 | if (index > 0) { | ||
1016 | enum ocfs2_ref_rec_contig tmp; | ||
1017 | |||
1018 | tmp = ocfs2_refcount_rec_adjacent(rb, index - 1); | ||
1019 | |||
1020 | if (tmp == REF_CONTIG_RIGHT) { | ||
1021 | if (ret == REF_CONTIG_RIGHT) | ||
1022 | ret = REF_CONTIG_LEFTRIGHT; | ||
1023 | else | ||
1024 | ret = REF_CONTIG_LEFT; | ||
1025 | } | ||
1026 | } | ||
1027 | |||
1028 | return ret; | ||
1029 | } | ||
1030 | |||
1031 | static void ocfs2_rotate_refcount_rec_left(struct ocfs2_refcount_block *rb, | ||
1032 | int index) | ||
1033 | { | ||
1034 | BUG_ON(rb->rf_records.rl_recs[index].r_refcount != | ||
1035 | rb->rf_records.rl_recs[index+1].r_refcount); | ||
1036 | |||
1037 | le32_add_cpu(&rb->rf_records.rl_recs[index].r_clusters, | ||
1038 | le32_to_cpu(rb->rf_records.rl_recs[index+1].r_clusters)); | ||
1039 | |||
1040 | if (index < le16_to_cpu(rb->rf_records.rl_used) - 2) | ||
1041 | memmove(&rb->rf_records.rl_recs[index + 1], | ||
1042 | &rb->rf_records.rl_recs[index + 2], | ||
1043 | sizeof(struct ocfs2_refcount_rec) * | ||
1044 | (le16_to_cpu(rb->rf_records.rl_used) - index - 2)); | ||
1045 | |||
1046 | memset(&rb->rf_records.rl_recs[le16_to_cpu(rb->rf_records.rl_used) - 1], | ||
1047 | 0, sizeof(struct ocfs2_refcount_rec)); | ||
1048 | le16_add_cpu(&rb->rf_records.rl_used, -1); | ||
1049 | } | ||
1050 | |||
1051 | /* | ||
1052 | * Merge the refcount rec if we are contiguous with the adjacent recs. | ||
1053 | */ | ||
1054 | static void ocfs2_refcount_rec_merge(struct ocfs2_refcount_block *rb, | ||
1055 | int index) | ||
1056 | { | ||
1057 | enum ocfs2_ref_rec_contig contig = | ||
1058 | ocfs2_refcount_rec_contig(rb, index); | ||
1059 | |||
1060 | if (contig == REF_CONTIG_NONE) | ||
1061 | return; | ||
1062 | |||
1063 | if (contig == REF_CONTIG_LEFT || contig == REF_CONTIG_LEFTRIGHT) { | ||
1064 | BUG_ON(index == 0); | ||
1065 | index--; | ||
1066 | } | ||
1067 | |||
1068 | ocfs2_rotate_refcount_rec_left(rb, index); | ||
1069 | |||
1070 | if (contig == REF_CONTIG_LEFTRIGHT) | ||
1071 | ocfs2_rotate_refcount_rec_left(rb, index); | ||
1072 | } | ||
1073 | |||
1074 | static int ocfs2_change_refcount_rec(handle_t *handle, | ||
1075 | struct ocfs2_caching_info *ci, | ||
1076 | struct buffer_head *ref_leaf_bh, | ||
1077 | int index, int change) | ||
1078 | { | ||
1079 | int ret; | ||
1080 | struct ocfs2_refcount_block *rb = | ||
1081 | (struct ocfs2_refcount_block *)ref_leaf_bh->b_data; | ||
1082 | struct ocfs2_refcount_rec *rec = &rb->rf_records.rl_recs[index]; | ||
1083 | |||
1084 | ret = ocfs2_journal_access_rb(handle, ci, ref_leaf_bh, | ||
1085 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1086 | if (ret) { | ||
1087 | mlog_errno(ret); | ||
1088 | goto out; | ||
1089 | } | ||
1090 | |||
1091 | mlog(0, "change index %d, old count %u, change %d\n", index, | ||
1092 | le32_to_cpu(rec->r_refcount), change); | ||
1093 | le32_add_cpu(&rec->r_refcount, change); | ||
1094 | |||
1095 | ocfs2_refcount_rec_merge(rb, index); | ||
1096 | |||
1097 | ret = ocfs2_journal_dirty(handle, ref_leaf_bh); | ||
1098 | if (ret) | ||
1099 | mlog_errno(ret); | ||
1100 | out: | ||
1101 | return ret; | ||
1102 | } | ||
1103 | |||
1104 | static int ocfs2_expand_inline_ref_root(handle_t *handle, | ||
1105 | struct ocfs2_caching_info *ci, | ||
1106 | struct buffer_head *ref_root_bh, | ||
1107 | struct buffer_head **ref_leaf_bh, | ||
1108 | struct ocfs2_alloc_context *meta_ac) | ||
1109 | { | ||
1110 | int ret; | ||
1111 | u16 suballoc_bit_start; | ||
1112 | u32 num_got; | ||
1113 | u64 blkno; | ||
1114 | struct super_block *sb = ocfs2_metadata_cache_get_super(ci); | ||
1115 | struct buffer_head *new_bh = NULL; | ||
1116 | struct ocfs2_refcount_block *new_rb; | ||
1117 | struct ocfs2_refcount_block *root_rb = | ||
1118 | (struct ocfs2_refcount_block *)ref_root_bh->b_data; | ||
1119 | |||
1120 | ret = ocfs2_journal_access_rb(handle, ci, ref_root_bh, | ||
1121 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1122 | if (ret) { | ||
1123 | mlog_errno(ret); | ||
1124 | goto out; | ||
1125 | } | ||
1126 | |||
1127 | ret = ocfs2_claim_metadata(OCFS2_SB(sb), handle, meta_ac, 1, | ||
1128 | &suballoc_bit_start, &num_got, | ||
1129 | &blkno); | ||
1130 | if (ret) { | ||
1131 | mlog_errno(ret); | ||
1132 | goto out; | ||
1133 | } | ||
1134 | |||
1135 | new_bh = sb_getblk(sb, blkno); | ||
1136 | if (new_bh == NULL) { | ||
1137 | ret = -EIO; | ||
1138 | mlog_errno(ret); | ||
1139 | goto out; | ||
1140 | } | ||
1141 | ocfs2_set_new_buffer_uptodate(ci, new_bh); | ||
1142 | |||
1143 | ret = ocfs2_journal_access_rb(handle, ci, new_bh, | ||
1144 | OCFS2_JOURNAL_ACCESS_CREATE); | ||
1145 | if (ret) { | ||
1146 | mlog_errno(ret); | ||
1147 | goto out; | ||
1148 | } | ||
1149 | |||
1150 | /* | ||
1151 | * Initialize ocfs2_refcount_block. | ||
1152 | * It should contain the same information as the old root. | ||
1153 | * so just memcpy it and change the corresponding field. | ||
1154 | */ | ||
1155 | memcpy(new_bh->b_data, ref_root_bh->b_data, sb->s_blocksize); | ||
1156 | |||
1157 | new_rb = (struct ocfs2_refcount_block *)new_bh->b_data; | ||
1158 | new_rb->rf_suballoc_slot = cpu_to_le16(OCFS2_SB(sb)->slot_num); | ||
1159 | new_rb->rf_suballoc_bit = cpu_to_le16(suballoc_bit_start); | ||
1160 | new_rb->rf_blkno = cpu_to_le64(blkno); | ||
1161 | new_rb->rf_cpos = cpu_to_le32(0); | ||
1162 | new_rb->rf_parent = cpu_to_le64(ref_root_bh->b_blocknr); | ||
1163 | new_rb->rf_flags = cpu_to_le32(OCFS2_REFCOUNT_LEAF_FL); | ||
1164 | ocfs2_journal_dirty(handle, new_bh); | ||
1165 | |||
1166 | /* Now change the root. */ | ||
1167 | memset(&root_rb->rf_list, 0, sb->s_blocksize - | ||
1168 | offsetof(struct ocfs2_refcount_block, rf_list)); | ||
1169 | root_rb->rf_list.l_count = cpu_to_le16(ocfs2_extent_recs_per_rb(sb)); | ||
1170 | root_rb->rf_clusters = cpu_to_le32(1); | ||
1171 | root_rb->rf_list.l_next_free_rec = cpu_to_le16(1); | ||
1172 | root_rb->rf_list.l_recs[0].e_blkno = cpu_to_le64(blkno); | ||
1173 | root_rb->rf_list.l_recs[0].e_leaf_clusters = cpu_to_le16(1); | ||
1174 | root_rb->rf_flags = cpu_to_le32(OCFS2_REFCOUNT_TREE_FL); | ||
1175 | |||
1176 | ocfs2_journal_dirty(handle, ref_root_bh); | ||
1177 | |||
1178 | mlog(0, "new leaf block %llu, used %u\n", (unsigned long long)blkno, | ||
1179 | le16_to_cpu(new_rb->rf_records.rl_used)); | ||
1180 | |||
1181 | *ref_leaf_bh = new_bh; | ||
1182 | new_bh = NULL; | ||
1183 | out: | ||
1184 | brelse(new_bh); | ||
1185 | return ret; | ||
1186 | } | ||
1187 | |||
1188 | static int ocfs2_refcount_rec_no_intersect(struct ocfs2_refcount_rec *prev, | ||
1189 | struct ocfs2_refcount_rec *next) | ||
1190 | { | ||
1191 | if (ocfs2_get_ref_rec_low_cpos(prev) + le32_to_cpu(prev->r_clusters) <= | ||
1192 | ocfs2_get_ref_rec_low_cpos(next)) | ||
1193 | return 1; | ||
1194 | |||
1195 | return 0; | ||
1196 | } | ||
1197 | |||
1198 | static int cmp_refcount_rec_by_low_cpos(const void *a, const void *b) | ||
1199 | { | ||
1200 | const struct ocfs2_refcount_rec *l = a, *r = b; | ||
1201 | u32 l_cpos = ocfs2_get_ref_rec_low_cpos(l); | ||
1202 | u32 r_cpos = ocfs2_get_ref_rec_low_cpos(r); | ||
1203 | |||
1204 | if (l_cpos > r_cpos) | ||
1205 | return 1; | ||
1206 | if (l_cpos < r_cpos) | ||
1207 | return -1; | ||
1208 | return 0; | ||
1209 | } | ||
1210 | |||
1211 | static int cmp_refcount_rec_by_cpos(const void *a, const void *b) | ||
1212 | { | ||
1213 | const struct ocfs2_refcount_rec *l = a, *r = b; | ||
1214 | u64 l_cpos = le64_to_cpu(l->r_cpos); | ||
1215 | u64 r_cpos = le64_to_cpu(r->r_cpos); | ||
1216 | |||
1217 | if (l_cpos > r_cpos) | ||
1218 | return 1; | ||
1219 | if (l_cpos < r_cpos) | ||
1220 | return -1; | ||
1221 | return 0; | ||
1222 | } | ||
1223 | |||
1224 | static void swap_refcount_rec(void *a, void *b, int size) | ||
1225 | { | ||
1226 | struct ocfs2_refcount_rec *l = a, *r = b, tmp; | ||
1227 | |||
1228 | tmp = *(struct ocfs2_refcount_rec *)l; | ||
1229 | *(struct ocfs2_refcount_rec *)l = | ||
1230 | *(struct ocfs2_refcount_rec *)r; | ||
1231 | *(struct ocfs2_refcount_rec *)r = tmp; | ||
1232 | } | ||
1233 | |||
1234 | /* | ||
1235 | * The refcount cpos are ordered by their 64bit cpos, | ||
1236 | * But we will use the low 32 bit to be the e_cpos in the b-tree. | ||
1237 | * So we need to make sure that this pos isn't intersected with others. | ||
1238 | * | ||
1239 | * Note: The refcount block is already sorted by their low 32 bit cpos, | ||
1240 | * So just try the middle pos first, and we will exit when we find | ||
1241 | * the good position. | ||
1242 | */ | ||
1243 | static int ocfs2_find_refcount_split_pos(struct ocfs2_refcount_list *rl, | ||
1244 | u32 *split_pos, int *split_index) | ||
1245 | { | ||
1246 | int num_used = le16_to_cpu(rl->rl_used); | ||
1247 | int delta, middle = num_used / 2; | ||
1248 | |||
1249 | for (delta = 0; delta < middle; delta++) { | ||
1250 | /* Let's check delta earlier than middle */ | ||
1251 | if (ocfs2_refcount_rec_no_intersect( | ||
1252 | &rl->rl_recs[middle - delta - 1], | ||
1253 | &rl->rl_recs[middle - delta])) { | ||
1254 | *split_index = middle - delta; | ||
1255 | break; | ||
1256 | } | ||
1257 | |||
1258 | /* For even counts, don't walk off the end */ | ||
1259 | if ((middle + delta + 1) == num_used) | ||
1260 | continue; | ||
1261 | |||
1262 | /* Now try delta past middle */ | ||
1263 | if (ocfs2_refcount_rec_no_intersect( | ||
1264 | &rl->rl_recs[middle + delta], | ||
1265 | &rl->rl_recs[middle + delta + 1])) { | ||
1266 | *split_index = middle + delta + 1; | ||
1267 | break; | ||
1268 | } | ||
1269 | } | ||
1270 | |||
1271 | if (delta >= middle) | ||
1272 | return -ENOSPC; | ||
1273 | |||
1274 | *split_pos = ocfs2_get_ref_rec_low_cpos(&rl->rl_recs[*split_index]); | ||
1275 | return 0; | ||
1276 | } | ||
1277 | |||
1278 | static int ocfs2_divide_leaf_refcount_block(struct buffer_head *ref_leaf_bh, | ||
1279 | struct buffer_head *new_bh, | ||
1280 | u32 *split_cpos) | ||
1281 | { | ||
1282 | int split_index = 0, num_moved, ret; | ||
1283 | u32 cpos = 0; | ||
1284 | struct ocfs2_refcount_block *rb = | ||
1285 | (struct ocfs2_refcount_block *)ref_leaf_bh->b_data; | ||
1286 | struct ocfs2_refcount_list *rl = &rb->rf_records; | ||
1287 | struct ocfs2_refcount_block *new_rb = | ||
1288 | (struct ocfs2_refcount_block *)new_bh->b_data; | ||
1289 | struct ocfs2_refcount_list *new_rl = &new_rb->rf_records; | ||
1290 | |||
1291 | mlog(0, "split old leaf refcount block %llu, count = %u, used = %u\n", | ||
1292 | (unsigned long long)ref_leaf_bh->b_blocknr, | ||
1293 | le32_to_cpu(rl->rl_count), le32_to_cpu(rl->rl_used)); | ||
1294 | |||
1295 | /* | ||
1296 | * XXX: Improvement later. | ||
1297 | * If we know all the high 32 bit cpos is the same, no need to sort. | ||
1298 | * | ||
1299 | * In order to make the whole process safe, we do: | ||
1300 | * 1. sort the entries by their low 32 bit cpos first so that we can | ||
1301 | * find the split cpos easily. | ||
1302 | * 2. call ocfs2_insert_extent to insert the new refcount block. | ||
1303 | * 3. move the refcount rec to the new block. | ||
1304 | * 4. sort the entries by their 64 bit cpos. | ||
1305 | * 5. dirty the new_rb and rb. | ||
1306 | */ | ||
1307 | sort(&rl->rl_recs, le16_to_cpu(rl->rl_used), | ||
1308 | sizeof(struct ocfs2_refcount_rec), | ||
1309 | cmp_refcount_rec_by_low_cpos, swap_refcount_rec); | ||
1310 | |||
1311 | ret = ocfs2_find_refcount_split_pos(rl, &cpos, &split_index); | ||
1312 | if (ret) { | ||
1313 | mlog_errno(ret); | ||
1314 | return ret; | ||
1315 | } | ||
1316 | |||
1317 | new_rb->rf_cpos = cpu_to_le32(cpos); | ||
1318 | |||
1319 | /* move refcount records starting from split_index to the new block. */ | ||
1320 | num_moved = le16_to_cpu(rl->rl_used) - split_index; | ||
1321 | memcpy(new_rl->rl_recs, &rl->rl_recs[split_index], | ||
1322 | num_moved * sizeof(struct ocfs2_refcount_rec)); | ||
1323 | |||
1324 | /*ok, remove the entries we just moved over to the other block. */ | ||
1325 | memset(&rl->rl_recs[split_index], 0, | ||
1326 | num_moved * sizeof(struct ocfs2_refcount_rec)); | ||
1327 | |||
1328 | /* change old and new rl_used accordingly. */ | ||
1329 | le16_add_cpu(&rl->rl_used, -num_moved); | ||
1330 | new_rl->rl_used = cpu_to_le32(num_moved); | ||
1331 | |||
1332 | sort(&rl->rl_recs, le16_to_cpu(rl->rl_used), | ||
1333 | sizeof(struct ocfs2_refcount_rec), | ||
1334 | cmp_refcount_rec_by_cpos, swap_refcount_rec); | ||
1335 | |||
1336 | sort(&new_rl->rl_recs, le16_to_cpu(new_rl->rl_used), | ||
1337 | sizeof(struct ocfs2_refcount_rec), | ||
1338 | cmp_refcount_rec_by_cpos, swap_refcount_rec); | ||
1339 | |||
1340 | *split_cpos = cpos; | ||
1341 | return 0; | ||
1342 | } | ||
1343 | |||
1344 | static int ocfs2_new_leaf_refcount_block(handle_t *handle, | ||
1345 | struct ocfs2_caching_info *ci, | ||
1346 | struct buffer_head *ref_root_bh, | ||
1347 | struct buffer_head *ref_leaf_bh, | ||
1348 | struct ocfs2_alloc_context *meta_ac) | ||
1349 | { | ||
1350 | int ret; | ||
1351 | u16 suballoc_bit_start; | ||
1352 | u32 num_got, new_cpos; | ||
1353 | u64 blkno; | ||
1354 | struct super_block *sb = ocfs2_metadata_cache_get_super(ci); | ||
1355 | struct ocfs2_refcount_block *root_rb = | ||
1356 | (struct ocfs2_refcount_block *)ref_root_bh->b_data; | ||
1357 | struct buffer_head *new_bh = NULL; | ||
1358 | struct ocfs2_refcount_block *new_rb; | ||
1359 | struct ocfs2_extent_tree ref_et; | ||
1360 | |||
1361 | BUG_ON(!(le32_to_cpu(root_rb->rf_flags) & OCFS2_REFCOUNT_TREE_FL)); | ||
1362 | |||
1363 | ret = ocfs2_journal_access_rb(handle, ci, ref_root_bh, | ||
1364 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1365 | if (ret) { | ||
1366 | mlog_errno(ret); | ||
1367 | goto out; | ||
1368 | } | ||
1369 | |||
1370 | ret = ocfs2_journal_access_rb(handle, ci, ref_leaf_bh, | ||
1371 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1372 | if (ret) { | ||
1373 | mlog_errno(ret); | ||
1374 | goto out; | ||
1375 | } | ||
1376 | |||
1377 | ret = ocfs2_claim_metadata(OCFS2_SB(sb), handle, meta_ac, 1, | ||
1378 | &suballoc_bit_start, &num_got, | ||
1379 | &blkno); | ||
1380 | if (ret) { | ||
1381 | mlog_errno(ret); | ||
1382 | goto out; | ||
1383 | } | ||
1384 | |||
1385 | new_bh = sb_getblk(sb, blkno); | ||
1386 | if (new_bh == NULL) { | ||
1387 | ret = -EIO; | ||
1388 | mlog_errno(ret); | ||
1389 | goto out; | ||
1390 | } | ||
1391 | ocfs2_set_new_buffer_uptodate(ci, new_bh); | ||
1392 | |||
1393 | ret = ocfs2_journal_access_rb(handle, ci, new_bh, | ||
1394 | OCFS2_JOURNAL_ACCESS_CREATE); | ||
1395 | if (ret) { | ||
1396 | mlog_errno(ret); | ||
1397 | goto out; | ||
1398 | } | ||
1399 | |||
1400 | /* Initialize ocfs2_refcount_block. */ | ||
1401 | new_rb = (struct ocfs2_refcount_block *)new_bh->b_data; | ||
1402 | memset(new_rb, 0, sb->s_blocksize); | ||
1403 | strcpy((void *)new_rb, OCFS2_REFCOUNT_BLOCK_SIGNATURE); | ||
1404 | new_rb->rf_suballoc_slot = cpu_to_le16(OCFS2_SB(sb)->slot_num); | ||
1405 | new_rb->rf_suballoc_bit = cpu_to_le16(suballoc_bit_start); | ||
1406 | new_rb->rf_fs_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation); | ||
1407 | new_rb->rf_blkno = cpu_to_le64(blkno); | ||
1408 | new_rb->rf_parent = cpu_to_le64(ref_root_bh->b_blocknr); | ||
1409 | new_rb->rf_flags = cpu_to_le32(OCFS2_REFCOUNT_LEAF_FL); | ||
1410 | new_rb->rf_records.rl_count = | ||
1411 | cpu_to_le16(ocfs2_refcount_recs_per_rb(sb)); | ||
1412 | new_rb->rf_generation = root_rb->rf_generation; | ||
1413 | |||
1414 | ret = ocfs2_divide_leaf_refcount_block(ref_leaf_bh, new_bh, &new_cpos); | ||
1415 | if (ret) { | ||
1416 | mlog_errno(ret); | ||
1417 | goto out; | ||
1418 | } | ||
1419 | |||
1420 | ocfs2_journal_dirty(handle, ref_leaf_bh); | ||
1421 | ocfs2_journal_dirty(handle, new_bh); | ||
1422 | |||
1423 | ocfs2_init_refcount_extent_tree(&ref_et, ci, ref_root_bh); | ||
1424 | |||
1425 | mlog(0, "insert new leaf block %llu at %u\n", | ||
1426 | (unsigned long long)new_bh->b_blocknr, new_cpos); | ||
1427 | |||
1428 | /* Insert the new leaf block with the specific offset cpos. */ | ||
1429 | ret = ocfs2_insert_extent(handle, &ref_et, new_cpos, new_bh->b_blocknr, | ||
1430 | 1, 0, meta_ac); | ||
1431 | if (ret) | ||
1432 | mlog_errno(ret); | ||
1433 | |||
1434 | out: | ||
1435 | brelse(new_bh); | ||
1436 | return ret; | ||
1437 | } | ||
1438 | |||
1439 | static int ocfs2_expand_refcount_tree(handle_t *handle, | ||
1440 | struct ocfs2_caching_info *ci, | ||
1441 | struct buffer_head *ref_root_bh, | ||
1442 | struct buffer_head *ref_leaf_bh, | ||
1443 | struct ocfs2_alloc_context *meta_ac) | ||
1444 | { | ||
1445 | int ret; | ||
1446 | struct buffer_head *expand_bh = NULL; | ||
1447 | |||
1448 | if (ref_root_bh == ref_leaf_bh) { | ||
1449 | /* | ||
1450 | * the old root bh hasn't been expanded to a b-tree, | ||
1451 | * so expand it first. | ||
1452 | */ | ||
1453 | ret = ocfs2_expand_inline_ref_root(handle, ci, ref_root_bh, | ||
1454 | &expand_bh, meta_ac); | ||
1455 | if (ret) { | ||
1456 | mlog_errno(ret); | ||
1457 | goto out; | ||
1458 | } | ||
1459 | } else { | ||
1460 | expand_bh = ref_leaf_bh; | ||
1461 | get_bh(expand_bh); | ||
1462 | } | ||
1463 | |||
1464 | |||
1465 | /* Now add a new refcount block into the tree.*/ | ||
1466 | ret = ocfs2_new_leaf_refcount_block(handle, ci, ref_root_bh, | ||
1467 | expand_bh, meta_ac); | ||
1468 | if (ret) | ||
1469 | mlog_errno(ret); | ||
1470 | out: | ||
1471 | brelse(expand_bh); | ||
1472 | return ret; | ||
1473 | } | ||
1474 | |||
1475 | /* | ||
1476 | * Adjust the extent rec in b-tree representing ref_leaf_bh. | ||
1477 | * | ||
1478 | * Only called when we have inserted a new refcount rec at index 0 | ||
1479 | * which means ocfs2_extent_rec.e_cpos may need some change. | ||
1480 | */ | ||
1481 | static int ocfs2_adjust_refcount_rec(handle_t *handle, | ||
1482 | struct ocfs2_caching_info *ci, | ||
1483 | struct buffer_head *ref_root_bh, | ||
1484 | struct buffer_head *ref_leaf_bh, | ||
1485 | struct ocfs2_refcount_rec *rec) | ||
1486 | { | ||
1487 | int ret = 0, i; | ||
1488 | u32 new_cpos, old_cpos; | ||
1489 | struct ocfs2_path *path = NULL; | ||
1490 | struct ocfs2_extent_tree et; | ||
1491 | struct ocfs2_refcount_block *rb = | ||
1492 | (struct ocfs2_refcount_block *)ref_root_bh->b_data; | ||
1493 | struct ocfs2_extent_list *el; | ||
1494 | |||
1495 | if (!(le32_to_cpu(rb->rf_flags) & OCFS2_REFCOUNT_TREE_FL)) | ||
1496 | goto out; | ||
1497 | |||
1498 | rb = (struct ocfs2_refcount_block *)ref_leaf_bh->b_data; | ||
1499 | old_cpos = le32_to_cpu(rb->rf_cpos); | ||
1500 | new_cpos = le64_to_cpu(rec->r_cpos) & OCFS2_32BIT_POS_MASK; | ||
1501 | if (old_cpos <= new_cpos) | ||
1502 | goto out; | ||
1503 | |||
1504 | ocfs2_init_refcount_extent_tree(&et, ci, ref_root_bh); | ||
1505 | |||
1506 | path = ocfs2_new_path_from_et(&et); | ||
1507 | if (!path) { | ||
1508 | ret = -ENOMEM; | ||
1509 | mlog_errno(ret); | ||
1510 | goto out; | ||
1511 | } | ||
1512 | |||
1513 | ret = ocfs2_find_path(ci, path, old_cpos); | ||
1514 | if (ret) { | ||
1515 | mlog_errno(ret); | ||
1516 | goto out; | ||
1517 | } | ||
1518 | |||
1519 | /* | ||
1520 | * 2 more credits, one for the leaf refcount block, one for | ||
1521 | * the extent block contains the extent rec. | ||
1522 | */ | ||
1523 | ret = ocfs2_extend_trans(handle, handle->h_buffer_credits + 2); | ||
1524 | if (ret < 0) { | ||
1525 | mlog_errno(ret); | ||
1526 | goto out; | ||
1527 | } | ||
1528 | |||
1529 | ret = ocfs2_journal_access_rb(handle, ci, ref_leaf_bh, | ||
1530 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1531 | if (ret < 0) { | ||
1532 | mlog_errno(ret); | ||
1533 | goto out; | ||
1534 | } | ||
1535 | |||
1536 | ret = ocfs2_journal_access_eb(handle, ci, path_leaf_bh(path), | ||
1537 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1538 | if (ret < 0) { | ||
1539 | mlog_errno(ret); | ||
1540 | goto out; | ||
1541 | } | ||
1542 | |||
1543 | /* change the leaf extent block first. */ | ||
1544 | el = path_leaf_el(path); | ||
1545 | |||
1546 | for (i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) | ||
1547 | if (le32_to_cpu(el->l_recs[i].e_cpos) == old_cpos) | ||
1548 | break; | ||
1549 | |||
1550 | BUG_ON(i == le16_to_cpu(el->l_next_free_rec)); | ||
1551 | |||
1552 | el->l_recs[i].e_cpos = cpu_to_le32(new_cpos); | ||
1553 | |||
1554 | /* change the r_cpos in the leaf block. */ | ||
1555 | rb->rf_cpos = cpu_to_le32(new_cpos); | ||
1556 | |||
1557 | ocfs2_journal_dirty(handle, path_leaf_bh(path)); | ||
1558 | ocfs2_journal_dirty(handle, ref_leaf_bh); | ||
1559 | |||
1560 | out: | ||
1561 | ocfs2_free_path(path); | ||
1562 | return ret; | ||
1563 | } | ||
1564 | |||
1565 | static int ocfs2_insert_refcount_rec(handle_t *handle, | ||
1566 | struct ocfs2_caching_info *ci, | ||
1567 | struct buffer_head *ref_root_bh, | ||
1568 | struct buffer_head *ref_leaf_bh, | ||
1569 | struct ocfs2_refcount_rec *rec, | ||
1570 | int index, | ||
1571 | struct ocfs2_alloc_context *meta_ac) | ||
1572 | { | ||
1573 | int ret; | ||
1574 | struct ocfs2_refcount_block *rb = | ||
1575 | (struct ocfs2_refcount_block *)ref_leaf_bh->b_data; | ||
1576 | struct ocfs2_refcount_list *rf_list = &rb->rf_records; | ||
1577 | struct buffer_head *new_bh = NULL; | ||
1578 | |||
1579 | BUG_ON(le32_to_cpu(rb->rf_flags) & OCFS2_REFCOUNT_TREE_FL); | ||
1580 | |||
1581 | if (rf_list->rl_used == rf_list->rl_count) { | ||
1582 | u64 cpos = le64_to_cpu(rec->r_cpos); | ||
1583 | u32 len = le32_to_cpu(rec->r_clusters); | ||
1584 | |||
1585 | ret = ocfs2_expand_refcount_tree(handle, ci, ref_root_bh, | ||
1586 | ref_leaf_bh, meta_ac); | ||
1587 | if (ret) { | ||
1588 | mlog_errno(ret); | ||
1589 | goto out; | ||
1590 | } | ||
1591 | |||
1592 | ret = ocfs2_get_refcount_rec(ci, ref_root_bh, | ||
1593 | cpos, len, NULL, &index, | ||
1594 | &new_bh); | ||
1595 | if (ret) { | ||
1596 | mlog_errno(ret); | ||
1597 | goto out; | ||
1598 | } | ||
1599 | |||
1600 | ref_leaf_bh = new_bh; | ||
1601 | rb = (struct ocfs2_refcount_block *)ref_leaf_bh->b_data; | ||
1602 | rf_list = &rb->rf_records; | ||
1603 | } | ||
1604 | |||
1605 | ret = ocfs2_journal_access_rb(handle, ci, ref_leaf_bh, | ||
1606 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1607 | if (ret) { | ||
1608 | mlog_errno(ret); | ||
1609 | goto out; | ||
1610 | } | ||
1611 | |||
1612 | if (index < le16_to_cpu(rf_list->rl_used)) | ||
1613 | memmove(&rf_list->rl_recs[index + 1], | ||
1614 | &rf_list->rl_recs[index], | ||
1615 | (le16_to_cpu(rf_list->rl_used) - index) * | ||
1616 | sizeof(struct ocfs2_refcount_rec)); | ||
1617 | |||
1618 | mlog(0, "insert refcount record start %llu, len %u, count %u " | ||
1619 | "to leaf block %llu at index %d\n", | ||
1620 | (unsigned long long)le64_to_cpu(rec->r_cpos), | ||
1621 | le32_to_cpu(rec->r_clusters), le32_to_cpu(rec->r_refcount), | ||
1622 | (unsigned long long)ref_leaf_bh->b_blocknr, index); | ||
1623 | |||
1624 | rf_list->rl_recs[index] = *rec; | ||
1625 | |||
1626 | le16_add_cpu(&rf_list->rl_used, 1); | ||
1627 | |||
1628 | ocfs2_refcount_rec_merge(rb, index); | ||
1629 | |||
1630 | ret = ocfs2_journal_dirty(handle, ref_leaf_bh); | ||
1631 | if (ret) { | ||
1632 | mlog_errno(ret); | ||
1633 | goto out; | ||
1634 | } | ||
1635 | |||
1636 | if (index == 0) { | ||
1637 | ret = ocfs2_adjust_refcount_rec(handle, ci, | ||
1638 | ref_root_bh, | ||
1639 | ref_leaf_bh, rec); | ||
1640 | if (ret) | ||
1641 | mlog_errno(ret); | ||
1642 | } | ||
1643 | out: | ||
1644 | brelse(new_bh); | ||
1645 | return ret; | ||
1646 | } | ||
1647 | |||
1648 | /* | ||
1649 | * Split the refcount_rec indexed by "index" in ref_leaf_bh. | ||
1650 | * This is much simple than our b-tree code. | ||
1651 | * split_rec is the new refcount rec we want to insert. | ||
1652 | * If split_rec->r_refcount > 0, we are changing the refcount(in case we | ||
1653 | * increase refcount or decrease a refcount to non-zero). | ||
1654 | * If split_rec->r_refcount == 0, we are punching a hole in current refcount | ||
1655 | * rec( in case we decrease a refcount to zero). | ||
1656 | */ | ||
1657 | static int ocfs2_split_refcount_rec(handle_t *handle, | ||
1658 | struct ocfs2_caching_info *ci, | ||
1659 | struct buffer_head *ref_root_bh, | ||
1660 | struct buffer_head *ref_leaf_bh, | ||
1661 | struct ocfs2_refcount_rec *split_rec, | ||
1662 | int index, | ||
1663 | struct ocfs2_alloc_context *meta_ac, | ||
1664 | struct ocfs2_cached_dealloc_ctxt *dealloc) | ||
1665 | { | ||
1666 | int ret, recs_need; | ||
1667 | u32 len; | ||
1668 | struct ocfs2_refcount_block *rb = | ||
1669 | (struct ocfs2_refcount_block *)ref_leaf_bh->b_data; | ||
1670 | struct ocfs2_refcount_list *rf_list = &rb->rf_records; | ||
1671 | struct ocfs2_refcount_rec *orig_rec = &rf_list->rl_recs[index]; | ||
1672 | struct ocfs2_refcount_rec *tail_rec = NULL; | ||
1673 | struct buffer_head *new_bh = NULL; | ||
1674 | |||
1675 | BUG_ON(le32_to_cpu(rb->rf_flags) & OCFS2_REFCOUNT_TREE_FL); | ||
1676 | |||
1677 | mlog(0, "original r_pos %llu, cluster %u, split %llu, cluster %u\n", | ||
1678 | le64_to_cpu(orig_rec->r_cpos), le32_to_cpu(orig_rec->r_clusters), | ||
1679 | le64_to_cpu(split_rec->r_cpos), | ||
1680 | le32_to_cpu(split_rec->r_clusters)); | ||
1681 | |||
1682 | /* | ||
1683 | * If we just need to split the header or tail clusters, | ||
1684 | * no more recs are needed, just split is OK. | ||
1685 | * Otherwise we at least need one new recs. | ||
1686 | */ | ||
1687 | if (!split_rec->r_refcount && | ||
1688 | (split_rec->r_cpos == orig_rec->r_cpos || | ||
1689 | le64_to_cpu(split_rec->r_cpos) + | ||
1690 | le32_to_cpu(split_rec->r_clusters) == | ||
1691 | le64_to_cpu(orig_rec->r_cpos) + le32_to_cpu(orig_rec->r_clusters))) | ||
1692 | recs_need = 0; | ||
1693 | else | ||
1694 | recs_need = 1; | ||
1695 | |||
1696 | /* | ||
1697 | * We need one more rec if we split in the middle and the new rec have | ||
1698 | * some refcount in it. | ||
1699 | */ | ||
1700 | if (split_rec->r_refcount && | ||
1701 | (split_rec->r_cpos != orig_rec->r_cpos && | ||
1702 | le64_to_cpu(split_rec->r_cpos) + | ||
1703 | le32_to_cpu(split_rec->r_clusters) != | ||
1704 | le64_to_cpu(orig_rec->r_cpos) + le32_to_cpu(orig_rec->r_clusters))) | ||
1705 | recs_need++; | ||
1706 | |||
1707 | /* If the leaf block don't have enough record, expand it. */ | ||
1708 | if (le16_to_cpu(rf_list->rl_used) + recs_need > rf_list->rl_count) { | ||
1709 | struct ocfs2_refcount_rec tmp_rec; | ||
1710 | u64 cpos = le64_to_cpu(orig_rec->r_cpos); | ||
1711 | len = le32_to_cpu(orig_rec->r_clusters); | ||
1712 | ret = ocfs2_expand_refcount_tree(handle, ci, ref_root_bh, | ||
1713 | ref_leaf_bh, meta_ac); | ||
1714 | if (ret) { | ||
1715 | mlog_errno(ret); | ||
1716 | goto out; | ||
1717 | } | ||
1718 | |||
1719 | /* | ||
1720 | * We have to re-get it since now cpos may be moved to | ||
1721 | * another leaf block. | ||
1722 | */ | ||
1723 | ret = ocfs2_get_refcount_rec(ci, ref_root_bh, | ||
1724 | cpos, len, &tmp_rec, &index, | ||
1725 | &new_bh); | ||
1726 | if (ret) { | ||
1727 | mlog_errno(ret); | ||
1728 | goto out; | ||
1729 | } | ||
1730 | |||
1731 | ref_leaf_bh = new_bh; | ||
1732 | rb = (struct ocfs2_refcount_block *)ref_leaf_bh->b_data; | ||
1733 | rf_list = &rb->rf_records; | ||
1734 | orig_rec = &rf_list->rl_recs[index]; | ||
1735 | } | ||
1736 | |||
1737 | ret = ocfs2_journal_access_rb(handle, ci, ref_leaf_bh, | ||
1738 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
1739 | if (ret) { | ||
1740 | mlog_errno(ret); | ||
1741 | goto out; | ||
1742 | } | ||
1743 | |||
1744 | /* | ||
1745 | * We have calculated out how many new records we need and store | ||
1746 | * in recs_need, so spare enough space first by moving the records | ||
1747 | * after "index" to the end. | ||
1748 | */ | ||
1749 | if (index != le16_to_cpu(rf_list->rl_used) - 1) | ||
1750 | memmove(&rf_list->rl_recs[index + 1 + recs_need], | ||
1751 | &rf_list->rl_recs[index + 1], | ||
1752 | (le16_to_cpu(rf_list->rl_used) - index - 1) * | ||
1753 | sizeof(struct ocfs2_refcount_rec)); | ||
1754 | |||
1755 | len = (le64_to_cpu(orig_rec->r_cpos) + | ||
1756 | le32_to_cpu(orig_rec->r_clusters)) - | ||
1757 | (le64_to_cpu(split_rec->r_cpos) + | ||
1758 | le32_to_cpu(split_rec->r_clusters)); | ||
1759 | |||
1760 | /* | ||
1761 | * If we have "len", the we will split in the tail and move it | ||
1762 | * to the end of the space we have just spared. | ||
1763 | */ | ||
1764 | if (len) { | ||
1765 | tail_rec = &rf_list->rl_recs[index + recs_need]; | ||
1766 | |||
1767 | memcpy(tail_rec, orig_rec, sizeof(struct ocfs2_refcount_rec)); | ||
1768 | le64_add_cpu(&tail_rec->r_cpos, | ||
1769 | le32_to_cpu(tail_rec->r_clusters) - len); | ||
1770 | tail_rec->r_clusters = le32_to_cpu(len); | ||
1771 | } | ||
1772 | |||
1773 | /* | ||
1774 | * If the split pos isn't the same as the original one, we need to | ||
1775 | * split in the head. | ||
1776 | * | ||
1777 | * Note: We have the chance that split_rec.r_refcount = 0, | ||
1778 | * recs_need = 0 and len > 0, which means we just cut the head from | ||
1779 | * the orig_rec and in that case we have done some modification in | ||
1780 | * orig_rec above, so the check for r_cpos is faked. | ||
1781 | */ | ||
1782 | if (split_rec->r_cpos != orig_rec->r_cpos && tail_rec != orig_rec) { | ||
1783 | len = le64_to_cpu(split_rec->r_cpos) - | ||
1784 | le64_to_cpu(orig_rec->r_cpos); | ||
1785 | orig_rec->r_clusters = cpu_to_le32(len); | ||
1786 | index++; | ||
1787 | } | ||
1788 | |||
1789 | le16_add_cpu(&rf_list->rl_used, recs_need); | ||
1790 | |||
1791 | if (split_rec->r_refcount) { | ||
1792 | rf_list->rl_recs[index] = *split_rec; | ||
1793 | mlog(0, "insert refcount record start %llu, len %u, count %u " | ||
1794 | "to leaf block %llu at index %d\n", | ||
1795 | (unsigned long long)le64_to_cpu(split_rec->r_cpos), | ||
1796 | le32_to_cpu(split_rec->r_clusters), | ||
1797 | le32_to_cpu(split_rec->r_refcount), | ||
1798 | (unsigned long long)ref_leaf_bh->b_blocknr, index); | ||
1799 | |||
1800 | ocfs2_refcount_rec_merge(rb, index); | ||
1801 | } | ||
1802 | |||
1803 | ret = ocfs2_journal_dirty(handle, ref_leaf_bh); | ||
1804 | if (ret) | ||
1805 | mlog_errno(ret); | ||
1806 | |||
1807 | out: | ||
1808 | brelse(new_bh); | ||
1809 | return ret; | ||
1810 | } | ||
1811 | |||
1812 | static int __ocfs2_increase_refcount(handle_t *handle, | ||
1813 | struct ocfs2_caching_info *ci, | ||
1814 | struct buffer_head *ref_root_bh, | ||
1815 | u64 cpos, u32 len, | ||
1816 | struct ocfs2_alloc_context *meta_ac, | ||
1817 | struct ocfs2_cached_dealloc_ctxt *dealloc) | ||
1818 | { | ||
1819 | int ret = 0, index; | ||
1820 | struct buffer_head *ref_leaf_bh = NULL; | ||
1821 | struct ocfs2_refcount_rec rec; | ||
1822 | unsigned int set_len = 0; | ||
1823 | |||
1824 | mlog(0, "Tree owner %llu, add refcount start %llu, len %u\n", | ||
1825 | (unsigned long long)ocfs2_metadata_cache_owner(ci), | ||
1826 | (unsigned long long)cpos, len); | ||
1827 | |||
1828 | while (len) { | ||
1829 | ret = ocfs2_get_refcount_rec(ci, ref_root_bh, | ||
1830 | cpos, len, &rec, &index, | ||
1831 | &ref_leaf_bh); | ||
1832 | if (ret) { | ||
1833 | mlog_errno(ret); | ||
1834 | goto out; | ||
1835 | } | ||
1836 | |||
1837 | set_len = le32_to_cpu(rec.r_clusters); | ||
1838 | |||
1839 | /* | ||
1840 | * Here we may meet with 3 situations: | ||
1841 | * | ||
1842 | * 1. If we find an already existing record, and the length | ||
1843 | * is the same, cool, we just need to increase the r_refcount | ||
1844 | * and it is OK. | ||
1845 | * 2. If we find a hole, just insert it with r_refcount = 1. | ||
1846 | * 3. If we are in the middle of one extent record, split | ||
1847 | * it. | ||
1848 | */ | ||
1849 | if (rec.r_refcount && le64_to_cpu(rec.r_cpos) == cpos && | ||
1850 | set_len <= len) { | ||
1851 | mlog(0, "increase refcount rec, start %llu, len %u, " | ||
1852 | "count %u\n", (unsigned long long)cpos, set_len, | ||
1853 | le32_to_cpu(rec.r_refcount)); | ||
1854 | ret = ocfs2_change_refcount_rec(handle, ci, | ||
1855 | ref_leaf_bh, index, 1); | ||
1856 | if (ret) { | ||
1857 | mlog_errno(ret); | ||
1858 | goto out; | ||
1859 | } | ||
1860 | } else if (!rec.r_refcount) { | ||
1861 | rec.r_refcount = cpu_to_le32(1); | ||
1862 | |||
1863 | mlog(0, "insert refcount rec, start %llu, len %u\n", | ||
1864 | (unsigned long long)le64_to_cpu(rec.r_cpos), | ||
1865 | set_len); | ||
1866 | ret = ocfs2_insert_refcount_rec(handle, ci, ref_root_bh, | ||
1867 | ref_leaf_bh, | ||
1868 | &rec, index, meta_ac); | ||
1869 | if (ret) { | ||
1870 | mlog_errno(ret); | ||
1871 | goto out; | ||
1872 | } | ||
1873 | } else { | ||
1874 | set_len = min((u64)(cpos + len), | ||
1875 | le64_to_cpu(rec.r_cpos) + set_len) - cpos; | ||
1876 | rec.r_cpos = cpu_to_le64(cpos); | ||
1877 | rec.r_clusters = cpu_to_le32(set_len); | ||
1878 | le32_add_cpu(&rec.r_refcount, 1); | ||
1879 | |||
1880 | mlog(0, "split refcount rec, start %llu, " | ||
1881 | "len %u, count %u\n", | ||
1882 | (unsigned long long)le64_to_cpu(rec.r_cpos), | ||
1883 | set_len, le32_to_cpu(rec.r_refcount)); | ||
1884 | ret = ocfs2_split_refcount_rec(handle, ci, | ||
1885 | ref_root_bh, ref_leaf_bh, | ||
1886 | &rec, index, | ||
1887 | meta_ac, dealloc); | ||
1888 | if (ret) { | ||
1889 | mlog_errno(ret); | ||
1890 | goto out; | ||
1891 | } | ||
1892 | } | ||
1893 | |||
1894 | cpos += set_len; | ||
1895 | len -= set_len; | ||
1896 | brelse(ref_leaf_bh); | ||
1897 | ref_leaf_bh = NULL; | ||
1898 | } | ||
1899 | |||
1900 | out: | ||
1901 | brelse(ref_leaf_bh); | ||
1902 | return ret; | ||
1903 | } | ||