aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-02-08 13:49:28 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:00 -0400
commit9069218d448ea547dbad5f1cbd537e88d6519d66 (patch)
treefafb142a36805f26678bb4e7a0ebe50d8c7f859a /fs/btrfs
parenta86c12c73d982c545a37a8ecdd66528ab260b770 (diff)
Btrfs: Fix i_blocks accounting
Now that delayed allocation accounting works, i_blocks accounting is changed to only modify i_blocks when extents inserted or removed. The fillattr call is changed to include the delayed allocation byte count in the i_blocks result. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/btrfs_inode.h1
-rw-r--r--fs/btrfs/ctree.h9
-rw-r--r--fs/btrfs/file.c17
-rw-r--r--fs/btrfs/inode.c43
4 files changed, 50 insertions, 20 deletions
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index 9a0647dc5a0b..9b9db9cbc019 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -36,6 +36,7 @@ struct btrfs_inode {
36 * transid of the trans_handle that last modified this inode 36 * transid of the trans_handle that last modified this inode
37 */ 37 */
38 u64 last_trans; 38 u64 last_trans;
39 u64 delalloc_bytes;
39 u32 flags; 40 u32 flags;
40}; 41};
41static inline struct btrfs_inode *BTRFS_I(struct inode *inode) 42static inline struct btrfs_inode *BTRFS_I(struct inode *inode)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index dfb700efcd6b..52144b04f1af 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1161,6 +1161,15 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
1161 struct btrfs_root *root, struct btrfs_path *path, 1161 struct btrfs_root *root, struct btrfs_path *path,
1162 u64 isize); 1162 u64 isize);
1163/* inode.c */ 1163/* inode.c */
1164static inline void dec_i_blocks(struct inode *inode, u64 dec)
1165{
1166 dec = dec >> 9;
1167 if (dec <= inode->i_blocks)
1168 inode->i_blocks -= dec;
1169 else
1170 inode->i_blocks = 0;
1171}
1172
1164unsigned long btrfs_force_ra(struct address_space *mapping, 1173unsigned long btrfs_force_ra(struct address_space *mapping,
1165 struct file_ra_state *ra, struct file *file, 1174 struct file_ra_state *ra, struct file *file,
1166 pgoff_t offset, pgoff_t last_index); 1175 pgoff_t offset, pgoff_t last_index);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index bfa4149c053d..f89396082544 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -175,6 +175,7 @@ static int noinline insert_inline_extent(struct btrfs_trans_handle *trans,
175 leaf = path->nodes[0]; 175 leaf = path->nodes[0];
176 ei = btrfs_item_ptr(leaf, path->slots[0], 176 ei = btrfs_item_ptr(leaf, path->slots[0],
177 struct btrfs_file_extent_item); 177 struct btrfs_file_extent_item);
178 inode->i_blocks += (offset + size - found_end) >> 9;
178 } 179 }
179 if (found_end < offset) { 180 if (found_end < offset) {
180 ptr = btrfs_file_extent_inline_start(ei) + found_size; 181 ptr = btrfs_file_extent_inline_start(ei) + found_size;
@@ -184,6 +185,7 @@ static int noinline insert_inline_extent(struct btrfs_trans_handle *trans,
184insert: 185insert:
185 btrfs_release_path(root, path); 186 btrfs_release_path(root, path);
186 datasize = offset + size - key.offset; 187 datasize = offset + size - key.offset;
188 inode->i_blocks += datasize >> 9;
187 datasize = btrfs_file_extent_calc_inline_size(datasize); 189 datasize = btrfs_file_extent_calc_inline_size(datasize);
188 ret = btrfs_insert_empty_item(trans, root, path, &key, 190 ret = btrfs_insert_empty_item(trans, root, path, &key,
189 datasize); 191 datasize);
@@ -256,7 +258,6 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans,
256 goto out_unlock; 258 goto out_unlock;
257 } 259 }
258 btrfs_set_trans_block_group(trans, inode); 260 btrfs_set_trans_block_group(trans, inode);
259 inode->i_blocks += num_bytes >> 9;
260 hint_byte = 0; 261 hint_byte = 0;
261 262
262 if ((end_of_last_block & 4095) == 0) { 263 if ((end_of_last_block & 4095) == 0) {
@@ -410,7 +411,7 @@ int btrfs_check_file(struct btrfs_root *root, struct inode *inode)
410 if (found_key.type != BTRFS_EXTENT_DATA_KEY) 411 if (found_key.type != BTRFS_EXTENT_DATA_KEY)
411 goto out; 412 goto out;
412 413
413 if (found_key.offset != last_offset) { 414 if (found_key.offset < last_offset) {
414 WARN_ON(1); 415 WARN_ON(1);
415 btrfs_print_leaf(root, leaf); 416 btrfs_print_leaf(root, leaf);
416 printk("inode %lu found offset %Lu expected %Lu\n", 417 printk("inode %lu found offset %Lu expected %Lu\n",
@@ -435,7 +436,7 @@ int btrfs_check_file(struct btrfs_root *root, struct inode *inode)
435 last_offset = extent_end; 436 last_offset = extent_end;
436 path->slots[0]++; 437 path->slots[0]++;
437 } 438 }
438 if (last_offset < inode->i_size) { 439 if (0 && last_offset < inode->i_size) {
439 WARN_ON(1); 440 WARN_ON(1);
440 btrfs_print_leaf(root, leaf); 441 btrfs_print_leaf(root, leaf);
441 printk("inode %lu found offset %Lu size %Lu\n", inode->i_ino, 442 printk("inode %lu found offset %Lu size %Lu\n", inode->i_ino,
@@ -608,8 +609,7 @@ next_slot:
608 extent); 609 extent);
609 if (btrfs_file_extent_disk_bytenr(leaf, 610 if (btrfs_file_extent_disk_bytenr(leaf,
610 extent)) { 611 extent)) {
611 inode->i_blocks -= 612 dec_i_blocks(inode, old_num - new_num);
612 (old_num - new_num) >> 9;
613 } 613 }
614 btrfs_set_file_extent_num_bytes(leaf, extent, 614 btrfs_set_file_extent_num_bytes(leaf, extent,
615 new_num); 615 new_num);
@@ -620,6 +620,8 @@ next_slot:
620 u32 new_size; 620 u32 new_size;
621 new_size = btrfs_file_extent_calc_inline_size( 621 new_size = btrfs_file_extent_calc_inline_size(
622 inline_limit - key.offset); 622 inline_limit - key.offset);
623 dec_i_blocks(inode, (extent_end - key.offset) -
624 (inline_limit - key.offset));
623 btrfs_truncate_item(trans, root, path, 625 btrfs_truncate_item(trans, root, path,
624 new_size, 1); 626 new_size, 1);
625 } 627 }
@@ -653,7 +655,7 @@ next_slot:
653 btrfs_release_path(root, path); 655 btrfs_release_path(root, path);
654 extent = NULL; 656 extent = NULL;
655 if (found_extent && disk_bytenr != 0) { 657 if (found_extent && disk_bytenr != 0) {
656 inode->i_blocks -= extent_num_bytes >> 9; 658 dec_i_blocks(inode, extent_num_bytes);
657 ret = btrfs_free_extent(trans, root, 659 ret = btrfs_free_extent(trans, root,
658 disk_bytenr, 660 disk_bytenr,
659 disk_num_bytes, 661 disk_num_bytes,
@@ -674,6 +676,8 @@ next_slot:
674 u32 new_size; 676 u32 new_size;
675 new_size = btrfs_file_extent_calc_inline_size( 677 new_size = btrfs_file_extent_calc_inline_size(
676 extent_end - end); 678 extent_end - end);
679 dec_i_blocks(inode, (extent_end - key.offset) -
680 (extent_end - end));
677 btrfs_truncate_item(trans, root, path, new_size, 0); 681 btrfs_truncate_item(trans, root, path, new_size, 0);
678 } 682 }
679 /* create bookend, splitting the extent in two */ 683 /* create bookend, splitting the extent in two */
@@ -718,6 +722,7 @@ next_slot:
718 } 722 }
719out: 723out:
720 btrfs_free_path(path); 724 btrfs_free_path(path);
725 btrfs_check_file(root, inode);
721 return ret; 726 return ret;
722} 727}
723 728
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 44fc94fee2c4..913ab128eee1 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -134,6 +134,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end)
134 ret = btrfs_insert_file_extent(trans, root, inode->i_ino, 134 ret = btrfs_insert_file_extent(trans, root, inode->i_ino,
135 start, ins.objectid, ins.offset, 135 start, ins.objectid, ins.offset,
136 ins.offset); 136 ins.offset);
137 inode->i_blocks += ins.offset >> 9;
137 btrfs_check_file(root, inode); 138 btrfs_check_file(root, inode);
138 num_bytes -= cur_alloc_size; 139 num_bytes -= cur_alloc_size;
139 alloc_hint = ins.objectid + ins.offset; 140 alloc_hint = ins.objectid + ins.offset;
@@ -142,6 +143,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end)
142 btrfs_drop_extent_cache(inode, orig_start, 143 btrfs_drop_extent_cache(inode, orig_start,
143 orig_start + orig_num_bytes - 1); 144 orig_start + orig_num_bytes - 1);
144 btrfs_add_ordered_inode(inode); 145 btrfs_add_ordered_inode(inode);
146 btrfs_update_inode(trans, root, inode);
145out: 147out:
146 btrfs_end_transaction(trans, root); 148 btrfs_end_transaction(trans, root);
147 return ret; 149 return ret;
@@ -265,6 +267,7 @@ int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end,
265 if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) { 267 if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) {
266 struct btrfs_root *root = BTRFS_I(inode)->root; 268 struct btrfs_root *root = BTRFS_I(inode)->root;
267 spin_lock(&root->fs_info->delalloc_lock); 269 spin_lock(&root->fs_info->delalloc_lock);
270 BTRFS_I(inode)->delalloc_bytes += end - start + 1;
268 root->fs_info->delalloc_bytes += end - start + 1; 271 root->fs_info->delalloc_bytes += end - start + 1;
269 spin_unlock(&root->fs_info->delalloc_lock); 272 spin_unlock(&root->fs_info->delalloc_lock);
270 } 273 }
@@ -281,8 +284,10 @@ int btrfs_clear_bit_hook(struct inode *inode, u64 start, u64 end,
281 printk("warning: delalloc account %Lu %Lu\n", 284 printk("warning: delalloc account %Lu %Lu\n",
282 end - start + 1, root->fs_info->delalloc_bytes); 285 end - start + 1, root->fs_info->delalloc_bytes);
283 root->fs_info->delalloc_bytes = 0; 286 root->fs_info->delalloc_bytes = 0;
287 BTRFS_I(inode)->delalloc_bytes = 0;
284 } else { 288 } else {
285 root->fs_info->delalloc_bytes -= end - start + 1; 289 root->fs_info->delalloc_bytes -= end - start + 1;
290 BTRFS_I(inode)->delalloc_bytes -= end - start + 1;
286 } 291 }
287 spin_unlock(&root->fs_info->delalloc_lock); 292 spin_unlock(&root->fs_info->delalloc_lock);
288 } 293 }
@@ -833,32 +838,37 @@ search_again:
833 btrfs_set_file_extent_num_bytes(leaf, fi, 838 btrfs_set_file_extent_num_bytes(leaf, fi,
834 extent_num_bytes); 839 extent_num_bytes);
835 num_dec = (orig_num_bytes - 840 num_dec = (orig_num_bytes -
836 extent_num_bytes) >> 9; 841 extent_num_bytes);
837 if (extent_start != 0) { 842 if (extent_start != 0)
838 inode->i_blocks -= num_dec; 843 dec_i_blocks(inode, num_dec);
839 }
840 btrfs_mark_buffer_dirty(leaf); 844 btrfs_mark_buffer_dirty(leaf);
841 } else { 845 } else {
842 extent_num_bytes = 846 extent_num_bytes =
843 btrfs_file_extent_disk_num_bytes(leaf, 847 btrfs_file_extent_disk_num_bytes(leaf,
844 fi); 848 fi);
845 /* FIXME blocksize != 4096 */ 849 /* FIXME blocksize != 4096 */
846 num_dec = btrfs_file_extent_num_bytes(leaf, 850 num_dec = btrfs_file_extent_num_bytes(leaf, fi);
847 fi) >> 9;
848 if (extent_start != 0) { 851 if (extent_start != 0) {
849 found_extent = 1; 852 found_extent = 1;
850 inode->i_blocks -= num_dec; 853 dec_i_blocks(inode, num_dec);
851 } 854 }
852 root_gen = btrfs_header_generation(leaf); 855 root_gen = btrfs_header_generation(leaf);
853 root_owner = btrfs_header_owner(leaf); 856 root_owner = btrfs_header_owner(leaf);
854 } 857 }
855 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE && 858 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
856 !del_item) { 859 if (!del_item) {
857 u32 newsize = inode->i_size - found_key.offset; 860 u32 newsize = inode->i_size - found_key.offset;
858 newsize = btrfs_file_extent_calc_inline_size(newsize); 861 dec_i_blocks(inode, item_end + 1 -
859 ret = btrfs_truncate_item(trans, root, path, 862 found_key.offset - newsize);
860 newsize, 1); 863 newsize =
861 BUG_ON(ret); 864 btrfs_file_extent_calc_inline_size(newsize);
865 ret = btrfs_truncate_item(trans, root, path,
866 newsize, 1);
867 BUG_ON(ret);
868 } else {
869 dec_i_blocks(inode, item_end + 1 -
870 found_key.offset);
871 }
862 } 872 }
863delete: 873delete:
864 if (del_item) { 874 if (del_item) {
@@ -1222,6 +1232,7 @@ static int btrfs_init_locked_inode(struct inode *inode, void *p)
1222 struct btrfs_iget_args *args = p; 1232 struct btrfs_iget_args *args = p;
1223 inode->i_ino = args->ino; 1233 inode->i_ino = args->ino;
1224 BTRFS_I(inode)->root = args->root; 1234 BTRFS_I(inode)->root = args->root;
1235 BTRFS_I(inode)->delalloc_bytes = 0;
1225 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS); 1236 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
1226 extent_io_tree_init(&BTRFS_I(inode)->io_tree, 1237 extent_io_tree_init(&BTRFS_I(inode)->io_tree,
1227 inode->i_mapping, GFP_NOFS); 1238 inode->i_mapping, GFP_NOFS);
@@ -1528,6 +1539,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
1528 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS); 1539 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
1529 extent_io_tree_init(&BTRFS_I(inode)->io_tree, 1540 extent_io_tree_init(&BTRFS_I(inode)->io_tree,
1530 inode->i_mapping, GFP_NOFS); 1541 inode->i_mapping, GFP_NOFS);
1542 BTRFS_I(inode)->delalloc_bytes = 0;
1531 BTRFS_I(inode)->root = root; 1543 BTRFS_I(inode)->root = root;
1532 1544
1533 if (mode & S_IFDIR) 1545 if (mode & S_IFDIR)
@@ -1746,6 +1758,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
1746 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS); 1758 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
1747 extent_io_tree_init(&BTRFS_I(inode)->io_tree, 1759 extent_io_tree_init(&BTRFS_I(inode)->io_tree,
1748 inode->i_mapping, GFP_NOFS); 1760 inode->i_mapping, GFP_NOFS);
1761 BTRFS_I(inode)->delalloc_bytes = 0;
1749 BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; 1762 BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
1750 } 1763 }
1751 dir->i_sb->s_dirt = 1; 1764 dir->i_sb->s_dirt = 1;
@@ -2797,6 +2810,7 @@ static int btrfs_getattr(struct vfsmount *mnt,
2797 struct inode *inode = dentry->d_inode; 2810 struct inode *inode = dentry->d_inode;
2798 generic_fillattr(inode, stat); 2811 generic_fillattr(inode, stat);
2799 stat->blksize = PAGE_CACHE_SIZE; 2812 stat->blksize = PAGE_CACHE_SIZE;
2813 stat->blocks = inode->i_blocks + (BTRFS_I(inode)->delalloc_bytes >> 9);
2800 return 0; 2814 return 0;
2801} 2815}
2802 2816
@@ -2912,6 +2926,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
2912 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS); 2926 extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
2913 extent_io_tree_init(&BTRFS_I(inode)->io_tree, 2927 extent_io_tree_init(&BTRFS_I(inode)->io_tree,
2914 inode->i_mapping, GFP_NOFS); 2928 inode->i_mapping, GFP_NOFS);
2929 BTRFS_I(inode)->delalloc_bytes = 0;
2915 BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; 2930 BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
2916 } 2931 }
2917 dir->i_sb->s_dirt = 1; 2932 dir->i_sb->s_dirt = 1;