@@ -540,15 +540,16 @@ static int lfs_commit_attrs(lfs_t *lfs, struct lfs_commit *commit,
540540 uint16_t id , const struct lfs_attr * attrs );
541541
542542static int lfs_commit_move (lfs_t * lfs , struct lfs_commit * commit ,
543- uint16_t fromid , uint16_t toid ,
543+ uint32_t frommask , uint32_t fromtag , uint32_t tomask , uint32_t totag ,
544544 const lfs_mdir_t * dir , const lfs_mattr_t * attrs );
545545
546546static int lfs_commit_attr (lfs_t * lfs , struct lfs_commit * commit ,
547547 uint32_t tag , const void * buffer ) {
548548 if (lfs_tag_subtype (tag ) == LFS_FROM_MOVE ) {
549549 // special case for moves
550550 return lfs_commit_move (lfs , commit ,
551- lfs_tag_size (tag ), lfs_tag_id (tag ),
551+ 0x003ff000 , LFS_MKTAG (0 , lfs_tag_size (tag ), 0 ),
552+ 0x003ff000 , LFS_MKTAG (0 , lfs_tag_id (tag ), 0 ),
552553 buffer , NULL );
553554 } else if (lfs_tag_subtype (tag ) == LFS_FROM_ATTRS ) {
554555 // special case for custom attributes
@@ -617,7 +618,7 @@ static int lfs_commit_attrs(lfs_t *lfs, struct lfs_commit *commit,
617618}
618619
619620static int lfs_commit_move (lfs_t * lfs , struct lfs_commit * commit ,
620- uint16_t fromid , uint16_t toid ,
621+ uint32_t frommask , uint32_t fromtag , uint32_t tomask , uint32_t totag ,
621622 const lfs_mdir_t * dir , const lfs_mattr_t * attrs ) {
622623 // iterate through list and commits, only committing unique entries
623624 lfs_off_t off = dir -> off ;
@@ -650,17 +651,15 @@ static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit,
650651 }
651652
652653 if (lfs_tag_type (tag ) == LFS_TYPE_DELETE &&
653- lfs_tag_id (tag ) <= fromid ) {
654+ lfs_tag_id (tag ) <= lfs_tag_id ( fromtag ) ) {
654655 // something was deleted, we need to move around it
655- fromid += 1 ;
656- } else if (lfs_tag_id (tag ) != fromid ) {
657- // ignore non-matching ids
658- } else {
656+ fromtag += LFS_MKTAG (0 , 1 , 0 );
657+ } else if ((tag & frommask ) == (fromtag & frommask )) {
659658 // check if type has already been committed
660659 int32_t res = lfs_commit_get (lfs , commit -> block ,
661660 commit -> off , commit -> ptag ,
662661 lfs_tag_isuser (tag ) ? 0x7ffff000 : 0x7c3ff000 ,
663- (tag & 0x7fc00000 ) | LFS_MKTAG ( 0 , toid , 0 ) ,
662+ (tag & ~ tomask ) | totag ,
664663 0 , NULL , true);
665664 if (res < 0 && res != LFS_ERR_NOENT ) {
666665 return res ;
@@ -669,7 +668,7 @@ static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit,
669668 if (res == LFS_ERR_NOENT ) {
670669 // update id and commit, as we are currently unique
671670 int err = lfs_commit_attr (lfs , commit ,
672- (tag & 0xffc00fff ) | LFS_MKTAG ( 0 , toid , 0 ) ,
671+ (tag & ~ tomask ) | totag ,
673672 buffer );
674673 if (err ) {
675674 return err ;
@@ -1068,8 +1067,7 @@ static int lfs_dir_compact(lfs_t *lfs,
10681067 // do we have enough space to expand?
10691068 if (res < lfs -> cfg -> block_count /2 ) {
10701069 LFS_DEBUG ("Expanding superblock at rev %" PRIu32 , dir -> rev );
1071- ack = 0 ;
1072- exhausted = (lfs_pair_cmp (dir -> pair , lfs -> root ) != 0 );
1070+ exhausted = true;
10731071 goto split ;
10741072 }
10751073 } else {
@@ -1118,7 +1116,9 @@ static int lfs_dir_compact(lfs_t *lfs,
11181116 // commit with a move
11191117 for (uint16_t id = begin ; id < end ; id ++ ) {
11201118 err = lfs_commit_move (lfs , & commit ,
1121- id , id - begin , source , attrs );
1119+ 0x003ff000 , LFS_MKTAG (0 , id , 0 ),
1120+ 0x003ff000 , LFS_MKTAG (0 , id - begin , 0 ),
1121+ source , attrs );
11221122 if (err ) {
11231123 if (err == LFS_ERR_NOSPC ) {
11241124 goto split ;
@@ -1134,7 +1134,23 @@ static int lfs_dir_compact(lfs_t *lfs,
11341134 // reopen reserved space at the end
11351135 commit .end = lfs -> cfg -> block_size - 8 ;
11361136
1137+ if (lfs_pair_cmp (dir -> pair , (const lfs_block_t [2 ]){0 , 1 }) == 0 ) {
1138+ // move over (duplicate) superblock if we are root
1139+ err = lfs_commit_move (lfs , & commit ,
1140+ 0x7c000000 , LFS_MKTAG (LFS_TYPE_SUPERBLOCK , 0 , 0 ),
1141+ 0x7ffff000 , LFS_MKTAG (LFS_TYPE_SUPERBLOCK , 0 , 0 ),
1142+ source , attrs );
1143+ if (err ) {
1144+ if (err == LFS_ERR_CORRUPT ) {
1145+ goto relocate ;
1146+ }
1147+ return err ;
1148+ }
1149+ }
1150+
11371151 if (!relocated ) {
1152+ // commit any globals, unless we're relocating, in which case our
1153+ // parent will steal our globals
11381154 err = lfs_commit_globals (lfs , & commit , & dir -> locals );
11391155 if (err ) {
11401156 if (err == LFS_ERR_CORRUPT ) {
@@ -1178,8 +1194,7 @@ static int lfs_dir_compact(lfs_t *lfs,
11781194 // commit no longer fits, need to split dir,
11791195 // drop caches and create tail
11801196 lfs_cache_drop (lfs , & lfs -> pcache );
1181-
1182- if (ack == -1 ) {
1197+ if (!exhausted && ack < 0 ) {
11831198 // If we can't fit in this block, we won't fit in next block
11841199 return LFS_ERR_NOSPC ;
11851200 }
@@ -1190,11 +1205,16 @@ static int lfs_dir_compact(lfs_t *lfs,
11901205 return err ;
11911206 }
11921207
1208+ if (exhausted ) {
1209+ lfs -> root [0 ] = tail .pair [0 ];
1210+ lfs -> root [1 ] = tail .pair [1 ];
1211+ }
1212+
11931213 tail .split = dir -> split ;
11941214 tail .tail [0 ] = dir -> tail [0 ];
11951215 tail .tail [1 ] = dir -> tail [1 ];
11961216
1197- err = lfs_dir_compact (lfs , & tail , attrs , source , ack + 1 - exhausted , end );
1217+ err = lfs_dir_compact (lfs , & tail , attrs , source , ack + 1 , end );
11981218 if (err ) {
11991219 return err ;
12001220 }
@@ -2770,9 +2790,19 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
27702790 return res ;
27712791 }
27722792
2793+ uint16_t id = lfs_tag_id (res );
2794+ if (id == 0x3ff ) {
2795+ // special case for root
2796+ id = 0 ;
2797+ int err = lfs_dir_fetch (lfs , & cwd , lfs -> root );
2798+ if (err ) {
2799+ return err ;
2800+ }
2801+ }
2802+
27732803 res = lfs_dir_get (lfs , & cwd , 0x7ffff000 ,
2774- LFS_MKTAG (0x100 | type , lfs_tag_id ( res ),
2775- lfs_min ( size , lfs -> attr_max )), buffer );
2804+ LFS_MKTAG (0x100 | type , id , lfs_min ( size , lfs -> attr_max ) ),
2805+ buffer );
27762806 if (res < 0 && res != LFS_ERR_NOENT ) {
27772807 return res ;
27782808 }
@@ -2792,8 +2822,18 @@ int lfs_setattr(lfs_t *lfs, const char *path,
27922822 return res ;
27932823 }
27942824
2825+ uint16_t id = lfs_tag_id (res );
2826+ if (id == 0x3ff ) {
2827+ // special case for root
2828+ id = 0 ;
2829+ int err = lfs_dir_fetch (lfs , & cwd , lfs -> root );
2830+ if (err ) {
2831+ return err ;
2832+ }
2833+ }
2834+
27952835 return lfs_dir_commit (lfs , & cwd ,
2796- LFS_MKATTR (0x100 | type , lfs_tag_id ( res ) , buffer , size ,
2836+ LFS_MKATTR (0x100 | type , id , buffer , size ,
27972837 NULL ));
27982838}
27992839
@@ -2941,9 +2981,8 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
29412981
29422982 lfs_superblock_tole32 (& superblock );
29432983 err = lfs_dir_commit (lfs , & root ,
2944- LFS_MKATTR (LFS_TYPE_SUPERBLOCK , 0 , & superblock , sizeof (superblock ),
2945- LFS_MKATTR (LFS_TYPE_ROOT , 1 , NULL , 0 ,
2946- NULL )));
2984+ LFS_MKATTR (LFS_TYPE_ROOT , 0 , & superblock , sizeof (superblock ),
2985+ NULL ));
29472986 if (err ) {
29482987 goto cleanup ;
29492988 }
@@ -2965,15 +3004,18 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
29653004 return err ;
29663005 }
29673006
2968- // load superblock
3007+ // find root/ superblock
29693008 lfs_mdir_t root ;
2970- err = lfs_dir_fetch (lfs , & root , (const lfs_block_t [2 ]){0 , 1 });
2971- if (err ) {
2972- return err ;
3009+ lfs_superblock_t superblock ;
3010+ int32_t tag = lfs_dir_find (lfs ,
3011+ & root , (const lfs_block_t [2 ]){0 , 1 }, false, 0x7fc00000 ,
3012+ LFS_MKTAG (LFS_TYPE_ROOT , 0 , 8 ), "littlefs" );
3013+ if (tag < 0 ) {
3014+ err = tag ;
3015+ goto cleanup ;
29733016 }
29743017
2975- lfs_superblock_t superblock ;
2976- int32_t res = lfs_dir_get (lfs , & root , 0x7fc00000 ,
3018+ int32_t res = lfs_dir_get (lfs , & root , 0x7c000000 ,
29773019 LFS_MKTAG (LFS_TYPE_SUPERBLOCK , 0 , sizeof (superblock )),
29783020 & superblock );
29793021 if (res < 0 ) {
@@ -2982,14 +3024,6 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
29823024 }
29833025 lfs_superblock_fromle32 (& superblock );
29843026
2985- // find root
2986- int32_t tag = lfs_dir_find (lfs ,
2987- & root , (const lfs_block_t [2 ]){0 , 1 }, false, 0x7fc00000 ,
2988- LFS_MKTAG (LFS_TYPE_ROOT , 0 , 0 ), NULL );
2989- if (tag < 0 ) {
2990- return tag ;
2991- }
2992-
29933027 lfs -> root [0 ] = root .pair [0 ];
29943028 lfs -> root [1 ] = root .pair [1 ];
29953029
@@ -3370,41 +3404,6 @@ static int lfs_fs_forceconsistency(lfs_t *lfs) {
33703404 return 0 ;
33713405}
33723406
3373- lfs_ssize_t lfs_fs_getattr (lfs_t * lfs ,
3374- uint8_t type , void * buffer , lfs_size_t size ) {
3375- lfs_mdir_t superdir ;
3376- int err = lfs_dir_fetch (lfs , & superdir , (const lfs_block_t [2 ]){0 , 1 });
3377- if (err ) {
3378- return err ;
3379- }
3380-
3381- int32_t res = lfs_dir_get (lfs , & superdir , 0x7ffff000 ,
3382- LFS_MKTAG (0x100 | type , 0 ,
3383- lfs_min (size , lfs -> attr_max )), buffer );
3384- if (res < 0 ) {
3385- return res ;
3386- }
3387-
3388- return (res == LFS_ERR_NOENT ) ? 0 : lfs_tag_size (res );
3389- }
3390-
3391- int lfs_fs_setattr (lfs_t * lfs ,
3392- uint8_t type , const void * buffer , lfs_size_t size ) {
3393- if (size > lfs -> attr_max ) {
3394- return LFS_ERR_NOSPC ;
3395- }
3396-
3397- lfs_mdir_t superdir ;
3398- int err = lfs_dir_fetch (lfs , & superdir , (const lfs_block_t [2 ]){0 , 1 });
3399- if (err ) {
3400- return err ;
3401- }
3402-
3403- return lfs_dir_commit (lfs , & superdir ,
3404- LFS_MKATTR (0x100 | type , 0 , buffer , size ,
3405- NULL ));
3406- }
3407-
34083407static int lfs_fs_size_count (void * p , lfs_block_t block ) {
34093408 (void )block ;
34103409 lfs_size_t * size = p ;
0 commit comments