Fix inode leak caused by the f_trunc() modifications
authorNick Downing <nick@ndcode.org>
Thu, 11 Apr 2019 13:26:26 +0000 (23:26 +1000)
committerNick Downing <nick@ndcode.org>
Thu, 11 Apr 2019 13:28:21 +0000 (23:28 +1000)
fuzix_fs.c
gen.sh
pool.h
process.c
process_test_run.c

index b198505..35c9ca0 100644 (file)
@@ -1303,28 +1303,25 @@ void i_deref(inoptr ino)
        ifnot(ino->c_refs)
            panic("inode freed.");
 
-       /* If the inode has no links and no refs, it must have
-          its blocks freed. */
+       ifnot(--ino->c_refs) {
+               /* If the inode has no links and no refs, it must have
+                  its blocks freed. */
 
-       ifnot(--ino->c_refs || ino->c_node.i_nlink) {
-/*
- SN  (mcy)
-*/
-
-               m = swizzle16(ino->c_node.i_mode);
-               if (((m & F_MASK) == F_REG) ||
-                   ((m & F_MASK) == F_DIR) || ((m & F_MASK) == F_PIPE)) {
-                       udata.u_offset = 0;
-                       f_trunc(ino);
-               }
-       }
-       /* If the inode was modified, we must write it to disk. */
-       if (!(ino->c_refs) && ino->c_dirty) {
                ifnot(ino->c_node.i_nlink) {
+                       m = swizzle16(ino->c_node.i_mode);
+                       if (((m & F_MASK) == F_REG) ||
+                           ((m & F_MASK) == F_DIR) ||
+                           ((m & F_MASK) == F_PIPE)) {
+                               udata.u_offset = 0;
+                               f_trunc(ino);
+                       }
                        ino->c_node.i_mode = 0;
                        i_free(ino->c_dev, ino->c_num);
                }
-               wr_inode(ino);
+
+               /* If the inode was modified, we must write it to disk. */
+               if (ino->c_dirty)
+                       wr_inode(ino);
        }
 }
 
@@ -1367,6 +1364,10 @@ void f_trunc(inoptr ino)
        int32_t blocks;
        int j;
 
+       /*
+        * Note: the previous i_deref() logic relied on f_trunc() always
+        * dirtying the file, and this is no longer the case, must fix it
+        */
        if (udata.u_offset >= ino->c_node.i_size)
                return;
 
diff --git a/gen.sh b/gen.sh
index 3749c71..f614f99 100755 (executable)
--- a/gen.sh
+++ b/gen.sh
@@ -47,3 +47,6 @@ sed -e 's/^\/\/#define INODE_SWAP 1/#define INODE_SWAP 1/' -i process.h
 ./pp.sh moveable_core_inode_swap
 rm moveable_core_inode_swap/swap.[ch]
 cp rassert.h fuzix_fs.[ch] util.[ch] moveable_core_inode_swap
+
+# must leave in a fit state for compiling the pool test
+sed -e 's/^\/\/#define CLASSIC_POOL 1/#define CLASSIC_POOL 1/' -i pool.h
diff --git a/pool.h b/pool.h
index 1b4d106..82c706c 100644 (file)
--- a/pool.h
+++ b/pool.h
@@ -3,7 +3,7 @@
 
 #include <stdbool.h>
 
-//#define CLASSIC_POOL 1
+#define CLASSIC_POOL 1
 #define MOVEABLE_POOL 1
 
 struct pool_item {
index 197ae84..f22bff1 100644 (file)
--- a/process.c
+++ b/process.c
@@ -330,6 +330,7 @@ bool process_alloc(struct process *process, long size) {
     (process->swap_inode = i_open(0, 0)) == NULL
   )
     return false;
+ //printf("open inode %d\n", process->swap_inode->c_num);
 
   // initialize swap inode
   process->swap_inode->c_node.i_uid = udata.u_euid;
@@ -364,6 +365,7 @@ bool process_alloc(struct process *process, long size) {
 #else
   if (!core_table_alloc(&process->core_item, blocks)) {
 #ifdef INODE_SWAP
+ //printf("deref inode %d\n", process->swap_inode->c_num);
     i_deref(process->swap_inode);
 #elif defined(PREALLOCATE_SWAP) && !defined(MOVEABLE_SWAP)
     swap_table_free(&process->swap_item);
@@ -846,6 +848,7 @@ void process_free(struct process *process) {
 #ifdef PREALLOCATE_SWAP
   swap_table_free(&process->swap_item);
 #elif defined(INODE_SWAP)
+ //printf("deref inode %d\n", process->swap_inode->c_num);
   i_deref(process->swap_inode);
 #endif
  
index 51e6a5f..b58aef8 100644 (file)
@@ -630,6 +630,7 @@ done:
 #endif
       );
 #ifdef INODE_SWAP
+ //printf("deref inode %d\n", processes[i].swap_inode->c_num);
       i_deref(processes[i].swap_inode);
 #elif defined(INDIRECT_SWAP)
       swap_block_free(swap_table_mem + swap_base, swap_blocks);