aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.c10
-rw-r--r--fs/btrfs/ctree.h28
-rw-r--r--fs/btrfs/disk-io.c13
3 files changed, 42 insertions, 9 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 70b6ddfe15a1..6ba5394834be 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -124,6 +124,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
124 btrfs_set_header_bytenr(cow, cow->start); 124 btrfs_set_header_bytenr(cow, cow->start);
125 btrfs_set_header_generation(cow, trans->transid); 125 btrfs_set_header_generation(cow, trans->transid);
126 btrfs_set_header_owner(cow, new_root_objectid); 126 btrfs_set_header_owner(cow, new_root_objectid);
127 btrfs_clear_header_flag(cow, BTRFS_HEADER_FLAG_WRITTEN);
127 128
128 WARN_ON(btrfs_header_generation(buf) > trans->transid); 129 WARN_ON(btrfs_header_generation(buf) > trans->transid);
129 ret = btrfs_inc_ref(trans, new_root, buf); 130 ret = btrfs_inc_ref(trans, new_root, buf);
@@ -183,6 +184,7 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans,
183 btrfs_set_header_bytenr(cow, cow->start); 184 btrfs_set_header_bytenr(cow, cow->start);
184 btrfs_set_header_generation(cow, trans->transid); 185 btrfs_set_header_generation(cow, trans->transid);
185 btrfs_set_header_owner(cow, root->root_key.objectid); 186 btrfs_set_header_owner(cow, root->root_key.objectid);
187 btrfs_clear_header_flag(cow, BTRFS_HEADER_FLAG_WRITTEN);
186 188
187 WARN_ON(btrfs_header_generation(buf) > trans->transid); 189 WARN_ON(btrfs_header_generation(buf) > trans->transid);
188 if (btrfs_header_generation(buf) != trans->transid) { 190 if (btrfs_header_generation(buf) != trans->transid) {
@@ -245,11 +247,14 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans,
245 } 247 }
246 248
247 header_trans = btrfs_header_generation(buf); 249 header_trans = btrfs_header_generation(buf);
248 if (header_trans == trans->transid) { 250 spin_lock(&root->fs_info->hash_lock);
251 if (header_trans == trans->transid &&
252 !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) {
249 *cow_ret = buf; 253 *cow_ret = buf;
254 spin_unlock(&root->fs_info->hash_lock);
250 return 0; 255 return 0;
251 } 256 }
252 257 spin_unlock(&root->fs_info->hash_lock);
253 search_start = buf->start & ~((u64)(1024 * 1024 * 1024) - 1); 258 search_start = buf->start & ~((u64)(1024 * 1024 * 1024) - 1);
254 ret = __btrfs_cow_block(trans, root, buf, parent, 259 ret = __btrfs_cow_block(trans, root, buf, parent,
255 parent_slot, cow_ret, search_start, 0); 260 parent_slot, cow_ret, search_start, 0);
@@ -1494,6 +1499,7 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
1494 btrfs_set_header_bytenr(split, split->start); 1499 btrfs_set_header_bytenr(split, split->start);
1495 btrfs_set_header_generation(split, trans->transid); 1500 btrfs_set_header_generation(split, trans->transid);
1496 btrfs_set_header_owner(split, root->root_key.objectid); 1501 btrfs_set_header_owner(split, root->root_key.objectid);
1502 btrfs_set_header_flags(split, 0);
1497 write_extent_buffer(split, root->fs_info->fsid, 1503 write_extent_buffer(split, root->fs_info->fsid,
1498 (unsigned long)btrfs_header_fsid(split), 1504 (unsigned long)btrfs_header_fsid(split),
1499 BTRFS_FSID_SIZE); 1505 BTRFS_FSID_SIZE);
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index fec96ba7c23b..67d533cf8f47 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -193,6 +193,8 @@ static inline unsigned long btrfs_chunk_item_size(int num_stripes)
193} 193}
194 194
195#define BTRFS_FSID_SIZE 16 195#define BTRFS_FSID_SIZE 16
196#define BTRFS_HEADER_FLAG_WRITTEN (1 << 0)
197
196/* 198/*
197 * every tree block (leaf or node) starts with this header. 199 * every tree block (leaf or node) starts with this header.
198 */ 200 */
@@ -200,10 +202,10 @@ struct btrfs_header {
200 u8 csum[BTRFS_CSUM_SIZE]; 202 u8 csum[BTRFS_CSUM_SIZE];
201 u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */ 203 u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
202 __le64 bytenr; /* which block this node is supposed to live in */ 204 __le64 bytenr; /* which block this node is supposed to live in */
205 __le64 flags;
203 __le64 generation; 206 __le64 generation;
204 __le64 owner; 207 __le64 owner;
205 __le32 nritems; 208 __le32 nritems;
206 __le16 flags;
207 u8 level; 209 u8 level;
208} __attribute__ ((__packed__)); 210} __attribute__ ((__packed__));
209 211
@@ -229,9 +231,10 @@ struct btrfs_header {
229 */ 231 */
230struct btrfs_super_block { 232struct btrfs_super_block {
231 u8 csum[BTRFS_CSUM_SIZE]; 233 u8 csum[BTRFS_CSUM_SIZE];
232 /* the first 3 fields must match struct btrfs_header */ 234 /* the first 4 fields must match struct btrfs_header */
233 u8 fsid[16]; /* FS specific uuid */ 235 u8 fsid[16]; /* FS specific uuid */
234 __le64 bytenr; /* this block number */ 236 __le64 bytenr; /* this block number */
237 __le64 flags;
235 __le64 magic; 238 __le64 magic;
236 __le64 generation; 239 __le64 generation;
237 __le64 root; 240 __le64 root;
@@ -1045,9 +1048,28 @@ BTRFS_SETGET_HEADER_FUNCS(header_generation, struct btrfs_header,
1045 generation, 64); 1048 generation, 64);
1046BTRFS_SETGET_HEADER_FUNCS(header_owner, struct btrfs_header, owner, 64); 1049BTRFS_SETGET_HEADER_FUNCS(header_owner, struct btrfs_header, owner, 64);
1047BTRFS_SETGET_HEADER_FUNCS(header_nritems, struct btrfs_header, nritems, 32); 1050BTRFS_SETGET_HEADER_FUNCS(header_nritems, struct btrfs_header, nritems, 32);
1048BTRFS_SETGET_HEADER_FUNCS(header_flags, struct btrfs_header, flags, 16); 1051BTRFS_SETGET_HEADER_FUNCS(header_flags, struct btrfs_header, flags, 64);
1049BTRFS_SETGET_HEADER_FUNCS(header_level, struct btrfs_header, level, 8); 1052BTRFS_SETGET_HEADER_FUNCS(header_level, struct btrfs_header, level, 8);
1050 1053
1054static inline int btrfs_header_flag(struct extent_buffer *eb, u64 flag)
1055{
1056 return (btrfs_header_flags(eb) & flag) == flag;
1057}
1058
1059static inline int btrfs_set_header_flag(struct extent_buffer *eb, u64 flag)
1060{
1061 u64 flags = btrfs_header_flags(eb);
1062 btrfs_set_header_flags(eb, flags | flag);
1063 return (flags & flag) == flag;
1064}
1065
1066static inline int btrfs_clear_header_flag(struct extent_buffer *eb, u64 flag)
1067{
1068 u64 flags = btrfs_header_flags(eb);
1069 btrfs_set_header_flags(eb, flags & ~flag);
1070 return (flags & flag) == flag;
1071}
1072
1051static inline u8 *btrfs_header_fsid(struct extent_buffer *eb) 1073static inline u8 *btrfs_header_fsid(struct extent_buffer *eb)
1052{ 1074{
1053 unsigned long ptr = offsetof(struct btrfs_header, fsid); 1075 unsigned long ptr = offsetof(struct btrfs_header, fsid);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 1c5e097a4df2..709e33d08bb5 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -159,17 +159,19 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
159 from_this_trans = 1; 159 from_this_trans = 1;
160 160
161 /* FIXME, this is not good */ 161 /* FIXME, this is not good */
162 if (from_this_trans == 0 && 162 if (memcmp_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE)) {
163 memcmp_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE)) {
164 u32 val; 163 u32 val;
165 u32 found = 0; 164 u32 found = 0;
166 memcpy(&found, result, BTRFS_CRC32_SIZE); 165 memcpy(&found, result, BTRFS_CRC32_SIZE);
167 166
168 read_extent_buffer(buf, &val, 0, BTRFS_CRC32_SIZE); 167 read_extent_buffer(buf, &val, 0, BTRFS_CRC32_SIZE);
168 WARN_ON(1);
169 printk("btrfs: %s checksum verify failed on %llu " 169 printk("btrfs: %s checksum verify failed on %llu "
170 "wanted %X found %X from_this_trans %d\n", 170 "wanted %X found %X from_this_trans %d "
171 "level %d\n",
171 root->fs_info->sb->s_id, 172 root->fs_info->sb->s_id,
172 buf->start, val, found, from_this_trans); 173 buf->start, val, found, from_this_trans,
174 btrfs_header_level(buf));
173 return 1; 175 return 1;
174 } 176 }
175 } else { 177 } else {
@@ -220,6 +222,9 @@ int csum_dirty_buffer(struct btrfs_root *root, struct page *page)
220 goto err; 222 goto err;
221 } 223 }
222 found_level = btrfs_header_level(eb); 224 found_level = btrfs_header_level(eb);
225 spin_lock(&root->fs_info->hash_lock);
226 btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
227 spin_unlock(&root->fs_info->hash_lock);
223 csum_tree_block(root, eb, 0); 228 csum_tree_block(root, eb, 0);
224err: 229err:
225 free_extent_buffer(eb); 230 free_extent_buffer(eb);