scoutfs: add scoutfs_block_move

Add a call to move a block's location in the cache without failure.  The
radix allocator is going to use this to dirty radix blocks while making
atomic changes to multipls paths through multiple radix trees.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2020-02-20 14:01:06 -08:00
committed by Zach Brown
parent 809d4be58e
commit 8681f920e0
3 changed files with 46 additions and 0 deletions

View File

@@ -802,6 +802,44 @@ void scoutfs_block_writer_forget(struct super_block *sb,
}
}
/*
* Change a cached block's location. We're careful to only change its
* position in the rbtree. If we find another block existing at the new
* location then we remove it from the cache and forget it if it was
* dirty.
*/
void scoutfs_block_move(struct super_block *sb,
struct scoutfs_block_writer *wri,
struct scoutfs_block *bl, u64 blkno)
{
DECLARE_BLOCK_INFO(sb, binf);
struct block_private *bp = BLOCK_PRIVATE(bl);
struct block_private *existing = NULL;
spin_lock(&binf->lock);
existing = walk_block_rbtree(&binf->root, blkno, NULL);
if (existing) {
/* only nesting of binf and wri locks */
if (test_bit(BLOCK_BIT_DIRTY, &bp->bits)) {
spin_lock(&wri->lock);
if (test_bit(BLOCK_BIT_DIRTY, &bp->bits))
block_forget(sb, wri, bp);
spin_unlock(&wri->lock);
}
block_remove(sb, existing);
}
rb_erase(&bp->node, &binf->root);
RB_CLEAR_NODE(&bp->node);
bp->bl.blkno = blkno;
walk_block_rbtree(&binf->root, blkno, bp);
TRACE_BLOCK(move, bp);
spin_unlock(&binf->lock);
}
/*
* The caller has ensured that no more dirtying will take place. This
* helps the caller avoid doing a bunch of work before calling into the

View File

@@ -44,6 +44,9 @@ void scoutfs_block_writer_forget_all(struct super_block *sb,
void scoutfs_block_writer_forget(struct super_block *sb,
struct scoutfs_block_writer *wri,
struct scoutfs_block *bl);
void scoutfs_block_move(struct super_block *sb,
struct scoutfs_block_writer *wri,
struct scoutfs_block *bl, u64 blkno);
bool scoutfs_block_writer_has_dirty(struct super_block *sb,
struct scoutfs_block_writer *wri);
u64 scoutfs_block_writer_dirty_bytes(struct super_block *sb,

View File

@@ -2191,6 +2191,11 @@ DEFINE_EVENT(scoutfs_block_class, scoutfs_block_invalidate,
int refcount, int io_count, unsigned long bits, u64 lru_moved),
TP_ARGS(sb, bp, blkno, refcount, io_count, bits, lru_moved)
);
DEFINE_EVENT(scoutfs_block_class, scoutfs_block_move,
TP_PROTO(struct super_block *sb, void *bp, u64 blkno,
int refcount, int io_count, unsigned long bits, u64 lru_moved),
TP_ARGS(sb, bp, blkno, refcount, io_count, bits, lru_moved)
);
DEFINE_EVENT(scoutfs_block_class, scoutfs_block_mark_dirty,
TP_PROTO(struct super_block *sb, void *bp, u64 blkno,
int refcount, int io_count, unsigned long bits, u64 lru_moved),