mirror of
https://github.com/versity/scoutfs.git
synced 2026-02-07 11:10:44 +00:00
Fix how dirty treap is tracked
The transaction writing thread tests if the manifest and alloc treaps are dirty. It did this by testing if there were any dirty nodes in the treap. But this misses the case where the treap has been modified and all nodes have been removed. In that case the root references no dirty nodes but needs to be written. Instead let's specifically mark the treap dirty when it's modified. From then on sync will always try to write it out. We also integrate updating the persistent root as part of writing the dirty nodes to the persistent ring. It's required and every caller did it so it was silly to make it a separate step. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -270,8 +270,7 @@ int scoutfs_alloc_dirty_ring(struct super_block *sb)
|
||||
kfree(pend);
|
||||
}
|
||||
|
||||
scoutfs_treap_dirty_ring(sal->treap);
|
||||
scoutfs_treap_update_root(&super->alloc_treap_root, sal->treap);
|
||||
scoutfs_treap_dirty_ring(sal->treap, &super->alloc_treap_root);
|
||||
ret = 0;
|
||||
out:
|
||||
up_write(&sal->rwsem);
|
||||
|
||||
@@ -612,8 +612,7 @@ int scoutfs_manifest_dirty_ring(struct super_block *sb)
|
||||
struct scoutfs_super_block *super = &sbi->super;
|
||||
|
||||
down_write(&mani->rwsem);
|
||||
scoutfs_treap_dirty_ring(mani->treap);
|
||||
scoutfs_treap_update_root(&super->manifest.root, mani->treap);
|
||||
scoutfs_treap_dirty_ring(mani->treap, &super->manifest.root);
|
||||
up_write(&mani->rwsem);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -117,6 +117,7 @@ struct scoutfs_treap {
|
||||
struct scoutfs_super_block *super;
|
||||
struct scoutfs_treap_ops *ops;
|
||||
struct treap_ref root_ref;
|
||||
bool dirty;
|
||||
u64 dirty_bytes;
|
||||
};
|
||||
|
||||
@@ -424,6 +425,7 @@ static bool mark_node_dirty(struct scoutfs_treap *treap, struct treap_ref *ref,
|
||||
return false;
|
||||
|
||||
treap->dirty_bytes += node_ring_bytes(node);
|
||||
treap->dirty = true;
|
||||
|
||||
node->off = tinf->dirty_off;
|
||||
node->gen = tinf->dirty_gen;
|
||||
@@ -1030,7 +1032,7 @@ out:
|
||||
|
||||
int scoutfs_treap_has_dirty(struct scoutfs_treap *treap)
|
||||
{
|
||||
return !!(treap->root_ref.aug_bits & SCOUTFS_TREAP_AUG_DIRTY);
|
||||
return treap->dirty;
|
||||
}
|
||||
|
||||
static void *pages_off_ptr(struct treap_info *tinf)
|
||||
@@ -1135,7 +1137,8 @@ static void copy_node_to_ring(struct scoutfs_treap *treap,
|
||||
*
|
||||
* This is called for multiple treaps before the ring is written.
|
||||
*/
|
||||
int scoutfs_treap_dirty_ring(struct scoutfs_treap *treap)
|
||||
int scoutfs_treap_dirty_ring(struct scoutfs_treap *treap,
|
||||
struct scoutfs_treap_root *root)
|
||||
{
|
||||
struct treap_node *node;
|
||||
unsigned bytes;
|
||||
@@ -1168,7 +1171,13 @@ int scoutfs_treap_dirty_ring(struct scoutfs_treap *treap)
|
||||
}
|
||||
}
|
||||
|
||||
/* point the persistent super root at the treap we wrote to the ring */
|
||||
root->ref.off = cpu_to_le64(treap->root_ref.off);
|
||||
root->ref.gen = cpu_to_le64(treap->root_ref.gen);
|
||||
root->ref.aug_bits = treap->root_ref.aug_bits;
|
||||
|
||||
treap->dirty_bytes = 0;
|
||||
treap->dirty = false;
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
@@ -1258,14 +1267,6 @@ struct scoutfs_treap *scoutfs_treap_alloc(struct super_block *sb,
|
||||
return treap;
|
||||
}
|
||||
|
||||
void scoutfs_treap_update_root(struct scoutfs_treap_root *root,
|
||||
struct scoutfs_treap *treap)
|
||||
{
|
||||
root->ref.off = cpu_to_le64(treap->root_ref.off);
|
||||
root->ref.gen = cpu_to_le64(treap->root_ref.gen);
|
||||
root->ref.aug_bits = treap->root_ref.aug_bits;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free all the allocated nodes in the treap and clear the root.
|
||||
*/
|
||||
|
||||
@@ -18,8 +18,6 @@ struct scoutfs_treap_ops {
|
||||
struct scoutfs_treap *scoutfs_treap_alloc(struct super_block *sb,
|
||||
struct scoutfs_treap_ops *ops,
|
||||
struct scoutfs_treap_root *root);
|
||||
void scoutfs_treap_update_root(struct scoutfs_treap_root *root,
|
||||
struct scoutfs_treap *treap);
|
||||
void scoutfs_treap_free(struct scoutfs_treap *treap);
|
||||
|
||||
void *scoutfs_treap_insert(struct scoutfs_treap *treap, void *key, u16 bytes,
|
||||
@@ -38,7 +36,8 @@ void *scoutfs_treap_next(struct scoutfs_treap *treap, void *data);
|
||||
void *scoutfs_treap_prev(struct scoutfs_treap *treap, void *data);
|
||||
|
||||
int scoutfs_treap_has_dirty(struct scoutfs_treap *treap);
|
||||
int scoutfs_treap_dirty_ring(struct scoutfs_treap *treap);
|
||||
int scoutfs_treap_dirty_ring(struct scoutfs_treap *treap,
|
||||
struct scoutfs_treap_root *root);
|
||||
int scoutfs_treap_submit_write(struct super_block *sb,
|
||||
struct scoutfs_bio_completion *comp);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user