mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	Removed .. and . entries
No longer need to be stored on disk, can be simulated on the chip side. As mentioned in other commits, the parent entries had dozens of problems with atomic updates, as well as making everything just a bit more complex than is needed.
This commit is contained in:
		
							
								
								
									
										88
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										88
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -522,8 +522,7 @@ static int lfs_pair_shift(lfs_t *lfs, lfs_block_t pair[2], | ||||
|  | ||||
| /// Directory operations /// | ||||
|  | ||||
| static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir, | ||||
|         lfs_block_t parent[2], lfs_block_t tail[2]) { | ||||
| static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir, lfs_block_t tail[2]) { | ||||
|     // Allocate pair of dir blocks | ||||
|     for (int i = 0; i < 2; i++) { | ||||
|         int err = lfs_alloc(lfs, &dir->pair[i]); | ||||
| @@ -549,35 +548,10 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir, | ||||
|     dir->d.tail[1] = tail[1]; | ||||
|  | ||||
|     // Write out to memory | ||||
|     if (!parent) { | ||||
|     return lfs_pair_commit(lfs, dir->pair, | ||||
|         1, (struct lfs_commit_region[]){ | ||||
|             {0, sizeof(dir->d), &dir->d} | ||||
|         }); | ||||
|     } else { | ||||
|         dir->d.size += 2*sizeof(struct lfs_disk_entry) + 3; | ||||
|         return lfs_pair_commit(lfs, dir->pair, | ||||
|             5, (struct lfs_commit_region[]){ | ||||
|                 {0, sizeof(dir->d), &dir->d}, | ||||
|                 {sizeof(dir->d), sizeof(struct lfs_disk_entry), | ||||
|                  &(struct lfs_disk_entry){ | ||||
|                     .type     = LFS_TYPE_DIR, | ||||
|                     .len      = sizeof(struct lfs_disk_entry)+1, | ||||
|                     .u.dir[0] = dir->pair[0], | ||||
|                     .u.dir[1] = dir->pair[1], | ||||
|                 }}, | ||||
|                 {sizeof(dir->d)+sizeof(struct lfs_disk_entry), 1, "."}, | ||||
|                 {sizeof(dir->d)+sizeof(struct lfs_disk_entry)+1, | ||||
|                  sizeof(struct lfs_disk_entry), | ||||
|                  &(struct lfs_disk_entry){ | ||||
|                     .type     = LFS_TYPE_DIR, | ||||
|                     .len      = sizeof(struct lfs_disk_entry)+2, | ||||
|                     .u.dir[0] = parent[0] ? parent[0] : dir->pair[0], | ||||
|                     .u.dir[1] = parent[1] ? parent[1] : dir->pair[1], | ||||
|                 }}, | ||||
|                 {sizeof(dir->d)+2*sizeof(struct lfs_disk_entry)+1, 2, ".."}, | ||||
|             }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int lfs_dir_fetch(lfs_t *lfs, lfs_dir_t *dir, lfs_block_t pair[2]) { | ||||
| @@ -725,7 +699,7 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | ||||
|         lfs_dir_t olddir; | ||||
|         memcpy(&olddir, dir, sizeof(olddir)); | ||||
|  | ||||
|         int err = lfs_dir_alloc(lfs, dir, 0, olddir.d.tail); | ||||
|         int err = lfs_dir_alloc(lfs, dir, olddir.d.tail); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } | ||||
| @@ -763,7 +737,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { | ||||
|  | ||||
|     // Build up new directory | ||||
|     lfs_dir_t dir; | ||||
|     err = lfs_dir_alloc(lfs, &dir, cwd.pair, cwd.d.tail); | ||||
|     err = lfs_dir_alloc(lfs, &dir, cwd.d.tail); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
| @@ -799,6 +773,8 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) { | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } else if (strcmp(path, "/") == 0) { | ||||
|         // special offset for '.' and '..' | ||||
|         dir->off = sizeof(dir->d) - 2; | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
| @@ -810,7 +786,14 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) { | ||||
|         return LFS_ERROR_NOT_DIR; | ||||
|     } | ||||
|  | ||||
|     return lfs_dir_fetch(lfs, dir, entry.d.u.dir); | ||||
|     err = lfs_dir_fetch(lfs, dir, entry.d.u.dir); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     // special offset for '.' and '..' | ||||
|     dir->off = sizeof(dir->d) - 2; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) { | ||||
| @@ -821,6 +804,18 @@ int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) { | ||||
| int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) { | ||||
|     memset(info, 0, sizeof(*info)); | ||||
|  | ||||
|     if (dir->off == sizeof(dir->d) - 2) { | ||||
|         info->type = LFS_TYPE_DIR; | ||||
|         strcpy(info->name, "."); | ||||
|         dir->off += 1; | ||||
|         return 1; | ||||
|     } else if (dir->off == sizeof(dir->d) - 1) { | ||||
|         info->type = LFS_TYPE_DIR; | ||||
|         strcpy(info->name, ".."); | ||||
|         dir->off += 1; | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     lfs_entry_t entry; | ||||
|     int err = lfs_dir_next(lfs, dir, &entry); | ||||
|     if (err) { | ||||
| @@ -1100,8 +1095,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *config) { | ||||
|  | ||||
|     // Write root directory | ||||
|     lfs_dir_t root; | ||||
|     err = lfs_dir_alloc(lfs, &root, | ||||
|             (lfs_block_t[2]){0, 0}, (lfs_block_t[2]){0, 0}); | ||||
|     err = lfs_dir_alloc(lfs, &root, (lfs_block_t[2]){0, 0}); | ||||
|     if (err) { | ||||
|         return err; | ||||
|     } | ||||
| @@ -1195,9 +1189,6 @@ int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) { | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         // skip '.' and '..' | ||||
|         dir.off += 2*sizeof(struct lfs_disk_entry) + 3; | ||||
|  | ||||
|         // iterate over contents | ||||
|         while ((0x7fffffff & dir.d.size) >= dir.off + sizeof(file.entry.d)) { | ||||
|             int err = lfs_bd_read(lfs, dir.pair[0], dir.off, | ||||
| @@ -1248,14 +1239,6 @@ static int lfs_parent(lfs_t *lfs, const lfs_block_t dir[2]) { | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         // skip .. and . entries | ||||
|         for (int i = 0; i < 2; i++) { | ||||
|             int err = lfs_dir_next(lfs, &parent, &entry); | ||||
|             if (err) { | ||||
|                 return err; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         while (true) { | ||||
|             int err = lfs_dir_next(lfs, &parent, &entry); | ||||
|             if (err && err != LFS_ERROR_NO_ENTRY) { | ||||
| @@ -1339,12 +1322,13 @@ int lfs_remove(lfs_t *lfs, const char *path) { | ||||
|  | ||||
|     lfs_dir_t dir; | ||||
|     if (entry.d.type == LFS_TYPE_DIR) { | ||||
|         // must be empty before removal | ||||
|         // must be empty before removal, checking size | ||||
|         // without masking top bit checks for any case where | ||||
|         // dir is not empty | ||||
|         int err = lfs_dir_fetch(lfs, &dir, entry.d.u.dir); | ||||
|         if (err) { | ||||
|             return err; | ||||
|         } else if (dir.d.size != sizeof(dir.d) + | ||||
|                 2*sizeof(struct lfs_disk_entry) + 3) { | ||||
|         } else if (dir.d.size != sizeof(dir.d)) { | ||||
|             return LFS_ERROR_INVALID; | ||||
|         } | ||||
|     } | ||||
| @@ -1367,6 +1351,17 @@ int lfs_remove(lfs_t *lfs, const char *path) { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // TODO easier check for head block? (common case) | ||||
|         if (!(pdir.d.size & 0x80000000)) { | ||||
|             int err = lfs_pair_shift(lfs, entry.dir, | ||||
|                 1, (struct lfs_commit_region[]) { | ||||
|                     {0, sizeof(cwd.d), &cwd.d}, | ||||
|                 }, | ||||
|                 entry.off, entry.d.len); | ||||
|             if (err) { | ||||
|                 return err; | ||||
|             } | ||||
|         } else { | ||||
|             pdir.d.tail[0] = cwd.d.tail[0]; | ||||
|             pdir.d.tail[1] = cwd.d.tail[1]; | ||||
|             pdir.d.rev += 1; | ||||
| @@ -1378,6 +1373,7 @@ int lfs_remove(lfs_t *lfs, const char *path) { | ||||
|             if (err) { | ||||
|                 return err; | ||||
|             } | ||||
|         } | ||||
|     } else { | ||||
|         int err = lfs_pair_shift(lfs, entry.dir, | ||||
|             1, (struct lfs_commit_region[]) { | ||||
|   | ||||
| @@ -17,7 +17,7 @@ tests/test.py << TEST | ||||
| TEST | ||||
| # remove most recent file, this should be the update to the previous | ||||
| # linked-list entry and should orphan the child | ||||
| rm -v "blocks/$(ls -t blocks | sed -n '/^[0-9a-f]*$/p' | sed -n '1p')" | ||||
| rm -v blocks/8 | ||||
| tests/test.py << TEST | ||||
|     lfs_mount(&lfs, &config) => 0; | ||||
|     lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERROR_NO_ENTRY; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user