[lvm-devel] master - [device/bcache] Add a couple of invalidate methods
David Teigland
teigland at sourceware.org
Mon Apr 23 13:46:46 UTC 2018
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=c4c4acfd423323cbe8fbfbdb8c1882edb4a92b29
Commit: c4c4acfd423323cbe8fbfbdb8c1882edb4a92b29
Parent: 0f0eb04edb00cb5e95c47cb9ca2e70574e6e49ce
Author: Joe Thornber <ejt at redhat.com>
AuthorDate: Fri Feb 2 07:59:49 2018 +0000
Committer: David Teigland <teigland at redhat.com>
CommitterDate: Fri Apr 20 11:12:50 2018 -0500
[device/bcache] Add a couple of invalidate methods
---
lib/device/bcache.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++
lib/device/bcache.h | 13 +++++++++++
2 files changed, 73 insertions(+), 0 deletions(-)
diff --git a/lib/device/bcache.c b/lib/device/bcache.c
index 5a7b2f9..09ef6ef 100644
--- a/lib/device/bcache.c
+++ b/lib/device/bcache.c
@@ -884,5 +884,65 @@ int bcache_flush(struct bcache *cache)
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);
+}
+
//----------------------------------------------------------------
diff --git a/lib/device/bcache.h b/lib/device/bcache.h
index 2730347..5c68e3c 100644
--- a/lib/device/bcache.h
+++ b/lib/device/bcache.h
@@ -93,6 +93,19 @@ void bcache_put(struct block *b);
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
More information about the lvm-devel
mailing list