aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/super.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-05-24 13:35:57 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-05-24 13:35:57 -0400
commit3a686375629da5d2e2ad019265b66ef113c87455 (patch)
tree1fbbedfcb92aeea38d90955ef11975187ddcc6f3 /fs/btrfs/super.c
parent2b8d99a723a3186a69b5bd941a272dbecae9205b (diff)
Btrfs: sparse files!
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r--fs/btrfs/super.c121
1 files changed, 99 insertions, 22 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index c1a0adde9b1c..5b87c4e9d491 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -17,6 +17,7 @@
17#include "transaction.h" 17#include "transaction.h"
18#include "btrfs_inode.h" 18#include "btrfs_inode.h"
19#include "ioctl.h" 19#include "ioctl.h"
20#include "print-tree.h"
20 21
21struct btrfs_iget_args { 22struct btrfs_iget_args {
22 u64 ino; 23 u64 ino;
@@ -421,14 +422,17 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
421 struct btrfs_file_extent_item); 422 struct btrfs_file_extent_item);
422 if (btrfs_file_extent_type(fi) != 423 if (btrfs_file_extent_type(fi) !=
423 BTRFS_FILE_EXTENT_INLINE) { 424 BTRFS_FILE_EXTENT_INLINE) {
425 u64 num_dec;
424 extent_start = 426 extent_start =
425 btrfs_file_extent_disk_blocknr(fi); 427 btrfs_file_extent_disk_blocknr(fi);
426 extent_num_blocks = 428 extent_num_blocks =
427 btrfs_file_extent_disk_num_blocks(fi); 429 btrfs_file_extent_disk_num_blocks(fi);
428 /* FIXME blocksize != 4096 */ 430 /* FIXME blocksize != 4096 */
429 inode->i_blocks -= 431 num_dec = btrfs_file_extent_num_blocks(fi) << 3;
430 btrfs_file_extent_num_blocks(fi) << 3; 432 if (extent_start != 0) {
431 found_extent = 1; 433 found_extent = 1;
434 inode->i_blocks -= num_dec;
435 }
432 } 436 }
433 } 437 }
434 ret = btrfs_del_item(trans, root, path); 438 ret = btrfs_del_item(trans, root, path);
@@ -448,6 +452,43 @@ error:
448 return ret; 452 return ret;
449} 453}
450 454
455static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
456{
457 struct inode *inode = dentry->d_inode;
458 int err;
459
460 err = inode_change_ok(inode, attr);
461 if (err)
462 return err;
463
464 if (S_ISREG(inode->i_mode) &&
465 attr->ia_valid & ATTR_SIZE && attr->ia_size > inode->i_size) {
466 struct btrfs_trans_handle *trans;
467 struct btrfs_root *root = BTRFS_I(inode)->root;
468 u64 mask = root->blocksize - 1;
469 u64 pos = (inode->i_size + mask) & ~mask;
470 u64 hole_size;
471
472 if (attr->ia_size < pos)
473 goto out;
474 hole_size = (attr->ia_size - pos + mask) & ~mask;
475 hole_size >>= inode->i_blkbits;
476
477 mutex_lock(&root->fs_info->fs_mutex);
478 trans = btrfs_start_transaction(root, 1);
479 btrfs_set_trans_block_group(trans, inode);
480 err = btrfs_insert_file_extent(trans, root, inode->i_ino,
481 pos, 0, 0, hole_size);
482 BUG_ON(err);
483 btrfs_end_transaction(trans, root);
484 mutex_unlock(&root->fs_info->fs_mutex);
485 }
486
487 err = inode_setattr(inode, attr);
488
489out:
490 return err;
491}
451static void btrfs_delete_inode(struct inode *inode) 492static void btrfs_delete_inode(struct inode *inode)
452{ 493{
453 struct btrfs_trans_handle *trans; 494 struct btrfs_trans_handle *trans;
@@ -1169,8 +1210,10 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock,
1169 if (found_type == BTRFS_FILE_EXTENT_REG) { 1210 if (found_type == BTRFS_FILE_EXTENT_REG) {
1170 extent_start = extent_start >> inode->i_blkbits; 1211 extent_start = extent_start >> inode->i_blkbits;
1171 extent_end = extent_start + btrfs_file_extent_num_blocks(item); 1212 extent_end = extent_start + btrfs_file_extent_num_blocks(item);
1213 err = 0;
1214 if (blocknr == 0)
1215 goto out;
1172 if (iblock >= extent_start && iblock < extent_end) { 1216 if (iblock >= extent_start && iblock < extent_end) {
1173 err = 0;
1174 btrfs_map_bh_to_logical(root, result, blocknr + 1217 btrfs_map_bh_to_logical(root, result, blocknr +
1175 iblock - extent_start); 1218 iblock - extent_start);
1176 goto out; 1219 goto out;
@@ -1591,7 +1634,7 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
1591 ptr, bh->b_data, offset + write_bytes); 1634 ptr, bh->b_data, offset + write_bytes);
1592 mark_buffer_dirty(path->nodes[0]); 1635 mark_buffer_dirty(path->nodes[0]);
1593 btrfs_free_path(path); 1636 btrfs_free_path(path);
1594 } else { 1637 } else if (buffer_mapped(bh)) {
1595 btrfs_csum_file_block(trans, root, inode->i_ino, 1638 btrfs_csum_file_block(trans, root, inode->i_ino,
1596 pages[i]->index << PAGE_CACHE_SHIFT, 1639 pages[i]->index << PAGE_CACHE_SHIFT,
1597 kmap(pages[i]), PAGE_CACHE_SIZE); 1640 kmap(pages[i]), PAGE_CACHE_SIZE);
@@ -1693,15 +1736,24 @@ static int drop_extents(struct btrfs_trans_handle *trans,
1693 goto out; 1736 goto out;
1694 } 1737 }
1695 1738
1696 search_start = extent_end; 1739 if (found_inline) {
1740 u64 mask = root->blocksize - 1;
1741 search_start = (extent_end + mask) & ~mask;
1742 } else
1743 search_start = extent_end;
1697 1744
1698 if (end < extent_end && end >= key.offset) { 1745 if (end < extent_end && end >= key.offset) {
1699 if (found_extent) { 1746 if (found_extent) {
1747 u64 disk_blocknr =
1748 btrfs_file_extent_disk_blocknr(extent);
1749 u64 disk_num_blocks =
1750 btrfs_file_extent_disk_num_blocks(extent);
1700 memcpy(&old, extent, sizeof(old)); 1751 memcpy(&old, extent, sizeof(old));
1701 ret = btrfs_inc_extent_ref(trans, root, 1752 if (disk_blocknr != 0) {
1702 btrfs_file_extent_disk_blocknr(&old), 1753 ret = btrfs_inc_extent_ref(trans, root,
1703 btrfs_file_extent_disk_num_blocks(&old)); 1754 disk_blocknr, disk_num_blocks);
1704 BUG_ON(ret); 1755 BUG_ON(ret);
1756 }
1705 } 1757 }
1706 WARN_ON(found_inline); 1758 WARN_ON(found_inline);
1707 bookend = 1; 1759 bookend = 1;
@@ -1719,7 +1771,10 @@ static int drop_extents(struct btrfs_trans_handle *trans,
1719 old_num = btrfs_file_extent_num_blocks(extent); 1771 old_num = btrfs_file_extent_num_blocks(extent);
1720 *hint_block = 1772 *hint_block =
1721 btrfs_file_extent_disk_blocknr(extent); 1773 btrfs_file_extent_disk_blocknr(extent);
1722 inode->i_blocks -= (old_num - new_num) << 3; 1774 if (btrfs_file_extent_disk_blocknr(extent)) {
1775 inode->i_blocks -=
1776 (old_num - new_num) << 3;
1777 }
1723 btrfs_set_file_extent_num_blocks(extent, 1778 btrfs_set_file_extent_num_blocks(extent,
1724 new_num); 1779 new_num);
1725 mark_buffer_dirty(path->nodes[0]); 1780 mark_buffer_dirty(path->nodes[0]);
@@ -1745,7 +1800,7 @@ static int drop_extents(struct btrfs_trans_handle *trans,
1745 BUG_ON(ret); 1800 BUG_ON(ret);
1746 btrfs_release_path(root, path); 1801 btrfs_release_path(root, path);
1747 extent = NULL; 1802 extent = NULL;
1748 if (found_extent) { 1803 if (found_extent && disk_blocknr != 0) {
1749 inode->i_blocks -= extent_num_blocks << 3; 1804 inode->i_blocks -= extent_num_blocks << 3;
1750 ret = btrfs_free_extent(trans, root, 1805 ret = btrfs_free_extent(trans, root,
1751 disk_blocknr, 1806 disk_blocknr,
@@ -1785,18 +1840,19 @@ static int drop_extents(struct btrfs_trans_handle *trans,
1785 btrfs_file_extent_offset(&old) + 1840 btrfs_file_extent_offset(&old) +
1786 ((end - key.offset) >> inode->i_blkbits)); 1841 ((end - key.offset) >> inode->i_blkbits));
1787 WARN_ON(btrfs_file_extent_num_blocks(&old) < 1842 WARN_ON(btrfs_file_extent_num_blocks(&old) <
1788 (end - key.offset) >> inode->i_blkbits); 1843 (extent_end - end) >> inode->i_blkbits);
1789 btrfs_set_file_extent_num_blocks(extent, 1844 btrfs_set_file_extent_num_blocks(extent,
1790 btrfs_file_extent_num_blocks(&old) - 1845 (extent_end - end) >> inode->i_blkbits);
1791 ((end - key.offset) >> inode->i_blkbits));
1792 1846
1793 btrfs_set_file_extent_type(extent, 1847 btrfs_set_file_extent_type(extent,
1794 BTRFS_FILE_EXTENT_REG); 1848 BTRFS_FILE_EXTENT_REG);
1795 btrfs_set_file_extent_generation(extent, 1849 btrfs_set_file_extent_generation(extent,
1796 btrfs_file_extent_generation(&old)); 1850 btrfs_file_extent_generation(&old));
1797 btrfs_mark_buffer_dirty(path->nodes[0]); 1851 btrfs_mark_buffer_dirty(path->nodes[0]);
1798 inode->i_blocks += 1852 if (btrfs_file_extent_disk_blocknr(&old) != 0) {
1799 btrfs_file_extent_num_blocks(extent) << 3; 1853 inode->i_blocks +=
1854 btrfs_file_extent_num_blocks(extent) << 3;
1855 }
1800 ret = 0; 1856 ret = 0;
1801 goto out; 1857 goto out;
1802 } 1858 }
@@ -1960,6 +2016,21 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
1960 ~((u64)root->blocksize - 1), &hint_block); 2016 ~((u64)root->blocksize - 1), &hint_block);
1961 BUG_ON(ret); 2017 BUG_ON(ret);
1962 } 2018 }
2019 if (inode->i_size < start_pos) {
2020 u64 last_pos_in_file;
2021 u64 hole_size;
2022 u64 mask = root->blocksize - 1;
2023 last_pos_in_file = (inode->i_size + mask) & ~mask;
2024 hole_size = (start_pos - last_pos_in_file + mask) & ~mask;
2025 hole_size >>= inode->i_blkbits;
2026 if (last_pos_in_file < start_pos) {
2027 ret = btrfs_insert_file_extent(trans, root,
2028 inode->i_ino,
2029 last_pos_in_file,
2030 0, 0, hole_size);
2031 }
2032 BUG_ON(ret);
2033 }
1963 if (inode->i_size >= PAGE_CACHE_SIZE || pos + count < inode->i_size || 2034 if (inode->i_size >= PAGE_CACHE_SIZE || pos + count < inode->i_size ||
1964 pos + count - start_pos > BTRFS_MAX_INLINE_DATA_SIZE(root)) { 2035 pos + count - start_pos > BTRFS_MAX_INLINE_DATA_SIZE(root)) {
1965 ret = btrfs_alloc_extent(trans, root, inode->i_ino, 2036 ret = btrfs_alloc_extent(trans, root, inode->i_ino,
@@ -1967,7 +2038,8 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
1967 &ins, 1); 2038 &ins, 1);
1968 BUG_ON(ret); 2039 BUG_ON(ret);
1969 ret = btrfs_insert_file_extent(trans, root, inode->i_ino, 2040 ret = btrfs_insert_file_extent(trans, root, inode->i_ino,
1970 start_pos, ins.objectid, ins.offset); 2041 start_pos, ins.objectid, ins.offset,
2042 ins.offset);
1971 BUG_ON(ret); 2043 BUG_ON(ret);
1972 } else { 2044 } else {
1973 ins.offset = 0; 2045 ins.offset = 0;
@@ -2044,10 +2116,13 @@ static int btrfs_read_actor(read_descriptor_t *desc, struct page *page,
2044 page->index << PAGE_CACHE_SHIFT, 2116 page->index << PAGE_CACHE_SHIFT,
2045 kmap(page), PAGE_CACHE_SIZE); 2117 kmap(page), PAGE_CACHE_SIZE);
2046 if (ret) { 2118 if (ret) {
2047 printk("failed to verify ino %lu page %lu\n", 2119 if (ret != -ENOENT) {
2048 page->mapping->host->i_ino, 2120 printk("failed to verify ino %lu page %lu\n",
2049 page->index); 2121 page->mapping->host->i_ino,
2050 memset(page_address(page), 0, PAGE_CACHE_SIZE); 2122 page->index);
2123 memset(page_address(page), 0, PAGE_CACHE_SIZE);
2124 flush_dcache_page(page);
2125 }
2051 } 2126 }
2052 SetPageChecked(page); 2127 SetPageChecked(page);
2053 kunmap(page); 2128 kunmap(page);
@@ -2759,6 +2834,7 @@ static struct inode_operations btrfs_dir_inode_operations = {
2759 .rmdir = btrfs_rmdir, 2834 .rmdir = btrfs_rmdir,
2760 .rename = btrfs_rename, 2835 .rename = btrfs_rename,
2761 .symlink = btrfs_symlink, 2836 .symlink = btrfs_symlink,
2837 .setattr = btrfs_setattr,
2762}; 2838};
2763 2839
2764static struct inode_operations btrfs_dir_ro_inode_operations = { 2840static struct inode_operations btrfs_dir_ro_inode_operations = {
@@ -2788,6 +2864,7 @@ static struct address_space_operations btrfs_symlink_aops = {
2788static struct inode_operations btrfs_file_inode_operations = { 2864static struct inode_operations btrfs_file_inode_operations = {
2789 .truncate = btrfs_truncate, 2865 .truncate = btrfs_truncate,
2790 .getattr = btrfs_getattr, 2866 .getattr = btrfs_getattr,
2867 .setattr = btrfs_setattr,
2791}; 2868};
2792 2869
2793static struct file_operations btrfs_file_operations = { 2870static struct file_operations btrfs_file_operations = {