@@ -540,15 +540,16 @@ static int lfs_commit_attrs(lfs_t *lfs, struct lfs_commit *commit,
540
540
uint16_t id , const struct lfs_attr * attrs );
541
541
542
542
static 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 ,
544
544
const lfs_mdir_t * dir , const lfs_mattr_t * attrs );
545
545
546
546
static int lfs_commit_attr (lfs_t * lfs , struct lfs_commit * commit ,
547
547
uint32_t tag , const void * buffer ) {
548
548
if (lfs_tag_subtype (tag ) == LFS_FROM_MOVE ) {
549
549
// special case for moves
550
550
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 ),
552
553
buffer , NULL );
553
554
} else if (lfs_tag_subtype (tag ) == LFS_FROM_ATTRS ) {
554
555
// special case for custom attributes
@@ -617,7 +618,7 @@ static int lfs_commit_attrs(lfs_t *lfs, struct lfs_commit *commit,
617
618
}
618
619
619
620
static 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 ,
621
622
const lfs_mdir_t * dir , const lfs_mattr_t * attrs ) {
622
623
// iterate through list and commits, only committing unique entries
623
624
lfs_off_t off = dir -> off ;
@@ -650,17 +651,15 @@ static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit,
650
651
}
651
652
652
653
if (lfs_tag_type (tag ) == LFS_TYPE_DELETE &&
653
- lfs_tag_id (tag ) <= fromid ) {
654
+ lfs_tag_id (tag ) <= lfs_tag_id ( fromtag ) ) {
654
655
// 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 )) {
659
658
// check if type has already been committed
660
659
int32_t res = lfs_commit_get (lfs , commit -> block ,
661
660
commit -> off , commit -> ptag ,
662
661
lfs_tag_isuser (tag ) ? 0x7ffff000 : 0x7c3ff000 ,
663
- (tag & 0x7fc00000 ) | LFS_MKTAG ( 0 , toid , 0 ) ,
662
+ (tag & ~ tomask ) | totag ,
664
663
0 , NULL , true);
665
664
if (res < 0 && res != LFS_ERR_NOENT ) {
666
665
return res ;
@@ -669,7 +668,7 @@ static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit,
669
668
if (res == LFS_ERR_NOENT ) {
670
669
// update id and commit, as we are currently unique
671
670
int err = lfs_commit_attr (lfs , commit ,
672
- (tag & 0xffc00fff ) | LFS_MKTAG ( 0 , toid , 0 ) ,
671
+ (tag & ~ tomask ) | totag ,
673
672
buffer );
674
673
if (err ) {
675
674
return err ;
@@ -1068,8 +1067,7 @@ static int lfs_dir_compact(lfs_t *lfs,
1068
1067
// do we have enough space to expand?
1069
1068
if (res < lfs -> cfg -> block_count /2 ) {
1070
1069
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;
1073
1071
goto split ;
1074
1072
}
1075
1073
} else {
@@ -1118,7 +1116,9 @@ static int lfs_dir_compact(lfs_t *lfs,
1118
1116
// commit with a move
1119
1117
for (uint16_t id = begin ; id < end ; id ++ ) {
1120
1118
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 );
1122
1122
if (err ) {
1123
1123
if (err == LFS_ERR_NOSPC ) {
1124
1124
goto split ;
@@ -1134,7 +1134,23 @@ static int lfs_dir_compact(lfs_t *lfs,
1134
1134
// reopen reserved space at the end
1135
1135
commit .end = lfs -> cfg -> block_size - 8 ;
1136
1136
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
+
1137
1151
if (!relocated ) {
1152
+ // commit any globals, unless we're relocating, in which case our
1153
+ // parent will steal our globals
1138
1154
err = lfs_commit_globals (lfs , & commit , & dir -> locals );
1139
1155
if (err ) {
1140
1156
if (err == LFS_ERR_CORRUPT ) {
@@ -1178,8 +1194,7 @@ static int lfs_dir_compact(lfs_t *lfs,
1178
1194
// commit no longer fits, need to split dir,
1179
1195
// drop caches and create tail
1180
1196
lfs_cache_drop (lfs , & lfs -> pcache );
1181
-
1182
- if (ack == -1 ) {
1197
+ if (!exhausted && ack < 0 ) {
1183
1198
// If we can't fit in this block, we won't fit in next block
1184
1199
return LFS_ERR_NOSPC ;
1185
1200
}
@@ -1190,11 +1205,16 @@ static int lfs_dir_compact(lfs_t *lfs,
1190
1205
return err ;
1191
1206
}
1192
1207
1208
+ if (exhausted ) {
1209
+ lfs -> root [0 ] = tail .pair [0 ];
1210
+ lfs -> root [1 ] = tail .pair [1 ];
1211
+ }
1212
+
1193
1213
tail .split = dir -> split ;
1194
1214
tail .tail [0 ] = dir -> tail [0 ];
1195
1215
tail .tail [1 ] = dir -> tail [1 ];
1196
1216
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 );
1198
1218
if (err ) {
1199
1219
return err ;
1200
1220
}
@@ -2770,9 +2790,19 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
2770
2790
return res ;
2771
2791
}
2772
2792
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
+
2773
2803
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 );
2776
2806
if (res < 0 && res != LFS_ERR_NOENT ) {
2777
2807
return res ;
2778
2808
}
@@ -2792,8 +2822,18 @@ int lfs_setattr(lfs_t *lfs, const char *path,
2792
2822
return res ;
2793
2823
}
2794
2824
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
+
2795
2835
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 ,
2797
2837
NULL ));
2798
2838
}
2799
2839
@@ -2941,9 +2981,8 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
2941
2981
2942
2982
lfs_superblock_tole32 (& superblock );
2943
2983
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 ));
2947
2986
if (err ) {
2948
2987
goto cleanup ;
2949
2988
}
@@ -2965,15 +3004,18 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
2965
3004
return err ;
2966
3005
}
2967
3006
2968
- // load superblock
3007
+ // find root/ superblock
2969
3008
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 ;
2973
3016
}
2974
3017
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 ,
2977
3019
LFS_MKTAG (LFS_TYPE_SUPERBLOCK , 0 , sizeof (superblock )),
2978
3020
& superblock );
2979
3021
if (res < 0 ) {
@@ -2982,14 +3024,6 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
2982
3024
}
2983
3025
lfs_superblock_fromle32 (& superblock );
2984
3026
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
-
2993
3027
lfs -> root [0 ] = root .pair [0 ];
2994
3028
lfs -> root [1 ] = root .pair [1 ];
2995
3029
@@ -3370,41 +3404,6 @@ static int lfs_fs_forceconsistency(lfs_t *lfs) {
3370
3404
return 0 ;
3371
3405
}
3372
3406
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
-
3408
3407
static int lfs_fs_size_count (void * p , lfs_block_t block ) {
3409
3408
(void )block ;
3410
3409
lfs_size_t * size = p ;
0 commit comments