Skip to content

Commit

Permalink
Btrfs: still corruption hunting
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Mason <chris.mason@oracle.com>
  • Loading branch information
Chris Mason authored and David Woodhouse committed Apr 2, 2007
1 parent d602557 commit 2c90e5d
Show file tree
Hide file tree
Showing 10 changed files with 265 additions and 95 deletions.
7 changes: 3 additions & 4 deletions fs/btrfs/bit-radix.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#define BIT_ARRAY_BYTES 256
#define BIT_RADIX_BITS_PER_ARRAY ((BIT_ARRAY_BYTES - sizeof(unsigned long)) * 8)

extern struct kmem_cache *btrfs_bit_radix_cachep;
int set_radix_bit(struct radix_tree_root *radix, unsigned long bit)
{
unsigned long *bits;
Expand All @@ -16,7 +17,7 @@ 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_NOFS);
bits = kmem_cache_alloc(btrfs_bit_radix_cachep, GFP_NOFS);
if (!bits)
return -ENOMEM;
memset(bits + 1, 0, BIT_ARRAY_BYTES - sizeof(unsigned long));
Expand Down Expand Up @@ -68,12 +69,10 @@ int clear_radix_bit(struct radix_tree_root *radix, unsigned long bit)
break;
}
}

if (empty) {
bits = radix_tree_delete(radix, slot);
synchronize_rcu();
BUG_ON(!bits);
kfree(bits);
kmem_cache_free(btrfs_bit_radix_cachep, bits);
}
#endif
return 0;
Expand Down
14 changes: 14 additions & 0 deletions fs/btrfs/btrfs_inode.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef __BTRFS_I__
#define __BTRFS_I__

struct btrfs_inode {
u32 magic;
struct inode vfs_inode;
u32 magic2;
};
static inline struct btrfs_inode *BTRFS_I(struct inode *inode)
{
return container_of(inode, struct btrfs_inode, vfs_inode);
}

#endif
42 changes: 30 additions & 12 deletions fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct
static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct btrfs_path *path, int level, int slot);

struct btrfs_path *btrfs_alloc_path(void)
{
return kmem_cache_alloc(btrfs_path_cachep, GFP_NOFS);
}

void btrfs_free_path(struct btrfs_path *p)
{
kmem_cache_free(btrfs_path_cachep, p);
}

inline void btrfs_init_path(struct btrfs_path *p)
{
memset(p, 0, sizeof(*p));
Expand Down Expand Up @@ -47,17 +57,18 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
}
cow = btrfs_alloc_free_block(trans, root);
cow_node = btrfs_buffer_node(cow);
if (buf->b_size != root->blocksize || cow->b_size != root->blocksize)
WARN_ON(1);
memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize);
btrfs_set_header_blocknr(&cow_node->header, cow->b_blocknr);
btrfs_set_header_generation(&cow_node->header, trans->transid);
*cow_ret = cow;
btrfs_mark_buffer_dirty(cow);
btrfs_inc_ref(trans, root, buf);
if (buf == root->node) {
root->node = cow;
get_bh(cow);
if (buf != root->commit_root)
if (buf != root->commit_root) {
btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1);
}
btrfs_block_release(root, buf);
} else {
btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot,
Expand All @@ -66,6 +77,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1);
}
btrfs_block_release(root, buf);
*cow_ret = cow;
return 0;
}

Expand Down Expand Up @@ -477,9 +489,12 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
p->slots[level + 1],
&cow_buf);
b = cow_buf;
c = btrfs_buffer_node(b);
}
BUG_ON(!cow && ins_len);
c = btrfs_buffer_node(b);
if (level != btrfs_header_level(&c->header))
WARN_ON(1);
level = btrfs_header_level(&c->header);
p->nodes[level] = b;
ret = check_block(root, p, level);
if (ret)
Expand Down Expand Up @@ -1257,19 +1272,22 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
data_size)
{
int ret = 0;
struct btrfs_path path;
struct btrfs_path *path;
u8 *ptr;

btrfs_init_path(&path);
ret = btrfs_insert_empty_item(trans, root, &path, cpu_key, data_size);
path = btrfs_alloc_path();
BUG_ON(!path);
btrfs_init_path(path);
ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
if (!ret) {
ptr = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]),
path.slots[0], u8);
btrfs_memcpy(root, path.nodes[0]->b_data,
ptr = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
path->slots[0], u8);
btrfs_memcpy(root, path->nodes[0]->b_data,
ptr, data, data_size);
btrfs_mark_buffer_dirty(path.nodes[0]);
btrfs_mark_buffer_dirty(path->nodes[0]);
}
btrfs_release_path(root, &path);
btrfs_release_path(root, path);
btrfs_free_path(path);
return ret;
}

Expand Down
3 changes: 3 additions & 0 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

struct btrfs_trans_handle;
struct btrfs_transaction;
extern struct kmem_cache *btrfs_path_cachep;

#define BTRFS_MAGIC "_BtRfS_M"

Expand Down Expand Up @@ -888,6 +889,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_key *key, struct btrfs_path *p, int
ins_len, int cow);
void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
struct btrfs_path *btrfs_alloc_path(void);
void btrfs_free_path(struct btrfs_path *p);
void btrfs_init_path(struct btrfs_path *p);
int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct btrfs_path *path);
Expand Down
Loading

0 comments on commit 2c90e5d

Please sign in to comment.