mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 00:32:38 +01:00 
			
		
		
		
	Fixed issue with splitting metadata-pairs in full filesystem
Depending on your perspective, this may not be a necessary operation, given that a nearly-full filesystem is already prone to ENOSPC errors, especially a COW filesystem. However, splitting metadata-pairs can happen in really unfortunate situations, such as removing files. The solution here is to allow "overcompaction", that is, a compaction without bounds checking to allow splitting. This unfortunately pushes our metadata-pairs past their reasonable limit of saturation, which means writes get exponentially costly. However it does allow littlefs to continue working in extreme situations.
This commit is contained in:
		
							
								
								
									
										19
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -1290,6 +1290,7 @@ static int lfs_dir_compact(lfs_t *lfs, | ||||
|         // setup compaction | ||||
|         bool splitted = false; | ||||
|         bool exhausted = false; | ||||
|         bool overcompacting = false; | ||||
|  | ||||
|         struct lfs_commit commit; | ||||
|         commit.block = dir->pair[1]; | ||||
| @@ -1310,9 +1311,11 @@ commit: | ||||
|         // cleanup delete, and we cap at half a block to give room | ||||
|         // for metadata updates | ||||
|         commit.begin = 0; | ||||
|         commit.end = lfs_min( | ||||
|              lfs_alignup(lfs->cfg->block_size/2, lfs->cfg->prog_size), | ||||
|              lfs->cfg->block_size - 38); | ||||
|         commit.end = lfs->cfg->block_size - 38; | ||||
|         if (!overcompacting) { | ||||
|             commit.end = lfs_min(commit.end, | ||||
|                     lfs_alignup(lfs->cfg->block_size/2, lfs->cfg->prog_size)); | ||||
|         } | ||||
|  | ||||
|         if (!splitted) { | ||||
|             // increment revision count | ||||
| @@ -1369,8 +1372,9 @@ commit: | ||||
|                         0x003ff000, LFS_MKTAG(0, id, 0), | ||||
|                         -LFS_MKTAG(0, begin, 0), | ||||
|                         source, attrs); | ||||
|                 if (err && !(splitted && err == LFS_ERR_NOSPC)) { | ||||
|                     if (err == LFS_ERR_NOSPC) { | ||||
|                 if (err && !(splitted && !overcompacting && | ||||
|                         err == LFS_ERR_NOSPC)) { | ||||
|                     if (!overcompacting && err == LFS_ERR_NOSPC) { | ||||
|                         goto split; | ||||
|                     } else if (err == LFS_ERR_CORRUPT) { | ||||
|                         goto relocate; | ||||
| @@ -1457,6 +1461,11 @@ split: | ||||
|         lfs_mdir_t tail; | ||||
|         err = lfs_dir_alloc(lfs, &tail); | ||||
|         if (err) { | ||||
|             if (err == LFS_ERR_NOSPC) { | ||||
|                 // No space to expand? Try overcompacting | ||||
|                 overcompacting = true; | ||||
|                 goto commit; | ||||
|             } | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user