@@ -75,10 +75,6 @@ static int lfs_bd_crc(lfs_t *lfs, lfs_block_t block,
7575
7676/// Block allocator ///
7777
78- // predeclared filesystem traversal
79- static int lfs_traverse (lfs_t * lfs , int (* cb )(void * , lfs_block_t ), void * data );
80- int lfs_deorphan (lfs_t * lfs );
81-
8278static int lfs_alloc_lookahead (void * p , lfs_block_t block ) {
8379 lfs_t * lfs = p ;
8480
@@ -1141,7 +1137,7 @@ int lfs_unmount(lfs_t *lfs) {
11411137 return 0 ;
11421138}
11431139
1144- static int lfs_traverse (lfs_t * lfs , int (* cb )(void * , lfs_block_t ), void * data ) {
1140+ int lfs_traverse (lfs_t * lfs , int (* cb )(void * , lfs_block_t ), void * data ) {
11451141 // iterate over metadata pairs
11461142 lfs_dir_t dir ;
11471143 lfs_file_t file ;
@@ -1199,83 +1195,94 @@ static int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) {
11991195 }
12001196}
12011197
1202- int lfs_deorphan (lfs_t * lfs ) {
1203- // iterate over all directories
1204- lfs_block_t pred [2 ] = {0 , 1 };
1205- lfs_block_t cwd [2 ] = {lfs -> root [0 ], lfs -> root [1 ]};
1198+ static int lfs_parent (lfs_t * lfs , const lfs_block_t dir [2 ]) {
1199+ // iterate over all directory directory entries
1200+ lfs_dir_t parent = {
1201+ .d .tail [0 ] = lfs -> root [0 ],
1202+ .d .tail [1 ] = lfs -> root [1 ],
1203+ };
12061204
1207- while (true ) {
1208- lfs_dir_t child ;
1209- int err = lfs_dir_fetch (lfs , & child , cwd );
1205+ while (parent . d . tail [ 0 ] ) {
1206+ lfs_entry_t entry ;
1207+ int err = lfs_dir_fetch (lfs , & parent , parent . d . tail );
12101208 if (err ) {
12111209 return err ;
12121210 }
12131211
1214- // orphans can only be empty dirs
1215- // there still might be a dir block with this size that isn't
1216- // the head of a directory, so we still have to check for '..'
1217- if (child .d .size == sizeof (child .d ) +
1218- 2 * sizeof (struct lfs_disk_entry ) + 3 ) {
1219- lfs_entry_t entry ;
1220- err = lfs_dir_find (lfs , & child , & (const char * ){".." }, & entry );
1221- if (err && err != LFS_ERROR_NO_ENTRY ) {
1212+ // skip .. and . entries
1213+ for (int i = 0 ; i < 2 ; i ++ ) {
1214+ int err = lfs_dir_next (lfs , & parent , & entry );
1215+ if (err ) {
12221216 return err ;
12231217 }
1218+ }
12241219
1225- // only the head of directories can be orphans
1226- if (err != LFS_ERROR_NO_ENTRY ) {
1227- lfs_dir_t dir ;
1228- int err = lfs_dir_fetch (lfs , & dir , entry .d .u .dir );
1229- if (err ) {
1230- return err ;
1231- }
1220+ while (true) {
1221+ int err = lfs_dir_next (lfs , & parent , & entry );
1222+ if (err && err != LFS_ERROR_NO_ENTRY ) {
1223+ return err ;
1224+ }
12321225
1233- // check if we are any of our parents children
1234- while (true) {
1235- int err = lfs_dir_next (lfs , & dir , & entry );
1236- if (err && err != LFS_ERROR_NO_ENTRY ) {
1237- return err ;
1238- }
1226+ if (err == LFS_ERROR_NO_ENTRY ) {
1227+ break ;
1228+ }
12391229
1240- if (err == LFS_ERROR_NO_ENTRY ) {
1241- // we are an orphan
1242- LFS_INFO ("Found orphan %d %d" , cwd [0 ], cwd [1 ]);
1243- int err = lfs_dir_fetch (lfs , & dir , pred );
1244- if (err ) {
1245- return err ;
1246- }
1247-
1248- dir .d .tail [0 ] = child .d .tail [0 ];
1249- dir .d .tail [1 ] = child .d .tail [1 ];
1250- dir .d .rev += 1 ;
1251-
1252- err = lfs_pair_commit (lfs , dir .pair ,
1253- 1 , (struct lfs_commit_region []) {
1254- {0 , sizeof (dir .d ), & dir .d },
1255- });
1256- if (err ) {
1257- return err ;
1258- }
1259-
1260- break ;
1261- } else if (lfs_paircmp (entry .d .u .dir , cwd ) == 0 ) {
1262- // has parent
1263- break ;
1264- }
1265- }
1230+ if ((0xf & entry .d .type ) == LFS_TYPE_DIR &&
1231+ lfs_paircmp (entry .d .u .dir , dir ) == 0 ) {
1232+ return true;
12661233 }
12671234 }
1235+ }
1236+
1237+ return false;
1238+ }
1239+
1240+ int lfs_deorphan (lfs_t * lfs ) {
1241+ // iterate over all directories
1242+ lfs_dir_t pdir ;
1243+ lfs_dir_t cdir ;
1244+
1245+ // skip root
1246+ int err = lfs_dir_fetch (lfs , & pdir , lfs -> root );
1247+ if (err ) {
1248+ return err ;
1249+ }
1250+
1251+ while (pdir .d .tail [0 ]) {
1252+ int err = lfs_dir_fetch (lfs , & cdir , pdir .d .tail );
1253+ if (err ) {
1254+ return err ;
1255+ }
12681256
1269- // to next directory
1270- pred [ 0 ] = cwd [ 0 ] ;
1271- pred [ 1 ] = cwd [ 1 ];
1272- cwd [ 0 ] = child . d . tail [ 0 ] ;
1273- cwd [ 1 ] = child . d . tail [ 1 ];
1257+ // check if we have a parent
1258+ int parent = lfs_parent ( lfs , pdir . d . tail ) ;
1259+ if ( parent < 0 ) {
1260+ return parent ;
1261+ }
12741262
1275- if (!cwd [0 ]) {
1276- return 0 ;
1263+ if (!parent ) {
1264+ // we are an orphan
1265+ LFS_INFO ("Found orphan %d %d" , pdir .d .tail [0 ], pdir .d .tail [1 ]);
1266+
1267+ pdir .d .tail [0 ] = cdir .d .tail [0 ];
1268+ pdir .d .tail [1 ] = cdir .d .tail [1 ];
1269+ pdir .d .rev += 1 ;
1270+
1271+ err = lfs_pair_commit (lfs , pdir .pair ,
1272+ 1 , (struct lfs_commit_region []) {
1273+ {0 , sizeof (pdir .d ), & pdir .d },
1274+ });
1275+ if (err ) {
1276+ return err ;
1277+ }
1278+
1279+ break ;
12771280 }
1281+
1282+ memcpy (& pdir , & cdir , sizeof (pdir ));
12781283 }
1284+
1285+ return 0 ;
12791286}
12801287
12811288int lfs_remove (lfs_t * lfs , const char * path ) {
0 commit comments