aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-09-26 15:46:06 -0400
committerJosef Bacik <josef@redhat.com>2011-10-19 15:12:48 -0400
commit726c35fa0edf1d9b8a88b73255532e73089aedda (patch)
tree5b2c95df5854b5b5829ce5f88e3e807eb4bc8d4a /fs
parent1728366efa5ebf48bd2ed544afa8700cd07ba822 (diff)
Btrfs: use the global reserve as a backup for deleting inodes
Xfstests 83 really stresses our ENOSPC since it uses a 100mb fs which ends up with the mixed block group stuff. Because of this we can run into a situation where we don't have enough space to delete inodes, or even worse we can't free the inodes when we next mount the fs which causes the orphan code to lose its mind. So if we fail to make our reservation, steal from the global reserve. The global reserve will end up taking up the entire rest of the free space on the fs in this worst case so there really is no other option. With this patch test 83 doesn't freak out. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/inode.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 8005be17625..96fc9e34221 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3526,7 +3526,7 @@ void btrfs_evict_inode(struct inode *inode)
{
struct btrfs_trans_handle *trans;
struct btrfs_root *root = BTRFS_I(inode)->root;
- struct btrfs_block_rsv *rsv;
+ struct btrfs_block_rsv *rsv, *global_rsv;
u64 min_size = btrfs_calc_trunc_metadata_size(root, 1);
unsigned long nr;
int ret;
@@ -3561,6 +3561,7 @@ void btrfs_evict_inode(struct inode *inode)
goto no_delete;
}
rsv->size = min_size;
+ global_rsv = &root->fs_info->global_block_rsv;
btrfs_i_size_write(inode, 0);
@@ -3577,6 +3578,15 @@ void btrfs_evict_inode(struct inode *inode)
*/
while (1) {
ret = btrfs_block_rsv_check(root, rsv, min_size, 0, 1);
+
+ /*
+ * Try and steal from the global reserve since we will
+ * likely not use this space anyway, we want to try as
+ * hard as possible to get this to work.
+ */
+ if (ret)
+ ret = btrfs_block_rsv_migrate(global_rsv, rsv, min_size);
+
if (ret) {
printk(KERN_WARNING "Could not get space for a "
"delete, will truncate on mount %d\n", ret);