소스 검색

Simplified config

Before, the lfs had multiple paths to determine config options:
- lfs_config struct passed during initialization
- lfs_bd_info struct passed during block device initialization
- compile time options

This allowed different developers to provide their own needs
to the filesystem, such as the block device capabilities and
the higher level user's own tweaks.

However, this comes with additional complexity and action required
when the configurations are incompatible.

For now, this has been reduced to all information (including block
device function pointers) being passed through the lfs_config struct.
We just defer more complicated handling of configuration options to
the top level user.

This simplifies configuration handling and gives the top level user
the responsibility to handle configuration, which they probably would
have wanted to do anyways.
Christopher Haster 8 년 전
부모
커밋
789286a257
13개의 변경된 파일249개의 추가작업 그리고 411개의 파일을 삭제
  1. 75 143
      emubd/lfs_emubd.c
  2. 20 31
      emubd/lfs_emubd.h
  3. 33 108
      lfs.c
  4. 40 11
      lfs.h
  5. 0 59
      lfs_bd.h
  6. 4 4
      tests/stats.py
  7. 29 7
      tests/template.fmt
  8. 6 6
      tests/test_alloc.sh
  9. 19 19
      tests/test_dirs.sh
  10. 5 5
      tests/test_files.sh
  11. 8 8
      tests/test_format.sh
  12. 3 3
      tests/test_orphan.sh
  13. 7 7
      tests/test_paths.sh

+ 75 - 143
emubd/lfs_emubd.c

@@ -19,9 +19,12 @@
 
 
 
 
 // Block device emulated on existing filesystem
 // Block device emulated on existing filesystem
-int lfs_emubd_create(lfs_emubd_t *emu, const char *path) {
-    memset(&emu->info, 0, sizeof(emu->info));
-    memset(&emu->stats, 0, sizeof(emu->stats));
+int lfs_emubd_create(const struct lfs_config *cfg, const char *path) {
+    lfs_emubd_t *emu = cfg->context;
+    emu->cfg.read_size   = cfg->read_size;
+    emu->cfg.prog_size   = cfg->prog_size;
+    emu->cfg.block_size  = cfg->block_size;
+    emu->cfg.block_count = cfg->block_count;
 
 
     // Allocate buffer for creating children files
     // Allocate buffer for creating children files
     size_t pathlen = strlen(path);
     size_t pathlen = strlen(path);
@@ -41,12 +44,6 @@ int lfs_emubd_create(lfs_emubd_t *emu, const char *path) {
         return -errno;
         return -errno;
     }
     }
 
 
-    // Setup info based on configuration
-    emu->info.read_size  = LFS_EMUBD_READ_SIZE;
-    emu->info.prog_size  = LFS_EMUBD_PROG_SIZE;
-    emu->info.erase_size = LFS_EMUBD_ERASE_SIZE;
-    emu->info.total_size = LFS_EMUBD_TOTAL_SIZE;
-
     // Load stats to continue incrementing
     // Load stats to continue incrementing
     snprintf(emu->child, LFS_NAME_MAX, "stats");
     snprintf(emu->child, LFS_NAME_MAX, "stats");
     FILE *f = fopen(emu->path, "r");
     FILE *f = fopen(emu->path, "r");
@@ -67,153 +64,131 @@ int lfs_emubd_create(lfs_emubd_t *emu, const char *path) {
     return 0;
     return 0;
 }
 }
 
 
-void lfs_emubd_destroy(lfs_emubd_t *emu) {
-    lfs_emubd_sync(emu);
+void lfs_emubd_destroy(const struct lfs_config *cfg) {
+    lfs_emubd_sync(cfg);
 
 
+    lfs_emubd_t *emu = cfg->context;
     free(emu->path);
     free(emu->path);
 }
 }
 
 
-int lfs_emubd_read(lfs_emubd_t *emu, lfs_block_t block,
+int lfs_emubd_read(const struct lfs_config *cfg, lfs_block_t block,
         lfs_off_t off, lfs_size_t size, void *buffer) {
         lfs_off_t off, lfs_size_t size, void *buffer) {
+    lfs_emubd_t *emu = cfg->context;
     uint8_t *data = buffer;
     uint8_t *data = buffer;
 
 
     // Check if read is valid
     // Check if read is valid
-    assert(off % emu->info.read_size == 0);
-    assert(size % emu->info.read_size == 0);
-    assert((uint64_t)block*emu->info.erase_size + off + size
-            < emu->info.total_size);
+    assert(off  % cfg->read_size == 0);
+    assert(size % cfg->read_size == 0);
+    assert(block < cfg->block_count);
 
 
     // Zero out buffer for debugging
     // Zero out buffer for debugging
     memset(data, 0, size);
     memset(data, 0, size);
 
 
-    // Iterate over blocks until enough data is read
-    while (size > 0) {
-        snprintf(emu->child, LFS_NAME_MAX, "%x", block);
-        size_t count = lfs_min(emu->info.erase_size - off, size);
+    // Read data
+    snprintf(emu->child, LFS_NAME_MAX, "%x", block);
+
+    FILE *f = fopen(emu->path, "rb");
+    if (!f && errno != ENOENT) {
+        return -errno;
+    }
 
 
-        FILE *f = fopen(emu->path, "rb");
-        if (!f && errno != ENOENT) {
+    if (f) {
+        int err = fseek(f, off, SEEK_SET);
+        if (err) {
             return -errno;
             return -errno;
         }
         }
 
 
-        if (f) {
-            int err = fseek(f, off, SEEK_SET);
-            if (err) {
-                return -errno;
-            }
-
-            size_t res = fread(data, 1, count, f);
-            if (res < count && !feof(f)) {
-                return -errno;
-            }
-
-            err = fclose(f);
-            if (err) {
-                return -errno;
-            }
+        size_t res = fread(data, 1, size, f);
+        if (res < size && !feof(f)) {
+            return -errno;
         }
         }
 
 
-        size -= count;
-        data += count;
-        block += 1;
-        off = 0;
+        err = fclose(f);
+        if (err) {
+            return -errno;
+        }
     }
     }
 
 
     emu->stats.read_count += 1;
     emu->stats.read_count += 1;
     return 0;
     return 0;
 }
 }
 
 
-int lfs_emubd_prog(lfs_emubd_t *emu, lfs_block_t block,
+int lfs_emubd_prog(const struct lfs_config *cfg, lfs_block_t block,
         lfs_off_t off, lfs_size_t size, const void *buffer) {
         lfs_off_t off, lfs_size_t size, const void *buffer) {
+    lfs_emubd_t *emu = cfg->context;
     const uint8_t *data = buffer;
     const uint8_t *data = buffer;
 
 
     // Check if write is valid
     // Check if write is valid
-    assert(off % emu->info.prog_size == 0);
-    assert(size % emu->info.prog_size == 0);
-    assert((uint64_t)block*emu->info.erase_size + off + size
-            < emu->info.total_size);
-
-    // Iterate over blocks until enough data is read
-    while (size > 0) {
-        snprintf(emu->child, LFS_NAME_MAX, "%x", block);
-        size_t count = lfs_min(emu->info.erase_size - off, size);
-
-        FILE *f = fopen(emu->path, "r+b");
-        if (!f && errno == ENOENT) {
-            f = fopen(emu->path, "w+b");
-            if (!f) {
-                return -errno;
-            }
-        }
+    assert(off  % cfg->prog_size == 0);
+    assert(size % cfg->prog_size == 0);
+    assert(block < cfg->block_count);
 
 
-        int err = fseek(f, off, SEEK_SET);
-        if (err) {
-            return -errno;
-        }
+    // Program data
+    snprintf(emu->child, LFS_NAME_MAX, "%x", block);
 
 
-        size_t res = fwrite(data, 1, count, f);
-        if (res < count) {
+    FILE *f = fopen(emu->path, "r+b");
+    if (!f && errno == ENOENT) {
+        f = fopen(emu->path, "w+b");
+        if (!f) {
             return -errno;
             return -errno;
         }
         }
+    }
 
 
-        err = fclose(f);
-        if (err) {
-            return -errno;
-        }
+    int err = fseek(f, off, SEEK_SET);
+    if (err) {
+        return -errno;
+    }
+
+    size_t res = fwrite(data, 1, size, f);
+    if (res < size) {
+        return -errno;
+    }
 
 
-        size -= count;
-        data += count;
-        block += 1;
-        off = 0;
+    err = fclose(f);
+    if (err) {
+        return -errno;
     }
     }
 
 
     emu->stats.prog_count += 1;
     emu->stats.prog_count += 1;
     return 0;
     return 0;
 }
 }
 
 
