Commit d6025579 authored by Chris Mason's avatar Chris Mason Committed by David Woodhouse

Btrfs: corruption hunt continues

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 22b0ebda
......@@ -16,12 +16,14 @@ int set_radix_bit(struct radix_tree_root *radix, unsigned long bit)
bits = radix_tree_lookup(radix, slot);
if (!bits) {
bits = kmalloc(BIT_ARRAY_BYTES, GFP_NOIO);
bits = kmalloc(BIT_ARRAY_BYTES, GFP_NOFS);
if (!bits)
return -ENOMEM;
memset(bits + 1, 0, BIT_ARRAY_BYTES - sizeof(unsigned long));
bits[0] = slot;
radix_tree_preload(GFP_NOFS);
ret = radix_tree_insert(radix, slot, bits);
radix_tree_preload_end();
if (ret)
return ret;
}
......@@ -59,7 +61,7 @@ int clear_radix_bit(struct radix_tree_root *radix, unsigned long bit)
if (!bits)
return 0;
clear_bit(bit_slot, bits + 1);
#if 0
for (i = 1; i < BIT_ARRAY_BYTES / sizeof(unsigned long); i++) {
if (bits[i]) {
empty = 0;
......@@ -69,8 +71,11 @@ int clear_radix_bit(struct radix_tree_root *radix, unsigned long bit)
if (empty) {
bits = radix_tree_delete(radix, slot);
synchronize_rcu();
BUG_ON(!bits);
kfree(bits);
}
#endif
return 0;
}
......
This diff is collapsed.
......@@ -2,6 +2,7 @@
#define __BTRFS__
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include "bit-radix.h"
struct btrfs_trans_handle;
......@@ -834,6 +835,37 @@ static inline struct btrfs_root *btrfs_sb(struct super_block *sb)
return sb->s_fs_info;
}
static inline void btrfs_check_bounds(void *vptr, size_t len,
void *vcontainer, size_t container_len)
{
char *ptr = vptr;
char *container = vcontainer;
WARN_ON(ptr < container);
WARN_ON(ptr + len > container + container_len);
}
static inline void btrfs_memcpy(struct btrfs_root *root,
void *dst_block,
void *dst, const void *src, size_t nr)
{
btrfs_check_bounds(dst, nr, dst_block, root->fs_info->sb->s_blocksize);
memcpy(dst, src, nr);
}
static inline void btrfs_memmove(struct btrfs_root *root,
void *dst_block,
void *dst, void *src, size_t nr)
{
btrfs_check_bounds(dst, nr, dst_block, root->fs_info->sb->s_blocksize);
memmove(dst, src, nr);
}
static inline void btrfs_mark_buffer_dirty(struct buffer_head *bh)
{
WARN_ON(!atomic_read(&bh->b_count));
mark_buffer_dirty(bh);
}
/* helper function to cast into the data area of the leaf. */
#define btrfs_item_ptr(leaf, slot, type) \
((type *)(btrfs_leaf_data(leaf) + \
......
......@@ -34,10 +34,8 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_dir_flags(dir_item, 0);
btrfs_set_dir_name_len(dir_item, name_len);
name_ptr = (char *)(dir_item + 1);
memcpy(name_ptr, name, name_len);
if (name_ptr + name_len > path.nodes[0]->b_data + 4096)
WARN_ON(1);
mark_buffer_dirty(path.nodes[0]);
btrfs_memcpy(root, path.nodes[0]->b_data, name_ptr, name, name_len);
btrfs_mark_buffer_dirty(path.nodes[0]);
out:
btrfs_release_path(root, &path);
return ret;
......
......@@ -8,6 +8,17 @@
#include "disk-io.h"
#include "transaction.h"
#define PATTERN 0xDEADBEEFUL
static inline void check_pattern(struct buffer_head *buf)
{
if (buf->b_private != (void *)PATTERN)
WARN_ON(1);
}
static inline void set_pattern(struct buffer_head *buf)
{
buf->b_private = (void *)PATTERN;
}
static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf)
{
......@@ -51,8 +62,10 @@ struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr)
} while (bh != head);
out_unlock:
unlock_page(page);
if (ret)
if (ret) {
touch_buffer(ret);
check_pattern(ret);
}
page_cache_release(page);
return ret;
}
......@@ -82,6 +95,7 @@ struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root,
bh->b_bdev = root->fs_info->sb->s_bdev;
bh->b_blocknr = first_block;
set_buffer_mapped(bh);
set_pattern(bh);
}
if (bh->b_blocknr == blocknr) {
ret = bh;
......@@ -225,6 +239,7 @@ struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr)
if (!buffer_uptodate(bh))
goto fail;
csum_tree_block(root, bh, 1);
set_pattern(bh);
} else {
unlock_buffer(bh);
}
......@@ -240,6 +255,7 @@ struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr)
int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct buffer_head *buf)
{
WARN_ON(atomic_read(&buf->b_count) == 0);
mark_buffer_dirty(buf);
return 0;
}
......@@ -247,6 +263,7 @@ int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct buffer_head *buf)
{
WARN_ON(atomic_read(&buf->b_count) == 0);
clear_buffer_dirty(buf);
return 0;
}
......@@ -431,6 +448,7 @@ int close_ctree(struct btrfs_root *root)
void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf)
{
check_pattern(buf);
brelse(buf);
}
......@@ -39,7 +39,7 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item);
refs = btrfs_extent_refs(item);
btrfs_set_extent_refs(item, refs + 1);
mark_buffer_dirty(path.nodes[0]);
btrfs_mark_buffer_dirty(path.nodes[0]);
btrfs_release_path(root->fs_info->extent_root, &path);
finish_current_insert(trans, root->fs_info->extent_root);
......@@ -177,10 +177,10 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending)
header = btrfs_buffer_header(bh);
if (btrfs_header_generation(header) ==
root->fs_info->running_transaction->transid) {
brelse(bh);
btrfs_block_release(root, bh);
return 0;
}
brelse(bh);
btrfs_block_release(root, bh);
}
err = set_radix_bit(&root->fs_info->pinned_radix, blocknr);
} else {
......@@ -224,7 +224,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
BUG_ON(ei->refs == 0);
refs = btrfs_extent_refs(ei) - 1;
btrfs_set_extent_refs(ei, refs);
mark_buffer_dirty(path.nodes[0]);
btrfs_mark_buffer_dirty(path.nodes[0]);
if (refs == 0) {
u64 super_blocks_used;
......
......@@ -34,7 +34,7 @@ int btrfs_alloc_file_extent(struct btrfs_trans_handle *trans,
btrfs_set_file_extent_offset(item, 0);
btrfs_set_file_extent_num_blocks(item, ins.offset);
btrfs_set_file_extent_generation(item, trans->transid);
mark_buffer_dirty(path.nodes[0]);
btrfs_mark_buffer_dirty(path.nodes[0]);
*result = ins.objectid;
btrfs_release_path(root, &path);
return 0;
......@@ -81,7 +81,7 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
struct btrfs_csum_item);
ret = 0;
ret = btrfs_csum_data(root, data, len, item->csum);
mark_buffer_dirty(path.nodes[0]);
btrfs_mark_buffer_dirty(path.nodes[0]);
fail:
btrfs_release_path(root, &path);
return ret;
......
......@@ -109,7 +109,7 @@ int btrfs_insert_inode_map(struct btrfs_trans_handle *trans,
inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]),
path.slots[0], struct btrfs_inode_map_item);
btrfs_cpu_key_to_disk(&inode_item->key, location);
mark_buffer_dirty(path.nodes[0]);
btrfs_mark_buffer_dirty(path.nodes[0]);
out:
btrfs_release_path(inode_root, &path);
return ret;
......
......@@ -45,6 +45,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
struct btrfs_leaf *l;
int ret;
int slot;
struct btrfs_root_item *update_item;
btrfs_init_path(&path);
ret = btrfs_search_slot(trans, root, key, &path, 0, 1);
......@@ -53,9 +54,9 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
BUG_ON(ret != 0);
l = btrfs_buffer_leaf(path.nodes[0]);
slot = path.slots[0];
memcpy(btrfs_item_ptr(l, slot, struct btrfs_root_item), item,
sizeof(*item));
mark_buffer_dirty(path.nodes[0]);
update_item = btrfs_item_ptr(l, slot, struct btrfs_root_item);
btrfs_memcpy(root, l, update_item, item, sizeof(*item));
btrfs_mark_buffer_dirty(path.nodes[0]);
out:
btrfs_release_path(root, &path);
return ret;
......
......@@ -557,7 +557,7 @@ static int btrfs_update_inode(struct btrfs_trans_handle *trans,
struct btrfs_inode_item);
fill_inode_item(inode_item, inode);
mark_buffer_dirty(path.nodes[0]);
btrfs_mark_buffer_dirty(path.nodes[0]);
failed:
btrfs_release_path(root, &path);
return 0;
......
......@@ -66,6 +66,7 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans,
cur_trans->num_writers--;
put_transaction(cur_trans);
mutex_unlock(&root->fs_info->trans_mutex);
memset(trans, 0, sizeof(*trans));
kfree(trans);
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment