[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[tyndur-devel] [PATCH 1/4] cdi/cache: Fehlerpfad gefixt



! cdi/cache: Wenn das Laden eines Cacheblocks fehlgeschlagen ist, gibt
  unsere CDI-Implementierung ihn wieder frei. Das ist schön, aber
  dann sollte man auch darauf achten, dass keine Dangling Pointers
  übrigbleiben.

Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
 src/modules/cdi/lib/cache.c | 46 +++++++++++++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 14 deletions(-)

diff --git a/src/modules/cdi/lib/cache.c b/src/modules/cdi/lib/cache.c
index 17b88c9..af8ed4e 100644
--- a/src/modules/cdi/lib/cache.c
+++ b/src/modules/cdi/lib/cache.c
@@ -328,6 +328,22 @@ static inline struct block* get_hint(struct cache* cache, uint64_t block)
 }
 
 /**
+ * Hint entfernen
+ *
+ * @param b Block-Struktur, die für die alte Blocknummer ungültig wurde
+ */
+static inline void invalidate_hint(struct cache* cache, struct block* b)
+{
+    int i;
+
+    for (i = 0; i < HINTCNT; i++) {
+        if (cache->hints[i] == b) {
+            cache->hints[i] = NULL;
+        }
+    }
+}
+
+/**
  * Hint setzen
  *
  * @param block Blocknummer
@@ -419,7 +435,6 @@ struct cdi_cache_block* cdi_cache_block_get(struct cdi_cache* cache,
     }
 
     if (!b) {
-        int in_tree = 0;
         if (c->blocks_used < c->block_count) {
             // Wir duerfen noch mehr neue Blocks in den Cache legen
             b = malloc(sizeof(*b));
@@ -436,8 +451,8 @@ struct cdi_cache_block* cdi_cache_block_get(struct cdi_cache* cache,
             if (!b) {
                 return NULL;
             }
-            in_tree = 1;
             tree_remove(c->tree, b);
+            invalidate_hint(c, b);
             b->cdi.number = blocknum;
             tree_insert(c->tree, b);
         }
@@ -446,19 +461,22 @@ struct cdi_cache_block* cdi_cache_block_get(struct cdi_cache* cache,
         if (!noread && !load_block(c, b)) {
             puts("cdi_cache: Einlesen des Blocks fehlgeschlagen.");
 
-            // Wenn der Knoten bis jetzt im Baum war, muss er rausgeworfen
-            // werden
-            if (in_tree) {
-                tree_remove(c->tree, b);
-
-                // Auch aus der LRU-Liste muss der Block ggf. entfernt werden
-                if (b->lru_next) {
-                    b->lru_next->lru_prev = b->lru_prev;
-                }
-                if (b->lru_prev) {
-                    b->lru_prev->lru_next = b->lru_next;
-                }
+            tree_remove(c->tree, b);
+
+            if (b->lru_next) {
+                b->lru_next->lru_prev = b->lru_prev;
             }
+            if (b->lru_prev) {
+                b->lru_prev->lru_next = b->lru_next;
+            }
+            if (c->lru_first == b) {
+                c->lru_first = b->lru_prev;
+            }
+            if (c->lru_last == b) {
+                c->lru_last = b->lru_next;
+            }
+            invalidate_hint(c, b);
+
             c->blocks_used--;
 
             free(b->cdi.data);
-- 
2.1.2