-int lfs_emubd_erase(lfs_emubd_t *emu, lfs_block_t block,
-        lfs_off_t off, lfs_size_t size) {
+int lfs_emubd_erase(const struct lfs_config *cfg, lfs_block_t block) {
+    lfs_emubd_t *emu = cfg->context;
 
 
     // Check if erase is valid
     // Check if erase is valid
-    assert(off % emu->info.erase_size == 0);
-    assert(size % emu->info.erase_size == 0);
-    assert((uint64_t)block*emu->info.erase_size + off + size
-            < emu->info.total_size);
-
-    // Iterate and erase blocks
-    while (size > 0) {
-        snprintf(emu->child, LFS_NAME_MAX, "%x", block);
-        struct stat st;
-        int err = stat(emu->path, &st);
-        if (err && errno != ENOENT) {
-            return -errno;
-        }
+    assert(block < cfg->block_count);
 
 
-        if (!err && S_ISREG(st.st_mode)) {
-            int err = unlink(emu->path);
-            if (err) {
-                return -errno;
-            }
-        }
+    // Erase the block
+    snprintf(emu->child, LFS_NAME_MAX, "%x", block);
+    struct stat st;
+    int err = stat(emu->path, &st);
+    if (err && errno != ENOENT) {
+        return -errno;
+    }
 
 
-        size -= emu->info.erase_size;
-        block += 1;
-        off = 0;
+    if (!err && S_ISREG(st.st_mode)) {
+        int err = unlink(emu->path);
+        if (err) {
+            return -errno;
+        }
     }
     }
 
 
     emu->stats.erase_count += 1;
     emu->stats.erase_count += 1;
     return 0;
     return 0;
 }
 }
 
 
-int lfs_emubd_sync(lfs_emubd_t *emu) {
+int lfs_emubd_sync(const struct lfs_config *cfg) {
+    lfs_emubd_t *emu = cfg->context;
+
     // Just write out info/stats for later lookup
     // Just write out info/stats for later lookup
-    snprintf(emu->child, LFS_NAME_MAX, "info");
+    snprintf(emu->child, LFS_NAME_MAX, "config");
     FILE *f = fopen(emu->path, "w");
     FILE *f = fopen(emu->path, "w");
     if (!f) {
     if (!f) {
         return -errno;
         return -errno;
     }
     }
 
 
-    size_t res = fwrite(&emu->info, sizeof(emu->info), 1, f);
+    size_t res = fwrite(&emu->cfg, sizeof(emu->cfg), 1, f);
     if (res < 1) {
     if (res < 1) {
         return -errno;
         return -errno;
     }
     }
@@ -242,46 +217,3 @@ int lfs_emubd_sync(lfs_emubd_t *emu) {
     return 0;
     return 0;
 }
 }
 
 
-int lfs_emubd_info(lfs_emubd_t *emu, struct lfs_bd_info *info) {
-    *info = emu->info;
-    return 0;
-}
-
-int lfs_emubd_stats(lfs_emubd_t *emu, struct lfs_bd_stats *stats) {
-    *stats = emu->stats;
-    return 0;
-}
-
-
-// Wrappers for void*s
-static int lfs_emubd_bd_read(void *bd, lfs_block_t block,
-        lfs_off_t off, lfs_size_t size, void *buffer) {
-    return lfs_emubd_read((lfs_emubd_t*)bd, block, off, size, buffer);
-}
-
-static int lfs_emubd_bd_prog(void *bd, lfs_block_t block,
-        lfs_off_t off, lfs_size_t size, const void *buffer) {
-    return lfs_emubd_prog((lfs_emubd_t*)bd, block, off, size, buffer);
-}
-
-static int lfs_emubd_bd_erase(void *bd, lfs_block_t block,
-        lfs_off_t off, lfs_size_t size) {
-    return lfs_emubd_erase((lfs_emubd_t*)bd, block, off, size);
-}
-
-static int lfs_emubd_bd_sync(void *bd) {
-    return lfs_emubd_sync((lfs_emubd_t*)bd);
-}
-
-static int lfs_emubd_bd_info(void *bd, struct lfs_bd_info *info) {
-    return lfs_emubd_info((lfs_emubd_t*)bd, info);
-}
-
-const struct lfs_bd_ops lfs_emubd_ops = {
-    .read = lfs_emubd_bd_read,
-    .prog = lfs_emubd_bd_prog,
-    .erase = lfs_emubd_bd_erase,
-    .sync = lfs_emubd_bd_sync,
-    .info = lfs_emubd_bd_info,
-};
-

+ 20 - 31
emubd/lfs_emubd.h

@@ -7,9 +7,8 @@
 #ifndef LFS_EMUBD_H
 #ifndef LFS_EMUBD_H
 #define LFS_EMUBD_H
 #define LFS_EMUBD_H
 
 
-#include "lfs_config.h"
+#include "lfs.h"
 #include "lfs_util.h"
 #include "lfs_util.h"
-#include "lfs_bd.h"
 
 
 
 
 // Config options
 // Config options
@@ -30,60 +29,50 @@
 #endif
 #endif
 
 
 
 
-// Stats for debugging and optimization
-struct lfs_bd_stats {
-    uint64_t read_count;
-    uint64_t prog_count;
-    uint64_t erase_count;
-};
-
 // The emu bd state
 // The emu bd state
 typedef struct lfs_emubd {
 typedef struct lfs_emubd {
     char *path;
     char *path;
     char *child;
     char *child;
-    struct lfs_bd_info info;
-    struct lfs_bd_stats stats;
+
+    struct {
+        uint64_t read_count;
+        uint64_t prog_count;
+        uint64_t erase_count;
+    } stats;
+
+    struct {
+        uint32_t read_size;
+        uint32_t prog_size;
+        uint32_t block_size;
+        uint32_t block_count;
+    } cfg;
 } lfs_emubd_t;
 } lfs_emubd_t;
 
 
 
 
 // Create a block device using path for the directory to store blocks
 // Create a block device using path for the directory to store blocks
-int lfs_emubd_create(lfs_emubd_t *emu, const char *path);
+int lfs_emubd_create(const struct lfs_config *cfg, const char *path);
 
 
 // Clean up memory associated with emu block device
 // Clean up memory associated with emu block device
-void lfs_emubd_destroy(lfs_emubd_t *emu);
+void lfs_emubd_destroy(const struct lfs_config *cfg);
 
 
 // Read a block
 // Read a block
-int lfs_emubd_read(lfs_emubd_t *bd, lfs_block_t block,
+int lfs_emubd_read(const struct lfs_config *cfg, lfs_block_t block,
         lfs_off_t off, lfs_size_t size, void *buffer);
         lfs_off_t off, lfs_size_t size, void *buffer);
 
 
 // Program a block
 // Program a block
 //
 //
 // The block must have previously been erased.
 // The block must have previously been erased.
-int lfs_emubd_prog(lfs_emubd_t *bd, lfs_block_t block,
+int lfs_emubd_prog(const struct lfs_config *cfg, lfs_block_t block,
         lfs_off_t off, lfs_size_t size, const void *buffer);
         lfs_off_t off, lfs_size_t size, const void *buffer);
 
 
 // Erase a block
 // Erase a block
 //
 //
 // A block must be erased before being programmed. The
 // A block must be erased before being programmed. The
 // state of an erased block is undefined.
 // state of an erased block is undefined.
-int lfs_emubd_erase(lfs_emubd_t *bd, lfs_block_t block,
-        lfs_off_t off, lfs_size_t size);
+int lfs_emubd_erase(const struct lfs_config *cfg, lfs_block_t block);
 
 
 // Sync the block device
 // Sync the block device
-int lfs_emubd_sync(lfs_emubd_t *bd);
-
-// Get a description of the block device
-//
-// Any unknown information may be left unmodified
-int lfs_emubd_info(lfs_emubd_t *bd, struct lfs_bd_info *info);
-
-// Get stats of operations on the block device
-//
-// Used for debugging and optimizations
-int lfs_emubd_stats(lfs_emubd_t *bd, struct lfs_bd_stats *stats);
-
-// Block device operations
-extern const struct lfs_bd_ops lfs_emubd_ops;
+int lfs_emubd_sync(const struct lfs_config *cfg);
 
 
 
 
 #endif
 #endif

+ 33 - 108
lfs.c

@@ -12,27 +12,22 @@
 
 
 
 
 /// Block device operations ///
 /// Block device operations ///
-static int lfs_bd_info(lfs_t *lfs, struct lfs_bd_info *info) {
-    return lfs->bd_ops->info(lfs->bd, info);
-}
-
 static int lfs_bd_read(lfs_t *lfs, lfs_block_t block,
 static int lfs_bd_read(lfs_t *lfs, lfs_block_t block,
         lfs_off_t off, lfs_size_t size, void *buffer) {
         lfs_off_t off, lfs_size_t size, void *buffer) {
-    return lfs->bd_ops->read(lfs->bd, block, off, size, buffer);
+    return lfs->cfg->read(lfs->cfg, block, off, size, buffer);
 }
 }
 
 
 static int lfs_bd_prog(lfs_t *lfs, lfs_block_t block,
 static int lfs_bd_prog(lfs_t *lfs, lfs_block_t block,
         lfs_off_t off, lfs_size_t size, const void *buffer) {
         lfs_off_t off, lfs_size_t size, const void *buffer) {
-    return lfs->bd_ops->prog(lfs->bd, block, off, size, buffer);
+    return lfs->cfg->prog(lfs->cfg, block, off, size, buffer);
 }
 }
 
 
-static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block,
-        lfs_off_t off, lfs_size_t size) {
-    return lfs->bd_ops->erase(lfs->bd, block, off, size);
+static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) {
+    return lfs->cfg->erase(lfs->cfg, block);
 }
 }
 
 
 static int lfs_bd_sync(lfs_t *lfs) {
 static int lfs_bd_sync(lfs_t *lfs) {
-    return lfs->bd_ops->sync(lfs->bd);
+    return lfs->cfg->sync(lfs->cfg);
 }
 }
 
 
 static int lfs_bd_cmp(lfs_t *lfs, lfs_block_t block,
 static int lfs_bd_cmp(lfs_t *lfs, lfs_block_t block,
@@ -101,7 +96,7 @@ static int lfs_alloc_scan(lfs_t *lfs) {
             // found free block, now find stride of free blocks
             // found free block, now find stride of free blocks
             // since this is relatively cheap (stress on relatively)
             // since this is relatively cheap (stress on relatively)
             lfs->free.begin += off;
             lfs->free.begin += off;
-            lfs->free.end = lfs->block_count; // before superblock
+            lfs->free.end = lfs->cfg->block_count; // before superblock
 
 
             // find maximum stride in tree
             // find maximum stride in tree
             return lfs_traverse(lfs, lfs_alloc_stride, lfs);
             return lfs_traverse(lfs, lfs_alloc_stride, lfs);
@@ -157,7 +152,7 @@ static int lfs_alloc_erased(lfs_t *lfs, lfs_block_t *block) {
         return err;
         return err;
     }
     }
 
 
-    return lfs_bd_erase(lfs, *block, 0, lfs->block_size);
+    return lfs_bd_erase(lfs, *block);
 }
 }
 
 
 
 
