aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c67
1 files changed, 48 insertions, 19 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 5d10b64e42df..0c65141b9993 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -89,6 +89,9 @@ static int run_delalloc_range(struct inode *inode, u64 start, u64 end)
89 ret = btrfs_drop_extents(trans, root, inode, 89 ret = btrfs_drop_extents(trans, root, inode,
90 start, start + num_bytes, start, &alloc_hint); 90 start, start + num_bytes, start, &alloc_hint);
91 91
92 if (alloc_hint == EXTENT_MAP_INLINE)
93 goto out;
94
92 ret = btrfs_alloc_extent(trans, root, inode->i_ino, num_bytes, 0, 95 ret = btrfs_alloc_extent(trans, root, inode->i_ino, num_bytes, 0,
93 alloc_hint, (u64)-1, &ins, 1); 96 alloc_hint, (u64)-1, &ins, 1);
94 if (ret) { 97 if (ret) {
@@ -558,6 +561,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
558 u64 item_end = 0; 561 u64 item_end = 0;
559 int found_extent; 562 int found_extent;
560 int del_item; 563 int del_item;
564 int extent_type = -1;
561 565
562 btrfs_drop_extent_cache(inode, inode->i_size, (u64)-1); 566 btrfs_drop_extent_cache(inode, inode->i_size, (u64)-1);
563 path = btrfs_alloc_path(); 567 path = btrfs_alloc_path();
@@ -597,10 +601,15 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
597 if (found_type == BTRFS_EXTENT_DATA_KEY) { 601 if (found_type == BTRFS_EXTENT_DATA_KEY) {
598 fi = btrfs_item_ptr(leaf, path->slots[0], 602 fi = btrfs_item_ptr(leaf, path->slots[0],
599 struct btrfs_file_extent_item); 603 struct btrfs_file_extent_item);
600 if (btrfs_file_extent_type(leaf, fi) != 604 extent_type = btrfs_file_extent_type(leaf, fi);
601 BTRFS_FILE_EXTENT_INLINE) { 605 if (extent_type != BTRFS_FILE_EXTENT_INLINE) {
602 item_end += 606 item_end +=
603 btrfs_file_extent_num_bytes(leaf, fi); 607 btrfs_file_extent_num_bytes(leaf, fi);
608 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
609 struct btrfs_item *item = btrfs_item_nr(leaf,
610 path->slots[0]);
611 item_end += btrfs_file_extent_inline_len(leaf,
612 item);
604 } 613 }
605 } 614 }
606 if (found_type == BTRFS_CSUM_ITEM_KEY) { 615 if (found_type == BTRFS_CSUM_ITEM_KEY) {
@@ -608,7 +617,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
608 inode->i_size); 617 inode->i_size);
609 BUG_ON(ret); 618 BUG_ON(ret);
610 } 619 }
611 if (item_end < inode->i_size) { 620 if (item_end <= inode->i_size) {
612 if (found_type == BTRFS_DIR_ITEM_KEY) { 621 if (found_type == BTRFS_DIR_ITEM_KEY) {
613 found_type = BTRFS_INODE_ITEM_KEY; 622 found_type = BTRFS_INODE_ITEM_KEY;
614 } else if (found_type == BTRFS_EXTENT_ITEM_KEY) { 623 } else if (found_type == BTRFS_EXTENT_ITEM_KEY) {
@@ -629,9 +638,10 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
629 found_extent = 0; 638 found_extent = 0;
630 639
631 /* FIXME, shrink the extent if the ref count is only 1 */ 640 /* FIXME, shrink the extent if the ref count is only 1 */
632 if (found_type == BTRFS_EXTENT_DATA_KEY && 641 if (found_type != BTRFS_EXTENT_DATA_KEY)
633 btrfs_file_extent_type(leaf, fi) != 642 goto delete;
634 BTRFS_FILE_EXTENT_INLINE) { 643
644 if (extent_type != BTRFS_FILE_EXTENT_INLINE) {
635 u64 num_dec; 645 u64 num_dec;
636 extent_start = btrfs_file_extent_disk_bytenr(leaf, fi); 646 extent_start = btrfs_file_extent_disk_bytenr(leaf, fi);
637 if (!del_item) { 647 if (!del_item) {
@@ -659,7 +669,15 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
659 inode->i_blocks -= num_dec; 669 inode->i_blocks -= num_dec;
660 } 670 }
661 } 671 }
672 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE &&
673 !del_item) {
674 u32 newsize = inode->i_size - found_key.offset;
675 newsize = btrfs_file_extent_calc_inline_size(newsize);
676 ret = btrfs_truncate_item(trans, root, path,
677 newsize, 1);
678 BUG_ON(ret);
662 } 679 }
680delete:
663 if (del_item) { 681 if (del_item) {
664 ret = btrfs_del_item(trans, root, path); 682 ret = btrfs_del_item(trans, root, path);
665 if (ret) 683 if (ret)
@@ -769,7 +787,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
769 u64 pos = (inode->i_size + mask) & ~mask; 787 u64 pos = (inode->i_size + mask) & ~mask;
770 u64 block_end = attr->ia_size | mask; 788 u64 block_end = attr->ia_size | mask;
771 u64 hole_size; 789 u64 hole_size;
772 u64 alloc_hint; 790 u64 alloc_hint = 0;
773 791
774 if (attr->ia_size <= pos) 792 if (attr->ia_size <= pos)
775 goto out; 793 goto out;
@@ -786,8 +804,11 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
786 pos, pos + hole_size, pos, 804 pos, pos + hole_size, pos,
787 &alloc_hint); 805 &alloc_hint);
788 806
789 err = btrfs_insert_file_extent(trans, root, inode->i_ino, 807 if (alloc_hint != EXTENT_MAP_INLINE) {
790 pos, 0, 0, hole_size); 808 err = btrfs_insert_file_extent(trans, root,
809 inode->i_ino,
810 pos, 0, 0, hole_size);
811 }
791 btrfs_end_transaction(trans, root); 812 btrfs_end_transaction(trans, root);
792 mutex_unlock(&root->fs_info->fs_mutex); 813 mutex_unlock(&root->fs_info->fs_mutex);
793 unlock_extent(em_tree, pos, block_end, GFP_NOFS); 814 unlock_extent(em_tree, pos, block_end, GFP_NOFS);
@@ -1531,8 +1552,8 @@ again:
1531 em->end = EXTENT_MAP_HOLE; 1552 em->end = EXTENT_MAP_HOLE;
1532 } 1553 }
1533 em->bdev = inode->i_sb->s_bdev; 1554 em->bdev = inode->i_sb->s_bdev;
1534 ret = btrfs_lookup_file_extent(NULL, root, path, 1555 ret = btrfs_lookup_file_extent(trans, root, path,
1535 objectid, start, 0); 1556 objectid, start, trans != NULL);
1536 if (ret < 0) { 1557 if (ret < 0) {
1537 err = ret; 1558 err = ret;
1538 goto out; 1559 goto out;
@@ -1627,15 +1648,23 @@ again:
1627 ((u64)root->sectorsize -1); 1648 ((u64)root->sectorsize -1);
1628 map = kmap(page); 1649 map = kmap(page);
1629 ptr = btrfs_file_extent_inline_start(item) + extent_offset; 1650 ptr = btrfs_file_extent_inline_start(item) + extent_offset;
1630 read_extent_buffer(leaf, map + page_offset, ptr, copy_size); 1651 if (create == 0 && !PageUptodate(page)) {
1631 1652 read_extent_buffer(leaf, map + page_offset, ptr,
1632 if (em->start + copy_size <= em->end) { 1653 copy_size);
1633 size = min_t(u64, em->end + 1 - em->start, 1654 flush_dcache_page(page);
1634 PAGE_CACHE_SIZE - page_offset) - copy_size; 1655 } else if (create && PageUptodate(page)) {
1635 memset(map + page_offset + copy_size, 0, size); 1656 if (!trans) {
1657 kunmap(page);
1658 free_extent_map(em);
1659 em = NULL;
1660 btrfs_release_path(root, path);
1661 trans = btrfs_start_transaction(root, 1);
1662 goto again;
1663 }
1664 write_extent_buffer(leaf, map + page_offset, ptr,
1665 copy_size);
1666 btrfs_mark_buffer_dirty(leaf);
1636 } 1667 }
1637
1638 flush_dcache_page(page);
1639 kunmap(page); 1668 kunmap(page);
1640 set_extent_uptodate(em_tree, em->start, em->end, GFP_NOFS); 1669 set_extent_uptodate(em_tree, em->start, em->end, GFP_NOFS);
1641 goto insert; 1670 goto insert;