Btrfs: avoid ENOSPC errors in btrfs_dirty_inode
authorChris Mason <chris.mason@oracle.com>
Wed, 26 May 2010 15:02:00 +0000 (11:02 -0400)
committerChris Mason <chris.mason@oracle.com>
Wed, 26 May 2010 15:02:00 +0000 (11:02 -0400)
btrfs_dirty_inode tries to sneak in without much waiting or
space reservation, mostly for performance reasons.  This
usually works well but can cause problems when there are
many many writers.

When btrfs_update_inode fails with ENOSPC, we fallback
to a slower btrfs_start_transaction call that will reserve
some space.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/inode.c

index ca9d5501d3400efe9716d6722d9260e0be8ba441..5d62f21b2e4598a58dfa30fc69c209aeefed99cf 100644 (file)
@@ -4308,10 +4308,18 @@ void btrfs_dirty_inode(struct inode *inode)
        btrfs_set_trans_block_group(trans, inode);
 
        ret = btrfs_update_inode(trans, root, inode);
-       if (ret)
-               printk(KERN_ERR"btrfs: fail to dirty inode %lu error %d\n",
-                       inode->i_ino, ret);
+       if (ret && ret == -ENOSPC) {
+               /* whoops, lets try again with the full transaction */
+               btrfs_end_transaction(trans, root);
+               trans = btrfs_start_transaction(root, 1);
+               btrfs_set_trans_block_group(trans, inode);
 
+               ret = btrfs_update_inode(trans, root, inode);
+               if (ret) {
+                       printk(KERN_ERR"btrfs: fail to dirty inode %lu error %d\n",
+                               inode->i_ino, ret);
+               }
+       }
        btrfs_end_transaction(trans, root);
 }