1 #include "logfsos.h"
2 #include "logfs.h"
3 #include "local.h"
4
5 char *
logfsformat(LogfsLowLevel * ll,long base,long limit,long bootsize,int trace)6 logfsformat(LogfsLowLevel *ll, long base, long limit, long bootsize, int trace)
7 {
8 long bootblocksdone, logblocksdone;
9 long u;
10 long baseblock, limitblock, bootblocks, sizeinblocks;
11 int magicfound;
12 void *llsave;
13
14 if(trace > 1)
15 print("logfsformat: base %ld limit %ld bootsize %lud\n", base, limit, bootsize);
16
17 if((*ll->getopenstatus)(ll))
18 return Eperm;
19
20 if(!(*ll->calcformat)(ll, base, limit, bootsize, &baseblock, &limitblock, &bootblocks))
21 return Ebadarg;
22
23 if(trace > 0)
24 print("logfsformat: baseblock %ld limitblock %ld bootblocks %ld\n", baseblock, limitblock, bootblocks);
25
26 bootblocksdone = 0;
27 logblocksdone = 0;
28 /*
29 * we need to create some fs blocks, and some boot blocks
30 * the number of boot blocks is fixed; the number of fs blocks
31 * occupies the remainder
32 * the layout is randomised to:
33 * 1) test the software
34 * 2) spread wear around if a lot of format commands are issued by
35 * the bootloader
36 */
37
38 sizeinblocks = limitblock - baseblock;
39
40 for(u = 0; u < sizeinblocks; u++) {
41 int r;
42 uchar tag;
43 long path;
44 LogfsLowLevelReadResult e;
45 char *errmsg;
46 int markedbad;
47
48 if(trace > 1)
49 print("block %lud:", u);
50 llsave = nil;
51 errmsg = (*ll->getblockstatus)(ll, u + baseblock, &magicfound, &llsave, &e);
52 if(errmsg)
53 return errmsg;
54 if(e == LogfsLowLevelReadResultBad) {
55 if(trace > 1)
56 print(" marked bad\n");
57 continue;
58 }
59 errmsg = (*ll->eraseblock)(ll, u + baseblock, nil, &markedbad);
60 if(errmsg)
61 return errmsg;
62 if(markedbad) {
63 if(trace > 1)
64 print(" marked bad\n");
65 continue;
66 }
67 if(e != LogfsLowLevelReadResultHardError && magicfound) {
68 if(trace > 1)
69 print(" previously formatted");
70 }
71 r = nrand(sizeinblocks - u);
72 if(bootblocksdone < bootblocks && r < (bootblocks - bootblocksdone)) {
73 tag = LogfsTboot;
74 path = mkdatapath(bootblocksdone, 0);
75 }
76 else {
77 tag = LogfsTnone;
78 path = ~0;
79 }
80 if(trace > 1)
81 print(" tag %s path %ld", logfstagname(tag), path);
82 errmsg = (*ll->formatblock)(ll, u + baseblock, tag, path, baseblock, sizeinblocks, 1, &bootblocks, llsave, &markedbad);
83 logfsfreemem(llsave);
84 if(errmsg)
85 return errmsg;
86 if(markedbad) {
87 if(trace > 1)
88 print(" marked bad\n");
89 continue;
90 }
91 switch(tag) {
92 case LogfsTboot:
93 bootblocksdone++;
94 break;
95 case LogfsTnone:
96 logblocksdone++;
97 break;
98 }
99 if(trace > 1)
100 print("\n");
101 }
102 if(bootblocksdone < bootblocks)
103 return "not enough capacity left for boot";
104 if(trace > 0)
105 print("log blocks %lud\n", logblocksdone);
106 return nil;
107 }
108