mirror of
https://github.com/versity/scoutfs.git
synced 2026-01-09 13:23:14 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user