diff mbox

[RFC,08/22] block/pcache: implement pickup parts of the cache

Message ID 20160825134421.20231-9-pbutsykin@virtuozzo.com (mailing list archive)
State New, archived
Headers show

Commit Message

Pavel Butsykin Aug. 25, 2016, 1:44 p.m. UTC
Implementation of obtaining fragments of the cache belonging to one area
of request. This will allow to handle the case when a request is partially
hits the cache.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
---
 block/pcache.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 59 insertions(+), 1 deletion(-)
diff mbox

Patch

diff --git a/block/pcache.c b/block/pcache.c
index 7504db8..28bd056 100644
--- a/block/pcache.c
+++ b/block/pcache.c
@@ -143,6 +143,24 @@  static int pcache_key_cmp(const RbNodeKey *key1, const RbNodeKey *key2)
     return 0;
 }
 
+static BlockNode *pcache_node_prev(BlockNode* node, RbNodeKey *key)
+{
+    while (node) {
+        struct RbNode *prev_rb_node = rb_prev(&node->rb_node);
+        BlockNode *prev_node;
+        if (prev_rb_node == NULL) {
+            break;
+        }
+        prev_node = container_of(prev_rb_node, BlockNode, rb_node);
+        if (prev_node->sector_num + prev_node->nb_sectors <= key->num) {
+            break;
+        }
+        node = prev_node;
+    }
+
+    return node;
+}
+
 static void *node_insert(struct RbRoot *root, BlockNode *node)
 {
     struct RbNode **new = &(root->rb_node), *parent = NULL;
@@ -152,7 +170,7 @@  static void *node_insert(struct RbRoot *root, BlockNode *node)
         BlockNode *this = container_of(*new, BlockNode, rb_node);
         int result = pcache_key_cmp(&node->key, &this->key);
         if (result == 0) {
-            return this;
+            return pcache_node_prev(this, &node->key);
         }
         parent = *new;
         new = result < 0 ? &((*new)->rb_left) : &((*new)->rb_right);
@@ -258,6 +276,45 @@  static inline void prefetch_init_key(PrefCacheAIOCB *acb, RbNodeKey* key)
     key->size = acb->nb_sectors;
 }
 
+static void pcache_pickup_parts_of_cache(PrefCacheAIOCB *acb, PCNode *node,
+                                         uint64_t num, uint32_t size)
+{
+    uint32_t up_size;
+
+    do {
+        if (num < node->cm.sector_num) {
+            PCNode *new_node;
+            RbNodeKey lc_key = {
+                .num = num,
+                .size = node->cm.sector_num - num,
+            };
+            up_size = lc_key.size;
+
+            if (!pcache_node_find_and_create(acb, &lc_key, &new_node)) {
+                node = new_node;
+                continue;
+            }
+            size -= up_size;
+            num += up_size;
+        }
+        /* XXX: node read */
+        up_size = MIN(node->cm.sector_num + node->cm.nb_sectors - num, size);
+
+        size -= up_size;
+        num += up_size;
+        if (size != 0) {
+            RbNodeKey lc_key = {
+                .num = num,
+                .size = size,
+            };
+            if (pcache_node_find_and_create(acb, &lc_key, &node)) {
+                size -= lc_key.size;
+                assert(size == 0);
+            }
+        }
+    } while (size);
+}
+
 enum {
     PREFETCH_NEW_NODE  = 0,
     PREFETCH_FULL_UP   = 1,
@@ -281,6 +338,7 @@  static int32_t pcache_prefetch(PrefCacheAIOCB *acb)
     {
         return PREFETCH_FULL_UP;
     }
+    pcache_pickup_parts_of_cache(acb, node, key.num, key.size);
 
     return PREFETCH_PART_UP;
 }