Commit 7f5c1516 authored by Chris Mason's avatar Chris Mason Committed by David Woodhouse

Add generation number to btrfs_header, readdir fixes, hash collision fixes

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent df2ce34c
#include <linux/module.h> #include <linux/module.h>
#include "ctree.h" #include "ctree.h"
#include "disk-io.h" #include "disk-io.h"
#include "transaction.h"
static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_path *path, int level); *root, struct btrfs_path *path, int level);
...@@ -39,7 +40,8 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -39,7 +40,8 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
struct buffer_head *cow; struct buffer_head *cow;
struct btrfs_node *cow_node; struct btrfs_node *cow_node;
if (buffer_dirty(buf)) { if (btrfs_header_generation(btrfs_buffer_header(buf)) ==
trans->transid) {
*cow_ret = buf; *cow_ret = buf;
return 0; return 0;
} }
...@@ -47,6 +49,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -47,6 +49,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
cow_node = btrfs_buffer_node(cow); cow_node = btrfs_buffer_node(cow);
memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize); memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize);
btrfs_set_header_blocknr(&cow_node->header, cow->b_blocknr); btrfs_set_header_blocknr(&cow_node->header, cow->b_blocknr);
btrfs_set_header_generation(&cow_node->header, trans->transid);
*cow_ret = cow; *cow_ret = cow;
mark_buffer_dirty(cow); mark_buffer_dirty(cow);
btrfs_inc_ref(trans, root, buf); btrfs_inc_ref(trans, root, buf);
...@@ -661,6 +664,7 @@ static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -661,6 +664,7 @@ static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_header_nritems(&c->header, 1); btrfs_set_header_nritems(&c->header, 1);
btrfs_set_header_level(&c->header, level); btrfs_set_header_level(&c->header, level);
btrfs_set_header_blocknr(&c->header, t->b_blocknr); btrfs_set_header_blocknr(&c->header, t->b_blocknr);
btrfs_set_header_generation(&c->header, trans->transid);
btrfs_set_header_parentid(&c->header, btrfs_set_header_parentid(&c->header,
btrfs_header_parentid(btrfs_buffer_header(root->node))); btrfs_header_parentid(btrfs_buffer_header(root->node)));
lower = btrfs_buffer_node(path->nodes[level-1]); lower = btrfs_buffer_node(path->nodes[level-1]);
...@@ -750,6 +754,7 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -750,6 +754,7 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
split = btrfs_buffer_node(split_buffer); split = btrfs_buffer_node(split_buffer);
btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header)); btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header));
btrfs_set_header_blocknr(&split->header, split_buffer->b_blocknr); btrfs_set_header_blocknr(&split->header, split_buffer->b_blocknr);
btrfs_set_header_generation(&split->header, trans->transid);
btrfs_set_header_parentid(&split->header, btrfs_set_header_parentid(&split->header,
btrfs_header_parentid(btrfs_buffer_header(root->node))); btrfs_header_parentid(btrfs_buffer_header(root->node)));
mid = (c_nritems + 1) / 2; mid = (c_nritems + 1) / 2;
...@@ -1096,6 +1101,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1096,6 +1101,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
} }
btrfs_set_header_nritems(&right->header, nritems - mid); btrfs_set_header_nritems(&right->header, nritems - mid);
btrfs_set_header_blocknr(&right->header, right_buffer->b_blocknr); btrfs_set_header_blocknr(&right->header, right_buffer->b_blocknr);
btrfs_set_header_generation(&right->header, trans->transid);
btrfs_set_header_level(&right->header, 0); btrfs_set_header_level(&right->header, 0);
btrfs_set_header_parentid(&right->header, btrfs_set_header_parentid(&right->header,
btrfs_header_parentid(btrfs_buffer_header(root->node))); btrfs_header_parentid(btrfs_buffer_header(root->node)));
......
...@@ -52,6 +52,7 @@ struct btrfs_key { ...@@ -52,6 +52,7 @@ struct btrfs_key {
struct btrfs_header { struct btrfs_header {
u8 fsid[16]; /* FS specific uuid */ u8 fsid[16]; /* FS specific uuid */
__le64 blocknr; /* which block this node is supposed to live in */ __le64 blocknr; /* which block this node is supposed to live in */
__le64 generation;
__le64 parentid; /* objectid of the tree root */ __le64 parentid; /* objectid of the tree root */
__le32 csum; __le32 csum;
__le32 ham; __le32 ham;
...@@ -600,6 +601,17 @@ static inline void btrfs_set_header_blocknr(struct btrfs_header *h, u64 blocknr) ...@@ -600,6 +601,17 @@ static inline void btrfs_set_header_blocknr(struct btrfs_header *h, u64 blocknr)
h->blocknr = cpu_to_le64(blocknr); h->blocknr = cpu_to_le64(blocknr);
} }
static inline u64 btrfs_header_generation(struct btrfs_header *h)
{
return le64_to_cpu(h->generation);
}
static inline void btrfs_set_header_generation(struct btrfs_header *h,
u64 val)
{
h->generation = cpu_to_le64(val);
}
static inline u64 btrfs_header_parentid(struct btrfs_header *h) static inline u64 btrfs_header_parentid(struct btrfs_header *h)
{ {
return le64_to_cpu(h->parentid); return le64_to_cpu(h->parentid);
...@@ -839,7 +851,7 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -839,7 +851,7 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_path *path, u64 dir, *root, struct btrfs_path *path, u64 dir,
const char *name, int name_len, int mod); const char *name, int name_len, int mod);
int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path,
char *name, int name_len); const char *name, int name_len);
int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
struct btrfs_root *fs_root, struct btrfs_root *fs_root,
u64 dirid, u64 *objectid); u64 dirid, u64 *objectid);
......
...@@ -60,8 +60,8 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -60,8 +60,8 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
} }
int btrfs_match_dir_item_name(struct btrfs_root *root, int btrfs_match_dir_item_name(struct btrfs_root *root,
struct btrfs_path *path, char struct btrfs_path *path,
*name, int name_len) const char *name, int name_len)
{ {
struct btrfs_dir_item *dir_item; struct btrfs_dir_item *dir_item;
char *name_ptr; char *name_ptr;
......
...@@ -11,11 +11,7 @@ static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) ...@@ -11,11 +11,7 @@ static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf)
BUG(); BUG();
if (root->node && btrfs_header_parentid(&node->header) != if (root->node && btrfs_header_parentid(&node->header) !=
btrfs_header_parentid(btrfs_buffer_header(root->node))) { btrfs_header_parentid(btrfs_buffer_header(root->node))) {
printk("block %Lu parentids don't match buf %Lu, root %Lu\n", BUG();
buf->b_blocknr,
btrfs_header_parentid(&node->header),
btrfs_header_parentid(btrfs_buffer_header(root->node)));
WARN_ON(1);
} }
return 0; return 0;
} }
......
...@@ -199,7 +199,7 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, ...@@ -199,7 +199,7 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry,
btrfs_init_path(&path); btrfs_init_path(&path);
ret = btrfs_lookup_dir_item(NULL, root, &path, dir->i_ino, name, ret = btrfs_lookup_dir_item(NULL, root, &path, dir->i_ino, name,
namelen, 0); namelen, 0);
if (ret) { if (ret || !btrfs_match_dir_item_name(root, &path, name, namelen)) {
*ino = 0; *ino = 0;
goto out; goto out;
} }
...@@ -247,7 +247,7 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -247,7 +247,7 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
int slot; int slot;
int advance; int advance;
unsigned char d_type = DT_UNKNOWN; unsigned char d_type = DT_UNKNOWN;
int over; int over = 0;
key.objectid = inode->i_ino; key.objectid = inode->i_ino;
key.flags = 0; key.flags = 0;
...@@ -258,7 +258,7 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -258,7 +258,7 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (ret < 0) { if (ret < 0) {
goto err; goto err;
} }
advance = filp->f_pos > 0 && ret != 0; advance = 0;
while(1) { while(1) {
leaf = btrfs_buffer_leaf(path.nodes[0]); leaf = btrfs_buffer_leaf(path.nodes[0]);
nritems = btrfs_header_nritems(&leaf->header); nritems = btrfs_header_nritems(&leaf->header);
...@@ -282,13 +282,17 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -282,13 +282,17 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
break; break;
if (btrfs_disk_key_type(&item->key) != BTRFS_DIR_ITEM_KEY) if (btrfs_disk_key_type(&item->key) != BTRFS_DIR_ITEM_KEY)
continue; continue;
if (btrfs_disk_key_offset(&item->key) < filp->f_pos)
continue;
di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
over = filldir(dirent, (const char *)(di + 1), over = filldir(dirent, (const char *)(di + 1),
btrfs_dir_name_len(di), btrfs_dir_name_len(di),
btrfs_disk_key_offset(&item->key), btrfs_disk_key_offset(&item->key),
btrfs_dir_objectid(di), d_type); btrfs_dir_objectid(di), d_type);
if (over) if (over) {
filp->f_pos = btrfs_disk_key_offset(&item->key);
break; break;
}
filp->f_pos = btrfs_disk_key_offset(&item->key) + 1; filp->f_pos = btrfs_disk_key_offset(&item->key) + 1;
} }
ret = 0; ret = 0;
...@@ -425,7 +429,6 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans, ...@@ -425,7 +429,6 @@ static int btrfs_add_link(struct btrfs_trans_handle *trans,
dentry->d_name.name, dentry->d_name.len, dentry->d_name.name, dentry->d_name.len,
dentry->d_parent->d_inode->i_ino, dentry->d_parent->d_inode->i_ino,
inode->i_ino, 0); inode->i_ino, 0);
BUG_ON(ret);
return ret; return ret;
} }
...@@ -466,6 +469,7 @@ static void btrfs_write_super(struct super_block *sb) ...@@ -466,6 +469,7 @@ static void btrfs_write_super(struct super_block *sb)
{ {
sb->s_dirt = 0; sb->s_dirt = 0;
printk("btrfs write_super!\n"); printk("btrfs write_super!\n");
filemap_flush(sb->s_bdev->bd_inode->i_mapping);
} }
static int btrfs_sync_fs(struct super_block *sb, int wait) static int btrfs_sync_fs(struct super_block *sb, int wait)
......
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