aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-11-01 11:28:41 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:57 -0400
commit179e29e488cc74f1e9bd67bc45f70b832740e9ec (patch)
treeaa055d77b8d3f2b4bc59b1bb8a5b98ec0b223fb5 /fs/btrfs/file.c
parent35ebb934bd7fcc7ca991b155b7980c3c4ff9f1a5 (diff)
Btrfs: Fix a number of inline extent problems that Yan Zheng reported.
The fixes do a number of things: 1) Most btrfs_drop_extent callers will try to leave the inline extents in place. It can truncate bytes off the beginning of the inline extent if required. 2) writepage can now update the inline extent, allowing mmap writes to go directly into the inline extent. 3) btrfs_truncate_in_transaction truncates inline extents 4) extent_map.c fixed to not merge inline extent mappings and hole mappings together Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index abdd9caad94e..4e52f7ec1cbe 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -115,8 +115,20 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
115 goto fail; 115 goto fail;
116 } 116 }
117 if (ret == 1) { 117 if (ret == 1) {
118 struct btrfs_key found_key;
119
120 if (path->slots[0] == 0)
121 goto insert;
122
118 path->slots[0]--; 123 path->slots[0]--;
119 leaf = path->nodes[0]; 124 leaf = path->nodes[0];
125 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
126
127 if (found_key.objectid != inode->i_ino)
128 goto insert;
129
130 if (found_key.type != BTRFS_EXTENT_DATA_KEY)
131 goto insert;
120 ei = btrfs_item_ptr(leaf, path->slots[0], 132 ei = btrfs_item_ptr(leaf, path->slots[0],
121 struct btrfs_file_extent_item); 133 struct btrfs_file_extent_item);
122 134
@@ -152,6 +164,7 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
152 ret = btrfs_search_slot(trans, root, &key, path, 164 ret = btrfs_search_slot(trans, root, &key, path,
153 offset + size - found_end, 1); 165 offset + size - found_end, 1);
154 BUG_ON(ret != 0); 166 BUG_ON(ret != 0);
167
155 ret = btrfs_extend_item(trans, root, path, 168 ret = btrfs_extend_item(trans, root, path,
156 offset + size - found_end); 169 offset + size - found_end);
157 if (ret) { 170 if (ret) {
@@ -292,7 +305,7 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
292 */ 305 */
293 inline_size = end_pos; 306 inline_size = end_pos;
294 if (isize >= BTRFS_MAX_INLINE_DATA_SIZE(root) || 307 if (isize >= BTRFS_MAX_INLINE_DATA_SIZE(root) ||
295 inline_size > 8192 || 308 inline_size > 32768 ||
296 inline_size >= BTRFS_MAX_INLINE_DATA_SIZE(root)) { 309 inline_size >= BTRFS_MAX_INLINE_DATA_SIZE(root)) {
297 u64 last_end; 310 u64 last_end;
298 311
@@ -312,7 +325,7 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
312 aligned_end = (pos + write_bytes + root->sectorsize - 1) & 325 aligned_end = (pos + write_bytes + root->sectorsize - 1) &
313 ~((u64)root->sectorsize - 1); 326 ~((u64)root->sectorsize - 1);
314 err = btrfs_drop_extents(trans, root, inode, start_pos, 327 err = btrfs_drop_extents(trans, root, inode, start_pos,
315 aligned_end, end_pos, &hint_byte); 328 aligned_end, aligned_end, &hint_byte);
316 if (err) 329 if (err)
317 goto failed; 330 goto failed;
318 err = insert_inline_extent(trans, root, inode, start_pos, 331 err = insert_inline_extent(trans, root, inode, start_pos,
@@ -456,13 +469,15 @@ next_slot:
456 goto next_slot; 469 goto next_slot;
457 } 470 }
458 471
459 /* FIXME, there's only one inline extent allowed right now */
460 if (found_inline) { 472 if (found_inline) {
461 u64 mask = root->sectorsize - 1; 473 u64 mask = root->sectorsize - 1;
462 search_start = (extent_end + mask) & ~mask; 474 search_start = (extent_end + mask) & ~mask;
463 } else 475 } else
464 search_start = extent_end; 476 search_start = extent_end;
465 477
478 if (end <= extent_end && start >= key.offset && found_inline) {
479 *hint_byte = EXTENT_MAP_INLINE;
480 }
466 if (end < extent_end && end >= key.offset) { 481 if (end < extent_end && end >= key.offset) {
467 if (found_extent) { 482 if (found_extent) {
468 u64 disk_bytenr = 483 u64 disk_bytenr =
@@ -479,8 +494,10 @@ next_slot:
479 BUG_ON(ret); 494 BUG_ON(ret);
480 } 495 }
481 } 496 }
482 if (!found_inline) 497 bookend = 1;
483 bookend = 1; 498 if (found_inline && start <= key.offset &&
499 inline_end < extent_end)
500 keep = 1;
484 } 501 }
485 /* truncate existing extent */ 502 /* truncate existing extent */
486 if (start > key.offset) { 503 if (start > key.offset) {
@@ -510,7 +527,7 @@ next_slot:
510 new_size = btrfs_file_extent_calc_inline_size( 527 new_size = btrfs_file_extent_calc_inline_size(
511 inline_end - key.offset); 528 inline_end - key.offset);
512 btrfs_truncate_item(trans, root, path, 529 btrfs_truncate_item(trans, root, path,
513 new_size); 530 new_size, 1);
514 } 531 }
515 } 532 }
516 /* delete the entire extent */ 533 /* delete the entire extent */
@@ -551,6 +568,13 @@ next_slot:
551 if (!bookend) 568 if (!bookend)
552 continue; 569 continue;
553 } 570 }
571 if (bookend && found_inline && start <= key.offset &&
572 inline_end < extent_end) {
573 u32 new_size;
574 new_size = btrfs_file_extent_calc_inline_size(
575 extent_end - inline_end);
576 btrfs_truncate_item(trans, root, path, new_size, 0);
577 }
554 /* create bookend, splitting the extent in two */ 578 /* create bookend, splitting the extent in two */
555 if (bookend && found_extent) { 579 if (bookend && found_extent) {
556 struct btrfs_key ins; 580 struct btrfs_key ins;