|
@@ -34,23 +34,24 @@
|
|
#include "locking.h"
|
|
#include "locking.h"
|
|
#include "free-space-cache.h"
|
|
#include "free-space-cache.h"
|
|
|
|
|
|
-/* control flags for do_chunk_alloc's force field
|
|
|
|
|
|
+/*
|
|
|
|
+ * control flags for do_chunk_alloc's force field
|
|
* CHUNK_ALLOC_NO_FORCE means to only allocate a chunk
|
|
* CHUNK_ALLOC_NO_FORCE means to only allocate a chunk
|
|
* if we really need one.
|
|
* if we really need one.
|
|
*
|
|
*
|
|
- * CHUNK_ALLOC_FORCE means it must try to allocate one
|
|
|
|
- *
|
|
|
|
* CHUNK_ALLOC_LIMITED means to only try and allocate one
|
|
* CHUNK_ALLOC_LIMITED means to only try and allocate one
|
|
* if we have very few chunks already allocated. This is
|
|
* if we have very few chunks already allocated. This is
|
|
* used as part of the clustering code to help make sure
|
|
* used as part of the clustering code to help make sure
|
|
* we have a good pool of storage to cluster in, without
|
|
* we have a good pool of storage to cluster in, without
|
|
* filling the FS with empty chunks
|
|
* filling the FS with empty chunks
|
|
*
|
|
*
|
|
|
|
+ * CHUNK_ALLOC_FORCE means it must try to allocate one
|
|
|
|
+ *
|
|
*/
|
|
*/
|
|
enum {
|
|
enum {
|
|
CHUNK_ALLOC_NO_FORCE = 0,
|
|
CHUNK_ALLOC_NO_FORCE = 0,
|
|
- CHUNK_ALLOC_FORCE = 1,
|
|
|
|
- CHUNK_ALLOC_LIMITED = 2,
|
|
|
|
|
|
+ CHUNK_ALLOC_LIMITED = 1,
|
|
|
|
+ CHUNK_ALLOC_FORCE = 2,
|
|
};
|
|
};
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -3414,7 +3415,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
|
|
|
|
|
|
again:
|
|
again:
|
|
spin_lock(&space_info->lock);
|
|
spin_lock(&space_info->lock);
|
|
- if (space_info->force_alloc)
|
|
|
|
|
|
+ if (force < space_info->force_alloc)
|
|
force = space_info->force_alloc;
|
|
force = space_info->force_alloc;
|
|
if (space_info->full) {
|
|
if (space_info->full) {
|
|
spin_unlock(&space_info->lock);
|
|
spin_unlock(&space_info->lock);
|
|
@@ -5794,6 +5795,7 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
|
|
u64 search_end, struct btrfs_key *ins,
|
|
u64 search_end, struct btrfs_key *ins,
|
|
u64 data)
|
|
u64 data)
|
|
{
|
|
{
|
|
|
|
+ bool final_tried = false;
|
|
int ret;
|
|
int ret;
|
|
u64 search_start = 0;
|
|
u64 search_start = 0;
|
|
|
|
|
|
@@ -5813,22 +5815,25 @@ again:
|
|
search_start, search_end, hint_byte,
|
|
search_start, search_end, hint_byte,
|
|
ins, data);
|
|
ins, data);
|
|
|
|
|
|
- if (ret == -ENOSPC && num_bytes > min_alloc_size) {
|
|
|
|
- num_bytes = num_bytes >> 1;
|
|
|
|
- num_bytes = num_bytes & ~(root->sectorsize - 1);
|
|
|
|
- num_bytes = max(num_bytes, min_alloc_size);
|
|
|
|
- do_chunk_alloc(trans, root->fs_info->extent_root,
|
|
|
|
- num_bytes, data, CHUNK_ALLOC_FORCE);
|
|
|
|
- goto again;
|
|
|
|
- }
|
|
|
|
- if (ret == -ENOSPC && btrfs_test_opt(root, ENOSPC_DEBUG)) {
|
|
|
|
- struct btrfs_space_info *sinfo;
|
|
|
|
-
|
|
|
|
- sinfo = __find_space_info(root->fs_info, data);
|
|
|
|
- printk(KERN_ERR "btrfs allocation failed flags %llu, "
|
|
|
|
- "wanted %llu\n", (unsigned long long)data,
|
|
|
|
- (unsigned long long)num_bytes);
|
|
|
|
- dump_space_info(sinfo, num_bytes, 1);
|
|
|
|
|
|
+ if (ret == -ENOSPC) {
|
|
|
|
+ if (!final_tried) {
|
|
|
|
+ num_bytes = num_bytes >> 1;
|
|
|
|
+ num_bytes = num_bytes & ~(root->sectorsize - 1);
|
|
|
|
+ num_bytes = max(num_bytes, min_alloc_size);
|
|
|
|
+ do_chunk_alloc(trans, root->fs_info->extent_root,
|
|
|
|
+ num_bytes, data, CHUNK_ALLOC_FORCE);
|
|
|
|
+ if (num_bytes == min_alloc_size)
|
|
|
|
+ final_tried = true;
|
|
|
|
+ goto again;
|
|
|
|
+ } else if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
|
|
|
|
+ struct btrfs_space_info *sinfo;
|
|
|
|
+
|
|
|
|
+ sinfo = __find_space_info(root->fs_info, data);
|
|
|
|
+ printk(KERN_ERR "btrfs allocation failed flags %llu, "
|
|
|
|
+ "wanted %llu\n", (unsigned long long)data,
|
|
|
|
+ (unsigned long long)num_bytes);
|
|
|
|
+ dump_space_info(sinfo, num_bytes, 1);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
trace_btrfs_reserved_extent_alloc(root, ins->objectid, ins->offset);
|
|
trace_btrfs_reserved_extent_alloc(root, ins->objectid, ins->offset);
|