[kernel] Fix block copying in the cache
[monolithium.git] / kernel / src / cache.c
index ff0751df6603d9b0e3c8e3de1add14efd879e418..fdbed04a7811ec2468f23b4ef8f5673242f70d11 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * cache.c
- * 
+ *
  * Copyright (C) 2016 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
- * 
+ *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
  * published by the Free Software Foundation, either version 3 of the
@@ -17,7 +17,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <block_device.h>
+#include <device.h>
 #include <cache.h>
 #include <heap.h>
 
@@ -65,6 +65,7 @@ dword_t read_cache(cache_descriptor_t *cache, void *context, byte_t *buffer, qwo
     bool_t exclusive = FALSE;
 
     acquire_resource_shared(&cache->resource);
+    *bytes_read = 0;
 
     for (i = first_block; i <= last_block; i++)
     {
@@ -99,11 +100,24 @@ dword_t read_cache(cache_descriptor_t *cache, void *context, byte_t *buffer, qwo
             element = &new_entry->tree;
         }
 
-        cache_entry_t *entry = CONTAINER_OF(element, cache_entry_t, tree);  
-        if (i == first_block) start_offset = (dword_t)(offset % (qword_t)cache->block_size);
-        if (i == last_block) bytes_to_copy = (dword_t)((offset + length - 1) % (qword_t)cache->block_size) - start_offset + 1;
+        cache_entry_t *entry = CONTAINER_OF(element, cache_entry_t, tree);
+
+        if (first_block == last_block)
+        {
+            start_offset = (dword_t)(offset % (qword_t)cache->block_size);
+            bytes_to_copy = length;
+        }
+        else if (i == first_block)
+        {
+            start_offset = (dword_t)(offset % (qword_t)cache->block_size);
+            bytes_to_copy -= start_offset;
+        }
+        else if (i == last_block)
+        {
+            bytes_to_copy = length - *bytes_read;
+        }
 
-        memcpy(&buffer[(i - first_block) * cache->block_size], &entry->data[start_offset], bytes_to_copy);
+        memcpy(&buffer[*bytes_read], &entry->data[start_offset], bytes_to_copy);
         *bytes_read += bytes_to_copy;
     }
 
@@ -119,6 +133,7 @@ dword_t write_cache(cache_descriptor_t *cache, void *context, const byte_t *buff
     qword_t last_block = (offset + length - 1) / (qword_t)cache->block_size;
 
     acquire_resource_exclusive(&cache->resource);
+    *bytes_written = 0;
 
     for (i = first_block; i <= last_block; i++)
     {
@@ -148,11 +163,24 @@ dword_t write_cache(cache_descriptor_t *cache, void *context, const byte_t *buff
             element = &new_entry->tree;
         }
 
-        cache_entry_t *entry = CONTAINER_OF(element, cache_entry_t, tree);  
-        if (i == first_block) start_offset = (dword_t)(offset % (qword_t)cache->block_size);
-        if (i == last_block) bytes_to_copy = (dword_t)((offset + length) % (qword_t)cache->block_size) - start_offset;
+        cache_entry_t *entry = CONTAINER_OF(element, cache_entry_t, tree);
+
+        if (first_block == last_block)
+        {
+            start_offset = (dword_t)(offset % (qword_t)cache->block_size);
+            bytes_to_copy = length;
+        }
+        else if (i == first_block)
+        {
+            start_offset = (dword_t)(offset % (qword_t)cache->block_size);
+            bytes_to_copy -= start_offset;
+        }
+        else if (i == last_block)
+        {
+            bytes_to_copy = length - *bytes_written;
+        }
 
-        memcpy(&entry->data[start_offset], &buffer[(i - first_block) * cache->block_size], bytes_to_copy);
+        memcpy(&entry->data[start_offset], &buffer[*bytes_written], bytes_to_copy);
         *bytes_written += bytes_to_copy;
 
         if (cache->flags & CACHE_WRITE_THROUGH)