diff options
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 36 |
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; |