xref: /inferno-os/liblogfs/format.c (revision 28942ead413418b56c5be78e8c4c400881fba72e)
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