aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-05-18 13:28:27 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-05-18 13:28:27 -0400
commitde428b63b16f9c74a24228a517713e8c65f79475 (patch)
tree0bb56423173f59e6237cf0cbc8052f72fb997347 /fs
parent098f59c2512426926722a96f82af127bd91fb5e4 (diff)
Btrfs: allocator optimizations, truncate readahead
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/disk-io.c12
-rw-r--r--fs/btrfs/extent-tree.c76
-rw-r--r--fs/btrfs/super.c76
4 files changed, 129 insertions, 37 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index d8caeba5d758..5830b4333d83 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1081,7 +1081,7 @@ static inline void btrfs_mark_buffer_dirty(struct buffer_head *bh)
1081struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, 1081struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
1082 struct btrfs_block_group_cache 1082 struct btrfs_block_group_cache
1083 *hint, u64 search_start, 1083 *hint, u64 search_start,
1084 int data); 1084 int data, int owner);
1085int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, 1085int btrfs_inc_root_ref(struct btrfs_trans_handle *trans,
1086 struct btrfs_root *root); 1086 struct btrfs_root *root);
1087struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, 1087struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 678456d1e2f9..4c0262b57664 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -257,24 +257,30 @@ static struct address_space_operations btree_aops = {
257int readahead_tree_block(struct btrfs_root *root, u64 blocknr) 257int readahead_tree_block(struct btrfs_root *root, u64 blocknr)
258{ 258{
259 struct buffer_head *bh = NULL; 259 struct buffer_head *bh = NULL;
260 int ret = 0;
260 261
261 bh = btrfs_find_create_tree_block(root, blocknr); 262 bh = btrfs_find_create_tree_block(root, blocknr);
262 if (!bh) 263 if (!bh)
263 return 0; 264 return 0;
264 if (buffer_uptodate(bh)) 265 if (buffer_uptodate(bh)) {
266 ret = 1;
265 goto done; 267 goto done;
266 if (test_set_buffer_locked(bh)) 268 }
269 if (test_set_buffer_locked(bh)) {
270 ret = 1;
267 goto done; 271 goto done;
272 }
268 if (!buffer_uptodate(bh)) { 273 if (!buffer_uptodate(bh)) {
269 get_bh(bh); 274 get_bh(bh);
270 bh->b_end_io = end_buffer_read_sync; 275 bh->b_end_io = end_buffer_read_sync;
271 submit_bh(READ, bh); 276 submit_bh(READ, bh);
272 } else { 277 } else {
273 unlock_buffer(bh); 278 unlock_buffer(bh);
279 ret = 1;
274 } 280 }
275done: 281done:
276 brelse(bh); 282 brelse(bh);
277 return 0; 283 return ret;
278} 284}
279 285
280struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) 286struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr)
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 1497ff98f0d3..e3c6bfea3751 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -12,6 +12,33 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
12static int del_pending_extents(struct btrfs_trans_handle *trans, struct 12static int del_pending_extents(struct btrfs_trans_handle *trans, struct
13 btrfs_root *extent_root); 13 btrfs_root *extent_root);
14 14
15static void reada_extent_leaves(struct btrfs_root *root,
16 struct btrfs_path *path, u64 limit)
17{
18 struct btrfs_node *node;
19 int i;
20 int nritems;
21 u64 item_objectid;
22 u64 blocknr;
23 int slot;
24 int ret;
25
26 if (!path->nodes[1])
27 return;
28 node = btrfs_buffer_node(path->nodes[1]);
29 slot = path->slots[1] + 1;
30 nritems = btrfs_header_nritems(&node->header);
31 for (i = slot; i < nritems && i < slot + 8; i++) {
32 item_objectid = btrfs_disk_key_objectid(&node->ptrs[i].key);
33 if (item_objectid > limit)
34 break;
35 blocknr = btrfs_node_blockptr(node, i);
36 ret = readahead_tree_block(root, blocknr);
37 if (ret)
38 break;
39 }
40}
41
15static int cache_block_group(struct btrfs_root *root, 42static int cache_block_group(struct btrfs_root *root,
16 struct btrfs_block_group_cache *block_group) 43 struct btrfs_block_group_cache *block_group)
17{ 44{
@@ -24,6 +51,7 @@ static int cache_block_group(struct btrfs_root *root,
24 u64 i; 51 u64 i;
25 u64 last = 0; 52 u64 last = 0;
26 u64 hole_size; 53 u64 hole_size;
54 u64 limit;
27 int found = 0; 55 int found = 0;
28 56
29 root = root->fs_info->extent_root; 57 root = root->fs_info->extent_root;
@@ -46,14 +74,17 @@ printk("cache block group %Lu\n", block_group->key.objectid);
46 return ret; 74 return ret;
47 if (ret && path->slots[0] > 0) 75 if (ret && path->slots[0] > 0)
48 path->slots[0]--; 76 path->slots[0]--;
77 limit = block_group->key.objectid + block_group->key.offset;
78 reada_extent_leaves(root, path, limit);
49 while(1) { 79 while(1) {
50 leaf = btrfs_buffer_leaf(path->nodes[0]); 80 leaf = btrfs_buffer_leaf(path->nodes[0]);
51 slot = path->slots[0]; 81 slot = path->slots[0];
52 if (slot >= btrfs_header_nritems(&leaf->header)) { 82 if (slot >= btrfs_header_nritems(&leaf->header)) {
83 reada_extent_leaves(root, path, limit);
53 ret = btrfs_next_leaf(root, path); 84 ret = btrfs_next_leaf(root, path);
54 if (ret == 0) 85 if (ret == 0) {
55 continue; 86 continue;
56 else { 87 } else {
57 if (found) { 88 if (found) {
58 hole_size = block_group->key.objectid + 89 hole_size = block_group->key.objectid +
59 block_group->key.offset - last; 90 block_group->key.offset - last;
@@ -187,7 +218,7 @@ new_group:
187 return max((*cache_ret)->last_alloc, search_start); 218 return max((*cache_ret)->last_alloc, search_start);
188 } 219 }
189 cache = btrfs_find_block_group(root, cache, 220 cache = btrfs_find_block_group(root, cache,
190 last + cache->key.offset - 1, 0); 221 last + cache->key.offset - 1, 0, 0);
191 *cache_ret = cache; 222 *cache_ret = cache;
192 goto again; 223 goto again;
193} 224}
@@ -195,7 +226,7 @@ new_group:
195struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, 226struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
196 struct btrfs_block_group_cache 227 struct btrfs_block_group_cache
197 *hint, u64 search_start, 228 *hint, u64 search_start,
198 int data) 229 int data, int owner)
199{ 230{
200 struct btrfs_block_group_cache *cache[8]; 231 struct btrfs_block_group_cache *cache[8];
201 struct btrfs_block_group_cache *found_group = NULL; 232 struct btrfs_block_group_cache *found_group = NULL;
@@ -207,6 +238,10 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
207 int i; 238 int i;
208 int ret; 239 int ret;
209 int full_search = 0; 240 int full_search = 0;
241 int factor = 8;
242
243 if (!owner)
244 factor = 5;
210 245
211 if (data) 246 if (data)
212 radix = &info->block_group_data_radix; 247 radix = &info->block_group_data_radix;
@@ -219,14 +254,14 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
219 if (shint->data == data) { 254 if (shint->data == data) {
220 used = btrfs_block_group_used(&shint->item); 255 used = btrfs_block_group_used(&shint->item);
221 if (used + shint->pinned < 256 if (used + shint->pinned <
222 (shint->key.offset * 8) / 10) { 257 (shint->key.offset * factor) / 10) {
223 return shint; 258 return shint;
224 } 259 }
225 } 260 }
226 } 261 }
227 if (hint && hint->data == data) { 262 if (hint && hint->data == data) {
228 used = btrfs_block_group_used(&hint->item); 263 used = btrfs_block_group_used(&hint->item);
229 if (used + hint->pinned < (hint->key.offset * 8) / 10) { 264 if (used + hint->pinned < (hint->key.offset * factor) / 10) {
230 return hint; 265 return hint;
231 } 266 }
232 if (used >= (hint->key.offset * 8) / 10) { 267 if (used >= (hint->key.offset * 8) / 10) {
@@ -261,7 +296,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
261 cache[i]->key.offset; 296 cache[i]->key.offset;
262 used = btrfs_block_group_used(&cache[i]->item); 297 used = btrfs_block_group_used(&cache[i]->item);
263 if (used + cache[i]->pinned < 298 if (used + cache[i]->pinned <
264 (cache[i]->key.offset * 8) / 10) { 299 (cache[i]->key.offset * factor) / 10) {
265 found_group = cache[i]; 300 found_group = cache[i];
266 goto found; 301 goto found;
267 } 302 }
@@ -272,6 +307,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
272 BTRFS_BLOCK_GROUP_AVAIL); 307 BTRFS_BLOCK_GROUP_AVAIL);
273 } 308 }
274 } 309 }
310 cond_resched();
275 } 311 }
276 last = hint_last; 312 last = hint_last;
277again: 313again:
@@ -295,13 +331,16 @@ again:
295 BTRFS_BLOCK_GROUP_AVAIL); 331 BTRFS_BLOCK_GROUP_AVAIL);
296 } 332 }
297 } 333 }
334 cond_resched();
298 } 335 }
299 if (!full_search) { 336 if (!full_search) {
337printk("find block group doing full search data %d start %Lu\n", data, search_start);
300 last = search_start; 338 last = search_start;
301 full_search = 1; 339 full_search = 1;
302 goto again; 340 goto again;
303 } 341 }
304 if (!found_group) { 342 if (!found_group) {
343printk("find block group bailing to zero data %d\n", data);
305 ret = radix_tree_gang_lookup(radix, 344 ret = radix_tree_gang_lookup(radix,
306 (void **)&found_group, 0, 1); 345 (void **)&found_group, 0, 1);
307 BUG_ON(ret != 1); 346 BUG_ON(ret != 1);
@@ -554,8 +593,8 @@ static int update_block_group(struct btrfs_trans_handle *trans,
554 blocknr + i); 593 blocknr + i);
555 } 594 }
556 } 595 }
557 if (old_val < (cache->key.offset * 6) / 10 && 596 if (old_val < (cache->key.offset * 5) / 10 &&
558 old_val + num >= (cache->key.offset * 6) / 10) { 597 old_val + num >= (cache->key.offset * 5) / 10) {
559printk("group %Lu now available\n", cache->key.objectid); 598printk("group %Lu now available\n", cache->key.objectid);
560 radix_tree_tag_set(cache->radix, 599 radix_tree_tag_set(cache->radix,
561 cache->key.objectid + 600 cache->key.objectid +
@@ -842,6 +881,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
842 int level; 881 int level;
843 struct btrfs_block_group_cache *block_group; 882 struct btrfs_block_group_cache *block_group;
844 int full_scan = 0; 883 int full_scan = 0;
884 u64 limit;
845 885
846 path = btrfs_alloc_path(); 886 path = btrfs_alloc_path();
847 ins->flags = 0; 887 ins->flags = 0;
@@ -858,11 +898,11 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
858 if (search_start) { 898 if (search_start) {
859 block_group = lookup_block_group(info, search_start); 899 block_group = lookup_block_group(info, search_start);
860 block_group = btrfs_find_block_group(root, block_group, 900 block_group = btrfs_find_block_group(root, block_group,
861 search_start, data); 901 search_start, data, 1);
862 } else { 902 } else {
863 block_group = btrfs_find_block_group(root, 903 block_group = btrfs_find_block_group(root,
864 trans->block_group, 0, 904 trans->block_group, 0,
865 data); 905 data, 1);
866 } 906 }
867 907
868check_failed: 908check_failed:
@@ -916,6 +956,12 @@ check_failed:
916 info->extent_tree_prealloc_nr = 0; 956 info->extent_tree_prealloc_nr = 0;
917 total_found = 0; 957 total_found = 0;
918 } 958 }
959 if (start_found)
960 limit = last_block +
961 block_group->key.offset / 2;
962 else
963 limit = search_start +
964 block_group->key.offset / 2;
919 ret = btrfs_next_leaf(root, path); 965 ret = btrfs_next_leaf(root, path);
920 if (ret == 0) 966 if (ret == 0)
921 continue; 967 continue;
@@ -960,6 +1006,7 @@ check_failed:
960 } 1006 }
961next: 1007next:
962 path->slots[0]++; 1008 path->slots[0]++;
1009 cond_resched();
963 } 1010 }
964 // FIXME -ENOSPC 1011 // FIXME -ENOSPC
965check_pending: 1012check_pending:
@@ -1049,7 +1096,8 @@ printk("doing full scan!\n");
1049 block_group = lookup_block_group(info, search_start); 1096 block_group = lookup_block_group(info, search_start);
1050 if (!full_scan) 1097 if (!full_scan)
1051 block_group = btrfs_find_block_group(root, block_group, 1098 block_group = btrfs_find_block_group(root, block_group,
1052 search_start, data); 1099 search_start, data, 0);
1100 cond_resched();
1053 goto check_failed; 1101 goto check_failed;
1054 1102
1055error: 1103error:
@@ -1102,7 +1150,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1102 * in the correct block group. 1150 * in the correct block group.
1103 */ 1151 */
1104 if (data) { 1152 if (data) {
1105 ret = find_free_extent(trans, root, 0, search_start, 1153 ret = find_free_extent(trans, root, 0, 0,
1106 search_end, &prealloc_key, 0); 1154 search_end, &prealloc_key, 0);
1107 if (ret) { 1155 if (ret) {
1108 return ret; 1156 return ret;
@@ -1173,7 +1221,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
1173 struct buffer_head *buf; 1221 struct buffer_head *buf;
1174 1222
1175 ret = btrfs_alloc_extent(trans, root, root->root_key.objectid, 1223 ret = btrfs_alloc_extent(trans, root, root->root_key.objectid,
1176 1, 0, (unsigned long)-1, &ins, 0); 1224 1, hint, (unsigned long)-1, &ins, 0);
1177 if (ret) { 1225 if (ret) {
1178 BUG(); 1226 BUG();
1179 return NULL; 1227 return NULL;
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index eaa48f09d1c4..0f79490123cf 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -351,6 +351,35 @@ static int btrfs_free_inode(struct btrfs_trans_handle *trans,
351 return ret; 351 return ret;
352} 352}
353 353
354static void reada_truncate(struct btrfs_root *root, struct btrfs_path *path,
355 u64 objectid)
356{
357 struct btrfs_node *node;
358 int i;
359 int nritems;
360 u64 item_objectid;
361 u64 blocknr;
362 int slot;
363 int ret;
364
365 if (!path->nodes[1])
366 return;
367 node = btrfs_buffer_node(path->nodes[1]);
368 slot = path->slots[1];
369 if (slot == 0)
370 return;
371 nritems = btrfs_header_nritems(&node->header);
372 for (i = slot - 1; i >= 0; i--) {
373 item_objectid = btrfs_disk_key_objectid(&node->ptrs[i].key);
374 if (item_objectid != objectid)
375 break;
376 blocknr = btrfs_node_blockptr(node, i);
377 ret = readahead_tree_block(root, blocknr);
378 if (ret)
379 break;
380 }
381}
382
354static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, 383static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
355 struct btrfs_root *root, 384 struct btrfs_root *root,
356 struct inode *inode) 385 struct inode *inode)
@@ -386,6 +415,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
386 BUG_ON(path->slots[0] == 0); 415 BUG_ON(path->slots[0] == 0);
387 path->slots[0]--; 416 path->slots[0]--;
388 } 417 }
418 reada_truncate(root, path, inode->i_ino);
389 leaf = btrfs_buffer_leaf(path->nodes[0]); 419 leaf = btrfs_buffer_leaf(path->nodes[0]);
390 found_key = &leaf->items[path->slots[0]].key; 420 found_key = &leaf->items[path->slots[0]].key;
391 if (btrfs_disk_key_objectid(found_key) != inode->i_ino) 421 if (btrfs_disk_key_objectid(found_key) != inode->i_ino)
@@ -587,28 +617,30 @@ printk("adding new root for inode %lu root %p (found %p)\n", inode->i_ino, sub_r
587 return d_splice_alias(inode, dentry); 617 return d_splice_alias(inode, dentry);
588} 618}
589 619
590static void reada_leaves(struct btrfs_root *root, struct btrfs_path *path) 620static void reada_leaves(struct btrfs_root *root, struct btrfs_path *path,
621 u64 objectid)
591{ 622{
592 struct btrfs_node *node; 623 struct btrfs_node *node;
593 int i; 624 int i;
594 int nritems; 625 u32 nritems;
595 u64 objectid;
596 u64 item_objectid; 626 u64 item_objectid;
597 u64 blocknr; 627 u64 blocknr;
598 int slot; 628 int slot;
629 int ret;
599 630
600 if (!path->nodes[1]) 631 if (!path->nodes[1])
601 return; 632 return;
602 node = btrfs_buffer_node(path->nodes[1]); 633 node = btrfs_buffer_node(path->nodes[1]);
603 slot = path->slots[1]; 634 slot = path->slots[1];
604 objectid = btrfs_disk_key_objectid(&node->ptrs[slot].key);
605 nritems = btrfs_header_nritems(&node->header); 635 nritems = btrfs_header_nritems(&node->header);
606 for (i = slot; i < nritems; i++) { 636 for (i = slot + 1; i < nritems; i++) {
607 item_objectid = btrfs_disk_key_objectid(&node->ptrs[i].key); 637 item_objectid = btrfs_disk_key_objectid(&node->ptrs[i].key);
608 if (item_objectid != objectid) 638 if (item_objectid != objectid)
609 break; 639 break;
610 blocknr = btrfs_node_blockptr(node, i); 640 blocknr = btrfs_node_blockptr(node, i);
611 readahead_tree_block(root, blocknr); 641 ret = readahead_tree_block(root, blocknr);
642 if (ret)
643 break;
612 } 644 }
613} 645}
614 646
@@ -646,21 +678,20 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
646 if (ret < 0) 678 if (ret < 0)
647 goto err; 679 goto err;
648 advance = 0; 680 advance = 0;
649 reada_leaves(root, path); 681 reada_leaves(root, path, inode->i_ino);
650 while(1) { 682 while(1) {
651 leaf = btrfs_buffer_leaf(path->nodes[0]); 683 leaf = btrfs_buffer_leaf(path->nodes[0]);
652 nritems = btrfs_header_nritems(&leaf->header); 684 nritems = btrfs_header_nritems(&leaf->header);
653 slot = path->slots[0]; 685 slot = path->slots[0];
654 if (advance || slot >= nritems) { 686 if (advance || slot >= nritems) {
655 if (slot >= nritems -1) { 687 if (slot >= nritems -1) {
688 reada_leaves(root, path, inode->i_ino);
656 ret = btrfs_next_leaf(root, path); 689 ret = btrfs_next_leaf(root, path);
657 if (ret) 690 if (ret)
658 break; 691 break;
659 leaf = btrfs_buffer_leaf(path->nodes[0]); 692 leaf = btrfs_buffer_leaf(path->nodes[0]);
660 nritems = btrfs_header_nritems(&leaf->header); 693 nritems = btrfs_header_nritems(&leaf->header);
661 slot = path->slots[0]; 694 slot = path->slots[0];
662 if (path->slots[1] == 0)
663 reada_leaves(root, path);
664 } else { 695 } else {
665 slot++; 696 slot++;
666 path->slots[0]++; 697 path->slots[0]++;
@@ -805,13 +836,18 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
805 struct btrfs_inode_item inode_item; 836 struct btrfs_inode_item inode_item;
806 struct btrfs_key *location; 837 struct btrfs_key *location;
807 int ret; 838 int ret;
839 int owner;
808 840
809 inode = new_inode(root->fs_info->sb); 841 inode = new_inode(root->fs_info->sb);
810 if (!inode) 842 if (!inode)
811 return ERR_PTR(-ENOMEM); 843 return ERR_PTR(-ENOMEM);
812 844
813 BTRFS_I(inode)->root = root; 845 BTRFS_I(inode)->root = root;
814 group = btrfs_find_block_group(root, group, 0, 0); 846 if (mode & S_IFDIR)
847 owner = 0;
848 else
849 owner = 1;
850 group = btrfs_find_block_group(root, group, 0, 0, owner);
815 BTRFS_I(inode)->block_group = group; 851 BTRFS_I(inode)->block_group = group;
816 852
817 inode->i_uid = current->fsuid; 853 inode->i_uid = current->fsuid;
@@ -1562,7 +1598,7 @@ failed:
1562static int drop_extents(struct btrfs_trans_handle *trans, 1598static int drop_extents(struct btrfs_trans_handle *trans,
1563 struct btrfs_root *root, 1599 struct btrfs_root *root,
1564 struct inode *inode, 1600 struct inode *inode,
1565 u64 start, u64 end) 1601 u64 start, u64 end, u64 *hint_block)
1566{ 1602{
1567 int ret; 1603 int ret;
1568 struct btrfs_key key; 1604 struct btrfs_key key;
@@ -1659,17 +1695,14 @@ static int drop_extents(struct btrfs_trans_handle *trans,
1659 new_num = (start - key.offset) >> 1695 new_num = (start - key.offset) >>
1660 inode->i_blkbits; 1696 inode->i_blkbits;
1661 old_num = btrfs_file_extent_num_blocks(extent); 1697 old_num = btrfs_file_extent_num_blocks(extent);
1698 *hint_block =
1699 btrfs_file_extent_disk_blocknr(extent);
1662 inode->i_blocks -= (old_num - new_num) << 3; 1700 inode->i_blocks -= (old_num - new_num) << 3;
1663 btrfs_set_file_extent_num_blocks(extent, 1701 btrfs_set_file_extent_num_blocks(extent,
1664 new_num); 1702 new_num);
1665 mark_buffer_dirty(path->nodes[0]); 1703 mark_buffer_dirty(path->nodes[0]);
1666 } else { 1704 } else {
1667 WARN_ON(1); 1705 WARN_ON(1);
1668 /*
1669 ret = btrfs_truncate_item(trans, root, path,
1670 start - key.offset);
1671 BUG_ON(ret);
1672 */
1673 } 1706 }
1674 } 1707 }
1675 if (!keep) { 1708 if (!keep) {
@@ -1683,6 +1716,8 @@ static int drop_extents(struct btrfs_trans_handle *trans,
1683 btrfs_file_extent_disk_num_blocks(extent); 1716 btrfs_file_extent_disk_num_blocks(extent);
1684 extent_num_blocks = 1717 extent_num_blocks =
1685 btrfs_file_extent_num_blocks(extent); 1718 btrfs_file_extent_num_blocks(extent);
1719 *hint_block =
1720 btrfs_file_extent_disk_blocknr(extent);
1686 } 1721 }
1687 ret = btrfs_del_item(trans, root, path); 1722 ret = btrfs_del_item(trans, root, path);
1688 BUG_ON(ret); 1723 BUG_ON(ret);
@@ -1831,6 +1866,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
1831 u64 start_pos; 1866 u64 start_pos;
1832 u64 num_blocks; 1867 u64 num_blocks;
1833 u64 alloc_extent_start; 1868 u64 alloc_extent_start;
1869 u64 hint_block;
1834 struct btrfs_trans_handle *trans; 1870 struct btrfs_trans_handle *trans;
1835 struct btrfs_key ins; 1871 struct btrfs_key ins;
1836 pinned[0] = NULL; 1872 pinned[0] = NULL;
@@ -1871,6 +1907,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
1871 } 1907 }
1872 if (first_index != last_index && 1908 if (first_index != last_index &&
1873 (last_index << PAGE_CACHE_SHIFT) < inode->i_size && 1909 (last_index << PAGE_CACHE_SHIFT) < inode->i_size &&
1910 pos + count < inode->i_size &&
1874 (count & (PAGE_CACHE_SIZE - 1))) { 1911 (count & (PAGE_CACHE_SIZE - 1))) {
1875 pinned[1] = grab_cache_page(inode->i_mapping, last_index); 1912 pinned[1] = grab_cache_page(inode->i_mapping, last_index);
1876 if (!PageUptodate(pinned[1])) { 1913 if (!PageUptodate(pinned[1])) {
@@ -1892,18 +1929,20 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
1892 btrfs_set_trans_block_group(trans, inode); 1929 btrfs_set_trans_block_group(trans, inode);
1893 /* FIXME blocksize != 4096 */ 1930 /* FIXME blocksize != 4096 */
1894 inode->i_blocks += num_blocks << 3; 1931 inode->i_blocks += num_blocks << 3;
1932 hint_block = 0;
1895 if (start_pos < inode->i_size) { 1933 if (start_pos < inode->i_size) {
1896 /* FIXME blocksize != pagesize */ 1934 /* FIXME blocksize != pagesize */
1897 ret = drop_extents(trans, root, inode, 1935 ret = drop_extents(trans, root, inode,
1898 start_pos, 1936 start_pos,
1899 (pos + count + root->blocksize -1) & 1937 (pos + count + root->blocksize -1) &
1900 ~((u64)root->blocksize - 1)); 1938 ~((u64)root->blocksize - 1), &hint_block);
1901 BUG_ON(ret); 1939 BUG_ON(ret);
1902 } 1940 }
1903 if (inode->i_size >= PAGE_CACHE_SIZE || pos + count < inode->i_size || 1941 if (inode->i_size >= PAGE_CACHE_SIZE || pos + count < inode->i_size ||
1904 pos + count - start_pos > BTRFS_MAX_INLINE_DATA_SIZE(root)) { 1942 pos + count - start_pos > BTRFS_MAX_INLINE_DATA_SIZE(root)) {
1905 ret = btrfs_alloc_extent(trans, root, inode->i_ino, 1943 ret = btrfs_alloc_extent(trans, root, inode->i_ino,
1906 num_blocks, 1, (u64)-1, &ins, 1); 1944 num_blocks, hint_block, (u64)-1,
1945 &ins, 1);
1907 BUG_ON(ret); 1946 BUG_ON(ret);
1908 ret = btrfs_insert_file_extent(trans, root, inode->i_ino, 1947 ret = btrfs_insert_file_extent(trans, root, inode->i_ino,
1909 start_pos, ins.objectid, ins.offset); 1948 start_pos, ins.objectid, ins.offset);
@@ -2455,7 +2494,6 @@ static int btrfs_get_sb(struct file_system_type *fs_type,
2455 btrfs_fill_super, mnt); 2494 btrfs_fill_super, mnt);
2456} 2495}
2457 2496
2458
2459static int btrfs_getattr(struct vfsmount *mnt, 2497static int btrfs_getattr(struct vfsmount *mnt,
2460 struct dentry *dentry, struct kstat *stat) 2498 struct dentry *dentry, struct kstat *stat)
2461{ 2499{