Skip to content

Commit

Permalink
Reorder the flags field in struct btrfs_header and record a flag on w…
Browse files Browse the repository at this point in the history
…riteout

This allows detection of blocks that have already been written in the
running transaction so they can be recowed instead of modified again.
It is step one in trusting the transid field of the block pointers.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
  • Loading branch information
Chris Mason committed Sep 25, 2008
1 parent 2d2ae54 commit 63b10fc
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 9 deletions.
10 changes: 8 additions & 2 deletions fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
btrfs_set_header_bytenr(cow, cow->start);
btrfs_set_header_generation(cow, trans->transid);
btrfs_set_header_owner(cow, new_root_objectid);
btrfs_clear_header_flag(cow, BTRFS_HEADER_FLAG_WRITTEN);

WARN_ON(btrfs_header_generation(buf) > trans->transid);
ret = btrfs_inc_ref(trans, new_root, buf);
Expand Down Expand Up @@ -183,6 +184,7 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans,
btrfs_set_header_bytenr(cow, cow->start);
btrfs_set_header_generation(cow, trans->transid);
btrfs_set_header_owner(cow, root->root_key.objectid);
btrfs_clear_header_flag(cow, BTRFS_HEADER_FLAG_WRITTEN);

WARN_ON(btrfs_header_generation(buf) > trans->transid);
if (btrfs_header_generation(buf) != trans->transid) {
Expand Down Expand Up @@ -245,11 +247,14 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans,
}

header_trans = btrfs_header_generation(buf);
if (header_trans == trans->transid) {
spin_lock(&root->fs_info->hash_lock);
if (header_trans == trans->transid &&
!btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) {
*cow_ret = buf;
spin_unlock(&root->fs_info->hash_lock);
return 0;
}

spin_unlock(&root->fs_info->hash_lock);
search_start = buf->start & ~((u64)(1024 * 1024 * 1024) - 1);
ret = __btrfs_cow_block(trans, root, buf, parent,
parent_slot, cow_ret, search_start, 0);
Expand Down Expand Up @@ -1494,6 +1499,7 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_header_bytenr(split, split->start);
btrfs_set_header_generation(split, trans->transid);
btrfs_set_header_owner(split, root->root_key.objectid);
btrfs_set_header_flags(split, 0);
write_extent_buffer(split, root->fs_info->fsid,
(unsigned long)btrfs_header_fsid(split),
BTRFS_FSID_SIZE);
Expand Down
28 changes: 25 additions & 3 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,17 +193,19 @@ static inline unsigned long btrfs_chunk_item_size(int num_stripes)
}

#define BTRFS_FSID_SIZE 16
#define BTRFS_HEADER_FLAG_WRITTEN (1 << 0)

/*
* every tree block (leaf or node) starts with this header.
*/
struct btrfs_header {
u8 csum[BTRFS_CSUM_SIZE];
u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
__le64 bytenr; /* which block this node is supposed to live in */
__le64 flags;
__le64 generation;
__le64 owner;
__le32 nritems;
__le16 flags;
u8 level;
} __attribute__ ((__packed__));

Expand All @@ -229,9 +231,10 @@ struct btrfs_header {
*/
struct btrfs_super_block {
u8 csum[BTRFS_CSUM_SIZE];
/* the first 3 fields must match struct btrfs_header */
/* the first 4 fields must match struct btrfs_header */
u8 fsid[16]; /* FS specific uuid */
__le64 bytenr; /* this block number */
__le64 flags;
__le64 magic;
__le64 generation;
__le64 root;
Expand Down Expand Up @@ -1045,9 +1048,28 @@ BTRFS_SETGET_HEADER_FUNCS(header_generation, struct btrfs_header,
generation, 64);
BTRFS_SETGET_HEADER_FUNCS(header_owner, struct btrfs_header, owner, 64);
BTRFS_SETGET_HEADER_FUNCS(header_nritems, struct btrfs_header, nritems, 32);
BTRFS_SETGET_HEADER_FUNCS(header_flags, struct btrfs_header, flags, 16);
BTRFS_SETGET_HEADER_FUNCS(header_flags, struct btrfs_header, flags, 64);
BTRFS_SETGET_HEADER_FUNCS(header_level, struct btrfs_header, level, 8);

static inline int btrfs_header_flag(struct extent_buffer *eb, u64 flag)
{
return (btrfs_header_flags(eb) & flag) == flag;
}

static inline int btrfs_set_header_flag(struct extent_buffer *eb, u64 flag)
{
u64 flags = btrfs_header_flags(eb);
btrfs_set_header_flags(eb, flags | flag);
return (flags & flag) == flag;
}

static inline int btrfs_clear_header_flag(struct extent_buffer *eb, u64 flag)
{
u64 flags = btrfs_header_flags(eb);
btrfs_set_header_flags(eb, flags & ~flag);
return (flags & flag) == flag;
}

static inline u8 *btrfs_header_fsid(struct extent_buffer *eb)
{
unsigned long ptr = offsetof(struct btrfs_header, fsid);
Expand Down
13 changes: 9 additions & 4 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,17 +159,19 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
from_this_trans = 1;

/* FIXME, this is not good */
if (from_this_trans == 0 &&
memcmp_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE)) {
if (memcmp_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE)) {
u32 val;
u32 found = 0;
memcpy(&found, result, BTRFS_CRC32_SIZE);

read_extent_buffer(buf, &val, 0, BTRFS_CRC32_SIZE);
WARN_ON(1);
printk("btrfs: %s checksum verify failed on %llu "
"wanted %X found %X from_this_trans %d\n",
"wanted %X found %X from_this_trans %d "
"level %d\n",
root->fs_info->sb->s_id,
buf->start, val, found, from_this_trans);
buf->start, val, found, from_this_trans,
btrfs_header_level(buf));
return 1;
}
} else {
Expand Down Expand Up @@ -220,6 +222,9 @@ int csum_dirty_buffer(struct btrfs_root *root, struct page *page)
goto err;
}
found_level = btrfs_header_level(eb);
spin_lock(&root->fs_info->hash_lock);
btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
spin_unlock(&root->fs_info->hash_lock);
csum_tree_block(root, eb, 0);
err:
free_extent_buffer(eb);
Expand Down

0 comments on commit 63b10fc

Please sign in to comment.