aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-11-30 10:45:38 -0500
committerJosef Bacik <josef@redhat.com>2011-12-15 11:04:21 -0500
commit22c44fe65adacd20a174f3f54686509ee94ef7be (patch)
tree1d590b9e0d238970debd73a730c4e6553c2f7f1b /fs/btrfs/inode.c
parent0dc3b84a73267f47a75468f924f5d58a840e3152 (diff)
Btrfs: deal with enospc from dirtying inodes properly
Now that we're properly keeping track of delayed inode space we've been getting a lot of warnings out of btrfs_dirty_inode() when running xfstest 83. This is because a bunch of people call mark_inode_dirty, which is void so we can't return ENOSPC. This needs to be fixed in a few areas 1) file_update_time - this updates the mtime and such when writing to a file, which will call mark_inode_dirty. So copy file_update_time into btrfs so we can call btrfs_dirty_inode directly and return an error if we get one appropriately. 2) fix symlinks to use btrfs_setattr for ->setattr. For some reason we weren't setting ->setattr for symlinks, even though we should have been. This catches one of the cases where we were getting errors in mark_inode_dirty. 3) Fix btrfs_setattr and btrfs_setsize to call btrfs_dirty_inode directly instead of mark_inode_dirty. This lets us return errors properly for truncate and chown/anything related to setattr. 4) Add a new btrfs_fs_dirty_inode which will just call btrfs_dirty_inode and print an error if we have one. The only remaining user we can't control for this is touch_atime(), but we don't really want to keep people from walking down the tree if we don't have space to save the atime update, so just complain but don't worry about it. With this patch xfstests 83 complains a handful of times instead of hundreds of times. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c80
1 files changed, 61 insertions, 19 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index c5ccec23984..eec33b9c953 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -38,6 +38,7 @@
38#include <linux/falloc.h> 38#include <linux/falloc.h>
39#include <linux/slab.h> 39#include <linux/slab.h>
40#include <linux/ratelimit.h> 40#include <linux/ratelimit.h>
41#include <linux/mount.h>
41#include "compat.h" 42#include "compat.h"
42#include "ctree.h" 43#include "ctree.h"
43#include "disk-io.h" 44#include "disk-io.h"
@@ -3386,7 +3387,7 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize)
3386 return ret; 3387 return ret;
3387 } 3388 }
3388 3389
3389 mark_inode_dirty(inode); 3390 ret = btrfs_dirty_inode(inode);
3390 } else { 3391 } else {
3391 3392
3392 /* 3393 /*
@@ -3426,9 +3427,9 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
3426 3427
3427 if (attr->ia_valid) { 3428 if (attr->ia_valid) {
3428 setattr_copy(inode, attr); 3429 setattr_copy(inode, attr);
3429 mark_inode_dirty(inode); 3430 err = btrfs_dirty_inode(inode);
3430 3431
3431 if (attr->ia_valid & ATTR_MODE) 3432 if (!err && attr->ia_valid & ATTR_MODE)
3432 err = btrfs_acl_chmod(inode); 3433 err = btrfs_acl_chmod(inode);
3433 } 3434 }
3434 3435
@@ -4204,42 +4205,80 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc)
4204 * FIXME, needs more benchmarking...there are no reasons other than performance 4205 * FIXME, needs more benchmarking...there are no reasons other than performance
4205 * to keep or drop this code. 4206 * to keep or drop this code.
4206 */ 4207 */
4207void btrfs_dirty_inode(struct inode *inode, int flags) 4208int btrfs_dirty_inode(struct inode *inode)
4208{ 4209{
4209 struct btrfs_root *root = BTRFS_I(inode)->root; 4210 struct btrfs_root *root = BTRFS_I(inode)->root;
4210 struct btrfs_trans_handle *trans; 4211 struct btrfs_trans_handle *trans;
4211 int ret; 4212 int ret;
4212 4213
4213 if (BTRFS_I(inode)->dummy_inode) 4214 if (BTRFS_I(inode)->dummy_inode)
4214 return; 4215 return 0;
4215 4216
4216 trans = btrfs_join_transaction(root); 4217 trans = btrfs_join_transaction(root);
4217 BUG_ON(IS_ERR(trans)); 4218 if (IS_ERR(trans))
4219 return PTR_ERR(trans);
4218 4220
4219 ret = btrfs_update_inode(trans, root, inode); 4221 ret = btrfs_update_inode(trans, root, inode);
4220 if (ret && ret == -ENOSPC) { 4222 if (ret && ret == -ENOSPC) {
4221 /* whoops, lets try again with the full transaction */ 4223 /* whoops, lets try again with the full transaction */
4222 btrfs_end_transaction(trans, root); 4224 btrfs_end_transaction(trans, root);
4223 trans = btrfs_start_transaction(root, 1); 4225 trans = btrfs_start_transaction(root, 1);
4224 if (IS_ERR(trans)) { 4226 if (IS_ERR(trans))
4225 printk_ratelimited(KERN_ERR "btrfs: fail to " 4227 return PTR_ERR(trans);
4226 "dirty inode %llu error %ld\n",
4227 (unsigned long long)btrfs_ino(inode),
4228 PTR_ERR(trans));
4229 return;
4230 }
4231 4228
4232 ret = btrfs_update_inode(trans, root, inode); 4229 ret = btrfs_update_inode(trans, root, inode);
4233 if (ret) {
4234 printk_ratelimited(KERN_ERR "btrfs: fail to "
4235 "dirty inode %llu error %d\n",
4236 (unsigned long long)btrfs_ino(inode),
4237 ret);
4238 }
4239 } 4230 }
4240 btrfs_end_transaction(trans, root); 4231 btrfs_end_transaction(trans, root);
4241 if (BTRFS_I(inode)->delayed_node) 4232 if (BTRFS_I(inode)->delayed_node)
4242 btrfs_balance_delayed_items(root); 4233 btrfs_balance_delayed_items(root);
4234
4235 return ret;
4236}
4237
4238/*
4239 * This is a copy of file_update_time. We need this so we can return error on
4240 * ENOSPC for updating the inode in the case of file write and mmap writes.
4241 */
4242int btrfs_update_time(struct file *file)
4243{
4244 struct inode *inode = file->f_path.dentry->d_inode;
4245 struct timespec now;
4246 int ret;
4247 enum { S_MTIME = 1, S_CTIME = 2, S_VERSION = 4 } sync_it = 0;
4248
4249 /* First try to exhaust all avenues to not sync */
4250 if (IS_NOCMTIME(inode))
4251 return 0;
4252
4253 now = current_fs_time(inode->i_sb);
4254 if (!timespec_equal(&inode->i_mtime, &now))
4255 sync_it = S_MTIME;
4256
4257 if (!timespec_equal(&inode->i_ctime, &now))
4258 sync_it |= S_CTIME;
4259
4260 if (IS_I_VERSION(inode))
4261 sync_it |= S_VERSION;
4262
4263 if (!sync_it)
4264 return 0;
4265
4266 /* Finally allowed to write? Takes lock. */
4267 if (mnt_want_write_file(file))
4268 return 0;
4269
4270 /* Only change inode inside the lock region */
4271 if (sync_it & S_VERSION)
4272 inode_inc_iversion(inode);
4273 if (sync_it & S_CTIME)
4274 inode->i_ctime = now;
4275 if (sync_it & S_MTIME)
4276 inode->i_mtime = now;
4277 ret = btrfs_dirty_inode(inode);
4278 if (!ret)
4279 mark_inode_dirty_sync(inode);
4280 mnt_drop_write(file->f_path.mnt);
4281 return ret;
4243} 4282}
4244 4283
4245/* 4284/*
@@ -6304,6 +6343,8 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
6304 u64 page_end; 6343 u64 page_end;
6305 6344
6306 ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); 6345 ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE);
6346 if (!ret)
6347 ret = btrfs_update_time(vma->vm_file);
6307 if (ret) { 6348 if (ret) {
6308 if (ret == -ENOMEM) 6349 if (ret == -ENOMEM)
6309 ret = VM_FAULT_OOM; 6350 ret = VM_FAULT_OOM;
@@ -7353,6 +7394,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
7353 .follow_link = page_follow_link_light, 7394 .follow_link = page_follow_link_light,
7354 .put_link = page_put_link, 7395 .put_link = page_put_link,
7355 .getattr = btrfs_getattr, 7396 .getattr = btrfs_getattr,
7397 .setattr = btrfs_setattr,
7356 .permission = btrfs_permission, 7398 .permission = btrfs_permission,
7357 .setxattr = btrfs_setxattr, 7399 .setxattr = btrfs_setxattr,
7358 .getxattr = btrfs_getxattr, 7400 .getxattr = btrfs_getxattr,