mirror of
https://github.com/versity/scoutfs.git
synced 2026-07-29 11:33:19 +00:00
scoutfs: add btree item extent allocator
Add an allocator which uses btree items to store extents. Both the client and server will use this for btree blocks, the client will use it for srch blocks and data extents, and the server will move extents between the core fs allocator btree roots and the clients' roots. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -10,6 +10,7 @@ CFLAGS_scoutfs_trace.o = -I$(src) # define_trace.h double include
|
||||
|
||||
scoutfs-y += \
|
||||
avl.o \
|
||||
alloc.o \
|
||||
block.o \
|
||||
btree.o \
|
||||
client.o \
|
||||
|
||||
+1112
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,124 @@
|
||||
#ifndef _SCOUTFS_ALLOC_H_
|
||||
#define _SCOUTFS_ALLOC_H_
|
||||
|
||||
#include "ext.h"
|
||||
|
||||
/*
|
||||
* These are implementation-specific metrics, they don't need to be
|
||||
* consistent across implementations. They should probably be run-time
|
||||
* knobs.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The largest extent that we'll try to allocate with fallocate. We're
|
||||
* trying not to completely consume a transactions data allocation all
|
||||
* at once. This is only allocation granularity, repeated allocations
|
||||
* can produce large contiguous extents.
|
||||
*/
|
||||
#define SCOUTFS_FALLOCATE_ALLOC_LIMIT \
|
||||
(128ULL * 1024 * 1024 >> SCOUTFS_BLOCK_SM_SHIFT)
|
||||
|
||||
/*
|
||||
* The largest aligned region that we'll try to allocate at the end of
|
||||
* the file as it's extended. This is also limited to the current file
|
||||
* size so we can only waste at most twice the total file size when
|
||||
* files are less than this. We try to keep this around the point of
|
||||
* diminishing returns in streaming performance of common data devices
|
||||
* to limit waste.
|
||||
*/
|
||||
#define SCOUTFS_DATA_EXTEND_PREALLOC_LIMIT \
|
||||
(8ULL * 1024 * 1024 >> SCOUTFS_BLOCK_SM_SHIFT)
|
||||
|
||||
/*
|
||||
* Small data allocations are satisfied by cached extents stored in
|
||||
* the run-time alloc struct to minimize item operations for small
|
||||
* block allocations. Large allocations come directly from btree
|
||||
* extent items, and this defines the threshold beetwen them.
|
||||
*/
|
||||
#define SCOUTFS_ALLOC_DATA_LG_THRESH \
|
||||
(8ULL * 1024 * 1024 >> SCOUTFS_BLOCK_SM_SHIFT)
|
||||
|
||||
/*
|
||||
* Fill client alloc roots to the target when they fall below the lo
|
||||
* threshold.
|
||||
*/
|
||||
#define SCOUTFS_SERVER_META_FILL_TARGET \
|
||||
(256ULL * 1024 * 1024 >> SCOUTFS_BLOCK_LG_SHIFT)
|
||||
#define SCOUTFS_SERVER_META_FILL_LO \
|
||||
(64ULL * 1024 * 1024 >> SCOUTFS_BLOCK_LG_SHIFT)
|
||||
#define SCOUTFS_SERVER_DATA_FILL_TARGET \
|
||||
(4ULL * 1024 * 1024 * 1024 >> SCOUTFS_BLOCK_SM_SHIFT)
|
||||
#define SCOUTFS_SERVER_DATA_FILL_LO \
|
||||
(1ULL * 1024 * 1024 * 1024 >> SCOUTFS_BLOCK_SM_SHIFT)
|
||||
|
||||
/*
|
||||
* Each of the server meta_alloc roots will try to keep a minimum amount
|
||||
* of free blocks. The server will use the next root once its current
|
||||
* root gets this low. It must have room for all the largest allocation
|
||||
* attempted in a transaction on the server.
|
||||
*/
|
||||
#define SCOUTFS_SERVER_META_ALLOC_MIN \
|
||||
(SCOUTFS_SERVER_META_FILL_TARGET * 2)
|
||||
|
||||
/*
|
||||
* A run-time use of a pair of persistent avail/freed roots as a
|
||||
* metadata allocator. It has the machinery needed to lock and avoid
|
||||
* recursion when dirtying the list blocks that are used during the
|
||||
* transaction.
|
||||
*/
|
||||
struct scoutfs_alloc {
|
||||
spinlock_t lock;
|
||||
struct mutex mutex;
|
||||
struct scoutfs_block *dirty_avail_bl;
|
||||
struct scoutfs_block *dirty_freed_bl;
|
||||
struct scoutfs_alloc_list_head avail;
|
||||
struct scoutfs_alloc_list_head freed;
|
||||
};
|
||||
|
||||
void scoutfs_alloc_init(struct scoutfs_alloc *alloc,
|
||||
struct scoutfs_alloc_list_head *avail,
|
||||
struct scoutfs_alloc_list_head *freed);
|
||||
int scoutfs_alloc_prepare_commit(struct super_block *sb,
|
||||
struct scoutfs_alloc *alloc,
|
||||
struct scoutfs_block_writer *wri);
|
||||
|
||||
int scoutfs_alloc_meta(struct super_block *sb, struct scoutfs_alloc *alloc,
|
||||
struct scoutfs_block_writer *wri, u64 *blkno);
|
||||
int scoutfs_free_meta(struct super_block *sb, struct scoutfs_alloc *alloc,
|
||||
struct scoutfs_block_writer *wri, u64 blkno);
|
||||
|
||||
int scoutfs_alloc_data(struct super_block *sb, struct scoutfs_alloc *alloc,
|
||||
struct scoutfs_block_writer *wri,
|
||||
struct scoutfs_alloc_root *root,
|
||||
struct scoutfs_extent *cached, u64 count,
|
||||
u64 *blkno_ret, u64 *count_ret);
|
||||
int scoutfs_free_data(struct super_block *sb, struct scoutfs_alloc *alloc,
|
||||
struct scoutfs_block_writer *wri,
|
||||
struct scoutfs_alloc_root *root, u64 blkno, u64 count);
|
||||
|
||||
int scoutfs_alloc_move(struct super_block *sb, struct scoutfs_alloc *alloc,
|
||||
struct scoutfs_block_writer *wri,
|
||||
struct scoutfs_alloc_root *dst,
|
||||
struct scoutfs_alloc_root *src, u64 total);
|
||||
|
||||
int scoutfs_alloc_fill_list(struct super_block *sb,
|
||||
struct scoutfs_alloc *alloc,
|
||||
struct scoutfs_block_writer *wri,
|
||||
struct scoutfs_alloc_list_head *lhead,
|
||||
struct scoutfs_alloc_root *root,
|
||||
u64 lo, u64 target);
|
||||
int scoutfs_alloc_empty_list(struct super_block *sb,
|
||||
struct scoutfs_alloc *alloc,
|
||||
struct scoutfs_block_writer *wri,
|
||||
struct scoutfs_alloc_root *root,
|
||||
struct scoutfs_alloc_list_head *lhead);
|
||||
int scoutfs_alloc_splice_list(struct super_block *sb,
|
||||
struct scoutfs_alloc *alloc,
|
||||
struct scoutfs_block_writer *wri,
|
||||
struct scoutfs_alloc_list_head *dst,
|
||||
struct scoutfs_alloc_list_head *src);
|
||||
|
||||
bool scoutfs_alloc_meta_lo_thresh(struct super_block *sb,
|
||||
struct scoutfs_alloc *alloc);
|
||||
|
||||
#endif
|
||||
+10
-1
@@ -12,6 +12,15 @@
|
||||
* other places by this macro. Don't forget to update LAST_COUNTER.
|
||||
*/
|
||||
#define EXPAND_EACH_COUNTER \
|
||||
EXPAND_COUNTER(alloc_alloc_data) \
|
||||
EXPAND_COUNTER(alloc_alloc_meta) \
|
||||
EXPAND_COUNTER(alloc_free_data) \
|
||||
EXPAND_COUNTER(alloc_free_meta) \
|
||||
EXPAND_COUNTER(alloc_list_avail_lo) \
|
||||
EXPAND_COUNTER(alloc_list_freed_hi) \
|
||||
EXPAND_COUNTER(alloc_move) \
|
||||
EXPAND_COUNTER(alloc_moved_extent) \
|
||||
EXPAND_COUNTER(alloc_stale_cached_list_block) \
|
||||
EXPAND_COUNTER(block_cache_access) \
|
||||
EXPAND_COUNTER(block_cache_alloc_failure) \
|
||||
EXPAND_COUNTER(block_cache_alloc_page_order) \
|
||||
@@ -185,7 +194,7 @@
|
||||
EXPAND_COUNTER(trans_commit_timer) \
|
||||
EXPAND_COUNTER(trans_commit_written)
|
||||
|
||||
#define FIRST_COUNTER block_cache_access
|
||||
#define FIRST_COUNTER alloc_alloc_data
|
||||
#define LAST_COUNTER trans_commit_written
|
||||
|
||||
#undef EXPAND_COUNTER
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define SCOUTFS_BLOCK_MAGIC_RADIX 0xebeb5e65
|
||||
#define SCOUTFS_BLOCK_MAGIC_SRCH_BLOCK 0x897e4a7d
|
||||
#define SCOUTFS_BLOCK_MAGIC_SRCH_PARENT 0xb23a2a05
|
||||
#define SCOUTFS_BLOCK_MAGIC_ALLOC_LIST 0x8a93ac83
|
||||
|
||||
/*
|
||||
* The super block, quorum block, and file data allocation granularity
|
||||
@@ -266,6 +267,53 @@ struct scoutfs_btree_block {
|
||||
#define SCOUTFS_BTREE_LEAF_ITEM_HASH_BYTES \
|
||||
(SCOUTFS_BTREE_LEAF_ITEM_HASH_NR * sizeof(__le16))
|
||||
|
||||
struct scoutfs_alloc_list_ref {
|
||||
__le64 blkno;
|
||||
__le64 seq;
|
||||
}__packed;
|
||||
|
||||
/*
|
||||
* first_nr tracks the nr of the first block in the list and is used for
|
||||
* allocation sizing. total_nr is the sum of the nr of all the blocks in
|
||||
* the list and is used for calculating total free block counts.
|
||||
*/
|
||||
struct scoutfs_alloc_list_head {
|
||||
struct scoutfs_alloc_list_ref ref;
|
||||
__le64 total_nr;
|
||||
__le32 first_nr;
|
||||
}__packed;
|
||||
|
||||
/*
|
||||
* While the main allocator uses extent items in btree blocks, metadata
|
||||
* allocations for a single transaction are recorded in arrays in
|
||||
* blocks. This limits the number of allocations and frees needed to
|
||||
* cow and modify the structure. The blocks can be stored in a list
|
||||
* which lets us create a persistent log of pending frees that are
|
||||
* generated as we cow btree blocks to insert freed extents.
|
||||
*
|
||||
* The array floats in the block so that both adding and removing blknos
|
||||
* only modifies an index.
|
||||
*/
|
||||
struct scoutfs_alloc_list_block {
|
||||
struct scoutfs_block_header hdr;
|
||||
struct scoutfs_alloc_list_ref next;
|
||||
__le32 start;
|
||||
__le32 nr;
|
||||
__le64 blknos[0]; /* naturally aligned for sorting */
|
||||
}__packed;
|
||||
|
||||
#define SCOUTFS_ALLOC_LIST_MAX_BLOCKS \
|
||||
((SCOUTFS_BLOCK_LG_SIZE - sizeof(struct scoutfs_alloc_list_block)) / \
|
||||
(member_sizeof(struct scoutfs_alloc_list_block, blknos[0])))
|
||||
|
||||
/*
|
||||
* These can safely be initialized to all-zeros.
|
||||
*/
|
||||
struct scoutfs_alloc_root {
|
||||
__le64 total_len;
|
||||
struct scoutfs_btree_root root;
|
||||
}__packed;
|
||||
|
||||
struct scoutfs_mounted_client_btree_val {
|
||||
__u8 flags;
|
||||
} __packed;
|
||||
|
||||
@@ -2490,6 +2490,123 @@ TRACE_EVENT(scoutfs_ext_alloc,
|
||||
STE_ENTRY_ARGS(ext), __entry->ret)
|
||||
);
|
||||
|
||||
TRACE_EVENT(scoutfs_alloc_alloc_meta,
|
||||
TP_PROTO(struct super_block *sb, u64 blkno, int ret),
|
||||
|
||||
TP_ARGS(sb, blkno, ret),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
SCSB_TRACE_FIELDS
|
||||
__field(__u64, blkno)
|
||||
__field(int, ret)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
SCSB_TRACE_ASSIGN(sb);
|
||||
__entry->blkno = blkno;
|
||||
__entry->ret = ret;
|
||||
),
|
||||
|
||||
TP_printk(SCSBF" blkno %llu ret %d",
|
||||
SCSB_TRACE_ARGS, __entry->blkno, __entry->ret)
|
||||
);
|
||||
|
||||
TRACE_EVENT(scoutfs_alloc_free_meta,
|
||||
TP_PROTO(struct super_block *sb, u64 blkno, int ret),
|
||||
|
||||
TP_ARGS(sb, blkno, ret),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
SCSB_TRACE_FIELDS
|
||||
__field(__u64, blkno)
|
||||
__field(int, ret)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
SCSB_TRACE_ASSIGN(sb);
|
||||
__entry->blkno = blkno;
|
||||
__entry->ret = ret;
|
||||
),
|
||||
|
||||
TP_printk(SCSBF" blkno %llu ret %d",
|
||||
SCSB_TRACE_ARGS, __entry->blkno, __entry->ret)
|
||||
);
|
||||
|
||||
TRACE_EVENT(scoutfs_alloc_alloc_data,
|
||||
TP_PROTO(struct super_block *sb, u64 req, u64 blkno, u64 count,
|
||||
int ret),
|
||||
|
||||
TP_ARGS(sb, req, blkno, count, ret),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
SCSB_TRACE_FIELDS
|
||||
__field(__u64, req)
|
||||
__field(__u64, blkno)
|
||||
__field(__u64, count)
|
||||
__field(int, ret)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
SCSB_TRACE_ASSIGN(sb);
|
||||
__entry->req = req;
|
||||
__entry->blkno = blkno;
|
||||
__entry->count = count;
|
||||
__entry->ret = ret;
|
||||
),
|
||||
|
||||
TP_printk(SCSBF" req %llu blkno %llu count %llu ret %d",
|
||||
SCSB_TRACE_ARGS, __entry->req, __entry->blkno,
|
||||
__entry->count, __entry->ret)
|
||||
);
|
||||
|
||||
TRACE_EVENT(scoutfs_alloc_free_data,
|
||||
TP_PROTO(struct super_block *sb, u64 blkno, u64 count, int ret),
|
||||
|
||||
TP_ARGS(sb, blkno, count, ret),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
SCSB_TRACE_FIELDS
|
||||
__field(__u64, blkno)
|
||||
__field(__u64, count)
|
||||
__field(int, ret)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
SCSB_TRACE_ASSIGN(sb);
|
||||
__entry->blkno = blkno;
|
||||
__entry->count = count;
|
||||
__entry->ret = ret;
|
||||
),
|
||||
|
||||
TP_printk(SCSBF" blkno %llu count %llu ret %d",
|
||||
SCSB_TRACE_ARGS, __entry->blkno, __entry->count,
|
||||
__entry->ret)
|
||||
);
|
||||
|
||||
TRACE_EVENT(scoutfs_alloc_move,
|
||||
TP_PROTO(struct super_block *sb, u64 total, u64 moved, int ret),
|
||||
|
||||
TP_ARGS(sb, total, moved, ret),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
SCSB_TRACE_FIELDS
|
||||
__field(__u64, total)
|
||||
__field(__u64, moved)
|
||||
__field(int, ret)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
SCSB_TRACE_ASSIGN(sb);
|
||||
__entry->total = total;
|
||||
__entry->moved = moved;
|
||||
__entry->ret = ret;
|
||||
),
|
||||
|
||||
TP_printk(SCSBF" total %llu moved %llu ret %d",
|
||||
SCSB_TRACE_ARGS, __entry->total, __entry->moved,
|
||||
__entry->ret)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_SCOUTFS_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
|
||||
Reference in New Issue
Block a user