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

btrfs_create, btrfs_write_super, btrfs_sync_fs

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 79154b1b
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* Fix ENOSPC handling * Fix ENOSPC handling
* make a real mkfs and superblock * make a real mkfs and superblock
* Do checksumming * Do checksumming
* Use a real check instead of mark_buffer_dirty
* Define FS objects in terms of different item types * Define FS objects in terms of different item types
* Add block mapping tree (simple dm layer) * Add block mapping tree (simple dm layer)
* Add simple tree locking (semaphore per tree) * Add simple tree locking (semaphore per tree)
......
...@@ -39,7 +39,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -39,7 +39,7 @@ 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 (buffer_dirty(buf)) {
*cow_ret = buf; *cow_ret = buf;
return 0; return 0;
} }
...@@ -48,6 +48,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -48,6 +48,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
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);
*cow_ret = cow; *cow_ret = cow;
mark_buffer_dirty(cow);
btrfs_inc_ref(trans, root, buf); btrfs_inc_ref(trans, root, buf);
if (buf == root->node) { if (buf == root->node) {
root->node = cow; root->node = cow;
...@@ -58,7 +59,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -58,7 +59,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
} else { } else {
btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot, btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot,
cow->b_blocknr); cow->b_blocknr);
BUG_ON(!buffer_dirty(parent)); mark_buffer_dirty(parent);
btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1);
} }
btrfs_block_release(root, buf); btrfs_block_release(root, buf);
...@@ -362,7 +363,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -362,7 +363,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
memcpy(&parent->ptrs[pslot + 1].key, memcpy(&parent->ptrs[pslot + 1].key,
&right->ptrs[0].key, &right->ptrs[0].key,
sizeof(struct btrfs_disk_key)); sizeof(struct btrfs_disk_key));
BUG_ON(!buffer_dirty(parent_buf)); mark_buffer_dirty(parent_buf);
} }
} }
if (btrfs_header_nritems(&mid->header) == 1) { if (btrfs_header_nritems(&mid->header) == 1) {
...@@ -398,7 +399,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -398,7 +399,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
/* update the parent key to reflect our changes */ /* update the parent key to reflect our changes */
memcpy(&parent->ptrs[pslot].key, &mid->ptrs[0].key, memcpy(&parent->ptrs[pslot].key, &mid->ptrs[0].key,
sizeof(struct btrfs_disk_key)); sizeof(struct btrfs_disk_key));
BUG_ON(!buffer_dirty(parent_buf)); mark_buffer_dirty(parent_buf);
} }
/* update the path */ /* update the path */
...@@ -539,7 +540,7 @@ static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -539,7 +540,7 @@ static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root
break; break;
t = btrfs_buffer_node(path->nodes[i]); t = btrfs_buffer_node(path->nodes[i]);
memcpy(&t->ptrs[tslot].key, key, sizeof(*key)); memcpy(&t->ptrs[tslot].key, key, sizeof(*key));
BUG_ON(!buffer_dirty(path->nodes[i])); mark_buffer_dirty(path->nodes[i]);
if (tslot != 0) if (tslot != 0)
break; break;
} }
...@@ -583,8 +584,8 @@ static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -583,8 +584,8 @@ static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
} }
btrfs_set_header_nritems(&src->header, src_nritems - push_items); btrfs_set_header_nritems(&src->header, src_nritems - push_items);
btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
BUG_ON(!buffer_dirty(src_buf)); mark_buffer_dirty(src_buf);
BUG_ON(!buffer_dirty(dst_buf)); mark_buffer_dirty(dst_buf);
return ret; return ret;
} }
...@@ -631,8 +632,8 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct ...@@ -631,8 +632,8 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct
btrfs_set_header_nritems(&src->header, src_nritems - push_items); btrfs_set_header_nritems(&src->header, src_nritems - push_items);
btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); btrfs_set_header_nritems(&dst->header, dst_nritems + push_items);
BUG_ON(!buffer_dirty(src_buf)); mark_buffer_dirty(src_buf);
BUG_ON(!buffer_dirty(dst_buf)); mark_buffer_dirty(dst_buf);
return ret; return ret;
} }
...@@ -669,6 +670,9 @@ static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -669,6 +670,9 @@ static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root
lower_key = &lower->ptrs[0].key; lower_key = &lower->ptrs[0].key;
memcpy(&c->ptrs[0].key, lower_key, sizeof(struct btrfs_disk_key)); memcpy(&c->ptrs[0].key, lower_key, sizeof(struct btrfs_disk_key));
btrfs_set_node_blockptr(c, 0, path->nodes[level - 1]->b_blocknr); btrfs_set_node_blockptr(c, 0, path->nodes[level - 1]->b_blocknr);
mark_buffer_dirty(t);
/* the super has an extra ref to root->node */ /* the super has an extra ref to root->node */
btrfs_block_release(root, root->node); btrfs_block_release(root, root->node);
root->node = t; root->node = t;
...@@ -708,7 +712,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -708,7 +712,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
memcpy(&lower->ptrs[slot].key, key, sizeof(struct btrfs_disk_key)); memcpy(&lower->ptrs[slot].key, key, sizeof(struct btrfs_disk_key));
btrfs_set_node_blockptr(lower, slot, blocknr); btrfs_set_node_blockptr(lower, slot, blocknr);
btrfs_set_header_nritems(&lower->header, nritems + 1); btrfs_set_header_nritems(&lower->header, nritems + 1);
BUG_ON(!buffer_dirty(path->nodes[level])); mark_buffer_dirty(path->nodes[level]);
return 0; return 0;
} }
...@@ -755,7 +759,8 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -755,7 +759,8 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_header_nritems(&c->header, mid); btrfs_set_header_nritems(&c->header, mid);
ret = 0; ret = 0;
BUG_ON(!buffer_dirty(t)); mark_buffer_dirty(t);
mark_buffer_dirty(split_buffer);
wret = insert_ptr(trans, root, path, &split->ptrs[0].key, wret = insert_ptr(trans, root, path, &split->ptrs[0].key,
split_buffer->b_blocknr, path->slots[level + 1] + 1, split_buffer->b_blocknr, path->slots[level + 1] + 1,
level + 1); level + 1);
...@@ -886,11 +891,11 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -886,11 +891,11 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
left_nritems -= push_items; left_nritems -= push_items;
btrfs_set_header_nritems(&left->header, left_nritems); btrfs_set_header_nritems(&left->header, left_nritems);
BUG_ON(!buffer_dirty(left_buf)); mark_buffer_dirty(left_buf);
BUG_ON(!buffer_dirty(right_buf)); mark_buffer_dirty(right_buf);
memcpy(&upper_node->ptrs[slot + 1].key, memcpy(&upper_node->ptrs[slot + 1].key,
&right->items[0].key, sizeof(struct btrfs_disk_key)); &right->items[0].key, sizeof(struct btrfs_disk_key));
BUG_ON(!buffer_dirty(upper)); mark_buffer_dirty(upper);
/* then fixup the leaf pointer in the path */ /* then fixup the leaf pointer in the path */
if (path->slots[0] >= left_nritems) { if (path->slots[0] >= left_nritems) {
...@@ -1004,8 +1009,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1004,8 +1009,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
push_space = btrfs_item_offset(right->items + i); push_space = btrfs_item_offset(right->items + i);
} }
BUG_ON(!buffer_dirty(t)); mark_buffer_dirty(t);
BUG_ON(!buffer_dirty(right_buf)); mark_buffer_dirty(right_buf);
wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1); wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1);
if (wret) if (wret)
...@@ -1115,8 +1120,8 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1115,8 +1120,8 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
right_buffer->b_blocknr, path->slots[1] + 1, 1); right_buffer->b_blocknr, path->slots[1] + 1, 1);
if (wret) if (wret)
ret = wret; ret = wret;
BUG_ON(!buffer_dirty(right_buffer)); mark_buffer_dirty(right_buffer);
BUG_ON(!buffer_dirty(l_buf)); mark_buffer_dirty(l_buf);
BUG_ON(path->slots[0] != slot); BUG_ON(path->slots[0] != slot);
if (mid <= slot) { if (mid <= slot) {
btrfs_block_release(root, path->nodes[0]); btrfs_block_release(root, path->nodes[0]);
...@@ -1202,12 +1207,12 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1202,12 +1207,12 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_item_offset(leaf->items + slot, data_end - data_size); btrfs_set_item_offset(leaf->items + slot, data_end - data_size);
btrfs_set_item_size(leaf->items + slot, data_size); btrfs_set_item_size(leaf->items + slot, data_size);
btrfs_set_header_nritems(&leaf->header, nritems + 1); btrfs_set_header_nritems(&leaf->header, nritems + 1);
mark_buffer_dirty(leaf_buf);
ret = 0; ret = 0;
if (slot == 0) if (slot == 0)
ret = fixup_low_keys(trans, root, path, &disk_key, 1); ret = fixup_low_keys(trans, root, path, &disk_key, 1);
BUG_ON(!buffer_dirty(leaf_buf));
if (btrfs_leaf_free_space(root, leaf) < 0) if (btrfs_leaf_free_space(root, leaf) < 0)
BUG(); BUG();
check_leaf(root, path, 0); check_leaf(root, path, 0);
...@@ -1233,6 +1238,7 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1233,6 +1238,7 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
ptr = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), ptr = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]),
path.slots[0], u8); path.slots[0], u8);
memcpy(ptr, data, data_size); memcpy(ptr, data, data_size);
mark_buffer_dirty(path.nodes[0]);
} }
btrfs_release_path(root, &path); btrfs_release_path(root, &path);
return ret; return ret;
...@@ -1273,7 +1279,7 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, ...@@ -1273,7 +1279,7 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if (wret) if (wret)
ret = wret; ret = wret;
} }
BUG_ON(!buffer_dirty(parent)); mark_buffer_dirty(parent);
return ret; return ret;
} }
...@@ -1368,8 +1374,11 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, ...@@ -1368,8 +1374,11 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if (wret) if (wret)
ret = wret; ret = wret;
} else { } else {
mark_buffer_dirty(leaf_buf);
btrfs_block_release(root, leaf_buf); btrfs_block_release(root, leaf_buf);
} }
} else {
mark_buffer_dirty(leaf_buf);
} }
} }
return ret; return ret;
......
...@@ -833,7 +833,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -833,7 +833,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct
btrfs_root_item *item, struct btrfs_key *key); btrfs_root_item *item, struct btrfs_key *key);
int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
*root, char *name, int name_len, u64 dir, u64 *root, const char *name, int name_len, u64 dir, u64
objectid, u8 type); objectid, u8 type);
int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root 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,
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include "transaction.h" #include "transaction.h"
int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
*root, char *name, int name_len, u64 dir, u64 *root, const char *name, int name_len, u64 dir, u64
objectid, u8 type) objectid, u8 type)
{ {
int ret = 0; int ret = 0;
...@@ -35,6 +35,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -35,6 +35,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_dir_name_len(dir_item, name_len); btrfs_set_dir_name_len(dir_item, name_len);
name_ptr = (char *)(dir_item + 1); name_ptr = (char *)(dir_item + 1);
memcpy(name_ptr, name, name_len); memcpy(name_ptr, name, name_len);
mark_buffer_dirty(path.nodes[0]);
out: out:
btrfs_release_path(root, &path); btrfs_release_path(root, &path);
return ret; return ret;
......
...@@ -145,19 +145,20 @@ struct btrfs_root *open_ctree(struct super_block *sb, ...@@ -145,19 +145,20 @@ struct btrfs_root *open_ctree(struct super_block *sb,
int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root
*root) *root)
{ {
return 0; struct buffer_head *bh = root->fs_info->sb_buffer;
#if 0 btrfs_set_super_root(root->fs_info->disk_super,
int ret; root->fs_info->tree_root->node->b_blocknr);
btrfs_set_super_root(s, root->fs_info->tree_root->node->b_blocknr); lock_buffer(bh);
clear_buffer_dirty(bh);
ret = pwrite(root->fs_info->fp, s, sizeof(*s), bh->b_end_io = end_buffer_write_sync;
BTRFS_SUPER_INFO_OFFSET); get_bh(bh);
if (ret != sizeof(*s)) { submit_bh(WRITE, bh);
fprintf(stderr, "failed to write new super block err %d\n", ret); wait_on_buffer(bh);
return ret; if (!buffer_uptodate(bh)) {
WARN_ON(1);
return -EIO;
} }
return 0; return 0;
#endif
} }
int close_ctree(struct btrfs_root *root) int close_ctree(struct btrfs_root *root)
......
...@@ -49,6 +49,7 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -49,6 +49,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); item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item);
refs = btrfs_extent_refs(item); refs = btrfs_extent_refs(item);
btrfs_set_extent_refs(item, refs + 1); btrfs_set_extent_refs(item, refs + 1);
mark_buffer_dirty(path.nodes[0]);
btrfs_release_path(root->fs_info->extent_root, &path); btrfs_release_path(root->fs_info->extent_root, &path);
finish_current_insert(trans, root->fs_info->extent_root); finish_current_insert(trans, root->fs_info->extent_root);
...@@ -103,7 +104,7 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, ...@@ -103,7 +104,7 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
btrfs_root *root) btrfs_root *root)
{ {
unsigned long gang[8]; struct buffer_head *gang[8];
u64 first = 0; u64 first = 0;
int ret; int ret;
int i; int i;
...@@ -116,12 +117,14 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct ...@@ -116,12 +117,14 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
if (!ret) if (!ret)
break; break;
if (!first) if (!first)
first = gang[0]; first = gang[0]->b_blocknr;
for (i = 0; i < ret; i++) { for (i = 0; i < ret; i++) {
radix_tree_delete(&root->fs_info->pinned_radix, radix_tree_delete(&root->fs_info->pinned_radix,
gang[i]); gang[i]->b_blocknr);
brelse(gang[i]);
} }
} }
if (root->fs_info->last_insert.objectid > first)
root->fs_info->last_insert.objectid = first; root->fs_info->last_insert.objectid = first;
root->fs_info->last_insert.offset = 0; root->fs_info->last_insert.offset = 0;
return 0; return 0;
...@@ -161,8 +164,10 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct ...@@ -161,8 +164,10 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
static int pin_down_block(struct btrfs_root *root, u64 blocknr, int tag) static int pin_down_block(struct btrfs_root *root, u64 blocknr, int tag)
{ {
int err; int err;
struct buffer_head *bh = sb_getblk(root->fs_info->sb, blocknr);
BUG_ON(!bh);
err = radix_tree_insert(&root->fs_info->pinned_radix, err = radix_tree_insert(&root->fs_info->pinned_radix,
blocknr, (void *)blocknr); blocknr, bh);
BUG_ON(err); BUG_ON(err);
if (err) if (err)
return err; return err;
...@@ -217,6 +222,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -217,6 +222,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
if (ret) if (ret)
BUG(); BUG();
} }
mark_buffer_dirty(path.nodes[0]);
btrfs_release_path(extent_root, &path); btrfs_release_path(extent_root, &path);
finish_current_insert(trans, extent_root); finish_current_insert(trans, extent_root);
return ret; return ret;
...@@ -232,7 +238,7 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct ...@@ -232,7 +238,7 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
int ret; int ret;
int wret; int wret;
int err = 0; int err = 0;
unsigned long gang[4]; struct buffer_head *gang[4];
int i; int i;
struct radix_tree_root *radix = &extent_root->fs_info->pinned_radix; struct radix_tree_root *radix = &extent_root->fs_info->pinned_radix;
...@@ -245,10 +251,12 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct ...@@ -245,10 +251,12 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
if (!ret) if (!ret)
break; break;
for (i = 0; i < ret; i++) { for (i = 0; i < ret; i++) {
radix_tree_tag_set(radix, gang[i], CTREE_EXTENT_PINNED); radix_tree_tag_set(radix, gang[i]->b_blocknr,
radix_tree_tag_clear(radix, gang[i], CTREE_EXTENT_PINNED);
radix_tree_tag_clear(radix, gang[i]->b_blocknr,
CTREE_EXTENT_PENDING_DEL); CTREE_EXTENT_PENDING_DEL);
wret = __free_extent(trans, extent_root, gang[i], 1); wret = __free_extent(trans, extent_root,
gang[i]->b_blocknr, 1);
if (wret) if (wret)
err = wret; err = wret;
} }
......
...@@ -108,6 +108,7 @@ int btrfs_insert_inode_map(struct btrfs_trans_handle *trans, ...@@ -108,6 +108,7 @@ int btrfs_insert_inode_map(struct btrfs_trans_handle *trans,
inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]),
path.slots[0], struct btrfs_inode_map_item); path.slots[0], struct btrfs_inode_map_item);
btrfs_cpu_key_to_disk(&inode_item->key, location); btrfs_cpu_key_to_disk(&inode_item->key, location);
mark_buffer_dirty(path.nodes[0]);
out: out:
btrfs_release_path(inode_root, &path); btrfs_release_path(inode_root, &path);
return ret; return ret;
......
...@@ -55,6 +55,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -55,6 +55,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
slot = path.slots[0]; slot = path.slots[0];
memcpy(btrfs_item_ptr(l, slot, struct btrfs_root_item), item, memcpy(btrfs_item_ptr(l, slot, struct btrfs_root_item), item,
sizeof(*item)); sizeof(*item));
mark_buffer_dirty(path.nodes[0]);
out: out:
btrfs_release_path(root, &path); btrfs_release_path(root, &path);
return ret; return ret;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include "ctree.h" #include "ctree.h"
#include "disk-io.h" #include "disk-io.h"
#include "transaction.h"
#define BTRFS_SUPER_MAGIC 0x9123682E #define BTRFS_SUPER_MAGIC 0x9123682E
...@@ -357,6 +358,131 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent) ...@@ -357,6 +358,131 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
return 0; return 0;
} }
static void fill_inode_item(struct btrfs_inode_item *item,
struct inode *inode)
{
btrfs_set_inode_uid(item, inode->i_uid);
btrfs_set_inode_gid(item, inode->i_gid);
btrfs_set_inode_size(item, inode->i_size);
btrfs_set_inode_mode(item, inode->i_mode);
btrfs_set_inode_nlink(item, inode->i_nlink);
btrfs_set_timespec_sec(&item->atime, inode->i_atime.tv_sec);
btrfs_set_timespec_nsec(&item->atime, inode->i_atime.tv_nsec);
btrfs_set_timespec_sec(&item->mtime, inode->i_mtime.tv_sec);
btrfs_set_timespec_nsec(&item->mtime, inode->i_mtime.tv_nsec);
btrfs_set_timespec_sec(&item->ctime, inode->i_ctime.tv_sec);
btrfs_set_timespec_nsec(&item->ctime, inode->i_ctime.tv_nsec);
btrfs_set_inode_nblocks(item, inode->i_blocks);
btrfs_set_inode_generation(item, inode->i_generation);
}
static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
struct inode *dir, int mode)
{
struct inode *inode;
struct btrfs_inode_item inode_item;
struct btrfs_root *root = btrfs_sb(dir->i_sb);
struct btrfs_key key;
int ret;
u64 objectid;
inode = new_inode(dir->i_sb);
if (!inode)
return ERR_PTR(-ENOMEM);
ret = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
BUG_ON(ret);
inode->i_uid = current->fsuid;
inode->i_gid = current->fsgid;
inode->i_mode = mode;
inode->i_ino = objectid;
inode->i_blocks = 0;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
fill_inode_item(&inode_item, inode);
key.objectid = objectid;
key.flags = 0;
key.offset = 0;
btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY);
ret = btrfs_insert_inode_map(trans, root, objectid, &key);
BUG_ON(ret);
ret = btrfs_insert_inode(trans, root, objectid, &inode_item);
BUG_ON(ret);
insert_inode_hash(inode);
// FIXME mark_inode_dirty(inode)
return inode;
}
static int btrfs_add_link(struct btrfs_trans_handle *trans,
struct dentry *dentry, struct inode *inode)
{
int ret;
ret = btrfs_insert_dir_item(trans, btrfs_sb(inode->i_sb),
dentry->d_name.name, dentry->d_name.len,
dentry->d_parent->d_inode->i_ino,
inode->i_ino, 0);
BUG_ON(ret);
return ret;
}
static int btrfs_add_nondir(struct btrfs_trans_handle *trans,
struct dentry *dentry, struct inode *inode)
{
int err = btrfs_add_link(trans, dentry, inode);
if (!err) {
d_instantiate(dentry, inode);
return 0;
}
inode_dec_link_count(inode);
iput(inode);
return err;
}
static int btrfs_create(struct inode *dir, struct dentry *dentry,
int mode, struct nameidata *nd)
{
struct btrfs_trans_handle *trans;
struct btrfs_root *root = btrfs_sb(dir->i_sb);
struct inode *inode;
int err;
trans = btrfs_start_transaction(root, 1);
inode = btrfs_new_inode(trans, dir, mode);
err = PTR_ERR(inode);
if (IS_ERR(inode))
return err;
// FIXME mark the inode dirty
err = btrfs_add_nondir(trans, dentry, inode);
dir->i_sb->s_dirt = 1;
btrfs_end_transaction(trans, root);
return err;
}
static void btrfs_write_super(struct super_block *sb)
{
sb->s_dirt = 0;
printk("btrfs write_super!\n");
}
static int btrfs_sync_fs(struct super_block *sb, int wait)
{
struct btrfs_trans_handle *trans;
struct btrfs_root *root;
int ret;
sb->s_dirt = 0;
root = btrfs_sb(sb);
trans = btrfs_start_transaction(root, 1);
ret = btrfs_commit_transaction(trans, root);
sb->s_dirt = 0;
BUG_ON(ret);
printk("btrfs sync_fs\n");
return 0;
}
static int btrfs_get_sb(struct file_system_type *fs_type, static int btrfs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data, struct vfsmount *mnt) int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{ {
...@@ -377,10 +503,13 @@ static struct super_operations btrfs_super_ops = { ...@@ -377,10 +503,13 @@ static struct super_operations btrfs_super_ops = {
.drop_inode = generic_delete_inode, .drop_inode = generic_delete_inode,
.put_super = btrfs_put_super, .put_super = btrfs_put_super,
.read_inode = btrfs_read_locked_inode, .read_inode = btrfs_read_locked_inode,
.write_super = btrfs_write_super,
.sync_fs = btrfs_sync_fs,
}; };
static struct inode_operations btrfs_dir_inode_operations = { static struct inode_operations btrfs_dir_inode_operations = {
.lookup = btrfs_lookup, .lookup = btrfs_lookup,
.create = btrfs_create,
}; };
static struct file_operations btrfs_dir_file_operations = { static struct file_operations btrfs_dir_file_operations = {
......
...@@ -25,7 +25,7 @@ static int join_transaction(struct btrfs_root *root) ...@@ -25,7 +25,7 @@ static int join_transaction(struct btrfs_root *root)
init_waitqueue_head(&cur_trans->writer_wait); init_waitqueue_head(&cur_trans->writer_wait);
init_waitqueue_head(&cur_trans->commit_wait); init_waitqueue_head(&cur_trans->commit_wait);
cur_trans->in_commit = 0; cur_trans->in_commit = 0;
cur_trans->use_count = 0; cur_trans->use_count = 1;
cur_trans->commit_done = 0; cur_trans->commit_done = 0;
} }
cur_trans->num_writers++; cur_trans->num_writers++;
...@@ -56,7 +56,7 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, ...@@ -56,7 +56,7 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans,
struct btrfs_transaction *cur_trans; struct btrfs_transaction *cur_trans;
mutex_lock(&root->fs_info->trans_mutex); mutex_lock(&root->fs_info->trans_mutex);
cur_trans = root->fs_info->running_transaction; cur_trans = root->fs_info->running_transaction;
WARN_ON(cur_trans->num_writers <= 1); WARN_ON(cur_trans->num_writers < 1);
if (waitqueue_active(&cur_trans->writer_wait)) if (waitqueue_active(&cur_trans->writer_wait))
wake_up(&cur_trans->writer_wait); wake_up(&cur_trans->writer_wait);
cur_trans->num_writers--; cur_trans->num_writers--;
...@@ -155,10 +155,13 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ...@@ -155,10 +155,13 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
cur_trans = root->fs_info->running_transaction; cur_trans = root->fs_info->running_transaction;
root->fs_info->running_transaction = NULL; root->fs_info->running_transaction = NULL;
mutex_unlock(&root->fs_info->trans_mutex);
if (root->node != root->commit_root) {
memcpy(&snap_key, &root->root_key, sizeof(snap_key)); memcpy(&snap_key, &root->root_key, sizeof(snap_key));
root->root_key.offset++; root->root_key.offset++;
}
mutex_unlock(&root->fs_info->trans_mutex);
if (btrfs_root_blocknr(&root->root_item) != root->node->b_blocknr) { if (btrfs_root_blocknr(&root->root_item) != root->node->b_blocknr) {
btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr); btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr);
......
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