aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-05-29 14:54:47 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-06-14 11:30:06 -0400
commitd52be818e618bd252601b340ca6df760d77410e8 (patch)
tree7d1fc410b90a96487cb3a949891fe2f6a5e96f87 /fs/btrfs/extent-tree.c
parentc6adc9cc082e3cffda153999c9b9f8a8baaaaf45 (diff)
Btrfs: simplify unlink reservations
Dave pointed out a problem where if you filled up a file system as much as possible you couldn't remove any files. The whole unlink reservation thing is convoluted because it tries to guess if it's going to add space to unlink something or not, and has all these odd uncommented cases where it simply does not try. So to fix this I've added a way to conditionally steal from the global reserve if we can't make our normal reservation. If we have more than half the space in the global reserve free we will go ahead and steal from the global reserve. With this patch Dave's reproducer now works and I can rm all the files on the file system. Thanks, Reported-by: David Sterba <dsterba@suse.cz> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 4ec8305fe078..e14f8bd4b310 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4297,6 +4297,31 @@ static void block_rsv_add_bytes(struct btrfs_block_rsv *block_rsv,
4297 spin_unlock(&block_rsv->lock); 4297 spin_unlock(&block_rsv->lock);
4298} 4298}
4299 4299
4300int btrfs_cond_migrate_bytes(struct btrfs_fs_info *fs_info,
4301 struct btrfs_block_rsv *dest, u64 num_bytes,
4302 int min_factor)
4303{
4304 struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
4305 u64 min_bytes;
4306
4307 if (global_rsv->space_info != dest->space_info)
4308 return -ENOSPC;
4309
4310 spin_lock(&global_rsv->lock);
4311 min_bytes = div_factor(global_rsv->size, min_factor);
4312 if (global_rsv->reserved < min_bytes + num_bytes) {
4313 spin_unlock(&global_rsv->lock);
4314 return -ENOSPC;
4315 }
4316 global_rsv->reserved -= num_bytes;
4317 if (global_rsv->reserved < global_rsv->size)
4318 global_rsv->full = 0;
4319 spin_unlock(&global_rsv->lock);
4320
4321 block_rsv_add_bytes(dest, num_bytes, 1);
4322 return 0;
4323}
4324
4300static void block_rsv_release_bytes(struct btrfs_fs_info *fs_info, 4325static void block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
4301 struct btrfs_block_rsv *block_rsv, 4326 struct btrfs_block_rsv *block_rsv,
4302 struct btrfs_block_rsv *dest, u64 num_bytes) 4327 struct btrfs_block_rsv *dest, u64 num_bytes)