]> sourceware.org Git - lvm2.git/commitdiff
[device/bcache] Add a couple of invalidate methods
authorJoe Thornber <ejt@redhat.com>
Fri, 2 Feb 2018 07:59:49 +0000 (07:59 +0000)
committerDavid Teigland <teigland@redhat.com>
Fri, 20 Apr 2018 16:12:50 +0000 (11:12 -0500)
lib/device/bcache.c
lib/device/bcache.h

index 5a7b2f93c43c1d4575978b303ff6ac56e76b9f20..09ef6ef7f589ab27592c1b40e5641fa0d51c8cf5 100644 (file)
@@ -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);
+}
+
 //----------------------------------------------------------------
 
index 2730347736162f681efff48a018d7d3327a64f53..5c68e3c299b7a4bcf6e4f925af2a10e3634d5f55 100644 (file)
@@ -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
This page took 0.041379 seconds and 5 git commands to generate.