1*28942eadSforsyth #include "logfsos.h"
237da2899SCharles.Forsyth #include "logfs.h"
337da2899SCharles.Forsyth #include "local.h"
437da2899SCharles.Forsyth
537da2899SCharles.Forsyth char *
logfsformat(LogfsLowLevel * ll,long base,long limit,long bootsize,int trace)637da2899SCharles.Forsyth logfsformat(LogfsLowLevel *ll, long base, long limit, long bootsize, int trace)
737da2899SCharles.Forsyth {
837da2899SCharles.Forsyth long bootblocksdone, logblocksdone;
937da2899SCharles.Forsyth long u;
1037da2899SCharles.Forsyth long baseblock, limitblock, bootblocks, sizeinblocks;
1137da2899SCharles.Forsyth int magicfound;
1237da2899SCharles.Forsyth void *llsave;
1337da2899SCharles.Forsyth
1437da2899SCharles.Forsyth if(trace > 1)
1537da2899SCharles.Forsyth print("logfsformat: base %ld limit %ld bootsize %lud\n", base, limit, bootsize);
1637da2899SCharles.Forsyth
1737da2899SCharles.Forsyth if((*ll->getopenstatus)(ll))
1837da2899SCharles.Forsyth return Eperm;
1937da2899SCharles.Forsyth
2037da2899SCharles.Forsyth if(!(*ll->calcformat)(ll, base, limit, bootsize, &baseblock, &limitblock, &bootblocks))
2137da2899SCharles.Forsyth return Ebadarg;
2237da2899SCharles.Forsyth
2337da2899SCharles.Forsyth if(trace > 0)
2437da2899SCharles.Forsyth print("logfsformat: baseblock %ld limitblock %ld bootblocks %ld\n", baseblock, limitblock, bootblocks);
2537da2899SCharles.Forsyth
2637da2899SCharles.Forsyth bootblocksdone = 0;
2737da2899SCharles.Forsyth logblocksdone = 0;
2837da2899SCharles.Forsyth /*
2937da2899SCharles.Forsyth * we need to create some fs blocks, and some boot blocks
3037da2899SCharles.Forsyth * the number of boot blocks is fixed; the number of fs blocks
3137da2899SCharles.Forsyth * occupies the remainder
3237da2899SCharles.Forsyth * the layout is randomised to:
3337da2899SCharles.Forsyth * 1) test the software
3437da2899SCharles.Forsyth * 2) spread wear around if a lot of format commands are issued by
3537da2899SCharles.Forsyth * the bootloader
3637da2899SCharles.Forsyth */
3737da2899SCharles.Forsyth
3837da2899SCharles.Forsyth sizeinblocks = limitblock - baseblock;
3937da2899SCharles.Forsyth
4037da2899SCharles.Forsyth for(u = 0; u < sizeinblocks; u++) {
4137da2899SCharles.Forsyth int r;
4237da2899SCharles.Forsyth uchar tag;
4337da2899SCharles.Forsyth long path;
4437da2899SCharles.Forsyth LogfsLowLevelReadResult e;
4537da2899SCharles.Forsyth char *errmsg;
4637da2899SCharles.Forsyth int markedbad;
4737da2899SCharles.Forsyth
4837da2899SCharles.Forsyth if(trace > 1)
4937da2899SCharles.Forsyth print("block %lud:", u);
5037da2899SCharles.Forsyth llsave = nil;
5137da2899SCharles.Forsyth errmsg = (*ll->getblockstatus)(ll, u + baseblock, &magicfound, &llsave, &e);
5237da2899SCharles.Forsyth if(errmsg)
5337da2899SCharles.Forsyth return errmsg;
5437da2899SCharles.Forsyth if(e == LogfsLowLevelReadResultBad) {
5537da2899SCharles.Forsyth if(trace > 1)
5637da2899SCharles.Forsyth print(" marked bad\n");
5737da2899SCharles.Forsyth continue;
5837da2899SCharles.Forsyth }
5937da2899SCharles.Forsyth errmsg = (*ll->eraseblock)(ll, u + baseblock, nil, &markedbad);
6037da2899SCharles.Forsyth if(errmsg)
6137da2899SCharles.Forsyth return errmsg;
6237da2899SCharles.Forsyth if(markedbad) {
6337da2899SCharles.Forsyth if(trace > 1)
6437da2899SCharles.Forsyth print(" marked bad\n");
6537da2899SCharles.Forsyth continue;
6637da2899SCharles.Forsyth }
6737da2899SCharles.Forsyth if(e != LogfsLowLevelReadResultHardError && magicfound) {
6837da2899SCharles.Forsyth if(trace > 1)
6937da2899SCharles.Forsyth print(" previously formatted");
7037da2899SCharles.Forsyth }
71*28942eadSforsyth r = nrand(sizeinblocks - u);
7237da2899SCharles.Forsyth if(bootblocksdone < bootblocks && r < (bootblocks - bootblocksdone)) {
7337da2899SCharles.Forsyth tag = LogfsTboot;
7437da2899SCharles.Forsyth path = mkdatapath(bootblocksdone, 0);
7537da2899SCharles.Forsyth }
7637da2899SCharles.Forsyth else {
7737da2899SCharles.Forsyth tag = LogfsTnone;
7837da2899SCharles.Forsyth path = ~0;
7937da2899SCharles.Forsyth }
8037da2899SCharles.Forsyth if(trace > 1)
8137da2899SCharles.Forsyth print(" tag %s path %ld", logfstagname(tag), path);
8237da2899SCharles.Forsyth errmsg = (*ll->formatblock)(ll, u + baseblock, tag, path, baseblock, sizeinblocks, 1, &bootblocks, llsave, &markedbad);
8337da2899SCharles.Forsyth logfsfreemem(llsave);
8437da2899SCharles.Forsyth if(errmsg)
8537da2899SCharles.Forsyth return errmsg;
8637da2899SCharles.Forsyth if(markedbad) {
8737da2899SCharles.Forsyth if(trace > 1)
8837da2899SCharles.Forsyth print(" marked bad\n");
8937da2899SCharles.Forsyth continue;
9037da2899SCharles.Forsyth }
9137da2899SCharles.Forsyth switch(tag) {
9237da2899SCharles.Forsyth case LogfsTboot:
9337da2899SCharles.Forsyth bootblocksdone++;
9437da2899SCharles.Forsyth break;
9537da2899SCharles.Forsyth case LogfsTnone:
9637da2899SCharles.Forsyth logblocksdone++;
9737da2899SCharles.Forsyth break;
9837da2899SCharles.Forsyth }
9937da2899SCharles.Forsyth if(trace > 1)
10037da2899SCharles.Forsyth print("\n");
10137da2899SCharles.Forsyth }
10237da2899SCharles.Forsyth if(bootblocksdone < bootblocks)
10337da2899SCharles.Forsyth return "not enough capacity left for boot";
10437da2899SCharles.Forsyth if(trace > 0)
10537da2899SCharles.Forsyth print("log blocks %lud\n", logblocksdone);
10637da2899SCharles.Forsyth return nil;
10737da2899SCharles.Forsyth }
108