mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 00:32:38 +01:00 
			
		
		
		
	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.
This commit is contained in:
		
							
								
								
									
										141
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										141
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -12,27 +12,22 @@ | ||||
|  | ||||
|  | ||||
| /// 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, | ||||
|         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, | ||||
|         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) { | ||||
|     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, | ||||
| @@ -101,7 +96,7 @@ static int lfs_alloc_scan(lfs_t *lfs) { | ||||
|             // found free block, now find stride of free blocks | ||||
|             // since this is relatively cheap (stress on relatively) | ||||
|             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 | ||||
|             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 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) { | ||||
|     lfs_off_t i = 0; | ||||
|     while (off > lfs->block_size) { | ||||
|     while (off > lfs->cfg->block_size) { | ||||
|         i = lfs_indexnext(lfs, i); | ||||
|         off -= lfs->block_size; | ||||
|         off -= lfs->cfg->block_size; | ||||
|     } | ||||
|  | ||||
|     return i; | ||||
| @@ -370,7 +365,7 @@ static int lfs_dir_fetch(lfs_t *lfs, | ||||
|         uint32_t crc = 0xffffffff; | ||||
|         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; | ||||
|             int err = lfs_bd_read(lfs, tpair[i], j, 4, &word); | ||||
|             if (err) { | ||||
| @@ -406,7 +401,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, | ||||
|     dir->d.rev += 1; | ||||
|     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) { | ||||
|         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; | ||||
|         int err = lfs_bd_read(lfs, dir->pair[0], off, 1, &data); | ||||
|         if (err) { | ||||
| @@ -467,7 +462,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, | ||||
|         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) { | ||||
|         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; | ||||
|     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) { | ||||
|         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; | ||||
|         int err = lfs_bd_read(lfs, dir->pair[0], woff, 1, &data); | ||||
|         if (err) { | ||||
| @@ -527,7 +522,7 @@ static int lfs_dir_shift(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | ||||
|         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) { | ||||
|         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) { | ||||
|     // check if we fit, if top bit is set we do not and move on | ||||
|     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[1] = dir->pair[1]; | ||||
|             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 cow the head i/d block | ||||
|     if (file->size < lfs->block_size) { | ||||
|     if (file->size < lfs->cfg->block_size) { | ||||
|         file->wblock = file->head; | ||||
|     } else { | ||||
|         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; | ||||
|  | ||||
|     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) { | ||||
|             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); | ||||
|         if (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; | ||||
|  | ||||
|     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 | ||||
|         if (file->size < lfs->block_size) { | ||||
|         if (file->size < lfs->cfg->block_size) { | ||||
|             file->rblock = file->head; | ||||
|         } else if (roff == 0) { | ||||
|             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_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); | ||||
|         if (err) { | ||||
|             return err; | ||||
| @@ -991,85 +986,17 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, | ||||
|  | ||||
|  | ||||
| /// 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 err = lfs_configure(lfs, config); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
|     lfs->cfg = config; | ||||
|     lfs->words = lfs->cfg->block_size / sizeof(uint32_t); | ||||
|  | ||||
|     // Create free list | ||||
|     lfs->free.begin = 0; | ||||
|     lfs->free.end = lfs->block_count-1; | ||||
|     lfs->free.end = lfs->cfg->block_count-1; | ||||
|  | ||||
|     // Create superblock dir | ||||
|     lfs_dir_t superdir; | ||||
|     err = lfs_dir_alloc(lfs, &superdir); | ||||
|     int err = lfs_dir_alloc(lfs, &superdir); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
| @@ -1096,8 +1023,8 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *config) { | ||||
|         .d.len = sizeof(superblock.d), | ||||
|         .d.version = 0x00000001, | ||||
|         .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]}, | ||||
|     }; | ||||
|     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 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_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) { | ||||
|         err = lfs_bd_read(lfs, dir.pair[0], | ||||
|                 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; | ||||
|             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); | ||||
|                     if (err) { | ||||
|                         return err; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user