mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	Combined superblock scan and fetch of xored-globals during mount
Conceptually these are two separate operations. However, they are both only needed during mount, both require iteration over the linked-list of metadata-pairs, and both are independent from each other. Combining these into one gives us a nice code savings. Additionally, this greatly simplifies the lookup of the root directory. Initially we used a flag to indicate which superblock was root, since we didn't want to fetch more pairs than we needed to. But since we're going to fetch all metadata-pairs anyways, we can just use the last superblock we find as the indicator of our root directory.
This commit is contained in:
		
							
								
								
									
										49
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -3116,7 +3116,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | ||||
|  | ||||
|     lfs_superblock_tole32(&superblock); | ||||
|     err = lfs_dir_commit(lfs, &root, | ||||
|             LFS_MKATTR(LFS_TYPE_ROOT, 0, &superblock, sizeof(superblock), | ||||
|             LFS_MKATTR(LFS_TYPE_SUPERBLOCK, 0, &superblock, sizeof(superblock), | ||||
|             NULL)); | ||||
|     if (err) { | ||||
|         goto cleanup; | ||||
| @@ -3139,20 +3139,28 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     // find root/superblock | ||||
|     lfs_mdir_t root; | ||||
|     lfs_superblock_t superblock; | ||||
|     lfs_stag_t tag = lfs_dir_findmatch(lfs, | ||||
|             &root, (const lfs_block_t[2]){0, 1}, false, 0x7fc00000, | ||||
|             LFS_MKTAG(LFS_TYPE_ROOT, 0, 8), | ||||
|     // scan directory blocks for superblock and any global updates | ||||
|     lfs_mdir_t dir = {.tail = {0, 1}}; | ||||
|     while (!lfs_pair_isnull(dir.tail)) { | ||||
|         // fetch next block in tail list | ||||
|         lfs_stag_t res = lfs_dir_fetchmatch(lfs, &dir, dir.tail, 0x7fc00000, | ||||
|                 LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, 8), | ||||
|                 lfs_dir_find_match, &(struct lfs_dir_find_match){ | ||||
|                     lfs, "littlefs", 8}); | ||||
|     if (tag < 0) { | ||||
|         err = tag; | ||||
|         if (res < 0) { | ||||
|             err = res; | ||||
|             goto cleanup; | ||||
|         } | ||||
|  | ||||
|     lfs_stag_t res = lfs_dir_get(lfs, &root, 0x7f800000, | ||||
|         // has superblock? | ||||
|         if (res) { | ||||
|             // update root | ||||
|             lfs->root[0] = dir.pair[0]; | ||||
|             lfs->root[1] = dir.pair[1]; | ||||
|  | ||||
|             // grab superblock | ||||
|             lfs_superblock_t superblock; | ||||
|             res = lfs_dir_get(lfs, &dir, 0x7f800000, | ||||
|                     LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, sizeof(superblock)), | ||||
|                     &superblock); | ||||
|             if (res < 0) { | ||||
| @@ -3161,9 +3169,6 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | ||||
|             } | ||||
|             lfs_superblock_fromle32(&superblock); | ||||
|  | ||||
|     lfs->root[0] = root.pair[0]; | ||||
|     lfs->root[1] = root.pair[1]; | ||||
|  | ||||
|             // check version | ||||
|             uint16_t major_version = (0xffff & (superblock.version >> 16)); | ||||
|             uint16_t minor_version = (0xffff & (superblock.version >>  0)); | ||||
| @@ -3208,28 +3213,20 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | ||||
|  | ||||
|                 lfs->inline_max = superblock.inline_max; | ||||
|             } | ||||
|  | ||||
|     // scan for any global updates | ||||
|     lfs_mdir_t dir = {.tail = {0, 1}}; | ||||
|     while (!lfs_pair_isnull(dir.tail)) { | ||||
|         res = lfs_dir_fetchmatch(lfs, &dir, dir.tail, 0x7c000000, | ||||
|                 LFS_MKTAG(LFS_TYPE_GLOBALS, 0, 10),  NULL, NULL); | ||||
|         if (res < 0) { | ||||
|             err = LFS_ERR_INVAL; | ||||
|             goto cleanup; | ||||
|         } | ||||
|  | ||||
|         if (res) { | ||||
|         // has globals? | ||||
|         lfs_global_t locals; | ||||
|         res = lfs_dir_get(lfs, &dir, 0x7c000000, | ||||
|                 LFS_MKTAG(LFS_TYPE_GLOBALS, 0, 10), &locals); | ||||
|             if (res < 0) { | ||||
|         if (res < 0 && res != LFS_ERR_NOENT) { | ||||
|             err = res; | ||||
|             goto cleanup; | ||||
|         } | ||||
|             locals.l.deorphaned = (lfs_tag_type(res) & 1); | ||||
|  | ||||
|             // xor together indirect deletes | ||||
|         if (res != LFS_ERR_NOENT) { | ||||
|             locals.l.deorphaned = (lfs_tag_type(res) & 1); | ||||
|             // xor together to find resulting globals | ||||
|             lfs_global_xor(&lfs->locals, &locals); | ||||
|         } | ||||
|     } | ||||
|   | ||||
							
								
								
									
										8
									
								
								lfs.h
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								lfs.h
									
									
									
									
									
								
							| @@ -94,27 +94,25 @@ enum lfs_type { | ||||
|  | ||||
|     // internally used types | ||||
|     LFS_TYPE_USER           = 0x100, | ||||
|     LFS_TYPE_SUPERBLOCK     = 0x001, | ||||
|     LFS_TYPE_ROOT           = 0x000, | ||||
|     LFS_TYPE_NAME           = 0x000, | ||||
|     LFS_TYPE_DELETE         = 0x020, | ||||
|     LFS_TYPE_STRUCT         = 0x040, | ||||
|     LFS_TYPE_GLOBALS        = 0x0e0, | ||||
|     LFS_TYPE_TAIL           = 0x080, | ||||
|     LFS_TYPE_SOFTTAIL       = 0x080, | ||||
|     LFS_TYPE_HARDTAIL       = 0x081, | ||||
|     LFS_TYPE_CRC            = 0x0a0, | ||||
|     LFS_TYPE_SUPERBLOCK     = 0x001, | ||||
|     LFS_TYPE_GLOBALS        = 0x0e0, | ||||
|  | ||||
|     LFS_TYPE_DIRSTRUCT      = 0x040, | ||||
|     LFS_TYPE_INLINESTRUCT   = 0x041, | ||||
|     LFS_TYPE_CTZSTRUCT      = 0x042, | ||||
|  | ||||
|     // internal chip sources | ||||
|     LFS_FROM_REGION         = 0x000, | ||||
|     LFS_FROM_MEM            = 0x000, | ||||
|     LFS_FROM_DISK           = 0x200, | ||||
|     LFS_FROM_MOVE           = 0x0c1, | ||||
|     LFS_FROM_USERATTRS      = 0x0c2, | ||||
|     LFS_FROM_SUPERBLOCK     = 0x0c3, | ||||
| }; | ||||
|  | ||||
| // File open flags | ||||
|   | ||||
| @@ -7,7 +7,6 @@ TYPES = { | ||||
|     (0x1ff, 0x002): 'reg', | ||||
|     (0x1ff, 0x003): 'dir', | ||||
|     (0x1ff, 0x001): 'superblock', | ||||
|     (0x1ff, 0x000): 'root', | ||||
|     (0x1ff, 0x020): 'delete', | ||||
|     (0x1f0, 0x0e0): 'globals', | ||||
|     (0x1ff, 0x080): 'tail soft', | ||||
|   | ||||
		Reference in New Issue
	
	Block a user