First cut at inode swapping, works, may have an inode leak somewhere
authorNick Downing <nick@ndcode.org>
Tue, 9 Apr 2019 14:10:56 +0000 (00:10 +1000)
committerNick Downing <nick@ndcode.org>
Tue, 9 Apr 2019 14:10:56 +0000 (00:10 +1000)
Makefile
inode_test_run.c
o.sh
process.c
process.h
process_test_run.c

index 3c1ae44..b36b816 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -19,13 +19,13 @@ process_test_gen: process_test_gen.o
 
 process_test_gen.o: process_test_gen.c
 
-process_test_run: process_test_run.o process.o core.o swap.o pool.o
+process_test_run: process_test_run.o process.o core.o fuzix_fs_or_swap.o pool.o
        ${CC} ${CFLAGS} -o $@ $^
 
-process_test_run.o: process_test_run.c process.h core.h swap.h pool.h 
-process.o: process.c process.h core.h swap.h pool.h
+process_test_run.o: process_test_run.c process.h core.h swap.h pool.h fuzix_fs.h util.h
+process.o: process.c process.h core.h swap.h pool.h fuzix_fs.h
 core.o: core.c core.h pool.h
-swap.o: swap.c swap.h core.h pool.h
+fuzix_fs_or_swap.o: fuzix_fs_or_swap.c fuzix_fs.c swap.h core.h pool.h fuzix_fs.h
 
 ucp.o: ucp.c fuzix_fs.h
 fuzix_fs.o: fuzix_fs.c fuzix_fs.h
