mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	Fixed issue where inlined files were not cleaned up
A relatively late change in v2 was to switch from implicit replacement of inline files to explicit replacement, which requires explicitly deleting the inline struct tag before creating a CTZ skip-list tag. Unfortunately I never added the actual logic to delete the tag. This went unnoticed as the later CTZ skip-list tag always overrides the search for the struct tag during a directory fetch. To fix we need to add an explicit delete. Also there was some clean up necessary for actually removing delete tags during compaction as well as some refactoring around outlining. Found by Johnxjj
This commit is contained in:
		
							
								
								
									
										38
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -415,6 +415,7 @@ static int lfs_dir_compact(lfs_t *lfs, | |||||||
|         lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount, |         lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount, | ||||||
|         lfs_mdir_t *source, uint16_t begin, uint16_t end); |         lfs_mdir_t *source, uint16_t begin, uint16_t end); | ||||||
| static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file); | static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file); | ||||||
|  | static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file); | ||||||
| static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file); | static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file); | ||||||
| static void lfs_fs_preporphans(lfs_t *lfs, int8_t orphans); | static void lfs_fs_preporphans(lfs_t *lfs, int8_t orphans); | ||||||
| static void lfs_fs_prepmove(lfs_t *lfs, | static void lfs_fs_prepmove(lfs_t *lfs, | ||||||
| @@ -633,8 +634,9 @@ static int lfs_dir_traverse_filter(void *p, | |||||||
|     // check for redundancy |     // check for redundancy | ||||||
|     uint32_t mask = LFS_MKTAG(0x7ff, 0x3ff, 0); |     uint32_t mask = LFS_MKTAG(0x7ff, 0x3ff, 0); | ||||||
|     if ((mask & tag) == (mask & *filtertag) || |     if ((mask & tag) == (mask & *filtertag) || | ||||||
|         (mask & tag) == (LFS_MKTAG(LFS_TYPE_DELETE, 0, 0) | |             lfs_tag_isdelete(*filtertag) || | ||||||
|             (LFS_MKTAG(0, 0x3ff, 0) & *filtertag))) { |             (mask & tag) == (LFS_MKTAG(LFS_TYPE_DELETE, 0, 0) | | ||||||
|  |                 (LFS_MKTAG(0, 0x3ff, 0) & *filtertag))) { | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1643,11 +1645,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir, | |||||||
|         if (dir != &f->m && lfs_pair_cmp(f->m.pair, dir->pair) == 0 && |         if (dir != &f->m && lfs_pair_cmp(f->m.pair, dir->pair) == 0 && | ||||||
|                 f->type == LFS_TYPE_REG && (f->flags & LFS_F_INLINE) && |                 f->type == LFS_TYPE_REG && (f->flags & LFS_F_INLINE) && | ||||||
|                 f->ctz.size > lfs->cfg->cache_size) { |                 f->ctz.size > lfs->cfg->cache_size) { | ||||||
|             f->flags &= ~LFS_F_READING; |             int err = lfs_file_outline(lfs, f); | ||||||
|             f->off = 0; |  | ||||||
|  |  | ||||||
|             lfs_alloc_ack(lfs); |  | ||||||
|             int err = lfs_file_relocate(lfs, f); |  | ||||||
|             if (err) { |             if (err) { | ||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
| @@ -2473,7 +2471,6 @@ static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) { | |||||||
|         lfs_cache_zero(lfs, &lfs->pcache); |         lfs_cache_zero(lfs, &lfs->pcache); | ||||||
|  |  | ||||||
|         file->block = nblock; |         file->block = nblock; | ||||||
|         file->flags &= ~LFS_F_INLINE; |  | ||||||
|         file->flags |= LFS_F_WRITING; |         file->flags |= LFS_F_WRITING; | ||||||
|         return 0; |         return 0; | ||||||
|  |  | ||||||
| @@ -2485,6 +2482,19 @@ relocate: | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file) { | ||||||
|  |     file->off = file->pos; | ||||||
|  |     lfs_alloc_ack(lfs); | ||||||
|  |     int err = lfs_file_relocate(lfs, file); | ||||||
|  |     if (err) { | ||||||
|  |         return err; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     file->flags &= ~LFS_F_INLINE; | ||||||
|  |     file->flags |= LFS_F_OUTLINE; | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) { | static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) { | ||||||
|     if (file->flags & LFS_F_READING) { |     if (file->flags & LFS_F_READING) { | ||||||
|         if (!(file->flags & LFS_F_INLINE)) { |         if (!(file->flags & LFS_F_INLINE)) { | ||||||
| @@ -2596,6 +2606,9 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | |||||||
|  |  | ||||||
|             // commit file data and attributes |             // commit file data and attributes | ||||||
|             err = lfs_dir_commit(lfs, &file->m, LFS_MKATTRS( |             err = lfs_dir_commit(lfs, &file->m, LFS_MKATTRS( | ||||||
|  |                     {file->flags & LFS_F_OUTLINE | ||||||
|  |                         ? LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0x3ff) | ||||||
|  |                         : LFS_MKTAG(LFS_FROM_NOOP, 0, 0), NULL}, | ||||||
|                     {LFS_MKTAG(type, file->id, size), buffer}, |                     {LFS_MKTAG(type, file->id, size), buffer}, | ||||||
|                     {LFS_MKTAG(LFS_FROM_USERATTRS, file->id, |                     {LFS_MKTAG(LFS_FROM_USERATTRS, file->id, | ||||||
|                         file->cfg->attr_count), file->cfg->attrs})); |                         file->cfg->attr_count), file->cfg->attrs})); | ||||||
| @@ -2607,15 +2620,14 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | |||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             file->flags &= ~LFS_F_DIRTY; |             file->flags &= ~LFS_F_DIRTY & ~LFS_F_OUTLINE; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return 0; |         return 0; | ||||||
|  |  | ||||||
| relocate: | relocate: | ||||||
|         // inline file doesn't fit anymore |         // inline file doesn't fit anymore | ||||||
|         file->off = file->pos; |         err = lfs_file_outline(lfs, file); | ||||||
|         err = lfs_file_relocate(lfs, file); |  | ||||||
|         if (err) { |         if (err) { | ||||||
|             file->flags |= LFS_F_ERRED; |             file->flags |= LFS_F_ERRED; | ||||||
|             return err; |             return err; | ||||||
| @@ -2740,9 +2752,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, | |||||||
|             lfs_min(0x3fe, lfs_min( |             lfs_min(0x3fe, lfs_min( | ||||||
|                 lfs->cfg->cache_size, lfs->cfg->block_size/8))) { |                 lfs->cfg->cache_size, lfs->cfg->block_size/8))) { | ||||||
|         // inline file doesn't fit anymore |         // inline file doesn't fit anymore | ||||||
|         file->off = file->pos; |         int err = lfs_file_outline(lfs, file); | ||||||
|         lfs_alloc_ack(lfs); |  | ||||||
|         int err = lfs_file_relocate(lfs, file); |  | ||||||
|         if (err) { |         if (err) { | ||||||
|             file->flags |= LFS_F_ERRED; |             file->flags |= LFS_F_ERRED; | ||||||
|             return err; |             return err; | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								lfs.h
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								lfs.h
									
									
									
									
									
								
							| @@ -122,13 +122,13 @@ enum lfs_type { | |||||||
| // File open flags | // File open flags | ||||||
| enum lfs_open_flags { | enum lfs_open_flags { | ||||||
|     // open flags |     // open flags | ||||||
|     LFS_O_RDONLY = 1,         // Open a file as read only |     LFS_O_RDONLY  = 1,        // Open a file as read only | ||||||
|     LFS_O_WRONLY = 2,         // Open a file as write only |     LFS_O_WRONLY  = 2,        // Open a file as write only | ||||||
|     LFS_O_RDWR   = 3,         // Open a file as read and write |     LFS_O_RDWR    = 3,        // Open a file as read and write | ||||||
|     LFS_O_CREAT  = 0x0100,    // Create a file if it does not exist |     LFS_O_CREAT   = 0x0100,   // Create a file if it does not exist | ||||||
|     LFS_O_EXCL   = 0x0200,    // Fail if a file already exists |     LFS_O_EXCL    = 0x0200,   // Fail if a file already exists | ||||||
|     LFS_O_TRUNC  = 0x0400,    // Truncate the existing file to zero size |     LFS_O_TRUNC   = 0x0400,   // Truncate the existing file to zero size | ||||||
|     LFS_O_APPEND = 0x0800,    // Move to end of file on every write |     LFS_O_APPEND  = 0x0800,   // Move to end of file on every write | ||||||
|  |  | ||||||
|     // internally used flags |     // internally used flags | ||||||
|     LFS_F_DIRTY   = 0x010000, // File does not match storage |     LFS_F_DIRTY   = 0x010000, // File does not match storage | ||||||
| @@ -136,6 +136,7 @@ enum lfs_open_flags { | |||||||
|     LFS_F_READING = 0x040000, // File has been read since last flush |     LFS_F_READING = 0x040000, // File has been read since last flush | ||||||
|     LFS_F_ERRED   = 0x080000, // An error occured during write |     LFS_F_ERRED   = 0x080000, // An error occured during write | ||||||
|     LFS_F_INLINE  = 0x100000, // Currently inlined in directory entry |     LFS_F_INLINE  = 0x100000, // Currently inlined in directory entry | ||||||
|  |     LFS_F_OUTLINE = 0x200000, // Need to delete inlined directory entry | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // File seek flags | // File seek flags | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user