mirror of
https://github.com/versity/scoutfs.git
synced 2026-09-19 14:34:16 +00:00
Return ENOSPC as space gets low
Returning ENOSPC is challenging because we have clients working on allocators which are a fraction of the whole and we use COW transactions so we need to be able to allocate to free. This adds support for returning ENOSPC to client posix allocators as free space gets low. For metadata, we reserve a number of free blocks for making progress with client and server transactions which can free space. The server sets the low flag in a client's allocator if we start to dip into reserved blocks. In the client we add an argument to entering a transaction which indicates if we're allocating new space (as opposed to just modifying existing data or freeing). When an allocating transaction runs low and the server low flag is set then we return ENOSPC. Adding an argument to transaciton holders and having it return ENOSPC gave us the opportunity to clean it up and make it a little clearer. More work is done outside the wait_event function and it now specifically waits for a transaction to cycle when it forces a commit rather than spinning until the transaction worker acquires the lock and stops it. For data the same pattern applies except there are no reserved blocks and we don't COW data so it's a simple case of returning the hard ENOSPC when the data allocator flag is set. The server needs to consider the reserved count when refilling the client's meta_avail allocator and when swapping between the two meta_avail and meta_free allocators. We add the reserved metadata block count to statfs_more so that df can subtract it from the free meta blocks and make it clear when enospc is going to be returned for metadata allocations. We increase the minimum device size in mkfs so that small testing devices provide sufficient reserved blocks. And finally we add a little test that makes sure we can fill both metadata and data to ENOSPC and then recover by deleting what we filled. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -86,6 +86,11 @@ static int do_df(struct df_args *args)
|
||||
data_free += ade[i].blocks;
|
||||
}
|
||||
|
||||
if (meta_free >= sfm.reserved_meta_blocks)
|
||||
meta_free -= sfm.reserved_meta_blocks;
|
||||
else
|
||||
meta_free = 0;
|
||||
|
||||
snprintf(cells[0][0], CHARS, "Type");
|
||||
snprintf(cells[0][1], CHARS, "Size");
|
||||
snprintf(cells[0][2], CHARS, "Total");
|
||||
|
||||
+4
-2
@@ -215,12 +215,14 @@ static int do_mkfs(struct mkfs_args *args)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = device_size(args->meta_device, meta_fd, 2ULL * (1024 * 1024 * 1024),
|
||||
/* minumum meta device size to make reserved blocks reasonably large */
|
||||
ret = device_size(args->meta_device, meta_fd, 64ULL * (1024 * 1024 * 1024),
|
||||
args->max_meta_size, "meta", &meta_size);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = device_size(args->data_device, data_fd, 8ULL * (1024 * 1024 * 1024),
|
||||
/* .. then arbitrarily the same minimum data device size */
|
||||
ret = device_size(args->data_device, data_fd, 64ULL * (1024 * 1024 * 1024),
|
||||
args->max_data_size, "data", &data_size);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
+4
-4
@@ -245,15 +245,15 @@ static int print_logs_item(struct scoutfs_key *key, void *val,
|
||||
le64_to_cpu((p)->blkno), le64_to_cpu((p)->seq)
|
||||
|
||||
#define AL_HEAD_F \
|
||||
AL_REF_F" total_nr %llu first_nr %u"
|
||||
AL_REF_F" total_nr %llu first_nr %u flags 0x%x"
|
||||
#define AL_HEAD_A(p) \
|
||||
AL_REF_A(&(p)->ref), le64_to_cpu((p)->total_nr),\
|
||||
le32_to_cpu((p)->first_nr)
|
||||
le32_to_cpu((p)->first_nr), le32_to_cpu((p)->flags)
|
||||
|
||||
#define ALCROOT_F \
|
||||
BTROOT_F" total_len %llu"
|
||||
BTROOT_F" total_len %llu flags 0x%x"
|
||||
#define ALCROOT_A(ar) \
|
||||
BTROOT_A(&(ar)->root), le64_to_cpu((ar)->total_len)
|
||||
BTROOT_A(&(ar)->root), le64_to_cpu((ar)->total_len), le32_to_cpu((ar)->flags)
|
||||
|
||||
#define SRE_FMT "%016llx.%llu.%llu"
|
||||
#define SRE_A(sre) \
|
||||
|
||||
Reference in New Issue
Block a user