diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-03-23 10:01:08 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-03-23 10:01:08 -0400 |
commit | d571976292839cec05a2820b08f7629b145ed157 (patch) | |
tree | 6a3f2f5a9b9c70f61d00ac10edaaaa60d5043474 /fs | |
parent | 79154b1b5bcf87903db7ff16a30b360b78d6fe4f (diff) |
btrfs_create, btrfs_write_super, btrfs_sync_fs
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/TODO | 1 | ||||
-rw-r--r-- | fs/btrfs/ctree.c | 49 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 2 | ||||
-rw-r--r-- | fs/btrfs/dir-item.c | 3 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 23 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 26 | ||||
-rw-r--r-- | fs/btrfs/inode-map.c | 1 | ||||
-rw-r--r-- | fs/btrfs/root-tree.c | 1 | ||||
-rw-r--r-- | fs/btrfs/super.c | 129 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 13 |
10 files changed, 201 insertions, 47 deletions
diff --git a/fs/btrfs/TODO b/fs/btrfs/TODO index c5d67bbd4d90..4b5bd05de94f 100644 --- a/fs/btrfs/TODO +++ b/fs/btrfs/TODO | |||
@@ -3,6 +3,7 @@ | |||
3 | * Fix ENOSPC handling | 3 | * Fix ENOSPC handling |
4 | * make a real mkfs and superblock | 4 | * make a real mkfs and superblock |
5 | * Do checksumming | 5 | * Do checksumming |
6 | * Use a real check instead of mark_buffer_dirty | ||
6 | * Define FS objects in terms of different item types | 7 | * Define FS objects in terms of different item types |
7 | * Add block mapping tree (simple dm layer) | 8 | * Add block mapping tree (simple dm layer) |
8 | * Add simple tree locking (semaphore per tree) | 9 | * Add simple tree locking (semaphore per tree) |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index e690e2bb47d2..052434a328ec 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -39,7 +39,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
39 | struct buffer_head *cow; | 39 | struct buffer_head *cow; |
40 | struct btrfs_node *cow_node; | 40 | struct btrfs_node *cow_node; |
41 | 41 | ||
42 | if (!buffer_dirty(buf)) { | 42 | if (buffer_dirty(buf)) { |
43 | *cow_ret = buf; | 43 | *cow_ret = buf; |
44 | return 0; | 44 | return 0; |
45 | } | 45 | } |
@@ -48,6 +48,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
48 | memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize); | 48 | memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize); |
49 | btrfs_set_header_blocknr(&cow_node->header, cow->b_blocknr); | 49 | btrfs_set_header_blocknr(&cow_node->header, cow->b_blocknr); |
50 | *cow_ret = cow; | 50 | *cow_ret = cow; |
51 | mark_buffer_dirty(cow); | ||
51 | btrfs_inc_ref(trans, root, buf); | 52 | btrfs_inc_ref(trans, root, buf); |
52 | if (buf == root->node) { | 53 | if (buf == root->node) { |
53 | root->node = cow; | 54 | root->node = cow; |
@@ -58,7 +59,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
58 | } else { | 59 | } else { |
59 | btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot, | 60 | btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot, |
60 | cow->b_blocknr); | 61 | cow->b_blocknr); |
61 | BUG_ON(!buffer_dirty(parent)); | 62 | mark_buffer_dirty(parent); |
62 | btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); | 63 | btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); |
63 | } | 64 | } |
64 | btrfs_block_release(root, buf); | 65 | btrfs_block_release(root, buf); |
@@ -362,7 +363,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
362 | memcpy(&parent->ptrs[pslot + 1].key, | 363 | memcpy(&parent->ptrs[pslot + 1].key, |
363 | &right->ptrs[0].key, | 364 | &right->ptrs[0].key, |
364 | sizeof(struct btrfs_disk_key)); | 365 | sizeof(struct btrfs_disk_key)); |
365 | BUG_ON(!buffer_dirty(parent_buf)); | 366 | mark_buffer_dirty(parent_buf); |
366 | } | 367 | } |
367 | } | 368 | } |
368 | if (btrfs_header_nritems(&mid->header) == 1) { | 369 | if (btrfs_header_nritems(&mid->header) == 1) { |
@@ -398,7 +399,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
398 | /* update the parent key to reflect our changes */ | 399 | /* update the parent key to reflect our changes */ |
399 | memcpy(&parent->ptrs[pslot].key, &mid->ptrs[0].key, | 400 | memcpy(&parent->ptrs[pslot].key, &mid->ptrs[0].key, |
400 | sizeof(struct btrfs_disk_key)); | 401 | sizeof(struct btrfs_disk_key)); |
401 | BUG_ON(!buffer_dirty(parent_buf)); | 402 | mark_buffer_dirty(parent_buf); |
402 | } | 403 | } |
403 | 404 | ||
404 | /* update the path */ | 405 | /* update the path */ |
@@ -539,7 +540,7 @@ static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root | |||
539 | break; | 540 | break; |
540 | t = btrfs_buffer_node(path->nodes[i]); | 541 | t = btrfs_buffer_node(path->nodes[i]); |
541 | memcpy(&t->ptrs[tslot].key, key, sizeof(*key)); | 542 | memcpy(&t->ptrs[tslot].key, key, sizeof(*key)); |
542 | BUG_ON(!buffer_dirty(path->nodes[i])); | 543 | mark_buffer_dirty(path->nodes[i]); |
543 | if (tslot != 0) | 544 | if (tslot != 0) |
544 | break; | 545 | break; |
545 | } | 546 | } |
@@ -583,8 +584,8 @@ static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
583 | } | 584 | } |
584 | btrfs_set_header_nritems(&src->header, src_nritems - push_items); | 585 | btrfs_set_header_nritems(&src->header, src_nritems - push_items); |
585 | btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); | 586 | btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); |
586 | BUG_ON(!buffer_dirty(src_buf)); | 587 | mark_buffer_dirty(src_buf); |
587 | BUG_ON(!buffer_dirty(dst_buf)); | 588 | mark_buffer_dirty(dst_buf); |
588 | return ret; | 589 | return ret; |
589 | } | 590 | } |
590 | 591 | ||
@@ -631,8 +632,8 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct | |||
631 | btrfs_set_header_nritems(&src->header, src_nritems - push_items); | 632 | btrfs_set_header_nritems(&src->header, src_nritems - push_items); |
632 | btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); | 633 | btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); |
633 | 634 | ||
634 | BUG_ON(!buffer_dirty(src_buf)); | 635 | mark_buffer_dirty(src_buf); |
635 | BUG_ON(!buffer_dirty(dst_buf)); | 636 | mark_buffer_dirty(dst_buf); |
636 | return ret; | 637 | return ret; |
637 | } | 638 | } |
638 | 639 | ||
@@ -669,6 +670,9 @@ static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
669 | lower_key = &lower->ptrs[0].key; | 670 | lower_key = &lower->ptrs[0].key; |
670 | memcpy(&c->ptrs[0].key, lower_key, sizeof(struct btrfs_disk_key)); | 671 | memcpy(&c->ptrs[0].key, lower_key, sizeof(struct btrfs_disk_key)); |
671 | btrfs_set_node_blockptr(c, 0, path->nodes[level - 1]->b_blocknr); | 672 | btrfs_set_node_blockptr(c, 0, path->nodes[level - 1]->b_blocknr); |
673 | |||
674 | mark_buffer_dirty(t); | ||
675 | |||
672 | /* the super has an extra ref to root->node */ | 676 | /* the super has an extra ref to root->node */ |
673 | btrfs_block_release(root, root->node); | 677 | btrfs_block_release(root, root->node); |
674 | root->node = t; | 678 | root->node = t; |
@@ -708,7 +712,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root | |||
708 | memcpy(&lower->ptrs[slot].key, key, sizeof(struct btrfs_disk_key)); | 712 | memcpy(&lower->ptrs[slot].key, key, sizeof(struct btrfs_disk_key)); |
709 | btrfs_set_node_blockptr(lower, slot, blocknr); | 713 | btrfs_set_node_blockptr(lower, slot, blocknr); |
710 | btrfs_set_header_nritems(&lower->header, nritems + 1); | 714 | btrfs_set_header_nritems(&lower->header, nritems + 1); |
711 | BUG_ON(!buffer_dirty(path->nodes[level])); | 715 | mark_buffer_dirty(path->nodes[level]); |
712 | return 0; | 716 | return 0; |
713 | } | 717 | } |
714 | 718 | ||
@@ -755,7 +759,8 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | |||
755 | btrfs_set_header_nritems(&c->header, mid); | 759 | btrfs_set_header_nritems(&c->header, mid); |
756 | ret = 0; | 760 | ret = 0; |
757 | 761 | ||
758 | BUG_ON(!buffer_dirty(t)); | 762 | mark_buffer_dirty(t); |
763 | mark_buffer_dirty(split_buffer); | ||
759 | wret = insert_ptr(trans, root, path, &split->ptrs[0].key, | 764 | wret = insert_ptr(trans, root, path, &split->ptrs[0].key, |
760 | split_buffer->b_blocknr, path->slots[level + 1] + 1, | 765 | split_buffer->b_blocknr, path->slots[level + 1] + 1, |
761 | level + 1); | 766 | level + 1); |
@@ -886,11 +891,11 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
886 | left_nritems -= push_items; | 891 | left_nritems -= push_items; |
887 | btrfs_set_header_nritems(&left->header, left_nritems); | 892 | btrfs_set_header_nritems(&left->header, left_nritems); |
888 | 893 | ||
889 | BUG_ON(!buffer_dirty(left_buf)); | 894 | mark_buffer_dirty(left_buf); |
890 | BUG_ON(!buffer_dirty(right_buf)); | 895 | mark_buffer_dirty(right_buf); |
891 | memcpy(&upper_node->ptrs[slot + 1].key, | 896 | memcpy(&upper_node->ptrs[slot + 1].key, |
892 | &right->items[0].key, sizeof(struct btrfs_disk_key)); | 897 | &right->items[0].key, sizeof(struct btrfs_disk_key)); |
893 | BUG_ON(!buffer_dirty(upper)); | 898 | mark_buffer_dirty(upper); |
894 | 899 | ||
895 | /* then fixup the leaf pointer in the path */ | 900 | /* then fixup the leaf pointer in the path */ |
896 | if (path->slots[0] >= left_nritems) { | 901 | if (path->slots[0] >= left_nritems) { |
@@ -1004,8 +1009,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1004 | push_space = btrfs_item_offset(right->items + i); | 1009 | push_space = btrfs_item_offset(right->items + i); |
1005 | } | 1010 | } |
1006 | 1011 | ||
1007 | BUG_ON(!buffer_dirty(t)); | 1012 | mark_buffer_dirty(t); |
1008 | BUG_ON(!buffer_dirty(right_buf)); | 1013 | mark_buffer_dirty(right_buf); |
1009 | 1014 | ||
1010 | wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1); | 1015 | wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1); |
1011 | if (wret) | 1016 | if (wret) |
@@ -1115,8 +1120,8 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1115 | right_buffer->b_blocknr, path->slots[1] + 1, 1); | 1120 | right_buffer->b_blocknr, path->slots[1] + 1, 1); |
1116 | if (wret) | 1121 | if (wret) |
1117 | ret = wret; | 1122 | ret = wret; |
1118 | BUG_ON(!buffer_dirty(right_buffer)); | 1123 | mark_buffer_dirty(right_buffer); |
1119 | BUG_ON(!buffer_dirty(l_buf)); | 1124 | mark_buffer_dirty(l_buf); |
1120 | BUG_ON(path->slots[0] != slot); | 1125 | BUG_ON(path->slots[0] != slot); |
1121 | if (mid <= slot) { | 1126 | if (mid <= slot) { |
1122 | btrfs_block_release(root, path->nodes[0]); | 1127 | 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 | btrfs_set_item_offset(leaf->items + slot, data_end - data_size); | 1207 | btrfs_set_item_offset(leaf->items + slot, data_end - data_size); |
1203 | btrfs_set_item_size(leaf->items + slot, data_size); | 1208 | btrfs_set_item_size(leaf->items + slot, data_size); |
1204 | btrfs_set_header_nritems(&leaf->header, nritems + 1); | 1209 | btrfs_set_header_nritems(&leaf->header, nritems + 1); |
1210 | mark_buffer_dirty(leaf_buf); | ||
1205 | 1211 | ||
1206 | ret = 0; | 1212 | ret = 0; |
1207 | if (slot == 0) | 1213 | if (slot == 0) |
1208 | ret = fixup_low_keys(trans, root, path, &disk_key, 1); | 1214 | ret = fixup_low_keys(trans, root, path, &disk_key, 1); |
1209 | 1215 | ||
1210 | BUG_ON(!buffer_dirty(leaf_buf)); | ||
1211 | if (btrfs_leaf_free_space(root, leaf) < 0) | 1216 | if (btrfs_leaf_free_space(root, leaf) < 0) |
1212 | BUG(); | 1217 | BUG(); |
1213 | check_leaf(root, path, 0); | 1218 | check_leaf(root, path, 0); |
@@ -1233,6 +1238,7 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1233 | ptr = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), | 1238 | ptr = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), |
1234 | path.slots[0], u8); | 1239 | path.slots[0], u8); |
1235 | memcpy(ptr, data, data_size); | 1240 | memcpy(ptr, data, data_size); |
1241 | mark_buffer_dirty(path.nodes[0]); | ||
1236 | } | 1242 | } |
1237 | btrfs_release_path(root, &path); | 1243 | btrfs_release_path(root, &path); |
1238 | return ret; | 1244 | return ret; |
@@ -1273,7 +1279,7 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1273 | if (wret) | 1279 | if (wret) |
1274 | ret = wret; | 1280 | ret = wret; |
1275 | } | 1281 | } |
1276 | BUG_ON(!buffer_dirty(parent)); | 1282 | mark_buffer_dirty(parent); |
1277 | return ret; | 1283 | return ret; |
1278 | } | 1284 | } |
1279 | 1285 | ||
@@ -1368,8 +1374,11 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1368 | if (wret) | 1374 | if (wret) |
1369 | ret = wret; | 1375 | ret = wret; |
1370 | } else { | 1376 | } else { |
1377 | mark_buffer_dirty(leaf_buf); | ||
1371 | btrfs_block_release(root, leaf_buf); | 1378 | btrfs_block_release(root, leaf_buf); |
1372 | } | 1379 | } |
1380 | } else { | ||
1381 | mark_buffer_dirty(leaf_buf); | ||
1373 | } | 1382 | } |
1374 | } | 1383 | } |
1375 | return ret; | 1384 | return ret; |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 4c19a3f12afd..983e3cc9ae9f 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -833,7 +833,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
833 | int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct | 833 | int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct |
834 | btrfs_root_item *item, struct btrfs_key *key); | 834 | btrfs_root_item *item, struct btrfs_key *key); |
835 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | 835 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root |
836 | *root, char *name, int name_len, u64 dir, u64 | 836 | *root, const char *name, int name_len, u64 dir, u64 |
837 | objectid, u8 type); | 837 | objectid, u8 type); |
838 | int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | 838 | int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root |
839 | *root, struct btrfs_path *path, u64 dir, | 839 | *root, struct btrfs_path *path, u64 dir, |
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 75d6e373e98d..f81cbcc83b66 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
@@ -5,7 +5,7 @@ | |||
5 | #include "transaction.h" | 5 | #include "transaction.h" |
6 | 6 | ||
7 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | 7 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root |
8 | *root, char *name, int name_len, u64 dir, u64 | 8 | *root, const char *name, int name_len, u64 dir, u64 |
9 | objectid, u8 type) | 9 | objectid, u8 type) |
10 | { | 10 | { |
11 | int ret = 0; | 11 | int ret = 0; |
@@ -35,6 +35,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
35 | btrfs_set_dir_name_len(dir_item, name_len); | 35 | btrfs_set_dir_name_len(dir_item, name_len); |
36 | name_ptr = (char *)(dir_item + 1); | 36 | name_ptr = (char *)(dir_item + 1); |
37 | memcpy(name_ptr, name, name_len); | 37 | memcpy(name_ptr, name, name_len); |
38 | mark_buffer_dirty(path.nodes[0]); | ||
38 | out: | 39 | out: |
39 | btrfs_release_path(root, &path); | 40 | btrfs_release_path(root, &path); |
40 | return ret; | 41 | return ret; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 9cacca0c525c..8e1dcda0839c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -145,19 +145,20 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
145 | int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root | 145 | int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root |
146 | *root) | 146 | *root) |
147 | { | 147 | { |
148 | return 0; | 148 | struct buffer_head *bh = root->fs_info->sb_buffer; |
149 | #if 0 | 149 | btrfs_set_super_root(root->fs_info->disk_super, |
150 | int ret; | 150 | root->fs_info->tree_root->node->b_blocknr); |
151 | btrfs_set_super_root(s, root->fs_info->tree_root->node->b_blocknr); | 151 | lock_buffer(bh); |
152 | 152 | clear_buffer_dirty(bh); | |
153 | ret = pwrite(root->fs_info->fp, s, sizeof(*s), | 153 | bh->b_end_io = end_buffer_write_sync; |
154 | BTRFS_SUPER_INFO_OFFSET); | 154 | get_bh(bh); |
155 | if (ret != sizeof(*s)) { | 155 | submit_bh(WRITE, bh); |
156 | fprintf(stderr, "failed to write new super block err %d\n", ret); | 156 | wait_on_buffer(bh); |
157 | return ret; | 157 | if (!buffer_uptodate(bh)) { |
158 | WARN_ON(1); | ||
159 | return -EIO; | ||
158 | } | 160 | } |
159 | return 0; | 161 | return 0; |
160 | #endif | ||
161 | } | 162 | } |
162 | 163 | ||
163 | int close_ctree(struct btrfs_root *root) | 164 | int close_ctree(struct btrfs_root *root) |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index e3af2c035687..2818f1c57170 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -49,6 +49,7 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
49 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); | 49 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); |
50 | refs = btrfs_extent_refs(item); | 50 | refs = btrfs_extent_refs(item); |
51 | btrfs_set_extent_refs(item, refs + 1); | 51 | btrfs_set_extent_refs(item, refs + 1); |
52 | mark_buffer_dirty(path.nodes[0]); | ||
52 | 53 | ||
53 | btrfs_release_path(root->fs_info->extent_root, &path); | 54 | btrfs_release_path(root->fs_info->extent_root, &path); |
54 | finish_current_insert(trans, root->fs_info->extent_root); | 55 | 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 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | 104 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct |
104 | btrfs_root *root) | 105 | btrfs_root *root) |
105 | { | 106 | { |
106 | unsigned long gang[8]; | 107 | struct buffer_head *gang[8]; |
107 | u64 first = 0; | 108 | u64 first = 0; |
108 | int ret; | 109 | int ret; |
109 | int i; | 110 | int i; |
@@ -116,13 +117,15 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | |||
116 | if (!ret) | 117 | if (!ret) |
117 | break; | 118 | break; |
118 | if (!first) | 119 | if (!first) |
119 | first = gang[0]; | 120 | first = gang[0]->b_blocknr; |
120 | for (i = 0; i < ret; i++) { | 121 | for (i = 0; i < ret; i++) { |
121 | radix_tree_delete(&root->fs_info->pinned_radix, | 122 | radix_tree_delete(&root->fs_info->pinned_radix, |
122 | gang[i]); | 123 | gang[i]->b_blocknr); |
124 | brelse(gang[i]); | ||
123 | } | 125 | } |
124 | } | 126 | } |
125 | root->fs_info->last_insert.objectid = first; | 127 | if (root->fs_info->last_insert.objectid > first) |
128 | root->fs_info->last_insert.objectid = first; | ||
126 | root->fs_info->last_insert.offset = 0; | 129 | root->fs_info->last_insert.offset = 0; |
127 | return 0; | 130 | return 0; |
128 | } | 131 | } |
@@ -161,8 +164,10 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
161 | static int pin_down_block(struct btrfs_root *root, u64 blocknr, int tag) | 164 | static int pin_down_block(struct btrfs_root *root, u64 blocknr, int tag) |
162 | { | 165 | { |
163 | int err; | 166 | int err; |
167 | struct buffer_head *bh = sb_getblk(root->fs_info->sb, blocknr); | ||
168 | BUG_ON(!bh); | ||
164 | err = radix_tree_insert(&root->fs_info->pinned_radix, | 169 | err = radix_tree_insert(&root->fs_info->pinned_radix, |
165 | blocknr, (void *)blocknr); | 170 | blocknr, bh); |
166 | BUG_ON(err); | 171 | BUG_ON(err); |
167 | if (err) | 172 | if (err) |
168 | return err; | 173 | return err; |
@@ -217,6 +222,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
217 | if (ret) | 222 | if (ret) |
218 | BUG(); | 223 | BUG(); |
219 | } | 224 | } |
225 | mark_buffer_dirty(path.nodes[0]); | ||
220 | btrfs_release_path(extent_root, &path); | 226 | btrfs_release_path(extent_root, &path); |
221 | finish_current_insert(trans, extent_root); | 227 | finish_current_insert(trans, extent_root); |
222 | return ret; | 228 | return ret; |
@@ -232,7 +238,7 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
232 | int ret; | 238 | int ret; |
233 | int wret; | 239 | int wret; |
234 | int err = 0; | 240 | int err = 0; |
235 | unsigned long gang[4]; | 241 | struct buffer_head *gang[4]; |
236 | int i; | 242 | int i; |
237 | struct radix_tree_root *radix = &extent_root->fs_info->pinned_radix; | 243 | struct radix_tree_root *radix = &extent_root->fs_info->pinned_radix; |
238 | 244 | ||
@@ -245,10 +251,12 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
245 | if (!ret) | 251 | if (!ret) |
246 | break; | 252 | break; |
247 | for (i = 0; i < ret; i++) { | 253 | for (i = 0; i < ret; i++) { |
248 | radix_tree_tag_set(radix, gang[i], CTREE_EXTENT_PINNED); | 254 | radix_tree_tag_set(radix, gang[i]->b_blocknr, |
249 | radix_tree_tag_clear(radix, gang[i], | 255 | CTREE_EXTENT_PINNED); |
256 | radix_tree_tag_clear(radix, gang[i]->b_blocknr, | ||
250 | CTREE_EXTENT_PENDING_DEL); | 257 | CTREE_EXTENT_PENDING_DEL); |
251 | wret = __free_extent(trans, extent_root, gang[i], 1); | 258 | wret = __free_extent(trans, extent_root, |
259 | gang[i]->b_blocknr, 1); | ||
252 | if (wret) | 260 | if (wret) |
253 | err = wret; | 261 | err = wret; |
254 | } | 262 | } |
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index c45aec258bd5..ad2d375b830d 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c | |||
@@ -108,6 +108,7 @@ int btrfs_insert_inode_map(struct btrfs_trans_handle *trans, | |||
108 | inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), | 108 | inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), |
109 | path.slots[0], struct btrfs_inode_map_item); | 109 | path.slots[0], struct btrfs_inode_map_item); |
110 | btrfs_cpu_key_to_disk(&inode_item->key, location); | 110 | btrfs_cpu_key_to_disk(&inode_item->key, location); |
111 | mark_buffer_dirty(path.nodes[0]); | ||
111 | out: | 112 | out: |
112 | btrfs_release_path(inode_root, &path); | 113 | btrfs_release_path(inode_root, &path); |
113 | return ret; | 114 | return ret; |
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index a4554c007ef7..a821b5d1e233 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
@@ -55,6 +55,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
55 | slot = path.slots[0]; | 55 | slot = path.slots[0]; |
56 | memcpy(btrfs_item_ptr(l, slot, struct btrfs_root_item), item, | 56 | memcpy(btrfs_item_ptr(l, slot, struct btrfs_root_item), item, |
57 | sizeof(*item)); | 57 | sizeof(*item)); |
58 | mark_buffer_dirty(path.nodes[0]); | ||
58 | out: | 59 | out: |
59 | btrfs_release_path(root, &path); | 60 | btrfs_release_path(root, &path); |
60 | return ret; | 61 | return ret; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 620430825840..6080a8133d71 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/backing-dev.h> | 10 | #include <linux/backing-dev.h> |
11 | #include "ctree.h" | 11 | #include "ctree.h" |
12 | #include "disk-io.h" | 12 | #include "disk-io.h" |
13 | #include "transaction.h" | ||
13 | 14 | ||
14 | #define BTRFS_SUPER_MAGIC 0x9123682E | 15 | #define BTRFS_SUPER_MAGIC 0x9123682E |
15 | 16 | ||
@@ -357,6 +358,131 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent) | |||
357 | return 0; | 358 | return 0; |
358 | } | 359 | } |
359 | 360 | ||
361 | static void fill_inode_item(struct btrfs_inode_item *item, | ||
362 | struct inode *inode) | ||
363 | { | ||
364 | btrfs_set_inode_uid(item, inode->i_uid); | ||
365 | btrfs_set_inode_gid(item, inode->i_gid); | ||
366 | btrfs_set_inode_size(item, inode->i_size); | ||
367 | btrfs_set_inode_mode(item, inode->i_mode); | ||
368 | btrfs_set_inode_nlink(item, inode->i_nlink); | ||
369 | btrfs_set_timespec_sec(&item->atime, inode->i_atime.tv_sec); | ||
370 | btrfs_set_timespec_nsec(&item->atime, inode->i_atime.tv_nsec); | ||
371 | btrfs_set_timespec_sec(&item->mtime, inode->i_mtime.tv_sec); | ||
372 | btrfs_set_timespec_nsec(&item->mtime, inode->i_mtime.tv_nsec); | ||
373 | btrfs_set_timespec_sec(&item->ctime, inode->i_ctime.tv_sec); | ||
374 | btrfs_set_timespec_nsec(&item->ctime, inode->i_ctime.tv_nsec); | ||
375 | btrfs_set_inode_nblocks(item, inode->i_blocks); | ||
376 | btrfs_set_inode_generation(item, inode->i_generation); | ||
377 | } | ||
378 | |||
379 | static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | ||
380 | struct inode *dir, int mode) | ||
381 | { | ||
382 | struct inode *inode; | ||
383 | struct btrfs_inode_item inode_item; | ||
384 | struct btrfs_root *root = btrfs_sb(dir->i_sb); | ||
385 | struct btrfs_key key; | ||
386 | int ret; | ||
387 | u64 objectid; | ||
388 | |||
389 | inode = new_inode(dir->i_sb); | ||
390 | if (!inode) | ||
391 | return ERR_PTR(-ENOMEM); | ||
392 | |||
393 | ret = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid); | ||
394 | BUG_ON(ret); | ||
395 | |||
396 | inode->i_uid = current->fsuid; | ||
397 | inode->i_gid = current->fsgid; | ||
398 | inode->i_mode = mode; | ||
399 | inode->i_ino = objectid; | ||
400 | inode->i_blocks = 0; | ||
401 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; | ||
402 | fill_inode_item(&inode_item, inode); | ||
403 | |||
404 | |||
405 | key.objectid = objectid; | ||
406 | key.flags = 0; | ||
407 | key.offset = 0; | ||
408 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | ||
409 | ret = btrfs_insert_inode_map(trans, root, objectid, &key); | ||
410 | BUG_ON(ret); | ||
411 | |||
412 | ret = btrfs_insert_inode(trans, root, objectid, &inode_item); | ||
413 | BUG_ON(ret); | ||
414 | |||
415 | insert_inode_hash(inode); | ||
416 | // FIXME mark_inode_dirty(inode) | ||
417 | return inode; | ||
418 | } | ||
419 | |||
420 | static int btrfs_add_link(struct btrfs_trans_handle *trans, | ||
421 | struct dentry *dentry, struct inode *inode) | ||
422 | { | ||
423 | int ret; | ||
424 | ret = btrfs_insert_dir_item(trans, btrfs_sb(inode->i_sb), | ||
425 | dentry->d_name.name, dentry->d_name.len, | ||
426 | dentry->d_parent->d_inode->i_ino, | ||
427 | inode->i_ino, 0); | ||
428 | BUG_ON(ret); | ||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | static int btrfs_add_nondir(struct btrfs_trans_handle *trans, | ||
433 | struct dentry *dentry, struct inode *inode) | ||
434 | { | ||
435 | int err = btrfs_add_link(trans, dentry, inode); | ||
436 | if (!err) { | ||
437 | d_instantiate(dentry, inode); | ||
438 | return 0; | ||
439 | } | ||
440 | inode_dec_link_count(inode); | ||
441 | iput(inode); | ||
442 | return err; | ||
443 | } | ||
444 | |||
445 | static int btrfs_create(struct inode *dir, struct dentry *dentry, | ||
446 | int mode, struct nameidata *nd) | ||
447 | { | ||
448 | struct btrfs_trans_handle *trans; | ||
449 | struct btrfs_root *root = btrfs_sb(dir->i_sb); | ||
450 | struct inode *inode; | ||
451 | int err; | ||
452 | |||
453 | trans = btrfs_start_transaction(root, 1); | ||
454 | inode = btrfs_new_inode(trans, dir, mode); | ||
455 | err = PTR_ERR(inode); | ||
456 | if (IS_ERR(inode)) | ||
457 | return err; | ||
458 | // FIXME mark the inode dirty | ||
459 | err = btrfs_add_nondir(trans, dentry, inode); | ||
460 | dir->i_sb->s_dirt = 1; | ||
461 | btrfs_end_transaction(trans, root); | ||
462 | return err; | ||
463 | } | ||
464 | |||
465 | static void btrfs_write_super(struct super_block *sb) | ||
466 | { | ||
467 | sb->s_dirt = 0; | ||
468 | printk("btrfs write_super!\n"); | ||
469 | } | ||
470 | |||
471 | static int btrfs_sync_fs(struct super_block *sb, int wait) | ||
472 | { | ||
473 | struct btrfs_trans_handle *trans; | ||
474 | struct btrfs_root *root; | ||
475 | int ret; | ||
476 | sb->s_dirt = 0; | ||
477 | root = btrfs_sb(sb); | ||
478 | trans = btrfs_start_transaction(root, 1); | ||
479 | ret = btrfs_commit_transaction(trans, root); | ||
480 | sb->s_dirt = 0; | ||
481 | BUG_ON(ret); | ||
482 | printk("btrfs sync_fs\n"); | ||
483 | return 0; | ||
484 | } | ||
485 | |||
360 | static int btrfs_get_sb(struct file_system_type *fs_type, | 486 | static int btrfs_get_sb(struct file_system_type *fs_type, |
361 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 487 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
362 | { | 488 | { |
@@ -377,10 +503,13 @@ static struct super_operations btrfs_super_ops = { | |||
377 | .drop_inode = generic_delete_inode, | 503 | .drop_inode = generic_delete_inode, |
378 | .put_super = btrfs_put_super, | 504 | .put_super = btrfs_put_super, |
379 | .read_inode = btrfs_read_locked_inode, | 505 | .read_inode = btrfs_read_locked_inode, |
506 | .write_super = btrfs_write_super, | ||
507 | .sync_fs = btrfs_sync_fs, | ||
380 | }; | 508 | }; |
381 | 509 | ||
382 | static struct inode_operations btrfs_dir_inode_operations = { | 510 | static struct inode_operations btrfs_dir_inode_operations = { |
383 | .lookup = btrfs_lookup, | 511 | .lookup = btrfs_lookup, |
512 | .create = btrfs_create, | ||
384 | }; | 513 | }; |
385 | 514 | ||
386 | static struct file_operations btrfs_dir_file_operations = { | 515 | static struct file_operations btrfs_dir_file_operations = { |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 8dc1c170f10f..4903b47c9780 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -25,7 +25,7 @@ static int join_transaction(struct btrfs_root *root) | |||
25 | init_waitqueue_head(&cur_trans->writer_wait); | 25 | init_waitqueue_head(&cur_trans->writer_wait); |
26 | init_waitqueue_head(&cur_trans->commit_wait); | 26 | init_waitqueue_head(&cur_trans->commit_wait); |
27 | cur_trans->in_commit = 0; | 27 | cur_trans->in_commit = 0; |
28 | cur_trans->use_count = 0; | 28 | cur_trans->use_count = 1; |
29 | cur_trans->commit_done = 0; | 29 | cur_trans->commit_done = 0; |
30 | } | 30 | } |
31 | cur_trans->num_writers++; | 31 | cur_trans->num_writers++; |
@@ -56,7 +56,7 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
56 | struct btrfs_transaction *cur_trans; | 56 | struct btrfs_transaction *cur_trans; |
57 | mutex_lock(&root->fs_info->trans_mutex); | 57 | mutex_lock(&root->fs_info->trans_mutex); |
58 | cur_trans = root->fs_info->running_transaction; | 58 | cur_trans = root->fs_info->running_transaction; |
59 | WARN_ON(cur_trans->num_writers <= 1); | 59 | WARN_ON(cur_trans->num_writers < 1); |
60 | if (waitqueue_active(&cur_trans->writer_wait)) | 60 | if (waitqueue_active(&cur_trans->writer_wait)) |
61 | wake_up(&cur_trans->writer_wait); | 61 | wake_up(&cur_trans->writer_wait); |
62 | cur_trans->num_writers--; | 62 | cur_trans->num_writers--; |
@@ -155,10 +155,13 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
155 | 155 | ||
156 | cur_trans = root->fs_info->running_transaction; | 156 | cur_trans = root->fs_info->running_transaction; |
157 | root->fs_info->running_transaction = NULL; | 157 | root->fs_info->running_transaction = NULL; |
158 | mutex_unlock(&root->fs_info->trans_mutex); | ||
159 | 158 | ||
160 | memcpy(&snap_key, &root->root_key, sizeof(snap_key)); | 159 | if (root->node != root->commit_root) { |
161 | root->root_key.offset++; | 160 | memcpy(&snap_key, &root->root_key, sizeof(snap_key)); |
161 | root->root_key.offset++; | ||
162 | } | ||
163 | |||
164 | mutex_unlock(&root->fs_info->trans_mutex); | ||
162 | 165 | ||
163 | if (btrfs_root_blocknr(&root->root_item) != root->node->b_blocknr) { | 166 | if (btrfs_root_blocknr(&root->root_item) != root->node->b_blocknr) { |
164 | btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr); | 167 | btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr); |