aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-03-23 10:01:08 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-03-23 10:01:08 -0400
commitd571976292839cec05a2820b08f7629b145ed157 (patch)
tree6a3f2f5a9b9c70f61d00ac10edaaaa60d5043474 /fs
parent79154b1b5bcf87903db7ff16a30b360b78d6fe4f (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/TODO1
-rw-r--r--fs/btrfs/ctree.c49
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/dir-item.c3
-rw-r--r--fs/btrfs/disk-io.c23
-rw-r--r--fs/btrfs/extent-tree.c26
-rw-r--r--fs/btrfs/inode-map.c1
-rw-r--r--fs/btrfs/root-tree.c1
-rw-r--r--fs/btrfs/super.c129
-rw-r--r--fs/btrfs/transaction.c13
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
833int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct 833int 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);
835int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root 835int 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);
838int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root 838int 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
7int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root 7int 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]);
38out: 39out:
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,
145int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root 145int 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
163int close_ctree(struct btrfs_root *root) 164int 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,
103int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct 104int 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
161static int pin_down_block(struct btrfs_root *root, u64 blocknr, int tag) 164static 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]);
111out: 112out:
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]);
58out: 59out:
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
361static 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
379static 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
420static 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
432static 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
445static 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
465static void btrfs_write_super(struct super_block *sb)
466{
467 sb->s_dirt = 0;
468printk("btrfs write_super!\n");
469}
470
471static 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);
482printk("btrfs sync_fs\n");
483 return 0;
484}
485
360static int btrfs_get_sb(struct file_system_type *fs_type, 486static 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
382static struct inode_operations btrfs_dir_inode_operations = { 510static struct inode_operations btrfs_dir_inode_operations = {
383 .lookup = btrfs_lookup, 511 .lookup = btrfs_lookup,
512 .create = btrfs_create,
384}; 513};
385 514
386static struct file_operations btrfs_dir_file_operations = { 515static 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);