Commit a41ad394 authored by Josef Bacik's avatar Josef Bacik

Btrfs: convert to the new truncate sequence

->truncate() is going away, instead all of the work needs to be done in
->setattr().  So this converts us over to do this.  It's fairly straightforward,
just get rid of our .truncate inode operation and call btrfs_truncate() directly
from btrfs_setsize.  This works out better for us since truncate can technically
return ENOSPC, and before we had no way of letting anybody know.  Thanks,
Signed-off-by: default avatarJosef Bacik <josef@redhat.com>
parent dc89e982
...@@ -2537,7 +2537,7 @@ void btrfs_orphan_post_snapshot(struct btrfs_trans_handle *trans, ...@@ -2537,7 +2537,7 @@ void btrfs_orphan_post_snapshot(struct btrfs_trans_handle *trans,
struct btrfs_pending_snapshot *pending); struct btrfs_pending_snapshot *pending);
void btrfs_orphan_commit_root(struct btrfs_trans_handle *trans, void btrfs_orphan_commit_root(struct btrfs_trans_handle *trans,
struct btrfs_root *root); struct btrfs_root *root);
int btrfs_cont_expand(struct inode *inode, loff_t size); int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size);
int btrfs_invalidate_inodes(struct btrfs_root *root); int btrfs_invalidate_inodes(struct btrfs_root *root);
void btrfs_add_delayed_iput(struct inode *inode); void btrfs_add_delayed_iput(struct inode *inode);
void btrfs_run_delayed_iputs(struct btrfs_root *root); void btrfs_run_delayed_iputs(struct btrfs_root *root);
......
...@@ -817,7 +817,7 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, ...@@ -817,7 +817,7 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
last_pos = ((u64)index + num_pages) << PAGE_CACHE_SHIFT; last_pos = ((u64)index + num_pages) << PAGE_CACHE_SHIFT;
if (start_pos > inode->i_size) { if (start_pos > inode->i_size) {
err = btrfs_cont_expand(inode, start_pos); err = btrfs_cont_expand(inode, i_size_read(inode), start_pos);
if (err) if (err)
return err; return err;
} }
...@@ -1330,7 +1330,8 @@ static long btrfs_fallocate(struct file *file, int mode, ...@@ -1330,7 +1330,8 @@ static long btrfs_fallocate(struct file *file, int mode,
goto out; goto out;
if (alloc_start > inode->i_size) { if (alloc_start > inode->i_size) {
ret = btrfs_cont_expand(inode, alloc_start); ret = btrfs_cont_expand(inode, i_size_read(inode),
alloc_start);
if (ret) if (ret)
goto out; goto out;
} }
......
...@@ -84,7 +84,8 @@ static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = { ...@@ -84,7 +84,8 @@ static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = {
[S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK, [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK,
}; };
static void btrfs_truncate(struct inode *inode); static int btrfs_setsize(struct inode *inode, loff_t newsize);
static int btrfs_truncate(struct inode *inode);
static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end); static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end);
static noinline int cow_file_range(struct inode *inode, static noinline int cow_file_range(struct inode *inode,
struct page *locked_page, struct page *locked_page,
...@@ -2371,6 +2372,11 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) ...@@ -2371,6 +2372,11 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
/* if we have links, this was a truncate, lets do that */ /* if we have links, this was a truncate, lets do that */
if (inode->i_nlink) { if (inode->i_nlink) {
if (!S_ISREG(inode->i_mode)) {
WARN_ON(1);
iput(inode);
continue;
}
nr_truncate++; nr_truncate++;
btrfs_truncate(inode); btrfs_truncate(inode);
} else { } else {
...@@ -3538,7 +3544,7 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from) ...@@ -3538,7 +3544,7 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from)
return ret; return ret;
} }
int btrfs_cont_expand(struct inode *inode, loff_t size) int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size)
{ {
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
...@@ -3546,7 +3552,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t size) ...@@ -3546,7 +3552,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t size)
struct extent_map *em = NULL; struct extent_map *em = NULL;
struct extent_state *cached_state = NULL; struct extent_state *cached_state = NULL;
u64 mask = root->sectorsize - 1; u64 mask = root->sectorsize - 1;
u64 hole_start = (inode->i_size + mask) & ~mask; u64 hole_start = (oldsize + mask) & ~mask;
u64 block_end = (size + mask) & ~mask; u64 block_end = (size + mask) & ~mask;
u64 last_byte; u64 last_byte;
u64 cur_offset; u64 cur_offset;
...@@ -3617,27 +3623,17 @@ int btrfs_cont_expand(struct inode *inode, loff_t size) ...@@ -3617,27 +3623,17 @@ int btrfs_cont_expand(struct inode *inode, loff_t size)
return err; return err;
} }
static int btrfs_setattr_size(struct inode *inode, struct iattr *attr) static int btrfs_setsize(struct inode *inode, loff_t newsize)
{ {
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
loff_t oldsize = i_size_read(inode);
unsigned long nr; unsigned long nr;
int ret; int ret;
if (attr->ia_size == inode->i_size) if (newsize == oldsize)
return 0; return 0;
if (attr->ia_size > inode->i_size) {
unsigned long limit;
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
if (attr->ia_size > inode->i_sb->s_maxbytes)
return -EFBIG;
if (limit != RLIM_INFINITY && attr->ia_size > limit) {
send_sig(SIGXFSZ, current, 0);
return -EFBIG;
}
}
trans = btrfs_start_transaction(root, 5); trans = btrfs_start_transaction(root, 5);
if (IS_ERR(trans)) if (IS_ERR(trans))
return PTR_ERR(trans); return PTR_ERR(trans);
...@@ -3651,16 +3647,16 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr) ...@@ -3651,16 +3647,16 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr)
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
btrfs_btree_balance_dirty(root, nr); btrfs_btree_balance_dirty(root, nr);
if (attr->ia_size > inode->i_size) { if (newsize > oldsize) {
ret = btrfs_cont_expand(inode, attr->ia_size); i_size_write(inode, newsize);
btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL);
truncate_pagecache(inode, oldsize, newsize);
ret = btrfs_cont_expand(inode, oldsize, newsize);
if (ret) { if (ret) {
btrfs_truncate(inode); btrfs_setsize(inode, oldsize);
return ret; return ret;
} }
i_size_write(inode, attr->ia_size);
btrfs_ordered_update_i_size(inode, inode->i_size, NULL);
trans = btrfs_start_transaction(root, 0); trans = btrfs_start_transaction(root, 0);
BUG_ON(IS_ERR(trans)); BUG_ON(IS_ERR(trans));
btrfs_set_trans_block_group(trans, inode); btrfs_set_trans_block_group(trans, inode);
...@@ -3676,22 +3672,22 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr) ...@@ -3676,22 +3672,22 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr)
nr = trans->blocks_used; nr = trans->blocks_used;
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
btrfs_btree_balance_dirty(root, nr); btrfs_btree_balance_dirty(root, nr);
return 0; } else {
}
/* /*
* We're truncating a file that used to have good data down to * We're truncating a file that used to have good data down to
* zero. Make sure it gets into the ordered flush list so that * zero. Make sure it gets into the ordered flush list so that
* any new writes get down to disk quickly. * any new writes get down to disk quickly.
*/ */
if (attr->ia_size == 0) if (newsize == 0)
BTRFS_I(inode)->ordered_data_close = 1; BTRFS_I(inode)->ordered_data_close = 1;
/* we don't support swapfiles, so vmtruncate shouldn't fail */ /* we don't support swapfiles, so vmtruncate shouldn't fail */
ret = vmtruncate(inode, attr->ia_size); truncate_setsize(inode, newsize);
BUG_ON(ret); ret = btrfs_truncate(inode);
}
return 0; return ret;
} }
static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
...@@ -3708,7 +3704,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3708,7 +3704,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
return err; return err;
if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
err = btrfs_setattr_size(inode, attr); err = btrfs_setsize(inode, attr->ia_size);
if (err) if (err)
return err; return err;
} }
...@@ -6478,7 +6474,7 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -6478,7 +6474,7 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
return ret; return ret;
} }
static void btrfs_truncate(struct inode *inode) static int btrfs_truncate(struct inode *inode)
{ {
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
int ret; int ret;
...@@ -6486,14 +6482,9 @@ static void btrfs_truncate(struct inode *inode) ...@@ -6486,14 +6482,9 @@ static void btrfs_truncate(struct inode *inode)
unsigned long nr; unsigned long nr;
u64 mask = root->sectorsize - 1; u64 mask = root->sectorsize - 1;
if (!S_ISREG(inode->i_mode)) {
WARN_ON(1);
return;
}
ret = btrfs_truncate_page(inode->i_mapping, inode->i_size); ret = btrfs_truncate_page(inode->i_mapping, inode->i_size);
if (ret) if (ret)
return; return ret;
btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1); btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1);
btrfs_ordered_update_i_size(inode, inode->i_size, NULL); btrfs_ordered_update_i_size(inode, inode->i_size, NULL);
...@@ -6568,6 +6559,8 @@ static void btrfs_truncate(struct inode *inode) ...@@ -6568,6 +6559,8 @@ static void btrfs_truncate(struct inode *inode)
ret = btrfs_end_transaction_throttle(trans, root); ret = btrfs_end_transaction_throttle(trans, root);
BUG_ON(ret); BUG_ON(ret);
btrfs_btree_balance_dirty(root, nr); btrfs_btree_balance_dirty(root, nr);
return ret;
} }
/* /*
...@@ -7367,7 +7360,6 @@ static const struct address_space_operations btrfs_symlink_aops = { ...@@ -7367,7 +7360,6 @@ static const struct address_space_operations btrfs_symlink_aops = {
}; };
static const struct inode_operations btrfs_file_inode_operations = { static const struct inode_operations btrfs_file_inode_operations = {
.truncate = btrfs_truncate,
.getattr = btrfs_getattr, .getattr = btrfs_getattr,
.setattr = btrfs_setattr, .setattr = btrfs_setattr,
.setxattr = btrfs_setxattr, .setxattr = btrfs_setxattr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment