Эх сурвалжийг харах

Added file list for tracking in flight allocations

Needed primarily for tracking block allocations, unfortunately
this prevents the freedom for the user to bitwise copy files.
Christopher Haster 8 жил өмнө
parent
commit
210b487325
3 өөрчлөгдсөн 132 нэмэгдсэн , 6 устгасан
  1. 47 6
      lfs.c
  2. 2 0
      lfs.h
  3. 83 0
      tests/test_alloc.sh

+ 47 - 6
lfs.c

@@ -232,7 +232,13 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
     }
 
     // scan again or die trying
-    return lfs_alloc_scan(lfs, block);
+    err = lfs_alloc_scan(lfs, block);
+    if (err) {
+        LFS_WARN("No more free space%s", "");
+        return err;
+    }
+
+    return 0;
 }
 
 
@@ -1010,11 +1016,25 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
         file->size = 0;
     }
 
+    // add to list of files
+    file->next = lfs->files;
+    lfs->files = file;
+
     return 0;
 }
 
 int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
-    return lfs_file_sync(lfs, file);
+    int err = lfs_file_sync(lfs, file);
+
+    // remove from list of files
+    for (lfs_file_t **p = &lfs->files; *p; p = &(*p)->next) {
+        if (*p == file) {
+            *p = file->next;
+            break;
+        }
+    }
+
+    return err;
 }
 
 static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
@@ -1453,6 +1473,9 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
         }
     }
 
+    // setup files as an empty list
+    lfs->files = NULL;
+
     return 0;
 }
 
@@ -1612,8 +1635,7 @@ int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) {
             dir.off += entry.d.len;
             if ((0xf & entry.d.type) == LFS_TYPE_REG) {
                 int err = lfs_index_traverse(lfs,
-                        entry.d.u.file.head, entry.d.u.file.size,
-                        cb, data);
+                        entry.d.u.file.head, entry.d.u.file.size, cb, data);
                 if (err) {
                     return err;
                 }
@@ -1623,10 +1645,29 @@ int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) {
         cwd[0] = dir.d.tail[0];
         cwd[1] = dir.d.tail[1];
 
-        if (!cwd[0]) {
-            return 0;
+        if (lfs_pairisnull(cwd)) {
+            break;
         }
     }
+
+    // iterate over any open files
+    for (lfs_file_t *f = lfs->files; f; f = f->next) {
+        if (f->flags & LFS_O_DIRTY) {
+            int err = lfs_index_traverse(lfs, f->head, f->size, cb, data);
+            if (err) {
+                return err;
+            }
+        }
+
+        if (f->wblock) {
+            int err = lfs_index_traverse(lfs, f->wblock, f->pos, cb, data);
+            if (err) {
+                return err;
+            }
+        }
+    }
+    
+    return 0;
 }
 
 static int lfs_parent(lfs_t *lfs, const lfs_block_t dir[2]) {

+ 2 - 0
lfs.h

@@ -145,6 +145,7 @@ typedef struct lfs_entry {
 } lfs_entry_t;
 
 typedef struct lfs_file {
+    struct lfs_file *next;
     lfs_block_t pair[2];
     lfs_off_t off;
     lfs_block_t head;
@@ -194,6 +195,7 @@ typedef struct lfs {
     lfs_size_t words;       // number of 32-bit words that can fit in a block
 
     lfs_block_t root[2];
+    lfs_file_t *files;
 
     struct {
         lfs_block_t block;

+ 83 - 0
tests/test_alloc.sh

@@ -110,5 +110,88 @@ lfs_alloc_singleproc multiprocreuse
 lfs_verify multiprocreuse
 lfs_verify singleprocreuse
 
+echo "--- Cleanup ---"
+lfs_remove multiprocreuse
+lfs_remove singleprocreuse
+
+echo "--- Exhaustion test ---"
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    lfs_file_open(&lfs, &file[0], "exhaustion", LFS_O_WRONLY | LFS_O_CREAT);
+    size = strlen("exhaustion");
+    memcpy(buffer, "exhaustion", size);
+    lfs_file_write(&lfs, &file[0], buffer, size) => size;
+
+    size = strlen("blahblahblahblah");
+    memcpy(buffer, "blahblahblahblah", size);
+    lfs_ssize_t res;
+    while (true) {
+        res = lfs_file_write(&lfs, &file[0], buffer, size);
+        if (res < 0) {
+            break;
+        }
+
+        res => size;
+    }
+    res => LFS_ERR_NOSPC;
+
+    lfs_file_close(&lfs, &file[0]) => 0;
+    lfs_unmount(&lfs) => 0;
+TEST
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    lfs_file_open(&lfs, &file[0], "exhaustion", LFS_O_RDONLY);
+    size = strlen("exhaustion");
+    lfs_file_read(&lfs, &file[0], buffer, size) => size;
+    memcmp(buffer, "exhaustion", size) => 0;
+    lfs_file_close(&lfs, &file[0]) => 0;
+    lfs_unmount(&lfs) => 0;
+TEST
+
+echo "--- Exhaustion wraparound test ---"
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    lfs_remove(&lfs, "exhaustion") => 0;
+
+    lfs_file_open(&lfs, &file[0], "padding", LFS_O_WRONLY | LFS_O_CREAT);
+    size = strlen("buffering");
+    memcpy(buffer, "buffering", size);
+    for (int i = 0; i < $SIZE; i++) {
+        lfs_file_write(&lfs, &file[0], buffer, size) => size;
+    }
+    lfs_file_close(&lfs, &file[0]) => 0;
+    lfs_remove(&lfs, "padding") => 0;
+
+    lfs_file_open(&lfs, &file[0], "exhaustion", LFS_O_WRONLY | LFS_O_CREAT);
+    size = strlen("exhaustion");
+    memcpy(buffer, "exhaustion", size);
+    lfs_file_write(&lfs, &file[0], buffer, size) => size;
+
+    size = strlen("blahblahblahblah");
+    memcpy(buffer, "blahblahblahblah", size);
+    lfs_ssize_t res;
+    while (true) {
+        res = lfs_file_write(&lfs, &file[0], buffer, size);
+        if (res < 0) {
+            break;
+        }
+
+        res => size;
+    }
+    res => LFS_ERR_NOSPC;
+
+    lfs_file_close(&lfs, &file[0]) => 0;
+    lfs_unmount(&lfs) => 0;
+TEST
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    lfs_file_open(&lfs, &file[0], "exhaustion", LFS_O_RDONLY);
+    size = strlen("exhaustion");
+    lfs_file_read(&lfs, &file[0], buffer, size) => size;
+    memcmp(buffer, "exhaustion", size) => 0;
+    lfs_file_close(&lfs, &file[0]) => 0;
+    lfs_unmount(&lfs) => 0;
+TEST
+
 echo "--- Results ---"
 tests/stats.py