aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
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;