Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 206350
b: refs/heads/master
c: 1d5385b
h: refs/heads/master
v: v3
  • Loading branch information
Ryusuke Konishi committed Jul 23, 2010
1 parent 3aa5049 commit 8168136
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cfa913a5077f7619869b2b4d1bf23ccb4f8b3d7b
refs/heads/master: 1d5385b9f30ae43209459db424416a3e1d8f2bde
50 changes: 47 additions & 3 deletions trunk/fs/nilfs2/btree.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,24 @@ static int nilfs_btree_get_block(const struct nilfs_btree *btree, __u64 ptr,
{
struct address_space *btnc =
&NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
struct buffer_head *bh;
int err;

err = nilfs_btnode_submit_block(btnc, ptr, 0, bhp);
if (err)
return err == -EEXIST ? 0 : err;

wait_on_buffer(*bhp);
if (!buffer_uptodate(*bhp)) {
brelse(*bhp);
bh = *bhp;
wait_on_buffer(bh);
if (!buffer_uptodate(bh)) {
brelse(bh);
return -EIO;
}
if (nilfs_btree_broken_node_block(bh)) {
clear_buffer_uptodate(bh);
brelse(bh);
return -EINVAL;
}
return 0;
}

Expand Down Expand Up @@ -382,6 +389,43 @@ static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node,
return s == 0;
}

/**
* nilfs_btree_node_broken - verify consistency of btree node
* @node: btree node block to be examined
* @size: node size (in bytes)
* @blocknr: block number
*
* Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned.
*/
static int nilfs_btree_node_broken(const struct nilfs_btree_node *node,
size_t size, sector_t blocknr)
{
int level, flags, nchildren;
int ret = 0;

level = nilfs_btree_node_get_level(node);
flags = nilfs_btree_node_get_flags(node);
nchildren = nilfs_btree_node_get_nchildren(node);

if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
level >= NILFS_BTREE_LEVEL_MAX ||
(flags & NILFS_BTREE_NODE_ROOT) ||
nchildren < 0 ||
nchildren > NILFS_BTREE_NODE_NCHILDREN_MAX(size))) {
printk(KERN_CRIT "NILFS: bad btree node (blocknr=%llu): "
"level = %d, flags = 0x%x, nchildren = %d\n",
(unsigned long long)blocknr, level, flags, nchildren);
ret = 1;
}
return ret;
}

int nilfs_btree_broken_node_block(struct buffer_head *bh)
{
return nilfs_btree_node_broken((struct nilfs_btree_node *)bh->b_data,
bh->b_size, bh->b_blocknr);
}

static inline struct nilfs_btree_node *
nilfs_btree_get_root(const struct nilfs_btree *btree)
{
Expand Down
2 changes: 2 additions & 0 deletions trunk/fs/nilfs2/btree.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,6 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *, __u64, __u64,
const __u64 *, const __u64 *, int);
void nilfs_btree_init_gc(struct nilfs_bmap *);

int nilfs_btree_broken_node_block(struct buffer_head *bh);

#endif /* _NILFS_BTREE_H */
9 changes: 7 additions & 2 deletions trunk/fs/nilfs2/gcinode.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,15 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh)
if (buffer_dirty(bh))
return -EEXIST;

if (buffer_nilfs_node(bh))
if (buffer_nilfs_node(bh)) {
if (nilfs_btree_broken_node_block(bh)) {
clear_buffer_uptodate(bh);
return -EIO;
}
nilfs_btnode_mark_dirty(bh);
else
} else {
nilfs_mdt_mark_buffer_dirty(bh);
}
return 0;
}

Expand Down

0 comments on commit 8168136

Please sign in to comment.