mirror of
git://sourceware.org/git/lvm2.git
synced 2025-03-10 16:58:47 +03:00
[device/bcache] Add a couple of invalidate methods
This commit is contained in:
parent
0f0eb04edb
commit
c4c4acfd42
@ -884,5 +884,65 @@ int bcache_flush(struct bcache *cache)
|
|||||||
return dm_list_empty(&cache->errored) ? 0 : -EIO;
|
return dm_list_empty(&cache->errored) ? 0 : -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _recycle_block(struct bcache *cache, struct block *b)
|
||||||
|
{
|
||||||
|
_unlink_block(b);
|
||||||
|
_hash_remove(b);
|
||||||
|
dm_list_add(&cache->free, &b->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* You can safely call this with a NULL block.
|
||||||
|
*/
|
||||||
|
static void _invalidate_block(struct bcache *cache, struct block *b)
|
||||||
|
{
|
||||||
|
if (!b)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_test_flags(b, BF_IO_PENDING))
|
||||||
|
_wait_specific(b);
|
||||||
|
|
||||||
|
if (b->ref_count)
|
||||||
|
log_warn("bcache_invalidate: block (%d, %llu) still held",
|
||||||
|
b->fd, (unsigned long long) index);
|
||||||
|
else {
|
||||||
|
if (_test_flags(b, BF_DIRTY)) {
|
||||||
|
_issue_write(b);
|
||||||
|
_wait_specific(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
_recycle_block(cache, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcache_invalidate(struct bcache *cache, int fd, block_address index)
|
||||||
|
{
|
||||||
|
_invalidate_block(cache, _hash_lookup(cache, fd, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: switch to a trie, or maybe 1 hash table per fd? To save iterating
|
||||||
|
// through the whole cache.
|
||||||
|
void bcache_invalidate_fd(struct bcache *cache, int fd)
|
||||||
|
{
|
||||||
|
struct block *b, *tmp;
|
||||||
|
|
||||||
|
// Start writing back any dirty blocks on this fd.
|
||||||
|
dm_list_iterate_items_safe (b, tmp, &cache->dirty)
|
||||||
|
if (b->fd == fd)
|
||||||
|
_issue_write(b);
|
||||||
|
|
||||||
|
_wait_all(cache);
|
||||||
|
|
||||||
|
// Everything should be in the clean list now.
|
||||||
|
dm_list_iterate_items_safe (b, tmp, &cache->clean)
|
||||||
|
if (b->fd == fd)
|
||||||
|
_invalidate_block(cache, b);
|
||||||
|
|
||||||
|
// Except they could be in the errored list :)
|
||||||
|
dm_list_iterate_items_safe (b, tmp, &cache->errored)
|
||||||
|
if (b->fd == fd)
|
||||||
|
_recycle_block(cache, b);
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -93,6 +93,19 @@ void bcache_put(struct block *b);
|
|||||||
|
|
||||||
int bcache_flush(struct bcache *cache);
|
int bcache_flush(struct bcache *cache);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Removes a block from the cache. If the block is dirty it will be written
|
||||||
|
* back first. If the block is currently held a warning will be issued, and it
|
||||||
|
* will not be removed.
|
||||||
|
*/
|
||||||
|
void bcache_invalidate(struct bcache *cache, int fd, block_address index);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Invalidates all blocks on the given descriptor. Call this before closing
|
||||||
|
* the descriptor to make sure everything is written back.
|
||||||
|
*/
|
||||||
|
void bcache_invalidate_fd(struct bcache *cache, int fd);
|
||||||
|
|
||||||
/*----------------------------------------------------------------*/
|
/*----------------------------------------------------------------*/
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user