mirror of
https://github.com/versity/scoutfs.git
synced 2026-04-30 09:56:55 +00:00
The btree forest item storage doesn't have as much item granular state as the item cache did. The item cache could tell if a cached item was populated from persistent storage or was created in memory. It could simply remove created items rather than leaving behind a deletion item. The cached btree blocks in the btree forest item storage mechanism can't do this. It has to create deletion items when deleting newly created items because it doesn't know if the item already exists in the persistent record or not. This created a problem with the extent storage we were using. The individual extent items were stored with a key set to the last logical block of their extent. As extents grew or shrank they often were deleted and created at different key values during a transaction. In the btree forest log trees this left a huge stream of deletion items beind, one for every previous version of the extent. Then searches for an extent covering a block would have to skip over all these deleted items before hitting the current stored extent. Streaming writes would operate on O(n) for every extent operation. It got to be out of hand. This large change solves the problem by using more coarse and stable item storage to track free blocks and blocks mapped into file data. For file data we now have large packed extent items which store packed representations of all the logical mappings of a fixed region of a file. The data code has loading and storage functions which transfer that persistent version to and from the version that is modified in memory. Free blocks are stored in bitmaps that are similarly efficiently packed into fixed size items. The client is no longer working with free extent items managed by the forest, it's working with free block bitmap btrees directly. It needs access to the client's metadata block allocator and block write contexts so we move those two out of the forest code and up into the transaction. Previously the client and server would exchange extents with network messages. Now the roots of the btrees that store the free block bitmap items are communicated along with the roots of the other trees involved in a transaction. The client doesn't need to send free extents back to the server so we can remove those tasks and rpcs. The server no longer has to manage free extents. It transfers block bitmap items between trees around commits. All of its extent manipulation can be removed. The item size portion of transaction item counts are removed because we're not using that level of granularity now that metadata transactions are dirty btree blocks instead of dirty items we pack into fixed sized segments. Signed-off-by: Zach Brown <zab@versity.com>
56 lines
2.3 KiB
C
56 lines
2.3 KiB
C
#ifndef _SCOUTFS_FOREST_H_
|
|
#define _SCOUTFS_FOREST_H_
|
|
|
|
struct scoutfs_balloc_allocator;
|
|
struct scoutfs_block_writer;
|
|
|
|
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);
|
|
|
|
void scoutfs_forest_init_btrees(struct super_block *sb,
|
|
struct scoutfs_balloc_allocator *alloc,
|
|
struct scoutfs_block_writer *wri,
|
|
struct scoutfs_log_trees *lt);
|
|
void scoutfs_forest_get_btrees(struct super_block *sb,
|
|
struct scoutfs_log_trees *lt);
|
|
|
|
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
|