mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	Fixed issue with big-endian CTZ lists intertwined in commit logic
Found while testing big-endian support. Basically, if littlefs is really really unlucky, the block allocator could kick in while committing a file's CTZ reference. If this happens, the block allocator will need to traverse all CTZ skip-lists in memory, including the skip-list we're committing. This means we can't convert the CTZ's endianness in place, and need to make a copy on big-endian systems. We rely on dead-code elimination from the compiler to make the conditional behaviour for big-endian vs little-endian system a noop determined by the lfs_tole32 intrinsic.
This commit is contained in:
		
							
								
								
									
										12
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -2199,25 +2199,27 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | |||||||
|             uint16_t type; |             uint16_t type; | ||||||
|             const void *buffer; |             const void *buffer; | ||||||
|             lfs_size_t size; |             lfs_size_t size; | ||||||
|  |             struct lfs_ctz ctz; | ||||||
|             if (file->flags & LFS_F_INLINE) { |             if (file->flags & LFS_F_INLINE) { | ||||||
|                 // inline the whole file |                 // inline the whole file | ||||||
|                 type = LFS_TYPE_INLINESTRUCT; |                 type = LFS_TYPE_INLINESTRUCT; | ||||||
|                 buffer = file->cache.buffer; |                 buffer = file->cache.buffer; | ||||||
|                 size = file->ctz.size; |                 size = file->ctz.size; | ||||||
|             } else { |             } else if (lfs_tole32(0x11223344) == 0x11223344) { | ||||||
|                 // update the ctz reference |                 // update the ctz reference | ||||||
|                 type = LFS_TYPE_CTZSTRUCT; |                 type = LFS_TYPE_CTZSTRUCT; | ||||||
|                 buffer = &file->ctz; |                 // copy ctz so alloc will work during a relocate | ||||||
|                 size = sizeof(file->ctz); |                 ctz = file->ctz; | ||||||
|  |                 lfs_ctz_tole32(&ctz); | ||||||
|  |                 buffer = &ctz; | ||||||
|  |                 size = sizeof(ctz); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             // commit file data and attributes |             // commit file data and attributes | ||||||
|             lfs_ctz_tole32(&file->ctz); |  | ||||||
|             err = lfs_dir_commit(lfs, &file->m, |             err = lfs_dir_commit(lfs, &file->m, | ||||||
|                     LFS_MKATTR(type, file->id, buffer, size, |                     LFS_MKATTR(type, file->id, buffer, size, | ||||||
|                     LFS_MKATTR(LFS_FROM_ATTRS, file->id, file->cfg->attrs, 0, |                     LFS_MKATTR(LFS_FROM_ATTRS, file->id, file->cfg->attrs, 0, | ||||||
|                     NULL))); |                     NULL))); | ||||||
|             lfs_ctz_fromle32(&file->ctz); |  | ||||||
|             if (err) { |             if (err) { | ||||||
|                 if (err == LFS_ERR_NOSPC && (file->flags & LFS_F_INLINE)) { |                 if (err == LFS_ERR_NOSPC && (file->flags & LFS_F_INLINE)) { | ||||||
|                     goto relocate; |                     goto relocate; | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								lfs_util.h
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								lfs_util.h
									
									
									
									
									
								
							| @@ -11,8 +11,8 @@ | |||||||
| // LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h). | // LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h). | ||||||
| // | // | ||||||
| // If LFS_CONFIG is used, none of the default utils will be emitted and must be | // If LFS_CONFIG is used, none of the default utils will be emitted and must be | ||||||
| // provided by the config file. To start I would suggest copying lfs_util.h and | // provided by the config file. To start, I would suggest copying lfs_util.h | ||||||
| // modifying as needed. | // and modifying as needed. | ||||||
| #ifdef LFS_CONFIG | #ifdef LFS_CONFIG | ||||||
| #define LFS_STRINGIZE(x) LFS_STRINGIZE2(x) | #define LFS_STRINGIZE(x) LFS_STRINGIZE2(x) | ||||||
| #define LFS_STRINGIZE2(x) #x | #define LFS_STRINGIZE2(x) #x | ||||||
| @@ -88,6 +88,15 @@ static inline uint32_t lfs_min(uint32_t a, uint32_t b) { | |||||||
|     return (a < b) ? a : b; |     return (a < b) ? a : b; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Align to nearest multiple of a size | ||||||
|  | static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) { | ||||||
|  |     return a - (a % alignment); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) { | ||||||
|  |     return lfs_aligndown(a + alignment-1, alignment); | ||||||
|  | } | ||||||
|  |  | ||||||
| // Find the next smallest power of 2 less than or equal to a | // Find the next smallest power of 2 less than or equal to a | ||||||
| static inline uint32_t lfs_npw2(uint32_t a) { | static inline uint32_t lfs_npw2(uint32_t a) { | ||||||
| #if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) | #if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) | ||||||
| @@ -177,15 +186,6 @@ static inline uint16_t lfs_tole16(uint16_t a) { | |||||||
|     return lfs_fromle16(a); |     return lfs_fromle16(a); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Align to nearest multiple of a size |  | ||||||
| static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) { |  | ||||||
|     return a - (a % alignment); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) { |  | ||||||
|     return lfs_aligndown(a + alignment-1, alignment); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Calculate CRC-32 with polynomial = 0x04c11db7 | // Calculate CRC-32 with polynomial = 0x04c11db7 | ||||||
| uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size); | uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user