index 77e899b..ed6a111 100644 (file)
@@ -27,7 +27,7 @@ bool hash_init(int file, struct cinode *inode, int base, int limit) {
 
     uint8_t buf[TRANSFER_SIZE];
     for (int i = 0; i < count; ++i) {
-      long long hash = file * 17 + (ptr + i) * 29;
+      long long hash = file * 17 + (i + ptr) * 29;
       hash = (hash & 0xffffffffLL) + (hash >> 32);
       hash = (hash & 0xffffLL) + (hash >> 16);
       hash = (hash & 0xffLL) + (hash >> 8);
@@ -60,15 +60,13 @@ void hash_verify(int file, struct cinode *inode, int base, int limit) {
     rassert(readi(inode) == count && udata.u_error == 0);
 
     for (int i = 0; i < count; ++i) {
-      long long hash = file * 17 + (ptr + i) * 29;
+      long long hash = file * 17 + (i + ptr) * 29;
       hash = (hash & 0xffffffffLL) + (hash >> 32);
       hash = (hash & 0xffffLL) + (hash >> 16);
       hash = (hash & 0xffLL) + (hash >> 8);
       hash = (hash & 0xffLL) + (hash >> 8);
       rassert(buf[i] == (uint8_t)hash);
     }
-
-    base += count;
   }
 }
 
diff --git a/o.sh b/o.sh
index a2d40dc..edeccf3 100755 (executable)
--- a/o.sh
+++ b/o.sh
@@ -4,4 +4,7 @@ echo "generate test script"
 ./process_test_gen 16 248 1024 32 >process_test.txt
 
 echo "run test script"
-./process_test_run 16 64 192 8 384 384 <process_test.txt
+#./process_test_run 16 64 192 8 384 384 <process_test.txt
+rm -f fs.bin
+./mkfs fs.bin 256 16384
+./process_test_run 16 64 fs.bin 8 384 384 <process_test.txt
index be68d10..56a9092 100644 (file)
--- a/process.c
+++ b/process.c
 #include "core.h"
 #include "process.h"
 #include "rassert.h"
+
+#ifdef INODE_SWAP
+#define UCP 1
+#include "fuzix_fs.h"
+#else
 #include "swap.h"
+#endif
 
 struct process *processes;
 int n_processes;
 
-int process_avail, process_spare;
+#ifdef INODE_SWAP
+long process_avail;
+#else
+int process_avail;
+#endif
 
 struct lru_item lru_head;
 
 struct process *victim;
 
-#if 1
-// won't work when compiled with NDEBUG
-static void check_invariants() {
-  int avail =
-#ifdef INDIRECT_CORE
-    n_core_blocks +
-#else
-    core_table.item.base -
-    core_table.item.limit +
-#endif
-#ifdef INDIRECT_SWAP
-    n_swap_blocks -
-#else
-    swap_table.item.base -
-    swap_table.item.limit -
-#endif
-    process_spare;
-#if defined(PREALLOCATE_CORE)
-  if (avail > core_table.item.base - core_table.item.limit)
-    avail = core_table.item.base - core_table.item.limit;
-#endif
-#if defined(PREALLOCATE_SWAP)
-  if (avail > swap_table.item.base - swap_table.item.limit)
-    avail = swap_table.item.base - swap_table.item.limit;
-#endif
-  if (victim == NULL) {
-#ifdef PREALLOCATE_CORE
-    assert(victim_core_blocks == 0);
-#endif
-#ifdef PREALLOCATE_SWAP
-    assert(victim_swap_blocks == 0);
-#endif
-  }
-  for (int i = 0; i < n_processes; ++i)
-    if (processes[i].size == -1L) {
-      assert(
-        processes[i].core_item.prev == NULL &&
-        processes[i].core_item.next == NULL
-      );
-      assert(
-        processes[i].swap_item.prev == NULL &&
-        processes[i].swap_item.next == NULL
-      );
-    }
-    else {
-#ifdef PREALLOCATE_CORE
-      assert(processes[i].core_item.prev && processes[i].core_item.next);
-#endif
-#ifdef PREALLOCATE_SWAP
-      assert(processes[i].swap_item.prev && processes[i].swap_item.next);
-#endif
-      if (processes[i].lru_item.prev) {
-        assert(processes + i != victim);
-        assert(processes[i].lru_item.prev->next == &processes[i].lru_item);
-        assert(processes[i].lru_item.next->prev == &processes[i].lru_item);
-#ifndef PREALLOCATE_CORE
-        assert(processes[i].core_item.prev && processes[i].core_item.next);
-        assert(
-          (int)((processes[i].size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT) ==
-            processes[i].core_item.limit - processes[i].core_item.base
-        );
-#endif
-#ifndef PREALLOCATE_SWAP
-        assert(
-          processes[i].swap_item.prev == NULL &&
-          processes[i].swap_item.next == NULL
-        );
-#endif
-      } 
-      else if (processes + i == victim) {
-        assert(victim->core_item.prev && victim->core_item.next);
-#ifndef PREALLOCATE_CORE
-        int victim_core_blocks =
-          victim->core_item.limit - victim->core_item.base;
-#endif
-        assert(victim_core_blocks);
-        assert(victim->swap_item.prev && victim->swap_item.next);
-#ifndef PREALLOCATE_SWAP
-        int victim_swap_blocks =
-          victim->swap_item.limit - victim->swap_item.base;
-#endif
-        assert(victim_swap_blocks);
-        assert(
-          (int)((processes[i].size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT) ==
-            victim_core_blocks + victim_swap_blocks
-        );
-      }
-      else {
-#ifndef PREALLOCATE_CORE
-        assert(
-          processes[i].core_item.prev == NULL &&
-          processes[i].core_item.next == NULL
-        );
-#endif
-#ifndef PREALLOCATE_SWAP
-        assert(processes[i].swap_item.prev && processes[i].swap_item.next);
-        assert(
-          (int)((processes[i].size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT) ==
-            processes[i].swap_item.limit - processes[i].swap_item.base
-        );
-#endif
-      }
-      avail -= (int)((processes[i].size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
+#ifdef INODE_SWAP
+long estimate_size(long size) {
+  long core_size;
+  int blocks, disk_blocks;
+  long disk_size;
+
+  core_size = (size + (BLOCK_SIZE - 1)) & ~(BLOCK_SIZE - 1);
+  assert(size < (long)DISK_BLOCK_SIZE << 16);
+  blocks = (int)((size + (DISK_BLOCK_SIZE - 1)) >> DISK_BLOCK_SHIFT);
+  disk_blocks = blocks;
+  if (blocks > 18) {
+    // has indirect blocks
+    blocks = (blocks + (DISK_INDIRECT_SIZE - 1 - 18)) >> DISK_INDIRECT_SHIFT;
+    disk_blocks += blocks;
+    if (blocks > 1) {
+      // has double indirect disk_blocks
+      blocks = (blocks + (DISK_INDIRECT_SIZE - 1 - 1)) >> DISK_INDIRECT_SHIFT;
+      assert(blocks == 1);
+      disk_blocks += blocks;
     }
-  assert(avail == process_avail);
+  }
+  disk_size = (long)disk_blocks << DISK_BLOCK_SHIFT;
+  return core_size >= disk_size ? core_size : disk_size;
 }
 #endif
 
 void process_init(int n, int spare) {
+#if defined(INODE_SWAP) && defined(PREALLOCATE_CORE)
+  long core_table_avail;
+#endif
   processes = calloc(n, sizeof(struct process));
   rassert(processes);
   n_processes = n;
@@ -134,6 +66,16 @@ void process_init(int n, int spare) {
     processes[i].size = -1L;
 #endif
 
+#ifdef INODE_SWAP
+  process_avail =
+    ((long)(core_avail() - spare) << BLOCK_SHIFT) + 
+    ((long)fs_tab[0].s_tfree << DISK_BLOCK_SHIFT);
+#ifdef PREALLOCATE_CORE
+  core_table_avail = (long)core_table.avail << BLOCK_SHIFT;
+  if (process_avail > core_table.avail)
+    process_avail = core_table.avail;
+#endif
+#else
   process_avail = core_avail() + swap_avail() - spare;
 #ifdef PREALLOCATE_CORE
   if (process_avail > core_table.avail)
@@ -143,7 +85,7 @@ void process_init(int n, int spare) {
   if (process_avail > swap_table.avail)
     process_avail = swap_table.avail;
 #endif
-  process_spare = spare;
+#endif
 
   lru_head.prev = &lru_head;
   lru_head.next = &lru_head;
@@ -157,7 +99,6 @@ void process_init(int n, int spare) {
   victim_swap_blocks = 0;
 #endif
 #endif
- check_invariants();
 }
 
 static void do_swap_out(int swap_out) {
@@ -167,7 +108,11 @@ static void do_swap_out(int swap_out) {
 #ifndef PREALLOCATE_SWAP
   int victim_swap_blocks;
 #endif
+#ifdef INODE_SWAP
+  int blocks, core_base;
+#else
   int blocks, swap_base, core_base;
+#endif
   long size;
 #if defined(INDIRECT_CORE) || defined(INDIRECT_SWAP)
   int i, j;
@@ -178,16 +123,22 @@ static void do_swap_out(int swap_out) {
     if (victim) {
       // calculate amount to swap out
 #ifndef PREALLOCATE_CORE
-      victim_core_blocks = victim->core_item.limit - victim->core_item.base;
+      victim_core_blocks =
+        victim->core_item.limit - victim->core_item.base;
 #endif
 #ifndef PREALLOCATE_SWAP
-      victim_swap_blocks = victim->swap_item.limit - victim->swap_item.base;
+      victim_swap_blocks =
+#ifdef INODE_SWAP
+        (int)(victim->swap_inode->c_node.i_size >> BLOCK_SHIFT);
+#else
+        victim->swap_item.limit - victim->swap_item.base;
+#endif
 #endif
       blocks = swap_out < victim_core_blocks ? swap_out : victim_core_blocks;
  printf("existing victim %d, swap out %d of %d\n", (int)(victim - processes), blocks, victim_core_blocks);
 
       // increase swap allocation
-#ifndef PREALLOCATE_SWAP
+#if !defined(INODE_SWAP) && !defined(PREALLOCATE_SWAP)
       rassert(
         swap_table_realloc(&victim->swap_item, victim_swap_blocks + blocks)
       );
@@ -216,17 +167,19 @@ static void do_swap_out(int swap_out) {
 
       // add to swap pool, using dedicated swap item
       victim_swap_blocks = 0;
-#ifndef PREALLOCATE_SWAP
+#if !defined(INODE_SWAP) && !defined(PREALLOCATE_SWAP)
       rassert(swap_table_alloc(&victim->swap_item, blocks));
 #endif
 
     loop_entry:
       // calculate transfer parameters
+#ifndef INODE_SWAP
 #ifdef PREALLOCATE_SWAP
       swap_base = victim->swap_item.base + victim_swap_blocks;
 #else
       swap_base = victim->swap_item.limit - blocks;
 #endif
+#endif
 #ifdef PREALLOCATE_CORE
       core_base = victim->core_item.base + victim_swap_blocks;
 #else
@@ -239,19 +192,31 @@ static void do_swap_out(int swap_out) {
       if (victim_core_blocks == 0)
         // yes, correct size for partial last block
         size += ((victim->size - 1L) | -BLOCK_SIZE) + 1L;
-      victim_swap_blocks += blocks;
 
       // transfer data to swap
 #ifdef INDIRECT_SWAP
       rassert(swap_block_alloc(swap_table_mem + swap_base, blocks));
 #endif
+#ifdef INODE_SWAP
+ printf("swap_write core [%d,%d) to swap [%d,%d)\n", core_base, core_base + blocks, victim_swap_blocks, victim_swap_blocks + blocks);
+#else
  printf("swap_write core [%d,%d) to swap [%d,%d)\n", core_base, core_base + blocks, swap_base, swap_base + blocks);
+#endif
 #if !defined(INDIRECT_CORE) && !defined(INDIRECT_SWAP)
+#ifdef INODE_SWAP
+      swap_write(
+        victim->swap_inode,
+        (long)victim_swap_blocks << BLOCK_SHIFT,
+        (long)core_base << BLOCK_SHIFT,
+        size
+      );
+#else
       core_to_swap_copy(
         (long)core_block << BLOCK_SHIFT,
         (long)swap_block << BLOCK_SHIFT,
         size
       );
+#endif
 #else
       j = (int)(size >> BLOCK_SHIFT);
  printf("blocks");
@@ -261,6 +226,14 @@ static void do_swap_out(int swap_out) {
         core_block = core_table_mem[core_block];
  printf(" %d", core_block);
 #endif
+#ifdef INODE_SWAP
+        swap_write(
+          victim->swap_inode,
+          (long)(victim_swap_blocks + i) << BLOCK_SHIFT,
+          (long)core_block << BLOCK_SHIFT,
+          size;
+        );
+#else
         int swap_block = swap_base + i;
 #ifdef INDIRECT_SWAP
         swap_block = swap_table_mem[swap_block];
@@ -275,6 +248,7 @@ static void do_swap_out(int swap_out) {
           (long)swap_block << BLOCK_SHIFT,
           BLOCK_SIZE
         );
+#endif
       }
       j = (int)size & (BLOCK_SIZE - 1);
       if (j) {
@@ -283,6 +257,14 @@ static void do_swap_out(int swap_out) {
         core_block = core_table_mem[core_block];
  printf(" %d", core_block);
 #endif
+#ifdef INODE_SWAP
+        swap_write(
+          victim->swap_inode,
+          (long)(victim_swap_blocks + i) << BLOCK_SHIFT,
+          (long)core_block << BLOCK_SHIFT,
+          j;
+        );
+#else
         int swap_block = swap_base + i;
 #ifdef INDIRECT_SWAP
         swap_block = swap_table_mem[swap_block];
@@ -298,12 +280,14 @@ static void do_swap_out(int swap_out) {
           (long)swap_block << BLOCK_SHIFT,
           j
         );
+#endif
       }
  printf("\n");
 #endif
 #ifdef INDIRECT_CORE
       core_block_free(core_table_mem + core_base, blocks);
 #endif
+      victim_swap_blocks += blocks;
 
       // see if victim fully swapped out
       if (victim_core_blocks) {
@@ -338,12 +322,36 @@ static void do_swap_out(int swap_out) {
 }
 
 bool process_alloc(struct process *process, long size) {
+#ifdef INODE_SWAP
+  long estimated_size;
+#endif
   int blocks, swap_out;
 
   // must not be already allocated
   assert(process->size == -1L);
 
   // check blocks
+#ifdef INODE_SWAP
+  estimated_size = estimate_size(size);
+  if (
+    process_avail < estimated_size ||
+    (process->swap_inode = i_open(0, 0)) == NULL
+  )
+    return false;
+
+  // initialize swap inode
+  process->swap_inode->c_node.i_uid = udata.u_euid;
+  process->swap_inode->c_node.i_gid = udata.u_egid;
+
+  process->swap_inode->c_node.i_mode = F_REG;   /* For the time being */
+  process->swap_inode->c_node.i_nlink = 0;
+  process->swap_inode->c_node.i_size = 0;
+  for (int i = 0; i < 20; ++i)
+    process->swap_inode->c_node.i_addr[i] = 0;
+  wr_inode(process->swap_inode);
+
+  blocks = (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
+#else
   blocks = (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
   if (
     process_avail < blocks
@@ -352,6 +360,7 @@ bool process_alloc(struct process *process, long size) {
 #endif
   )
     return false;
+#endif
 
   // free up as much core as we need to
   swap_out = blocks - core_avail();
@@ -362,7 +371,9 @@ bool process_alloc(struct process *process, long size) {
   rassert(core_table_alloc(&process->core_item, blocks));
 #else
   if (!core_table_alloc(&process->core_item, blocks)) {
-#if defined(PREALLOCATE_SWAP) && !defined(MOVEABLE_SWAP)
+#ifdef INODE_SWAP
+    i_deref(process->core_inode);
+#elif defined(PREALLOCATE_SWAP) && !defined(MOVEABLE_SWAP)
     swap_table_free(&process->swap_item);
 #endif
     return false;
@@ -390,12 +401,18 @@ bool process_alloc(struct process *process, long size) {
 
   // track total allocation
   process->size = size;
+#ifdef INODE_SWAP
+  process_avail -= estimated_size;
+#else
   process_avail -= blocks;
- check_invariants();
+#endif
   return true;
 }
 
 bool process_realloc(struct process *process, long size) {
+#ifdef INODE_SWAP
+  long estimated_size, old_estimated_size, estimated_size_change;
+#endif
   int blocks, old_blocks, swap_out;
 
   // must be already allocated
@@ -405,11 +422,24 @@ bool process_realloc(struct process *process, long size) {
   assert(process->lru_item.prev != NULL);
 
   // check blocks
+#ifdef INODE_SWAP
+  estimated_size = estimate_size(size);
+  old_estimated_size = estimate_size(process->size);
+  estimated_size_change = estimated_size - old_estimated_size;
+  if (process_avail < estimated_size_change)
+    return false;
+
+  blocks = (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
+  old_blocks = (int)((process->size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
+  int blocks_change = blocks - old_blocks;
+#else 
   blocks = (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
   old_blocks = (int)((process->size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
   int blocks_change = blocks - old_blocks;
   if (process_avail < blocks_change)
     return false;
+#endif
 #if defined(PREALLOCATE_SWAP) && !defined(MOVEABLE_SWAP)
   swap_table_free(&process->swap_item);
   if (!swap_table_alloc(&process->swap_item, blocks)) {
@@ -457,15 +487,27 @@ bool process_realloc(struct process *process, long size) {
  
   // track total allocation
   process->size = size;
+#ifdef INODE_SWAP
+  process_avail -= estimated_size_change;
+#else
   process_avail -= blocks_change;
- check_invariants();
+#endif
   return true;
 }
 
 void process_run(struct process *process) {
-  int blocks, swap_out, excess;
+  int blocks, swap_out;
+#ifndef INODE_SWAP // temporarily remove until we can fix the logic
+#if !defined(PREALLOCATE_SWAP) || defined(INDIRECT_SWAP)
+  int excess;
+#endif
+#endif
   int process_core_blocks, process_swap_blocks;
+#ifdef INODE_SWAP
+  int core_base;
+#else
   int swap_base, core_base;
+#endif
   long size;
 #if defined(INDIRECT_CORE) || defined(INDIRECT_SWAP)
   int i, j;
@@ -488,17 +530,26 @@ void process_run(struct process *process) {
     if (process != victim) {
       // fully in swap, only the swap item is meaningful
       process_swap_blocks =
+#ifdef INODE_SWAP
+        (int)(
+          ((long)process->swap_inode->c_node.i_size + (BLOCK_SIZE - 1)) >>
+          BLOCK_SHIFT
+        );
+#else
         process->swap_item.limit - process->swap_item.base;
+#endif
 
       // calculate amounts to swap out then in
       blocks = process_swap_blocks;
       swap_out = blocks - core_avail();
+#ifndef INODE_SWAP // temporarily remove until we can fix the logic
 #if !defined(PREALLOCATE_SWAP) || defined(INDIRECT_SWAP)
       excess = swap_out - swap_avail();
       if (excess > 0) {
         blocks -= excess;
         swap_out = swap_avail();
       }
+#endif
 #endif
 
       // free up as much core as we can
@@ -529,7 +580,11 @@ void process_run(struct process *process) {
 #endif
 #else
     process_swap_blocks =
+#ifdef INODE_SWAP
+      (int)(victim->swap_inode->c_node.i_size >> BLOCK_SHIFT);
+#else
       victim->swap_item.limit - victim->swap_item.base;
+#endif
 #endif
     victim = NULL;
 #ifndef PREALLOCATE_SWAP
@@ -540,18 +595,26 @@ void process_run(struct process *process) {
     do {
 #ifndef PREALLOCATE_SWAP
       // reduce swap allocation
+#ifdef INODE_SWAP
+      udata.u_offset = (long)process_swap_blocks << BLOCK_SHIFT;
+      f_trunc(process->swap_inode);
+#else
       rassert(swap_table_realloc(&process->swap_item, process_swap_blocks));
+#endif
 
     loop_entry_partial:
 #endif
       // calculate amounts to swap out then in
       blocks = process_swap_blocks;
       swap_out = blocks - core_avail();
+#ifndef INODE_SWAP // temporarily remove until we can fix the logic
 #if !defined(PREALLOCATE_SWAP) || defined(INDIRECT_SWAP)
-      if (swap_out > swap_avail()) {
-        blocks += swap_avail() - swap_out;
+      excess = swap_out - swap_avail();
+      if (excess > 0) {
+        blocks -= excess;
         swap_out = swap_avail();
       }
+#endif
 #endif
 
       // free up as much core as we can
@@ -570,11 +633,13 @@ void process_run(struct process *process) {
     loop_entry_full:
       // calculate transfer parameters
       process_swap_blocks -= blocks;
+#ifndef INODE_SWAP
 #ifdef PREALLOCATE_SWAP
       swap_base = process->swap_item.base + process_swap_blocks;
 #else
       swap_base = process->swap_item.limit - blocks;
 #endif
+#endif
 #ifdef PREALLOCATE_CORE
       core_base = process->core_item.base + process_swap_blocks;
 #else
@@ -593,29 +658,50 @@ void process_run(struct process *process) {
 #ifdef INDIRECT_CORE
       core_block_alloc(core_table_mem + core_base, blocks);
 #endif
+#ifdef INODE_SWAP
+ printf("swap_read swap [%d,%d) to core [%d,%d)\n", process_swap_blocks, process_swap_blocks + blocks, core_base, core_base + blocks);
+#else
  printf("swap_read swap [%d,%d) to core [%d,%d)\n", swap_base, swap_base + blocks, core_base, core_base + blocks);
+#endif
 #if !defined(INDIRECT_CORE) && !defined(INDIRECT_SWAP)
+#ifdef INODE_SWAP
+      swap_read(
+        process->swap_inode,
+        (long)process_swap_blocks << BLOCK_SHIFT,
+        (long)core_base << BLOCK_SHIFT,
+        size
+      );
+#else
       swap_to_core_copy(
         (long)swap_block << BLOCK_SHIFT,
         (long)core_block << BLOCK_SHIFT,
         size
       );
+#endif
 #else
       j = (int)(size >> BLOCK_SHIFT);
  printf("blocks");
       for (i = 0; i < j; ++i) {
-        int swap_block = swap_base + i;
-#ifdef INDIRECT_SWAP
-        swap_block = swap_table_mem[swap_block];
- printf(" %d", swap_block);
-#endif
         int core_block = core_base + i;
 #ifdef INDIRECT_CORE
         core_block = core_table_mem[core_block];
+ printf(" %d", core_block);
+#endif
+#ifdef INODE_SWAP
+        swap_read(
+          process->swap_inode,
+          (long)(process_swap_blocks + i) << BLOCK_SHIFT,
+          (long)core_block << BLOCK_SHIFT,
+          BLOCK_SIZE;
+        );
+#else
+        int swap_block = swap_base + i;
 #ifdef INDIRECT_SWAP
- printf(",%d", core_block);
+        swap_block = swap_table_mem[swap_block];
+#ifdef INDIRECT_SWAP
+ printf(",%d", swap_block);
 #else
- printf(" %d", core_block);
+ printf(" %d", swap_block);
 #endif
 #endif
         swap_to_core_copy(
@@ -623,29 +709,38 @@ void process_run(struct process *process) {
           (long)core_block << BLOCK_SHIFT,
           BLOCK_SIZE
         );
+#endif
       }
       j = (int)size & (BLOCK_SIZE - 1);
       if (j) {
-        int swap_block = swap_base + i;
-#ifdef INDIRECT_SWAP
-        swap_block = swap_table_mem[swap_block];
- printf(" %d", swap_block);
-#endif
         int core_block = core_base + i;
 #ifdef INDIRECT_CORE
         core_block = core_table_mem[core_block];
+ printf(" %d", core_block);
+#endif
+#ifdef INODE_SWAP
+        swap_read(
+          process->swap_inode,
+          (long)(process_swap_blocks + i) << BLOCK_SHIFT,
+          (long)core_block << BLOCK_SHIFT,
+          BLOCK_SIZE;
+        );
+#else
+        int swap_block = swap_base + i;
+#ifdef INDIRECT_SWAP
+        swap_block = swap_table_mem[swap_block];
 #ifdef INDIRECT_SWAP
- printf(",%d", core_block);
+ printf(",%d", swap_block);
 #else
- printf(" %d", core_block);
+ printf(" %d", swap_block);
 #endif
 #endif
- putchar('*');
         swap_to_core_copy(
           (long)swap_block << BLOCK_SHIFT,
           (long)core_block << BLOCK_SHIFT,
           j 
         );
+#endif
       }
  printf("\n");
 #endif
@@ -654,7 +749,11 @@ void process_run(struct process *process) {
 #endif
     } while (process_swap_blocks);
 
-#ifndef PREALLOCATE_SWAP
+#ifdef INODE_SWAP
+    // delete swap data, retain swap inode
+    udata.u_offset = 0;
+    f_trunc(process->swap_inode);
+#elif !defined(PREALLOCATE_SWAP)
     // remove from swap pool
     swap_table_free(&process->swap_item);
 #endif
@@ -665,7 +764,6 @@ void process_run(struct process *process) {
   process->lru_item.next = lru_head.next;
   process->lru_item.prev->next = &process->lru_item;
   process->lru_item.next->prev = &process->lru_item;
- check_invariants();
 }
 
 void process_free(struct process *process) {
@@ -715,13 +813,17 @@ void process_free(struct process *process) {
 #endif
 #ifdef PREALLOCATE_SWAP
     victim_swap_blocks = 0;
-#else
+#elif !defined(INODE_SWAP)
     swap_table_free(&victim->swap_item);
 #endif
 #ifdef INDIRECT_CORE
 #ifdef PREALLOCATE_CORE
 #if defined(PREALLOCATE_SWAP) || defined(INDIRECT_SWAP)
     core_base = victim->core_item.base + victim_swap_blocks;
+#elif defined(INODE_SWAP)
+    core_base =
+      victim->core_item.base +
+      (int)(victim->swap_inode.c_node.i_size >> BLOCK_SHIFT);
 #else
     core_base =
       victim->core_item.base +
@@ -750,7 +852,7 @@ void process_free(struct process *process) {
       process->swap_item.limit - swap_base
     );
 #endif
-#ifndef PREALLOCATE_SWAP
+#if !defined(INODE_SWAP) && !defined(PREALLOCATE_SWAP)
     swap_table_free(&process->swap_item);
 #endif
   }
@@ -761,12 +863,17 @@ void process_free(struct process *process) {
 #endif
 #ifdef PREALLOCATE_SWAP
   swap_table_free(&process->swap_item);
+#elif defined(INODE_SWAP)
+  i_deref(process->swap_inode);
 #endif
  
   // track total allocation
+#ifdef INODE_SWAP
+  process_avail += estimate_size(process->size);
+#else
   process_avail += (int)((process->size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
+#endif
 #ifndef NDEBUG
   process->size = -1L;
 #endif
- check_invariants();
 }
index aa82c82..0fe70db 100644 (file)
--- a/process.h
+++ b/process.h
@@ -6,6 +6,12 @@
 #define BLOCK_SIZE 0x1000
 #define BLOCK_SHIFT 12
 
+#define INODE_SWAP 1
+#define DISK_BLOCK_SIZE 0x200
+#define DISK_BLOCK_SHIFT 9
+#define DISK_INDIRECT_SIZE 0x100
+#define DISK_INDIRECT_SHIFT 8
+
 struct lru_item {
   struct lru_item *prev;
   struct lru_item *next;
@@ -14,12 +20,20 @@ struct lru_item {
 extern struct process {
   struct lru_item lru_item; // must be first
   struct pool_item core_item;
+#ifdef INODE_SWAP
+  struct cinode *swap_inode;
+#else
   struct pool_item swap_item;
+#endif
   long size; // brk level
 } *processes;
 int n_processes;
 
-extern int process_avail, process_spare;
+#ifdef INODE_SWAP
+extern long process_avail;
+#else
+extern int process_avail;
+#endif
 
 extern struct lru_item lru_head;
 
@@ -32,7 +46,22 @@ void process_run(struct process *process);
 void process_free(struct process *process);
  
 // abstract
+#ifdef INODE_SWAP
+void swap_read(
+  struct cinode *inode,
+  long offset,
+  long core_base,
+  long size
+);
+void swap_write(
+  struct cinode *inode,
+  long offset,
+  long core_base,
+  long size
+);
+#else
 void core_to_swap_copy(long src_base, long dest_base, long size);
 void swap_to_core_copy(long src_base, long dest_base, long size);
+#endif
 
 #endif
index 510ce58..589ff96 100644 (file)
@@ -5,10 +5,21 @@
 #include "core.h"
 #include "process.h"
 #include "rassert.h"
+
+#ifdef INODE_SWAP
+#define UCP 1
+#include "fuzix_fs.h"
+#include "util.h"
+#else
 #include "swap.h"
+#endif
+
+#define TRANSFER_SIZE 0x8000
 
 uint8_t *core_block_mem;
+#ifndef INODE_SWAP
 uint8_t *swap_block_mem;
+#endif
 
 void core_hash_init(int process, long base, long size, long offset) {
  //printf("core_hash_init %d %ld(%d) %ld(%d) %ld(%d)\n", process, base, (int)(base >> BLOCK_SHIFT), size, (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT), offset, (int)(offset >> BLOCK_SHIFT));
@@ -49,8 +60,37 @@ void core_hash_verify(int process, long base, long size, long offset) {
   }
 }
 
-void swap_hash_verify(int process, long base, long size, long offset) {
- //printf("swap_hash_verify %d %ld(%d) %ld(%d) %ld(%d)\n", process, base, (int)(base >> BLOCK_SHIFT), size, (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT), offset, (int)(offset >> BLOCK_SHIFT));
+#ifdef INODE_SWAP
+void swap_hash_verify(int process, struct cinode *inode) {
+  long count;
+  for (
+    long offset = 0;
+    (count = (long)inode->c_node.i_size - offset) > 0;
+    offset += count
+  ) {
+    if (count > TRANSFER_SIZE)
+      count = TRANSFER_SIZE;
+
+    uint8_t buf[TRANSFER_SIZE];
+    udata.u_base = (char *)buf;
+    udata.u_count = count;
+    udata.u_offset = offset;
+    udata.u_error = 0;
+    rassert(readi(inode) == count && udata.u_error == 0);
+
+    for (int i = 0; i < count; ++i) {
+      long long hash = process * 17 + (i + offset) * 29;
+      hash = (hash & 0xffffffffLL) + (hash >> 32);
+      hash = (hash & 0xffffLL) + (hash >> 16);
+      hash = (hash & 0xffLL) + (hash >> 8);
+      hash = (hash & 0xffLL) + (hash >> 8);
+      rassert(buf[i] == (uint8_t)hash);
+    }
+  }
+}
+#else
+void swap_hash_verify(int process, long base, long size) {
+ //printf("swap_hash_verify %d %ld(%d) %ld(%d)\n", process, base, (int)(base >> BLOCK_SHIFT), size, (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT));
   for (long i = 0L; i < size; ++i) {
     long addr = base + i;
 #ifdef INDIRECT_SWAP
@@ -58,7 +98,7 @@ void swap_hash_verify(int process, long base, long size, long offset) {
       (swap_table_mem[addr >> BLOCK_SHIFT] << BLOCK_SHIFT) |
       (addr & (BLOCK_SIZE - 1));
 #endif
-    long long hash = process * 17 + (i + offset) * 29;
+    long long hash = process * 17 + i * 29;
     hash = (hash & 0xffffffffLL) + (hash >> 32);
     hash = (hash & 0xffffLL) + (hash >> 16);
     hash = (hash & 0xffLL) + (hash >> 8);
@@ -67,6 +107,7 @@ void swap_hash_verify(int process, long base, long size, long offset) {
     swap_block_mem[addr] = 0xaa;
   }
 }
+#endif
 
 #ifndef INDIRECT_CORE
 void core_copy(long src_base, long dest_base, long size) {
@@ -91,6 +132,52 @@ void core_copy_up(long src_limit, long dest_limit, long size) {
 }
 #endif
 
+#ifdef INODE_SWAP
+void swap_read(
+  struct cinode *inode,
+  long offset,
+  long core_base,
+  long size
+) {
+ //printf("read %ld %ld %ld\n", offset, core_base, size);
+  for (long i = 0; i < size; ++i)
+    rassert(core_block_mem[core_base + i] == 0xaa);
+
+  long count;
+  for (long i = 0; (count = size - i) > 0; i += count) {
+    if (count > TRANSFER_SIZE)
+      count = TRANSFER_SIZE;
+    udata.u_base = (char *)(core_block_mem + core_base + i);
+    udata.u_count = (int)count;
+    udata.u_offset = (uint32_t)(offset + i);
+    udata.u_error = 0;
+    rassert(readi(inode) == (int)count && udata.u_error == 0);
+  }
+}
+
+void swap_write(
+  struct cinode *inode,
+  long offset,
+  long core_base,
+  long size
+) {
+ //printf("write %ld %ld %ld\n", offset, core_base, size);
+  long count;
+  for (long i = 0; (count = size - i) > 0; i += count) {
+    if (count > TRANSFER_SIZE)
+      count = TRANSFER_SIZE;
+    udata.u_base = (char *)(core_block_mem + core_base + i);
+    udata.u_count = (int)count;
+    udata.u_offset = (uint32_t)(offset + i);
+    udata.u_error = 0;
+    rassert(writei(inode) == (int)count && udata.u_error == 0);
+  }
+
+  memset(core_block_mem + core_base, 0xaa, size);
+}
+#else
 #ifndef INDIRECT_SWAP
 void swap_copy(long src_base, long dest_base, long size) {
  //printf("swap_copy %ld(%d) %ld(%d) %ld(%d)\n", src_base, (int)(src_base >> BLOCK_SHIFT), dest_base, (int)(dest_base >> BLOCK_SHIFT), size, (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT));
@@ -129,23 +216,37 @@ void swap_to_core_copy(long src_base, long dest_base, long size) {
   memcpy(core_block_mem + dest_base, swap_block_mem + src_base, size);
   memset(swap_block_mem + src_base, 0xaa, size);
 }
+#endif
 
 int main(int argc, char **argv) {
   if (argc < 5) {
+    printf(
+      "usage: %s n_processes n_core_blocks "
+#ifdef INODE_SWAP
+      "fs_path "
+#else
+      "n_swap_blocks "
+#endif
+      "spare"
 #if defined(INDIRECT_CORE) && defined(INDIRECT_SWAP)
-    printf("usage: %s n_processes n_core_blocks n_swap_blocks spare [core_table_blocks [swap_table_blocks]]\n", argv[0]);
+      "[core_table_blocks [swap_table_blocks]]"
 #elif defined(INDIRECT_CORE)
-    printf("usage: %s n_processes n_core_blocks n_swap_blocks spare [core_table_blocks]\n", argv[0]);
+      "[core_table_blocks]"
 #elif defined(INDIRECT_SWAP)
-    printf("usage: %s n_processes n_core_blocks n_swap_blocks spare [swap_table_blocks]\n", argv[0]);
-#else
-    printf("usage: %s n_processes n_core_blocks n_swap_blocks spare\n", argv[0]);
+      "[swap_table_blocks]"
 #endif
+      "\n",
+      argv[0]
+    );
     exit(EXIT_FAILURE);
   }
   int n_processes = atoi(argv[1]);
   int n_core_blocks = atoi(argv[2]);
+#ifdef INODE_SWAP
+  char *fs_path = argv[3];
+#else
   int n_swap_blocks = atoi(argv[3]);
+#endif
   int spare = atoi(argv[4]);
 #if defined(INDIRECT_CORE) && defined(INDIRECT_SWAP)
   int core_table_blocks = argc >= 6 ? atoi(argv[5]) : n_core_blocks;
@@ -155,9 +256,6 @@ int main(int argc, char **argv) {
 #elif defined(INDIRECT_SWAP)
   int swap_table_blocks = argc >= 6 ? atoi(argv[5]) : n_swap_blocks;
 #endif
-  swap_block_mem = malloc((long)n_swap_blocks << BLOCK_SHIFT);
-  rassert(swap_block_mem);
-  memset(swap_block_mem, 0xaa, (long)n_swap_blocks << BLOCK_SHIFT);
 
 #ifdef INDIRECT_CORE
   core_init(n_core_blocks, core_table_blocks);
@@ -168,11 +266,21 @@ int main(int argc, char **argv) {
   rassert(core_block_mem);
   memset(core_block_mem, 0xaa, (long)n_core_blocks << BLOCK_SHIFT);
 
+#ifdef INODE_SWAP
+  fd_open(fs_path);
+  xfs_init(0);
+  printf("free inodes %d blocks %d\n", fs_tab[0].s_tinode, fs_tab[0].s_tfree);
+#else
 #ifdef INDIRECT_SWAP
   swap_init(n_swap_blocks, swap_table_blocks);
 #else
   swap_init(n_swap_blocks);
 #endif
+  swap_block_mem = malloc((long)n_swap_blocks << BLOCK_SHIFT);
+  rassert(swap_block_mem);
+  memset(swap_block_mem, 0xaa, (long)n_swap_blocks << BLOCK_SHIFT);
+#endif
+
   process_init(n_processes, spare);
   for (int i = 0; i < n_processes; ++i)
     processes[i].size = -1L;
@@ -266,7 +374,7 @@ int main(int argc, char **argv) {
         printf("... not allocated, ignore\n");
       else {
         int core_base = processes[process].core_item.base;
-        int actual_old_size = processes[process].size;
+        long actual_old_size = processes[process].size;
         int actual_old_blocks =
           (int)((actual_old_size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
         rassert(
@@ -374,30 +482,41 @@ int main(int argc, char **argv) {
           core_blocks = processes[process].core_item.limit - core_base;
           core_size = processes[process].size;
         }
-        else if (processes + process == victim) { // victim
-          swap_base = victim->swap_item.base;
+        else {
+#ifdef INODE_SWAP
+          swap_base = 0;
+          swap_size = (long)processes[process].swap_inode->c_node.i_size;
+          swap_blocks = (int)((swap_size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
+#endif
+          if (processes + process == victim) { // victim
+#ifndef INODE_SWAP
+            swap_base = victim->swap_item.base;
 #ifdef PREALLOCATE_SWAP
-          swap_blocks = victim_swap_blocks;
+            swap_blocks = victim_swap_blocks;
 #else
-          swap_blocks = victim->swap_item.limit - victim->swap_item.base;
+            swap_blocks = victim->swap_item.limit - victim->swap_item.base;
+#endif
+            swap_size = swap_blocks << BLOCK_SHIFT;
 #endif
-          swap_size = swap_blocks << BLOCK_SHIFT;
 #ifdef PREALLOCATE_CORE
-          core_base = victim->core_item.base + swap_blocks;
-          core_blocks = victim_core_blocks;
+            core_base = victim->core_item.base + swap_blocks;
+            core_blocks = victim_core_blocks;
 #else
-          core_base = victim->core_item.base;
-          core_blocks = victim->core_item.limit - core_base;
+            core_base = victim->core_item.base;
+            core_blocks = victim->core_item.limit - core_base;
 #endif
-          core_size = victim->size - swap_size;
-        }
-        else { // fully in swap
-          swap_base = processes[process].swap_item.base;
-          swap_blocks = processes[process].swap_item.limit - swap_base;
-          swap_size = processes[process].size;
-          core_base = -1;
-          core_blocks = 0;
-          core_size = 0L;
+            core_size = victim->size - swap_size;
+          }
+          else { // fully in swap
+#ifndef INODE_SWAP
+            swap_base = processes[process].swap_item.base;
+            swap_blocks = processes[process].swap_item.limit - swap_base;
+            swap_size = processes[process].size;
+#endif
+            core_base = -1;
+            core_blocks = 0;
+            core_size = 0L;
+          }
         }
         rassert(core_blocks + swap_blocks == actual_old_blocks);
  printf("old core [%d,%d) swap [%d,%d)\n", core_base, core_base + core_blocks, swap_base, swap_base + swap_blocks);
@@ -410,9 +529,12 @@ int main(int argc, char **argv) {
         );
         swap_hash_verify(
           process,
+#ifdef INODE_SWAP
+          processes[process].swap_inode
+#else
           (long)swap_base << BLOCK_SHIFT,
-          swap_size,
-          0L
+          swap_size
+#endif
         );
         process_free(processes + process);
         processes[process].size = -1L;
@@ -442,30 +564,41 @@ done:
         core_blocks = processes[i].core_item.limit - core_base;
         core_size = processes[i].size;
       }
-      else if (processes + i == victim) { // victim
-        swap_base = victim->swap_item.base;
+      else {
+#ifdef INODE_SWAP
+        swap_base = 0;
+        swap_size = (long)processes[i].swap_inode->c_node.i_size;
+        swap_blocks = (int)((swap_size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
+#endif
+        if (processes + i == victim) { // victim
+#ifndef INODE_SWAP
+          swap_base = victim->swap_item.base;
 #ifdef PREALLOCATE_SWAP
-        swap_blocks = victim_swap_blocks;
+          swap_blocks = victim_swap_blocks;
 #else
-        swap_blocks = victim->swap_item.limit - victim->swap_item.base;
+          swap_blocks = victim->swap_item.limit - victim->swap_item.base;
+#endif
+          swap_size = swap_blocks << BLOCK_SHIFT;
 #endif
-        swap_size = swap_blocks << BLOCK_SHIFT;
 #ifdef PREALLOCATE_CORE
-        core_base = victim->core_item.base + swap_blocks;
-        core_blocks = victim_core_blocks;
+          core_base = victim->core_item.base + swap_blocks;
+          core_blocks = victim_core_blocks;
 #else
-        core_base = victim->core_item.base;
-        core_blocks = victim->core_item.limit - core_base;
+          core_base = victim->core_item.base;
+          core_blocks = victim->core_item.limit - core_base;
 #endif
-        core_size = victim->size - swap_size;
-      }
-      else { // fully in swap
-        swap_base = processes[i].swap_item.base;
-        swap_blocks = processes[i].swap_item.limit - swap_base;
-        swap_size = processes[i].size;
-        core_base = -1;
-        core_blocks = 0;
-        core_size = 0L;
+          core_size = victim->size - swap_size;
+        }
+        else { // fully in swap
+#ifndef INODE_SWAP
+          swap_base = processes[i].swap_item.base;
+          swap_blocks = processes[i].swap_item.limit - swap_base;
+          swap_size = processes[i].size;
+#endif
+          core_base = -1;
+          core_blocks = 0;
+          core_size = 0L;
+        }
       }
       rassert(
         core_blocks + swap_blocks ==
@@ -490,11 +623,16 @@ done:
 #endif
       swap_hash_verify(
         i,
+#ifdef INODE_SWAP
+        processes[i].swap_inode
+#else
         (long)swap_base << BLOCK_SHIFT,
-        swap_size,
-        0L
+        swap_size
+#endif
       );
-#ifdef INDIRECT_SWAP
+#ifdef INODE_SWAP
+      i_deref(processes[i].swap_inode);
+#elif defined(INDIRECT_SWAP)
       swap_block_free(swap_table_mem + swap_base, swap_blocks);
 #endif
     }
@@ -517,6 +655,9 @@ done:
     for (int i = 0; i < j; ++i)
       rassert(core_block_mem[i] == 0xaa);
   }
+#ifdef INODE_SWAP
+  printf("free inodes %d blocks %d\n", fs_tab[0].s_tinode, fs_tab[0].s_tfree);
+#else
 #ifdef INDIRECT_SWAP
   for (int i = 0; i < swap_table_blocks; ++i)
     rassert(swap_table_mem[i] == 0x55555555);
@@ -534,6 +675,7 @@ done:
     for (int i = 0; i < j; ++i)
       rassert(swap_block_mem[i] == 0xaa);
   }
+#endif
 
   return 0;
 }