mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +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 |         // setup compaction | ||||||
|         bool splitted = false; |         bool splitted = false; | ||||||
|         bool exhausted = false; |         bool exhausted = false; | ||||||
|  |         bool overcompacting = false; | ||||||
|  |  | ||||||
|         struct lfs_commit commit; |         struct lfs_commit commit; | ||||||
|         commit.block = dir->pair[1]; |         commit.block = dir->pair[1]; | ||||||
| @@ -1310,9 +1311,11 @@ commit: | |||||||
|         // cleanup delete, and we cap at half a block to give room |         // cleanup delete, and we cap at half a block to give room | ||||||
|         // for metadata updates |         // for metadata updates | ||||||
|         commit.begin = 0; |         commit.begin = 0; | ||||||
|         commit.end = lfs_min( |         commit.end = lfs->cfg->block_size - 38; | ||||||
|              lfs_alignup(lfs->cfg->block_size/2, lfs->cfg->prog_size), |         if (!overcompacting) { | ||||||
|              lfs->cfg->block_size - 38); |             commit.end = lfs_min(commit.end, | ||||||
|  |                     lfs_alignup(lfs->cfg->block_size/2, lfs->cfg->prog_size)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if (!splitted) { |         if (!splitted) { | ||||||
|             // increment revision count |             // increment revision count | ||||||
| @@ -1369,8 +1372,9 @@ commit: | |||||||
|                         0x003ff000, LFS_MKTAG(0, id, 0), |                         0x003ff000, LFS_MKTAG(0, id, 0), | ||||||
|                         -LFS_MKTAG(0, begin, 0), |                         -LFS_MKTAG(0, begin, 0), | ||||||
|                         source, attrs); |                         source, attrs); | ||||||
|                 if (err && !(splitted && err == LFS_ERR_NOSPC)) { |                 if (err && !(splitted && !overcompacting && | ||||||
|                     if (err == LFS_ERR_NOSPC) { |                         err == LFS_ERR_NOSPC)) { | ||||||
|  |                     if (!overcompacting && err == LFS_ERR_NOSPC) { | ||||||
|                         goto split; |                         goto split; | ||||||
|                     } else if (err == LFS_ERR_CORRUPT) { |                     } else if (err == LFS_ERR_CORRUPT) { | ||||||
|                         goto relocate; |                         goto relocate; | ||||||
| @@ -1457,6 +1461,11 @@ split: | |||||||
|         lfs_mdir_t tail; |         lfs_mdir_t tail; | ||||||
|         err = lfs_dir_alloc(lfs, &tail); |         err = lfs_dir_alloc(lfs, &tail); | ||||||
|         if (err) { |         if (err) { | ||||||
|  |             if (err == LFS_ERR_NOSPC) { | ||||||
|  |                 // No space to expand? Try overcompacting | ||||||
|  |                 overcompacting = true; | ||||||
|  |                 goto commit; | ||||||
|  |             } | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user