mirror of
https://github.com/versity/scoutfs.git
synced 2026-09-01 05:37:33 +00:00
Using the treap to be able to incrementally read and write the manifest and allocation storage from all nodes wasn't quite ready for prime time. The biggest problem is that invalidating cached nodes which are the target of native pointers, either for consistency or memory pressure, is problematic. This was getting in the way of adding shared support as readers and writers try to use as much of their treap caches as they can. There were other serious problems that we'd run into eventually: memory pressure from duplicate caching in native nodes and the page cache, small IOs from reading a page at a time, the risk of pathologically imbalanced treaps, and the ring being corrupted if the migration balancing doesn't work (the model assumed you could always dirty an individual node in a transaction, you have to dirty all the parents in each new transaction). Let's back off to a much simpler mechanism while we build the rest of the system around it. We can revisit aggressively optimizing this when it's our worst problem. We'll store the indexes that the manifest server needs in simple preallocated rings with log entries. The server has to read the index in its entirety into a native rbtree before it can work on it. We won't access the physical ring from mounts anymore, they'll send messages to the server. The ring callers are now working with a pinned tree in memory so the interface can be a bit simpler. By storing the indexes in their own rings the code and write path become a lot simper: we have an IO submission path for each index instead of "dirtying" calls per index and then a writing call. All this is much more robust and much less likely to get in our way as we stand up the rest of the system around it. Signed-off-by: Zach Brown <zab@versity.com>
56 lines
1.7 KiB
C
56 lines
1.7 KiB
C
#ifndef _SCOUTFS_RING_H_
|
|
#define _SCOUTFS_RING_H_
|
|
|
|
struct scoutfs_bio_completion;
|
|
|
|
typedef int (*scoutfs_ring_cmp_t)(void *a, void *b);
|
|
|
|
struct scoutfs_ring_info {
|
|
struct scoutfs_ring_descriptor *rdesc;
|
|
|
|
scoutfs_ring_cmp_t compare_key;
|
|
scoutfs_ring_cmp_t compare_data;
|
|
|
|
struct rb_root rb_root;
|
|
|
|
struct list_head clean_list;
|
|
struct list_head dirty_list;
|
|
|
|
unsigned long dirty_bytes;
|
|
u64 first_dirty_block;
|
|
u64 first_dirty_seq;
|
|
|
|
struct page **pages;
|
|
unsigned long nr_pages;
|
|
};
|
|
|
|
void scoutfs_ring_init(struct scoutfs_ring_info *ring,
|
|
struct scoutfs_ring_descriptor *rdesc,
|
|
scoutfs_ring_cmp_t compare_key,
|
|
scoutfs_ring_cmp_t compare_data);
|
|
|
|
int scoutfs_ring_load(struct super_block *sb, struct scoutfs_ring_info *ring);
|
|
|
|
void *scoutfs_ring_insert(struct scoutfs_ring_info *ring, void *key,
|
|
unsigned data_len);
|
|
|
|
void *scoutfs_ring_first(struct scoutfs_ring_info *ring);
|
|
void *scoutfs_ring_lookup(struct scoutfs_ring_info *ring, void *key);
|
|
void *scoutfs_ring_lookup_next(struct scoutfs_ring_info *ring, void *key);
|
|
void *scoutfs_ring_lookup_prev(struct scoutfs_ring_info *ring, void *key);
|
|
|
|
void *scoutfs_ring_next(struct scoutfs_ring_info *ring, void *rdata);
|
|
void *scoutfs_ring_prev(struct scoutfs_ring_info *ring, void *rdata);
|
|
void scoutfs_ring_dirty(struct scoutfs_ring_info *ring, void *rdata);
|
|
void scoutfs_ring_delete(struct scoutfs_ring_info *ring, void *rdata);
|
|
|
|
int scoutfs_ring_has_dirty(struct scoutfs_ring_info *ring);
|
|
int scoutfs_ring_submit_write(struct super_block *sb,
|
|
struct scoutfs_ring_info *ring,
|
|
struct scoutfs_bio_completion *comp);
|
|
void scoutfs_ring_write_complete(struct scoutfs_ring_info *ring);
|
|
|
|
void scoutfs_ring_destroy(struct scoutfs_ring_info *ring);
|
|
|
|
#endif
|