scoutfs: add forest subsystem

The forest code presents a consistent item interface that's implemented
on top of a forest of persistent btrees.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2020-01-17 11:21:36 -08:00
committed by Zach Brown
parent e6af174c79
commit 858dad1d51
6 changed files with 1505 additions and 3 deletions
+1
View File
@@ -21,6 +21,7 @@ scoutfs-y += \
export.o \
extents.o \
file.o \
forest.o \
inode.o \
ioctl.o \
item.o \
+1389
View File
File diff suppressed because it is too large Load Diff
+51
View File
@@ -0,0 +1,51 @@
#ifndef _SCOUTFS_FOREST_H_
#define _SCOUTFS_FOREST_H_
int scoutfs_forest_lookup(struct super_block *sb, struct scoutfs_key *key,
struct kvec *val, struct scoutfs_lock *lock);
int scoutfs_forest_lookup_exact(struct super_block *sb,
struct scoutfs_key *key, struct kvec *val,
struct scoutfs_lock *lock);
int scoutfs_forest_next(struct super_block *sb, struct scoutfs_key *key,
struct scoutfs_key *last, struct kvec *val,
struct scoutfs_lock *lock);
int scoutfs_forest_next_hint(struct super_block *sb, struct scoutfs_key *key,
struct scoutfs_key *next);
int scoutfs_forest_prev(struct super_block *sb, struct scoutfs_key *key,
struct scoutfs_key *first, struct kvec *val,
struct scoutfs_lock *lock);
int scoutfs_forest_create(struct super_block *sb, struct scoutfs_key *key,
struct kvec *val, struct scoutfs_lock *lock);
int scoutfs_forest_create_force(struct super_block *sb,
struct scoutfs_key *key, struct kvec *val,
struct scoutfs_lock *lock);
int scoutfs_forest_update(struct super_block *sb, struct scoutfs_key *key,
struct kvec *val, struct scoutfs_lock *lock);
int scoutfs_forest_delete_dirty(struct super_block *sb,
struct scoutfs_key *key);
int scoutfs_forest_delete(struct super_block *sb, struct scoutfs_key *key,
struct scoutfs_lock *lock);
int scoutfs_forest_delete_force(struct super_block *sb,
struct scoutfs_key *key,
struct scoutfs_lock *lock);
int scoutfs_forest_delete_save(struct super_block *sb,
struct scoutfs_key *key,
struct list_head *list,
struct scoutfs_lock *lock);
int scoutfs_forest_restore(struct super_block *sb, struct list_head *list,
struct scoutfs_lock *lock);
void scoutfs_forest_free_batch(struct super_block *sb, struct list_head *list);
int scoutfs_forest_get_log_trees(struct super_block *sb);
bool scoutfs_forest_has_dirty(struct super_block *sb);
unsigned long scoutfs_forest_dirty_bytes(struct super_block *sb);
int scoutfs_forest_write(struct super_block *sb);
int scoutfs_forest_commit(struct super_block *sb);
void scoutfs_forest_clear_lock(struct super_block *sb,
struct scoutfs_lock *lock);
int scoutfs_forest_setup(struct super_block *sb);
void scoutfs_forest_destroy(struct super_block *sb);
#endif
+59 -3
View File
@@ -7,6 +7,7 @@
/* block header magic values, chosen at random */
#define SCOUTFS_BLOCK_MAGIC_SUPER 0x103c428b
#define SCOUTFS_BLOCK_MAGIC_BTREE 0xe597f96d
#define SCOUTFS_BLOCK_MAGIC_BLOOM 0x31995604
/*
* The super block and btree blocks are fixed 4k.
@@ -329,6 +330,61 @@ struct scoutfs_mounted_client_btree_val {
#define SCOUTFS_MOUNTED_CLIENT_VOTER (1 << 0)
struct scoutfs_log_trees {
struct scoutfs_balloc_root alloc_root;
struct scoutfs_balloc_root free_root;
struct scoutfs_btree_root item_root;
struct scoutfs_btree_ref bloom_ref;
__le64 rid;
__le64 nr;
} __packed;
struct scoutfs_log_trees_key {
__be64 rid;
__be64 nr;
} __packed;
struct scoutfs_log_trees_val {
struct scoutfs_balloc_root alloc_root;
struct scoutfs_balloc_root free_root;
struct scoutfs_btree_root item_root;
struct scoutfs_btree_ref bloom_ref;
} __packed;
struct scoutfs_log_item_value {
__le64 vers;
__u8 flags;
__u8 data[0];
} __packed;
/*
* FS items are limited by the max btree value length with the log item
* value header.
*/
#define SCOUTFS_MAX_VAL_SIZE \
(SCOUTFS_BTREE_MAX_VAL_LEN - sizeof(struct scoutfs_log_item_value))
#define SCOUTFS_LOG_ITEM_FLAG_DELETION (1 << 0)
struct scoutfs_bloom_block {
struct scoutfs_block_header hdr;
__le64 total_set;
__le64 bits[0];
} __packed;
/*
* Log trees include a tree of items that make up a fixed size bloom
* filter. Just a few megs worth of items lets us test for the presence
* of locks that cover billions of files with a .1% chance of false
* positives. The log trees should be finalized and merged long before
* the bloom filters fill up and start returning excessive false positives.
*/
#define SCOUTFS_FOREST_BLOOM_NRS 7
#define SCOUTFS_FOREST_BLOOM_BITS \
(((SCOUTFS_BLOCK_SIZE - sizeof(struct scoutfs_bloom_block)) / \
member_sizeof(struct scoutfs_bloom_block, bits[0])) * \
member_sizeof(struct scoutfs_bloom_block, bits[0]) * 8) \
/*
* The max number of links defines the max number of entries that we can
* index in o(log n) and the static list head storage size in the
@@ -496,6 +552,8 @@ struct scoutfs_super_block {
__le64 core_balloc_cursor;
__le64 free_blocks;
__le64 alloc_cursor;
__le64 first_fs_blkno;
__le64 last_fs_blkno;
struct scoutfs_btree_ring bring;
__le64 next_seg_seq;
__le64 next_compact_id;
@@ -507,8 +565,8 @@ struct scoutfs_super_block {
struct scoutfs_balloc_root core_balloc_alloc;
struct scoutfs_balloc_root core_balloc_free;
struct scoutfs_btree_root alloc_root;
struct scoutfs_manifest manifest;
struct scoutfs_btree_root fs_root;
struct scoutfs_manifest manifest;
struct scoutfs_btree_root logs_root;
struct scoutfs_btree_root lock_clients;
struct scoutfs_btree_root trans_seqs;
@@ -617,8 +675,6 @@ enum {
DIV_ROUND_UP(sizeof(struct scoutfs_xattr) + name_len + val_len, \
SCOUTFS_XATTR_MAX_PART_SIZE);
#define SCOUTFS_MAX_VAL_SIZE SCOUTFS_XATTR_MAX_PART_SIZE
#define SCOUTFS_LOCK_INODE_GROUP_NR 1024
#define SCOUTFS_LOCK_INODE_GROUP_MASK (SCOUTFS_LOCK_INODE_GROUP_NR - 1)
#define SCOUTFS_LOCK_SEQ_GROUP_MASK ((1ULL << 10) - 1)
+3
View File
@@ -36,6 +36,9 @@ struct scoutfs_lock {
unsigned int users[SCOUTFS_LOCK_NR_MODES];
struct scoutfs_tseq_entry tseq_entry;
/* the forest btree code stores data per lock */
struct forest_lock_private *forest_private;
};
struct scoutfs_lock_coverage {
+2
View File
@@ -27,6 +27,7 @@ struct sysfs_info;
struct options_sb_info;
struct net_info;
struct block_info;
struct forest_info;
struct scoutfs_sb_info {
struct super_block *sb;
@@ -50,6 +51,7 @@ struct scoutfs_sb_info {
struct net_info *net_info;
struct quorum_info *quorum_info;
struct block_info *block_info;
struct forest_info *forest_info;
wait_queue_head_t trans_hold_wq;
struct task_struct *trans_task;