* Boston, MA 021110-1307, USA.
*/
+#include <linux/bio.h>
#include <linux/buffer_head.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
#include "btrfs_inode.h"
#include "ioctl.h"
#include "print-tree.h"
+#include "volumes.h"
struct btrfs_iget_args {
u64 ino;
ret = btrfs_insert_file_extent(trans, root, inode->i_ino,
start, ins.objectid, ins.offset,
ins.offset);
+ inode->i_blocks += ins.offset >> 9;
btrfs_check_file(root, inode);
num_bytes -= cur_alloc_size;
alloc_hint = ins.objectid + ins.offset;
btrfs_drop_extent_cache(inode, orig_start,
orig_start + orig_num_bytes - 1);
btrfs_add_ordered_inode(inode);
+ btrfs_update_inode(trans, root, inode);
out:
btrfs_end_transaction(trans, root);
return ret;
if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) {
struct btrfs_root *root = BTRFS_I(inode)->root;
spin_lock(&root->fs_info->delalloc_lock);
+ BTRFS_I(inode)->delalloc_bytes += end - start + 1;
root->fs_info->delalloc_bytes += end - start + 1;
spin_unlock(&root->fs_info->delalloc_lock);
}
printk("warning: delalloc account %Lu %Lu\n",
end - start + 1, root->fs_info->delalloc_bytes);
root->fs_info->delalloc_bytes = 0;
+ BTRFS_I(inode)->delalloc_bytes = 0;
} else {
root->fs_info->delalloc_bytes -= end - start + 1;
+ BTRFS_I(inode)->delalloc_bytes -= end - start + 1;
}
spin_unlock(&root->fs_info->delalloc_lock);
}
return 0;
}
-int btrfs_writepage_io_hook(struct page *page, u64 start, u64 end)
+int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
+ size_t size, struct bio *bio)
+{
+ struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;
+ struct btrfs_mapping_tree *map_tree;
+ u64 logical = bio->bi_sector << 9;
+ u64 length = 0;
+ u64 map_length;
+ struct bio_vec *bvec;
+ int i;
+ int ret;
+
+ bio_for_each_segment(bvec, bio, i) {
+ length += bvec->bv_len;
+ }
+ map_tree = &root->fs_info->mapping_tree;
+ map_length = length;
+ ret = btrfs_map_block(map_tree, READ, logical,
+ &map_length, NULL);
+
+ if (map_length < length + size) {
+ return 1;
+ }
+ return 0;
+}
+
+int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio)
{
- struct inode *inode = page->mapping->host;
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_trans_handle *trans;
- char *kaddr;
int ret = 0;
- u64 page_start = (u64)page->index << PAGE_CACHE_SHIFT;
- size_t offset = start - page_start;
+
+ if (rw != WRITE) {
+ goto mapit;
+ }
+
if (btrfs_test_opt(root, NODATASUM) ||
- btrfs_test_flag(inode, NODATASUM))
- return 0;
+ btrfs_test_flag(inode, NODATASUM)) {
+ goto mapit;
+ }
+
mutex_lock(&root->fs_info->fs_mutex);
trans = btrfs_start_transaction(root, 1);
btrfs_set_trans_block_group(trans, inode);
- kaddr = kmap(page);
- btrfs_csum_file_block(trans, root, inode, inode->i_ino,
- start, kaddr + offset, end - start + 1);
- kunmap(page);
+ btrfs_csum_file_blocks(trans, root, inode, bio);
ret = btrfs_end_transaction(trans, root);
BUG_ON(ret);
mutex_unlock(&root->fs_info->fs_mutex);
- return ret;
+mapit:
+ return btrfs_map_bio(root, rw, bio);
}
int btrfs_readpage_io_hook(struct page *page, u64 start, u64 end)
if (btrfs_test_opt(root, NODATASUM) ||
btrfs_test_flag(inode, NODATASUM))
return 0;
-
- if (state->start == start) {
+ if (state && state->start == start) {
private = state->private;
ret = 0;
} else {
struct btrfs_path *path;
struct extent_buffer *leaf;
struct btrfs_inode_item *inode_item;
- struct btrfs_inode_timespec *tspec;
+ struct btrfs_timespec *tspec;
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_key location;
u64 alloc_group_block;
BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item);
if (!BTRFS_I(inode)->block_group) {
BTRFS_I(inode)->block_group = btrfs_find_block_group(root,
- NULL, 0, 0, 0);
+ NULL, 0,
+ BTRFS_BLOCK_GROUP_METADATA, 0);
}
btrfs_free_path(path);
inode_item = NULL;
switch (inode->i_mode & S_IFMT) {
case S_IFREG:
inode->i_mapping->a_ops = &btrfs_aops;
+ inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
inode->i_fop = &btrfs_file_operations;
inode->i_op = &btrfs_file_inode_operations;
case S_IFLNK:
inode->i_op = &btrfs_symlink_inode_operations;
inode->i_mapping->a_ops = &btrfs_symlink_aops;
+ inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
break;
default:
init_special_inode(inode, inode->i_mode, rdev);
btrfs_set_file_extent_num_bytes(leaf, fi,
extent_num_bytes);
num_dec = (orig_num_bytes -
- extent_num_bytes) >> 9;
- if (extent_start != 0) {
- inode->i_blocks -= num_dec;
- }
+ extent_num_bytes);
+ if (extent_start != 0)
+ dec_i_blocks(inode, num_dec);
btrfs_mark_buffer_dirty(leaf);
} else {
extent_num_bytes =
btrfs_file_extent_disk_num_bytes(leaf,
fi);
/* FIXME blocksize != 4096 */
- num_dec = btrfs_file_extent_num_bytes(leaf,
- fi) >> 9;
+ num_dec = btrfs_file_extent_num_bytes(leaf, fi);
if (extent_start != 0) {
found_extent = 1;
- inode->i_blocks -= num_dec;
+ dec_i_blocks(inode, num_dec);
}
root_gen = btrfs_header_generation(leaf);
root_owner = btrfs_header_owner(leaf);
}
- } else if (extent_type == BTRFS_FILE_EXTENT_INLINE &&
- !del_item) {
- u32 newsize = inode->i_size - found_key.offset;
- newsize = btrfs_file_extent_calc_inline_size(newsize);
- ret = btrfs_truncate_item(trans, root, path,
- newsize, 1);
- BUG_ON(ret);
+ } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
+ if (!del_item) {
+ u32 newsize = inode->i_size - found_key.offset;
+ dec_i_blocks(inode, item_end + 1 -
+ found_key.offset - newsize);
+ newsize =
+ btrfs_file_extent_calc_inline_size(newsize);
+ ret = btrfs_truncate_item(trans, root, path,
+ newsize, 1);
+ BUG_ON(ret);
+ } else {
+ dec_i_blocks(inode, item_end + 1 -
+ found_key.offset);
+ }
}
delete:
if (del_item) {
struct btrfs_iget_args *args = p;
inode->i_ino = args->ino;
BTRFS_I(inode)->root = args->root;
+ BTRFS_I(inode)->delalloc_bytes = 0;
extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
extent_io_tree_init(&BTRFS_I(inode)->io_tree,
inode->i_mapping, GFP_NOFS);
di = (struct btrfs_dir_item *)((char *)di + di_len);
}
}
- filp->f_pos = INT_LIMIT(typeof(filp->f_pos));
+ if (key_type == BTRFS_DIR_INDEX_KEY)
+ filp->f_pos = INT_LIMIT(typeof(filp->f_pos));
+ else
+ filp->f_pos++;
nopos:
ret = 0;
err:
{
struct inode *inode;
struct btrfs_inode_item *inode_item;
+ struct btrfs_block_group_cache *new_inode_group;
struct btrfs_key *location;
struct btrfs_path *path;
struct btrfs_inode_ref *ref;
extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
extent_io_tree_init(&BTRFS_I(inode)->io_tree,
inode->i_mapping, GFP_NOFS);
+ BTRFS_I(inode)->delalloc_bytes = 0;
BTRFS_I(inode)->root = root;
if (mode & S_IFDIR)
owner = 0;
else
owner = 1;
- group = btrfs_find_block_group(root, group, 0, 0, owner);
- BTRFS_I(inode)->block_group = group;
+ new_inode_group = btrfs_find_block_group(root, group, 0,
+ BTRFS_BLOCK_GROUP_METADATA, owner);
+ if (!new_inode_group) {
+ printk("find_block group failed\n");
+ new_inode_group = group;
+ }
+ BTRFS_I(inode)->block_group = new_inode_group;
BTRFS_I(inode)->flags = 0;
key[0].objectid = objectid;
drop_inode = 1;
else {
inode->i_mapping->a_ops = &btrfs_aops;
+ inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
inode->i_fop = &btrfs_file_operations;
inode->i_op = &btrfs_file_inode_operations;
extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
extent_io_tree_init(&BTRFS_I(inode)->io_tree,
inode->i_mapping, GFP_NOFS);
+ BTRFS_I(inode)->delalloc_bytes = 0;
BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
}
dir->i_sb->s_dirt = 1;
struct inode *inode = dentry->d_inode;
generic_fillattr(inode, stat);
stat->blksize = PAGE_CACHE_SIZE;
+ stat->blocks = inode->i_blocks + (BTRFS_I(inode)->delalloc_bytes >> 9);
return 0;
}
drop_inode = 1;
else {
inode->i_mapping->a_ops = &btrfs_aops;
+ inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
inode->i_fop = &btrfs_file_operations;
inode->i_op = &btrfs_file_inode_operations;
extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
extent_io_tree_init(&BTRFS_I(inode)->io_tree,
inode->i_mapping, GFP_NOFS);
+ BTRFS_I(inode)->delalloc_bytes = 0;
BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
}
dir->i_sb->s_dirt = 1;
inode->i_op = &btrfs_symlink_inode_operations;
inode->i_mapping->a_ops = &btrfs_symlink_aops;
+ inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
inode->i_size = name_len - 1;
err = btrfs_update_inode(trans, root, inode);
if (err)
static struct extent_io_ops btrfs_extent_io_ops = {
.fill_delalloc = run_delalloc_range,
- .writepage_io_hook = btrfs_writepage_io_hook,
+ .submit_bio_hook = btrfs_submit_bio_hook,
+ .merge_bio_hook = btrfs_merge_bio_hook,
.readpage_io_hook = btrfs_readpage_io_hook,
.readpage_end_io_hook = btrfs_readpage_end_io_hook,
.set_bit_hook = btrfs_set_bit_hook,