Add generation number to btrfs_header, readdir fixes, hash collision fixes
Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
df2ce34c88
commit
7f5c15160e
5 changed files with 32 additions and 14 deletions
|
@ -1,6 +1,7 @@
|
||||||
#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
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
}
|
}
|
||||||
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 {
|
||||||
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)
|
||||||
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
|
||||||
*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
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
|
Loading…
Reference in a new issue