@@ -175,9 +170,9 @@ static lfs_off_t lfs_indexnext(lfs_t *lfs, lfs_off_t ioff) {
 
 
 static lfs_off_t lfs_indexfrom(lfs_t *lfs, lfs_off_t off) {
 static lfs_off_t lfs_indexfrom(lfs_t *lfs, lfs_off_t off) {
     lfs_off_t i = 0;
     lfs_off_t i = 0;
-    while (off > lfs->block_size) {
+    while (off > lfs->cfg->block_size) {
         i = lfs_indexnext(lfs, i);
         i = lfs_indexnext(lfs, i);
-        off -= lfs->block_size;
+        off -= lfs->cfg->block_size;
     }
     }
 
 
     return i;
     return i;
@@ -370,7 +365,7 @@ static int lfs_dir_fetch(lfs_t *lfs,
         uint32_t crc = 0xffffffff;
         uint32_t crc = 0xffffffff;
         crc = lfs_crc(crc, sizeof(test), &test);
         crc = lfs_crc(crc, sizeof(test), &test);
 
 
-        for (lfs_off_t j = sizeof(test); j < lfs->block_size; j += 4) {
+        for (lfs_off_t j = sizeof(test); j < lfs->cfg->block_size; j += 4) {
             uint32_t word;
             uint32_t word;
             int err = lfs_bd_read(lfs, tpair[i], j, 4, &word);
             int err = lfs_bd_read(lfs, tpair[i], j, 4, &word);
             if (err) {
             if (err) {
@@ -406,7 +401,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir,
     dir->d.rev += 1;
     dir->d.rev += 1;
     lfs_pairswap(dir->pair);
     lfs_pairswap(dir->pair);
 
 
-    int err = lfs_bd_erase(lfs, dir->pair[0], 0, lfs->block_size);
+    int err = lfs_bd_erase(lfs, dir->pair[0]);
     if (err) {
     if (err) {
         return err;
         return err;
     }
     }
@@ -456,7 +451,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir,
         }
         }
     }
     }
 
 
-    while (off < lfs->block_size-4) {
+    while (off < lfs->cfg->block_size-4) {
         uint8_t data;
         uint8_t data;
         int err = lfs_bd_read(lfs, dir->pair[0], off, 1, &data);
         int err = lfs_bd_read(lfs, dir->pair[0], off, 1, &data);
         if (err) {
         if (err) {
@@ -467,7 +462,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir,
         off += 1;
         off += 1;
     }
     }
 
 
-    err = lfs_bd_prog(lfs, dir->pair[0], lfs->block_size-4, 4, &crc);
+    err = lfs_bd_prog(lfs, dir->pair[0], lfs->cfg->block_size-4, 4, &crc);
     if (err) {
     if (err) {
         return err;
         return err;
     }
     }
@@ -480,7 +475,7 @@ static int lfs_dir_shift(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
     dir->d.size -= entry->d.len;
     dir->d.size -= entry->d.len;
     lfs_pairswap(dir->pair);
     lfs_pairswap(dir->pair);
 
 
-    int err = lfs_bd_erase(lfs, dir->pair[0], 0, lfs->block_size);
+    int err = lfs_bd_erase(lfs, dir->pair[0]);
     if (err) {
     if (err) {
         return err;
         return err;
     }
     }
@@ -516,7 +511,7 @@ static int lfs_dir_shift(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
         }
         }
     }
     }
 
 
-    while (woff < lfs->block_size-4) {
+    while (woff < lfs->cfg->block_size-4) {
         uint8_t data;
         uint8_t data;
         int err = lfs_bd_read(lfs, dir->pair[0], woff, 1, &data);
         int err = lfs_bd_read(lfs, dir->pair[0], woff, 1, &data);
         if (err) {
         if (err) {
@@ -527,7 +522,7 @@ static int lfs_dir_shift(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
         woff += 1;
         woff += 1;
     }
     }
 
 
-    err = lfs_bd_prog(lfs, dir->pair[0], lfs->block_size-4, 4, &crc);
+    err = lfs_bd_prog(lfs, dir->pair[0], lfs->cfg->block_size-4, 4, &crc);
     if (err) {
     if (err) {
         return err;
         return err;
     }
     }
@@ -539,7 +534,7 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
         lfs_entry_t *entry, const void *data) {
         lfs_entry_t *entry, const void *data) {
     // check if we fit, if top bit is set we do not and move on
     // check if we fit, if top bit is set we do not and move on
     while (true) {
     while (true) {
-        if (dir->d.size + entry->d.len <= lfs->block_size - 4) {
+        if (dir->d.size + entry->d.len <= lfs->cfg->block_size - 4) {
             entry->pair[0] = dir->pair[0];
             entry->pair[0] = dir->pair[0];
             entry->pair[1] = dir->pair[1];
             entry->pair[1] = dir->pair[1];
             entry->off = dir->d.size;
             entry->off = dir->d.size;
@@ -882,7 +877,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
 
 
     // TODO do this lazily in write?
     // TODO do this lazily in write?
     // TODO cow the head i/d block
     // TODO cow the head i/d block
-    if (file->size < lfs->block_size) {
+    if (file->size < lfs->cfg->block_size) {
         file->wblock = file->head;
         file->wblock = file->head;
     } else {
     } else {
         int err = lfs_index_find(lfs, file->head, file->windex,
         int err = lfs_index_find(lfs, file->head, file->windex,
@@ -915,7 +910,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
     lfs_size_t nsize = size;
     lfs_size_t nsize = size;
 
 
     while (nsize > 0) {
     while (nsize > 0) {
-        lfs_off_t woff = file->size % lfs->block_size;
+        lfs_off_t woff = file->size % lfs->cfg->block_size;
 
 
         if (file->size == 0) {
         if (file->size == 0) {
             int err = lfs_alloc_erased(lfs, &file->wblock);
             int err = lfs_alloc_erased(lfs, &file->wblock);
@@ -938,7 +933,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
             }
             }
         }
         }
 
 
-        lfs_size_t diff = lfs_min(nsize, lfs->block_size - woff);
+        lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - woff);
         int err = lfs_bd_prog(lfs, file->wblock, woff, diff, data);
         int err = lfs_bd_prog(lfs, file->wblock, woff, diff, data);
         if (err) {
         if (err) {
             return err;
             return err;
@@ -958,10 +953,10 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
     lfs_size_t nsize = size;
     lfs_size_t nsize = size;
 
 
     while (nsize > 0 && file->roff < file->size) {
     while (nsize > 0 && file->roff < file->size) {
-        lfs_off_t roff = file->roff % lfs->block_size;
+        lfs_off_t roff = file->roff % lfs->cfg->block_size;
 
 
         // TODO cache index blocks
         // TODO cache index blocks
-        if (file->size < lfs->block_size) {
+        if (file->size < lfs->cfg->block_size) {
             file->rblock = file->head;
             file->rblock = file->head;
         } else if (roff == 0) {
         } else if (roff == 0) {
             int err = lfs_index_find(lfs, file->head, file->windex,
             int err = lfs_index_find(lfs, file->head, file->windex,
@@ -975,7 +970,7 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
 
 
         lfs_size_t diff = lfs_min(
         lfs_size_t diff = lfs_min(
                 lfs_min(nsize, file->size-file->roff),
                 lfs_min(nsize, file->size-file->roff),
-                lfs->block_size - roff);
+                lfs->cfg->block_size - roff);
         int err = lfs_bd_read(lfs, file->rblock, roff, diff, data);
         int err = lfs_bd_read(lfs, file->rblock, roff, diff, data);
         if (err) {
         if (err) {
             return err;
             return err;
@@ -991,85 +986,17 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
 
 
 
 
 /// Generic filesystem operations ///
 /// Generic filesystem operations ///
-static int lfs_configure(lfs_t *lfs, const struct lfs_config *config) {
-    lfs->bd = config->bd;
-    lfs->bd_ops = config->bd_ops;
-
-    struct lfs_bd_info info;
-    int err = lfs_bd_info(lfs, &info);
-    if (err) {
-        return err;
-    }
-
-    if (config->read_size) {
-        if (config->read_size < info.read_size ||
-            config->read_size % info.read_size != 0) {
-            LFS_ERROR("Invalid read size %u, device has %u\n",
-                config->read_size, info.read_size);
-            return LFS_ERROR_INVALID;
-        }
-
-        lfs->read_size = config->read_size;
-    } else {
-        lfs->read_size = info.read_size;
-    }
-
-    if (config->prog_size) {
-        if (config->prog_size < info.prog_size ||
-            config->prog_size % info.prog_size != 0) {
-            LFS_ERROR("Invalid prog size %u, device has %u\n",
-                config->prog_size, info.prog_size);
-            return LFS_ERROR_INVALID;
-        }
-
-        lfs->prog_size = config->prog_size;
-    } else {
-        lfs->prog_size = info.prog_size;
-    }
-
-    if (config->block_size) {
-        if (config->block_size < info.erase_size ||
-            config->block_size % info.erase_size != 0) {
-            LFS_ERROR("Invalid block size %u, device has %u\n",
-                config->prog_size, info.prog_size);
-            return LFS_ERROR_INVALID;
-        }
-
-        lfs->block_size = config->block_size;
-    } else {
-        lfs->block_size = lfs_min(512, info.erase_size);
-    }
-
-    if (config->block_count) {
-        if (config->block_count > info.total_size/info.erase_size) {
-            LFS_ERROR("Invalid block size %u, device has %u\n",
-                config->block_size,
-                (uint32_t)(info.total_size/info.erase_size));
-            return LFS_ERROR_INVALID;
-        }
-
-        lfs->block_count = config->block_count;
-    } else {
-        lfs->block_count = info.total_size / info.erase_size;
-    }
-
-    lfs->words = lfs->block_size / sizeof(uint32_t);
-    return 0;
-}
-
 int lfs_format(lfs_t *lfs, const struct lfs_config *config) {
 int lfs_format(lfs_t *lfs, const struct lfs_config *config) {
-    int err = lfs_configure(lfs, config);
-    if (err) {
-        return err;
-    }
+    lfs->cfg = config;
+    lfs->words = lfs->cfg->block_size / sizeof(uint32_t);
 
 
     // Create free list
     // Create free list
     lfs->free.begin = 0;
     lfs->free.begin = 0;
-    lfs->free.end = lfs->block_count-1;
+    lfs->free.end = lfs->cfg->block_count-1;
 
 
     // Create superblock dir
     // Create superblock dir
     lfs_dir_t superdir;
     lfs_dir_t superdir;
-    err = lfs_dir_alloc(lfs, &superdir);
+    int err = lfs_dir_alloc(lfs, &superdir);
     if (err) {
     if (err) {
         return err;
         return err;
     }
     }
@@ -1096,8 +1023,8 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *config) {
         .d.len = sizeof(superblock.d),
         .d.len = sizeof(superblock.d),
         .d.version = 0x00000001,
         .d.version = 0x00000001,
         .d.magic = {"littlefs"},
         .d.magic = {"littlefs"},
-        .d.block_size  = lfs->block_size,
-        .d.block_count = lfs->block_count,
+        .d.block_size  = lfs->cfg->block_size,
+        .d.block_count = lfs->cfg->block_count,
         .d.root = {lfs->root[0], lfs->root[1]},
         .d.root = {lfs->root[0], lfs->root[1]},
     };
     };
     superdir.d.tail[0] = root.pair[0];
     superdir.d.tail[0] = root.pair[0];
@@ -1121,14 +1048,12 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *config) {
 }
 }
 
 
 int lfs_mount(lfs_t *lfs, const struct lfs_config *config) {
 int lfs_mount(lfs_t *lfs, const struct lfs_config *config) {
-    int err = lfs_configure(lfs, config);
-    if (err) {
-        return err;
-    }
+    lfs->cfg = config;
+    lfs->words = lfs->cfg->block_size / sizeof(uint32_t);
 
 
     lfs_dir_t dir;
     lfs_dir_t dir;
     lfs_superblock_t superblock;
     lfs_superblock_t superblock;
-    err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1});
+    int err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1});
     if (!err) {
     if (!err) {
         err = lfs_bd_read(lfs, dir.pair[0],
         err = lfs_bd_read(lfs, dir.pair[0],
                 sizeof(dir.d), sizeof(superblock.d), &superblock.d);
                 sizeof(dir.d), sizeof(superblock.d), &superblock.d);
@@ -1186,7 +1111,7 @@ int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) {
 
 
             dir.off += file.entry.d.len;
             dir.off += file.entry.d.len;
             if ((0xf & file.entry.d.type) == LFS_TYPE_REG) {
             if ((0xf & file.entry.d.type) == LFS_TYPE_REG) {
-                if (file.entry.d.u.file.size < lfs->block_size) {
+                if (file.entry.d.u.file.size < lfs->cfg->block_size) {
                     int err = cb(data, file.entry.d.u.file.head);
                     int err = cb(data, file.entry.d.u.file.head);
                     if (err) {
                     if (err) {
                         return err;
                         return err;

+ 40 - 11
lfs.h

@@ -8,10 +8,9 @@
 #define LFS_H
 #define LFS_H
 
 
 #include "lfs_config.h"
 #include "lfs_config.h"
-#include "lfs_bd.h"
 
 
 
 
-// Data structures
+// The littefs constants
 enum lfs_error {
 enum lfs_error {
     LFS_ERROR_OK       = 0,
     LFS_ERROR_OK       = 0,
     LFS_ERROR_CORRUPT  = -3,
     LFS_ERROR_CORRUPT  = -3,
@@ -41,23 +40,56 @@ enum lfs_open_flags {
 };
 };
 
 
 
 
+// Configuration provided during initialization of the littlefs
 struct lfs_config {
 struct lfs_config {
-    lfs_bd_t *bd;
-    const struct lfs_bd_ops *bd_ops;
+    // Opaque user provided context
+    void *context;
 
 
+    // Read a region in a block
+    int (*read)(const struct lfs_config *c, lfs_block_t block,
+            lfs_off_t off, lfs_size_t size, void *buffer);
+
+    // Program a region in a block. The block must have previously
+    // been erased.
+    int (*prog)(const struct lfs_config *c, lfs_block_t block,
+            lfs_off_t off, lfs_size_t size, const void *buffer);
+
+    // Erase a block. A block must be erased before being programmed.
+    // The state of an erased block is undefined.
+    int (*erase)(const struct lfs_config *c, lfs_block_t block);
+
+    // Sync the state of the underlying block device
+    int (*sync)(const struct lfs_config *c);
+
+    // Minimum size of a read. This may be larger than the physical
+    // read size to cache reads from the block device.
     lfs_size_t read_size;
     lfs_size_t read_size;
+
+    // Minimum size of a program. This may be larger than the physical
+    // program size to cache programs to the block device.
     lfs_size_t prog_size;
     lfs_size_t prog_size;
 
 
+    // Size of an erasable block.
     lfs_size_t block_size;
     lfs_size_t block_size;
+
+    // Number of erasable blocks on the device.
     lfs_size_t block_count;
     lfs_size_t block_count;
 };
 };
 
 
+// File info structure
 struct lfs_info {
 struct lfs_info {
+    // Type of the file, either REG or DIR
     uint8_t type;
     uint8_t type;
+
+    // Size of the file, only valid for REG files
     lfs_size_t size;
     lfs_size_t size;
+
+    // Name of the file stored as a null-terminated string
     char name[LFS_NAME_MAX+1];
     char name[LFS_NAME_MAX+1];
 };
 };
 
 
+
+// Internal data structures
 typedef struct lfs_entry {
 typedef struct lfs_entry {
     lfs_block_t pair[2];
     lfs_block_t pair[2];
     lfs_off_t off;
     lfs_off_t off;
@@ -115,17 +147,12 @@ typedef struct lfs_superblock {
     } d;
     } d;
 } lfs_superblock_t;
 } lfs_superblock_t;
 
 
+
 // Little filesystem type
 // Little filesystem type
 typedef struct lfs {
 typedef struct lfs {
-    lfs_size_t read_size;   // size of read
-    lfs_size_t prog_size;   // size of program
-    lfs_size_t block_size;  // size of erase (block size)
-    lfs_size_t block_count; // number of erasable blocks
+    const struct lfs_config *cfg;
     lfs_size_t words;       // number of 32-bit words that can fit in a block
     lfs_size_t words;       // number of 32-bit words that can fit in a block
 
 
-    lfs_bd_t *bd;
-    const struct lfs_bd_ops *bd_ops;
-
     lfs_block_t root[2];
     lfs_block_t root[2];
     struct {
     struct {
         lfs_block_t begin;
         lfs_block_t begin;
@@ -135,6 +162,7 @@ typedef struct lfs {
     uint32_t lookahead[LFS_CFG_LOOKAHEAD/32];
     uint32_t lookahead[LFS_CFG_LOOKAHEAD/32];
 } lfs_t;
 } lfs_t;
 
 
+
 // Functions
 // Functions
 int lfs_format(lfs_t *lfs, const struct lfs_config *config);
 int lfs_format(lfs_t *lfs, const struct lfs_config *config);
 int lfs_mount(lfs_t *lfs, const struct lfs_config *config);
 int lfs_mount(lfs_t *lfs, const struct lfs_config *config);
@@ -160,4 +188,5 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
 int lfs_deorphan(lfs_t *lfs);
 int lfs_deorphan(lfs_t *lfs);
 int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);
 int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);
 
 
+
 #endif
 #endif

+ 0 - 59
lfs_bd.h

@@ -1,59 +0,0 @@
-/*
- * Block device interface
- *
- * Copyright (c) 2017 Christopher Haster
- * Distributed under the MIT license
- */
-#ifndef LFS_BD_H
-#define LFS_BD_H
-
-#include "lfs_config.h"
-
-
-// Opaque type for block devices
-typedef void lfs_bd_t;
-
-// Description of block devices
-struct lfs_bd_info {
-    lfs_size_t read_size;   // Size of readable block
-    lfs_size_t prog_size;   // Size of programmable block
-    lfs_size_t erase_size;  // Size of erase block
-
-    uint64_t total_size; // Total size of the device
-};
-
-// Block device operations
-//
-// The little file system takes in a pointer to an opaque type
-// and this struct, all operations are passed the opaque pointer
-// which can be used to reference any state associated with the
-// block device
-struct lfs_bd_ops {
-    // Read a block
-    int (*read)(lfs_bd_t *bd, lfs_block_t block,
-            lfs_off_t off, lfs_size_t size, void *buffer);
-
-    // Program a block
-    //
-    // The block must have previously been erased.
-    int (*prog)(lfs_bd_t *bd, lfs_block_t block,
-            lfs_off_t off, lfs_size_t size, const void *buffer);
-
-    // Erase a block
-    //
-    // A block must be erased before being programmed. The
-    // state of an erased block is undefined.
-    int (*erase)(lfs_bd_t *bd, lfs_block_t block,
-            lfs_off_t off, lfs_size_t size);
-
-    // Sync the block device
-    int (*sync)(lfs_bd_t *bd);
-
-    // Get a description of the block device
-    //
-    // Any unknown information may be left as zero
-    int (*info)(lfs_bd_t *bd, struct lfs_bd_info *info);
-};
-
-
-#endif

+ 4 - 4
tests/stats.py

@@ -7,12 +7,12 @@ import os
 import re
 import re
 
 
 def main():
 def main():
-    with open('blocks/info') as file:
-        s = struct.unpack('<LLL4xQ', file.read())
+    with open('blocks/config') as file:
+        s = struct.unpack('<LLLL', file.read())
         print 'read_size: %d' % s[0]
         print 'read_size: %d' % s[0]
         print 'prog_size: %d' % s[1]
         print 'prog_size: %d' % s[1]
-        print 'erase_size: %d' % s[2]
-        print 'total_size: %d' % s[3]
+        print 'block_size: %d' % s[2]
+        print 'block_size: %d' % s[3]
 
 
     print 'real_size: %d' % sum(
     print 'real_size: %d' % sum(
         os.path.getsize(os.path.join('blocks', f))
         os.path.getsize(os.path.join('blocks', f))

+ 29 - 7
tests/template.fmt

@@ -43,8 +43,6 @@ lfs_t lfs;
 lfs_emubd_t bd;
 lfs_emubd_t bd;
 lfs_file_t file[4];
 lfs_file_t file[4];
 lfs_dir_t dir[4];
 lfs_dir_t dir[4];
-struct lfs_bd_info bd_info;
-struct lfs_bd_stats bd_stats;
 struct lfs_info info;
 struct lfs_info info;
 
 
 uint8_t buffer[1024];
 uint8_t buffer[1024];
@@ -56,17 +54,41 @@ lfs_size_t rsize;
 
 
 uintmax_t res;
 uintmax_t res;
 
 
-const struct lfs_config config = {{
-    .bd = &bd,
-    .bd_ops = &lfs_emubd_ops,
+#ifndef LFS_READ_SIZE
+#define LFS_READ_SIZE 1
+#endif
+
+#ifndef LFS_PROG_SIZE
+#define LFS_PROG_SIZE 1
+#endif
+
+#ifndef LFS_BLOCK_SIZE
+#define LFS_BLOCK_SIZE 512
+#endif
+
+#ifndef LFS_BLOCK_COUNT
+#define LFS_BLOCK_COUNT 1024
+#endif
+
+const struct lfs_config cfg = {{
+    .context = &bd,
+    .read  = &lfs_emubd_read,
+    .prog  = &lfs_emubd_prog,
+    .erase = &lfs_emubd_erase,
+    .sync  = &lfs_emubd_sync,
+
+    .read_size   = LFS_READ_SIZE,
+    .prog_size   = LFS_PROG_SIZE,
+    .block_size  = LFS_BLOCK_SIZE,
+    .block_count = LFS_BLOCK_COUNT,
 }};
 }};
 
 
 
 
 // Entry point
 // Entry point
 int main() {{
 int main() {{
-    lfs_emubd_create(&bd, "blocks");
+    lfs_emubd_create(&cfg, "blocks");
 
 
 {tests}
 {tests}
 
 
-    lfs_emubd_destroy(&bd);
+    lfs_emubd_destroy(&cfg);
 }}
 }}

+ 6 - 6
tests/test_alloc.sh

@@ -4,14 +4,14 @@ set -eu
 echo "=== Allocator tests ==="
 echo "=== Allocator tests ==="
 rm -rf blocks
 rm -rf blocks
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_format(&lfs, &config) => 0;
+    lfs_format(&lfs, &cfg) => 0;
 TEST
 TEST
 
 
 SIZE=15000
 SIZE=15000
 
 
 lfs_mkdir() {
 lfs_mkdir() {
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_mkdir(&lfs, "$1") => 0;
     lfs_mkdir(&lfs, "$1") => 0;
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 TEST
@@ -19,7 +19,7 @@ TEST
 
 
 lfs_remove() {
 lfs_remove() {
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_remove(&lfs, "$1/eggs") => 0;
     lfs_remove(&lfs, "$1/eggs") => 0;
     lfs_remove(&lfs, "$1/bacon") => 0;
     lfs_remove(&lfs, "$1/bacon") => 0;
     lfs_remove(&lfs, "$1/pancakes") => 0;
     lfs_remove(&lfs, "$1/pancakes") => 0;
@@ -31,7 +31,7 @@ TEST
 lfs_alloc_singleproc() {
 lfs_alloc_singleproc() {
 tests/test.py << TEST
 tests/test.py << TEST
     const char *names[] = {"bacon", "eggs", "pancakes"};
     const char *names[] = {"bacon", "eggs", "pancakes"};
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     for (int n = 0; n < sizeof(names)/sizeof(names[0]); n++) {
     for (int n = 0; n < sizeof(names)/sizeof(names[0]); n++) {
         sprintf((char*)buffer, "$1/%s", names[n]);
         sprintf((char*)buffer, "$1/%s", names[n]);
         lfs_file_open(&lfs, &file[n], (char*)buffer,
         lfs_file_open(&lfs, &file[n], (char*)buffer,
@@ -54,7 +54,7 @@ lfs_alloc_multiproc() {
 for name in bacon eggs pancakes
 for name in bacon eggs pancakes
 do
 do
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_file_open(&lfs, &file[0], "$1/$name",
     lfs_file_open(&lfs, &file[0], "$1/$name",
             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
     size = strlen("$name");
     size = strlen("$name");
@@ -72,7 +72,7 @@ lfs_verify() {
 for name in bacon eggs pancakes
 for name in bacon eggs pancakes
 do
 do
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_file_open(&lfs, &file[0], "$1/$name", LFS_O_RDONLY) => 0;
     lfs_file_open(&lfs, &file[0], "$1/$name", LFS_O_RDONLY) => 0;
     size = strlen("$name");
     size = strlen("$name");
     for (int i = 0; i < $SIZE; i++) {
     for (int i = 0; i < $SIZE; i++) {

+ 19 - 19
tests/test_dirs.sh

@@ -6,12 +6,12 @@ LARGESIZE=128
 echo "=== Directory tests ==="
 echo "=== Directory tests ==="
 rm -rf blocks
 rm -rf blocks
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_format(&lfs, &config) => 0;
+    lfs_format(&lfs, &cfg) => 0;
 TEST
 TEST
 
 
 echo "--- Root directory ---"
 echo "--- Root directory ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_dir_open(&lfs, &dir[0], "/") => 0;
     lfs_dir_open(&lfs, &dir[0], "/") => 0;
     lfs_dir_close(&lfs, &dir[0]) => 0;
     lfs_dir_close(&lfs, &dir[0]) => 0;
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
@@ -19,14 +19,14 @@ TEST
 
 
 echo "--- Directory creation ---"
 echo "--- Directory creation ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_mkdir(&lfs, "potato") => 0;
     lfs_mkdir(&lfs, "potato") => 0;
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 TEST
 
 
 echo "--- File creation ---"
 echo "--- File creation ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_file_open(&lfs, &file[0], "burito", LFS_O_CREAT | LFS_O_WRONLY) => 0;
     lfs_file_open(&lfs, &file[0], "burito", LFS_O_CREAT | LFS_O_WRONLY) => 0;
     lfs_file_close(&lfs, &file[0]) => 0;
     lfs_file_close(&lfs, &file[0]) => 0;
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
@@ -34,7 +34,7 @@ TEST
 
 
 echo "--- Directory iteration ---"
 echo "--- Directory iteration ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_dir_open(&lfs, &dir[0], "/") => 0;
     lfs_dir_open(&lfs, &dir[0], "/") => 0;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     strcmp(info.name, ".") => 0;
     strcmp(info.name, ".") => 0;
@@ -55,7 +55,7 @@ TEST
 
 
 echo "--- Directory failures ---"
 echo "--- Directory failures ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_mkdir(&lfs, "potato") => LFS_ERROR_EXISTS;
     lfs_mkdir(&lfs, "potato") => LFS_ERROR_EXISTS;
     lfs_dir_open(&lfs, &dir[0], "tomato") => LFS_ERROR_NO_ENTRY;
     lfs_dir_open(&lfs, &dir[0], "tomato") => LFS_ERROR_NO_ENTRY;
     lfs_dir_open(&lfs, &dir[0], "burito") => LFS_ERROR_NOT_DIR;
     lfs_dir_open(&lfs, &dir[0], "burito") => LFS_ERROR_NOT_DIR;
@@ -66,14 +66,14 @@ TEST
 
 
 echo "--- Nested directories ---"
 echo "--- Nested directories ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_mkdir(&lfs, "potato/baked") => 0;
     lfs_mkdir(&lfs, "potato/baked") => 0;
     lfs_mkdir(&lfs, "potato/sweet") => 0;
     lfs_mkdir(&lfs, "potato/sweet") => 0;
     lfs_mkdir(&lfs, "potato/fried") => 0;
     lfs_mkdir(&lfs, "potato/fried") => 0;
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 TEST
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_dir_open(&lfs, &dir[0], "potato") => 0;
     lfs_dir_open(&lfs, &dir[0], "potato") => 0;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     strcmp(info.name, ".") => 0;
     strcmp(info.name, ".") => 0;
@@ -97,7 +97,7 @@ TEST
 
 
 echo "--- Multi-block directory ---"
 echo "--- Multi-block directory ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_mkdir(&lfs, "cactus") => 0;
     lfs_mkdir(&lfs, "cactus") => 0;
     for (int i = 0; i < $LARGESIZE; i++) {
     for (int i = 0; i < $LARGESIZE; i++) {
         sprintf((char*)buffer, "cactus/test%d", i);
         sprintf((char*)buffer, "cactus/test%d", i);
@@ -106,7 +106,7 @@ tests/test.py << TEST
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 TEST
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_dir_open(&lfs, &dir[0], "cactus") => 0;
     lfs_dir_open(&lfs, &dir[0], "cactus") => 0;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     strcmp(info.name, ".") => 0;
     strcmp(info.name, ".") => 0;
@@ -125,7 +125,7 @@ TEST
 
 
 echo "--- Directory remove ---"
 echo "--- Directory remove ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_remove(&lfs, "potato") => LFS_ERROR_INVALID;
     lfs_remove(&lfs, "potato") => LFS_ERROR_INVALID;
     lfs_remove(&lfs, "potato/sweet") => 0;
     lfs_remove(&lfs, "potato/sweet") => 0;
     lfs_remove(&lfs, "potato/baked") => 0;
     lfs_remove(&lfs, "potato/baked") => 0;
@@ -161,7 +161,7 @@ tests/test.py << TEST
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 TEST
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_dir_open(&lfs, &dir[0], "/") => 0;
     lfs_dir_open(&lfs, &dir[0], "/") => 0;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     strcmp(info.name, ".") => 0;
     strcmp(info.name, ".") => 0;
@@ -182,7 +182,7 @@ TEST
 
 
 echo "--- Directory rename ---"
 echo "--- Directory rename ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_mkdir(&lfs, "coldpotato") => 0;
     lfs_mkdir(&lfs, "coldpotato") => 0;
     lfs_mkdir(&lfs, "coldpotato/baked") => 0;
     lfs_mkdir(&lfs, "coldpotato/baked") => 0;
     lfs_mkdir(&lfs, "coldpotato/sweet") => 0;
     lfs_mkdir(&lfs, "coldpotato/sweet") => 0;
@@ -190,12 +190,12 @@ tests/test.py << TEST
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 TEST
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_rename(&lfs, "coldpotato", "hotpotato") => 0;
     lfs_rename(&lfs, "coldpotato", "hotpotato") => 0;
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 TEST
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_dir_open(&lfs, &dir[0], "hotpotato") => 0;
     lfs_dir_open(&lfs, &dir[0], "hotpotato") => 0;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     strcmp(info.name, ".") => 0;
     strcmp(info.name, ".") => 0;
@@ -217,7 +217,7 @@ tests/test.py << TEST
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 TEST
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_mkdir(&lfs, "warmpotato") => 0;
     lfs_mkdir(&lfs, "warmpotato") => 0;
     lfs_mkdir(&lfs, "warmpotato/mushy") => 0;
     lfs_mkdir(&lfs, "warmpotato/mushy") => 0;
     lfs_rename(&lfs, "hotpotato", "warmpotato") => LFS_ERROR_INVALID;
     lfs_rename(&lfs, "hotpotato", "warmpotato") => LFS_ERROR_INVALID;
@@ -228,7 +228,7 @@ tests/test.py << TEST
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 TEST
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_dir_open(&lfs, &dir[0], "warmpotato") => 0;
     lfs_dir_open(&lfs, &dir[0], "warmpotato") => 0;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     strcmp(info.name, ".") => 0;
     strcmp(info.name, ".") => 0;
@@ -250,7 +250,7 @@ tests/test.py << TEST
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 TEST
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_mkdir(&lfs, "coldpotato") => 0;
     lfs_mkdir(&lfs, "coldpotato") => 0;
     lfs_rename(&lfs, "warmpotato/baked", "coldpotato/baked") => 0;
     lfs_rename(&lfs, "warmpotato/baked", "coldpotato/baked") => 0;
     lfs_rename(&lfs, "warmpotato/sweet", "coldpotato/sweet") => 0;
     lfs_rename(&lfs, "warmpotato/sweet", "coldpotato/sweet") => 0;
@@ -260,7 +260,7 @@ tests/test.py << TEST
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 TEST
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_dir_open(&lfs, &dir[0], "coldpotato") => 0;
     lfs_dir_open(&lfs, &dir[0], "coldpotato") => 0;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     strcmp(info.name, ".") => 0;
     strcmp(info.name, ".") => 0;

+ 5 - 5
tests/test_files.sh

@@ -8,12 +8,12 @@ LARGESIZE=262144
 echo "=== File tests ==="
 echo "=== File tests ==="
 rm -rf blocks
 rm -rf blocks
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_format(&lfs, &config) => 0;
+    lfs_format(&lfs, &cfg) => 0;
 TEST
 TEST
 
 
 echo "--- Simple file test ---"
 echo "--- Simple file test ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_file_open(&lfs, &file[0], "hello", LFS_O_RDWR | LFS_O_CREAT | LFS_O_APPEND) => 0;
     lfs_file_open(&lfs, &file[0], "hello", LFS_O_RDWR | LFS_O_CREAT | LFS_O_APPEND) => 0;
     size = strlen("Hello World!\n");
     size = strlen("Hello World!\n");
     memcpy(wbuffer, "Hello World!\n", size);
     memcpy(wbuffer, "Hello World!\n", size);
@@ -29,7 +29,7 @@ tests/test.py << TEST
     lfs_size_t size = $1;
     lfs_size_t size = $1;
     lfs_size_t chunk = 31;
     lfs_size_t chunk = 31;
     srand(0);
     srand(0);
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_file_open(&lfs, &file[0], "$2", LFS_O_WRONLY | LFS_O_CREAT) => 0;
     lfs_file_open(&lfs, &file[0], "$2", LFS_O_WRONLY | LFS_O_CREAT) => 0;
     for (lfs_size_t i = 0; i < size; i += chunk) {
     for (lfs_size_t i = 0; i < size; i += chunk) {
         chunk = (chunk < size - i) ? chunk : size - i;
         chunk = (chunk < size - i) ? chunk : size - i;
@@ -48,7 +48,7 @@ tests/test.py << TEST
     lfs_size_t size = $1;
     lfs_size_t size = $1;
     lfs_size_t chunk = 29;
     lfs_size_t chunk = 29;
     srand(0);
     srand(0);
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_file_open(&lfs, &file[0], "$2", LFS_O_RDONLY) => 0;
     lfs_file_open(&lfs, &file[0], "$2", LFS_O_RDONLY) => 0;
     for (lfs_size_t i = 0; i < size; i += chunk) {
     for (lfs_size_t i = 0; i < size; i += chunk) {
         chunk = (chunk < size - i) ? chunk : size - i;
         chunk = (chunk < size - i) ? chunk : size - i;
@@ -81,7 +81,7 @@ r_test $LARGESIZE largeavacado
 
 
 echo "--- Dir check ---"
 echo "--- Dir check ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_dir_open(&lfs, &dir[0], "/") => 0;
     lfs_dir_open(&lfs, &dir[0], "/") => 0;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;
     lfs_dir_read(&lfs, &dir[0], &info) => 1;

+ 8 - 8
tests/test_format.sh

@@ -6,42 +6,42 @@ rm -rf blocks
 
 
 echo "--- Basic formatting ---"
 echo "--- Basic formatting ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_format(&lfs, &config) => 0;
+    lfs_format(&lfs, &cfg) => 0;
 TEST
 TEST
 
 
 echo "--- Invalid superblocks ---"
 echo "--- Invalid superblocks ---"
 ln -f -s /dev/null blocks/0
 ln -f -s /dev/null blocks/0
 ln -f -s /dev/null blocks/1
 ln -f -s /dev/null blocks/1
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_format(&lfs, &config) => LFS_ERROR_CORRUPT;
+    lfs_format(&lfs, &cfg) => LFS_ERROR_CORRUPT;
 TEST
 TEST
 rm blocks/0 blocks/1
 rm blocks/0 blocks/1
 
 
 echo "--- Basic mounting ---"
 echo "--- Basic mounting ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_format(&lfs, &config) => 0;
+    lfs_format(&lfs, &cfg) => 0;
 TEST
 TEST
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 TEST
 
 
 echo "--- Invalid mount ---"
 echo "--- Invalid mount ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_format(&lfs, &config) => 0;
+    lfs_format(&lfs, &cfg) => 0;
 TEST
 TEST
 rm blocks/0 blocks/1
 rm blocks/0 blocks/1
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => LFS_ERROR_CORRUPT;
+    lfs_mount(&lfs, &cfg) => LFS_ERROR_CORRUPT;
 TEST
 TEST
 
 
 echo "--- Valid corrupt mount ---"
 echo "--- Valid corrupt mount ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_format(&lfs, &config) => 0;
+    lfs_format(&lfs, &cfg) => 0;
 TEST
 TEST
 rm blocks/0
 rm blocks/0
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 TEST
 
 

+ 3 - 3
tests/test_orphan.sh

@@ -4,12 +4,12 @@ set -eu
 echo "=== Orphan tests ==="
 echo "=== Orphan tests ==="
 rm -rf blocks
 rm -rf blocks
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_format(&lfs, &config) => 0;
+    lfs_format(&lfs, &cfg) => 0;
 TEST
 TEST
 
 
 echo "--- Orphan test ---"
 echo "--- Orphan test ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_mkdir(&lfs, "parent") => 0;
     lfs_mkdir(&lfs, "parent") => 0;
     lfs_mkdir(&lfs, "parent/orphan") => 0;
     lfs_mkdir(&lfs, "parent/orphan") => 0;
     lfs_mkdir(&lfs, "parent/child") => 0;
     lfs_mkdir(&lfs, "parent/child") => 0;
@@ -19,7 +19,7 @@ TEST
 # linked-list entry and should orphan the child
 # linked-list entry and should orphan the child
 rm -v blocks/8
 rm -v blocks/8
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERROR_NO_ENTRY;
     lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERROR_NO_ENTRY;
     unsigned before = 0;
     unsigned before = 0;
     lfs_traverse(&lfs, test_count, &before) => 0;
     lfs_traverse(&lfs, test_count, &before) => 0;

+ 7 - 7
tests/test_paths.sh

@@ -4,11 +4,11 @@ set -eu
 echo "=== Path tests ==="
 echo "=== Path tests ==="
 rm -rf blocks
 rm -rf blocks
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_format(&lfs, &config) => 0;
+    lfs_format(&lfs, &cfg) => 0;
 TEST
 TEST
 
 
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_mkdir(&lfs, "tea") => 0;
     lfs_mkdir(&lfs, "tea") => 0;
     lfs_mkdir(&lfs, "coffee") => 0;
     lfs_mkdir(&lfs, "coffee") => 0;
     lfs_mkdir(&lfs, "soda") => 0;
     lfs_mkdir(&lfs, "soda") => 0;
@@ -26,7 +26,7 @@ TEST
 
 
 echo "--- Root path tests ---"
 echo "--- Root path tests ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_stat(&lfs, "tea/hottea", &info) => 0;
     lfs_stat(&lfs, "tea/hottea", &info) => 0;
     strcmp(info.name, "hottea") => 0;
     strcmp(info.name, "hottea") => 0;
     lfs_stat(&lfs, "/tea/hottea", &info) => 0;
     lfs_stat(&lfs, "/tea/hottea", &info) => 0;
@@ -36,7 +36,7 @@ TEST
 
 
 echo "--- Redundant slash path tests ---"
 echo "--- Redundant slash path tests ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_stat(&lfs, "/tea/hottea", &info) => 0;
     lfs_stat(&lfs, "/tea/hottea", &info) => 0;
     strcmp(info.name, "hottea") => 0;
     strcmp(info.name, "hottea") => 0;
     lfs_stat(&lfs, "//tea//hottea", &info) => 0;
     lfs_stat(&lfs, "//tea//hottea", &info) => 0;
@@ -48,7 +48,7 @@ TEST
 
 
 echo "--- Dot path tests ---"
 echo "--- Dot path tests ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_stat(&lfs, "./tea/hottea", &info) => 0;
     lfs_stat(&lfs, "./tea/hottea", &info) => 0;
     strcmp(info.name, "hottea") => 0;
     strcmp(info.name, "hottea") => 0;
     lfs_stat(&lfs, "/./tea/hottea", &info) => 0;
     lfs_stat(&lfs, "/./tea/hottea", &info) => 0;
@@ -62,7 +62,7 @@ TEST
 
 
 echo "--- Dot dot path tests ---"
 echo "--- Dot dot path tests ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_stat(&lfs, "coffee/../tea/hottea", &info) => 0;
     lfs_stat(&lfs, "coffee/../tea/hottea", &info) => 0;
     strcmp(info.name, "hottea") => 0;
     strcmp(info.name, "hottea") => 0;
     lfs_stat(&lfs, "tea/coldtea/../hottea", &info) => 0;
     lfs_stat(&lfs, "tea/coldtea/../hottea", &info) => 0;
@@ -76,7 +76,7 @@ TEST
 
 
 echo "--- Root dot dot path tests ---"
 echo "--- Root dot dot path tests ---"
 tests/test.py << TEST
 tests/test.py << TEST
-    lfs_mount(&lfs, &config) => 0;
+    lfs_mount(&lfs, &cfg) => 0;
     lfs_stat(&lfs, "coffee/../../../../../../tea/hottea", &info) => 0;
     lfs_stat(&lfs, "coffee/../../../../../../tea/hottea", &info) => 0;
     strcmp(info.name, "hottea") => 0;
     strcmp(info.name, "hottea") => 0;
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;