@@ -75,10 +75,6 @@ static int lfs_bd_crc(lfs_t *lfs, lfs_block_t block,
75
75
76
76
/// Block allocator ///
77
77
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
-
82
78
static int lfs_alloc_lookahead (void * p , lfs_block_t block ) {
83
79
lfs_t * lfs = p ;
84
80
@@ -1141,7 +1137,7 @@ int lfs_unmount(lfs_t *lfs) {
1141
1137
return 0 ;
1142
1138
}
1143
1139
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 ) {
1145
1141
// iterate over metadata pairs
1146
1142
lfs_dir_t dir ;
1147
1143
lfs_file_t file ;
@@ -1199,83 +1195,94 @@ static int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) {
1199
1195
}
1200
1196
}
1201
1197
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
+ };
1206
1204
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 );
1210
1208
if (err ) {
1211
1209
return err ;
1212
1210
}
1213
1211
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 ) {
1222
1216
return err ;
1223
1217
}
1218
+ }
1224
1219
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
+ }
1232
1225
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
+ }
1239
1229
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;
1266
1233
}
1267
1234
}
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
+ }
1268
1256
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
+ }
1274
1262
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 ;
1277
1280
}
1281
+
1282
+ memcpy (& pdir , & cdir , sizeof (pdir ));
1278
1283
}
1284
+
1285
+ return 0 ;
1279
1286
}
1280
1287
1281
1288
int lfs_remove (lfs_t * lfs , const char * path ) {
0 commit comments