mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	Fixed mkdir when inserting into a non-end block
This was an oversight on my part when adding strict ordering to directories. Unfortunately now we can't take advantage of the atomic creation of tail+dir entries. Now we need to first create the tail, then create the actually directory entry. If we lose power, the orphan is cleaned up like orphans created during remove. Note that we still take advantage of the atomic tail+dir entries if we are an end block. This is actually because this corner case is complicated to _not_ do atomically, needing to update the directory we just committed to.
This commit is contained in:
		| @@ -126,7 +126,7 @@ jobs: | |||||||
|         - mkdir mount/littlefs |         - mkdir mount/littlefs | ||||||
|         - cp -r $(git ls-tree --name-only HEAD) mount/littlefs |         - cp -r $(git ls-tree --name-only HEAD) mount/littlefs | ||||||
|         - cd mount/littlefs |         - cd mount/littlefs | ||||||
|         - ls |         - ls -flh | ||||||
|         - make -B test_dirs test_files QUIET=1 |         - make -B test_dirs test_files QUIET=1 | ||||||
|  |  | ||||||
|       # Automatically update releases |       # Automatically update releases | ||||||
|   | |||||||
							
								
								
									
										45
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -1746,29 +1746,58 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { | |||||||
|  |  | ||||||
|     // build up new directory |     // build up new directory | ||||||
|     lfs_alloc_ack(lfs); |     lfs_alloc_ack(lfs); | ||||||
|  |  | ||||||
|     lfs_mdir_t dir; |     lfs_mdir_t dir; | ||||||
|     err = lfs_dir_alloc(lfs, &dir); |     err = lfs_dir_alloc(lfs, &dir); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     dir.tail[0] = cwd.tail[0]; |     // find end of list | ||||||
|     dir.tail[1] = cwd.tail[1]; |     lfs_mdir_t pred = cwd; | ||||||
|  |     while (pred.split) { | ||||||
|  |         err = lfs_dir_fetch(lfs, &pred, pred.tail); | ||||||
|  |         if (err) { | ||||||
|  |             return err; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // setup dir | ||||||
|  |     dir.tail[0] = pred.tail[0]; | ||||||
|  |     dir.tail[1] = pred.tail[1]; | ||||||
|     err = lfs_dir_commit(lfs, &dir, NULL); |     err = lfs_dir_commit(lfs, &dir, NULL); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // get next slot and commit |     // current block end of list? | ||||||
|     cwd.tail[0] = dir.pair[0]; |     if (!cwd.split) { | ||||||
|     cwd.tail[1] = dir.pair[1]; |         // update atomically | ||||||
|  |         cwd.tail[0] = dir.pair[0]; | ||||||
|  |         cwd.tail[1] = dir.pair[1]; | ||||||
|  |     } else { | ||||||
|  |         // update tails, this creates a desync | ||||||
|  |         pred.tail[0] = dir.pair[0]; | ||||||
|  |         pred.tail[1] = dir.pair[1]; | ||||||
|  |         lfs_global_orphans(lfs, +1); | ||||||
|  |         err = lfs_dir_commit(lfs, &pred, | ||||||
|  |                 LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x1ff, | ||||||
|  |                     pred.tail, sizeof(pred.tail), | ||||||
|  |                 NULL)); | ||||||
|  |         if (err) { | ||||||
|  |             return err; | ||||||
|  |         } | ||||||
|  |         lfs_global_orphans(lfs, -1); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // now insert into our parent block | ||||||
|     lfs_pair_tole32(dir.pair); |     lfs_pair_tole32(dir.pair); | ||||||
|     err = lfs_dir_commit(lfs, &cwd, |     err = lfs_dir_commit(lfs, &cwd, | ||||||
|             LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x1ff, cwd.tail, sizeof(cwd.tail), |  | ||||||
|             LFS_MKATTR(LFS_TYPE_DIRSTRUCT, id, dir.pair, sizeof(dir.pair), |             LFS_MKATTR(LFS_TYPE_DIRSTRUCT, id, dir.pair, sizeof(dir.pair), | ||||||
|             LFS_MKATTR(LFS_TYPE_DIR, id, path, nlen, |             LFS_MKATTR(LFS_TYPE_DIR, id, path, nlen, | ||||||
|             NULL)))); |             (!cwd.split) | ||||||
|  |                 ? LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x1ff, | ||||||
|  |                     cwd.tail, sizeof(cwd.tail), NULL) | ||||||
|  |                 : NULL))); | ||||||
|     lfs_pair_fromle32(dir.pair); |     lfs_pair_fromle32(dir.pair); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|   | |||||||
| @@ -89,7 +89,7 @@ do | |||||||
|     rm -rf blocks |     rm -rf blocks | ||||||
|     mkdir blocks |     mkdir blocks | ||||||
|     lfs_mktree |     lfs_mktree | ||||||
|     chmod a-w blocks/$b |     chmod a-w blocks/$b || true | ||||||
|     lfs_mktree |     lfs_mktree | ||||||
|     lfs_chktree |     lfs_chktree | ||||||
| done | done | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user