19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <auth.h>
49a747e4fSDavid du Colombier #include <fcall.h>
59a747e4fSDavid du Colombier #include <thread.h>
69a747e4fSDavid du Colombier #include <9p.h>
79a747e4fSDavid du Colombier #include "flashfs.h"
89a747e4fSDavid du Colombier
99a747e4fSDavid du Colombier enum
109a747e4fSDavid du Colombier {
119a747e4fSDavid du Colombier debug = 0,
129a747e4fSDavid du Colombier diags = 1,
139a747e4fSDavid du Colombier };
149a747e4fSDavid du Colombier
159a747e4fSDavid du Colombier typedef struct Gen Gen;
169a747e4fSDavid du Colombier typedef struct Sect Sect;
179a747e4fSDavid du Colombier
189a747e4fSDavid du Colombier struct Gen
199a747e4fSDavid du Colombier {
209a747e4fSDavid du Colombier int gnum;
219a747e4fSDavid du Colombier int count;
229a747e4fSDavid du Colombier int low;
239a747e4fSDavid du Colombier int high;
249a747e4fSDavid du Colombier Sect* head;
259a747e4fSDavid du Colombier Sect* tail;
269a747e4fSDavid du Colombier Sect* dup;
279a747e4fSDavid du Colombier Sect** vect;
289a747e4fSDavid du Colombier };
299a747e4fSDavid du Colombier
309a747e4fSDavid du Colombier struct Sect
319a747e4fSDavid du Colombier {
329a747e4fSDavid du Colombier int sect;
339a747e4fSDavid du Colombier ulong seq;
349a747e4fSDavid du Colombier int coff;
359a747e4fSDavid du Colombier int toff;
369a747e4fSDavid du Colombier int sum;
379a747e4fSDavid du Colombier ulong time;
389a747e4fSDavid du Colombier Sect* next;
399a747e4fSDavid du Colombier };
409a747e4fSDavid du Colombier
419a747e4fSDavid du Colombier static Gen gens[2];
429a747e4fSDavid du Colombier static Sect* freehead;
439a747e4fSDavid du Colombier static Sect* freetail;
449a747e4fSDavid du Colombier static int nfree;
459a747e4fSDavid du Colombier static int nbad;
469a747e4fSDavid du Colombier static ulong ltime;
479a747e4fSDavid du Colombier static int cursect;
489a747e4fSDavid du Colombier
499a747e4fSDavid du Colombier /*
509a747e4fSDavid du Colombier * If we have a delta then file times are in the future.
519a747e4fSDavid du Colombier * But they drift back to reality.
529a747e4fSDavid du Colombier */
539a747e4fSDavid du Colombier ulong
now(void)549a747e4fSDavid du Colombier now(void)
559a747e4fSDavid du Colombier {
569a747e4fSDavid du Colombier ulong cur, drift;
579a747e4fSDavid du Colombier static ulong last;
589a747e4fSDavid du Colombier
599a747e4fSDavid du Colombier cur = time(0);
609a747e4fSDavid du Colombier if(cur < last)
619a747e4fSDavid du Colombier delta += last - cur;
629a747e4fSDavid du Colombier else if(delta != 0 && last != 0) {
639a747e4fSDavid du Colombier drift = (cur - last + 1) / 2;
649a747e4fSDavid du Colombier if(drift > delta)
659a747e4fSDavid du Colombier delta = 0;
669a747e4fSDavid du Colombier else
679a747e4fSDavid du Colombier delta -= drift;
689a747e4fSDavid du Colombier }
699a747e4fSDavid du Colombier last = cur;
709a747e4fSDavid du Colombier return cur + delta;
719a747e4fSDavid du Colombier }
729a747e4fSDavid du Colombier
739a747e4fSDavid du Colombier static void
damaged(char * mesg)749a747e4fSDavid du Colombier damaged(char *mesg)
759a747e4fSDavid du Colombier {
76*14cc0f53SDavid du Colombier sysfatal("damaged filesystem: %s", mesg);
779a747e4fSDavid du Colombier }
789a747e4fSDavid du Colombier
799a747e4fSDavid du Colombier static void
lddisc(char * mesg)809a747e4fSDavid du Colombier lddisc(char *mesg)
819a747e4fSDavid du Colombier {
829a747e4fSDavid du Colombier if(debug)
839a747e4fSDavid du Colombier fprint(2, "discard %s\n", mesg);
84a21ce2d6SDavid du Colombier else
85a21ce2d6SDavid du Colombier USED(mesg);
869a747e4fSDavid du Colombier }
879a747e4fSDavid du Colombier
889a747e4fSDavid du Colombier static Sect *
getsect(void)899a747e4fSDavid du Colombier getsect(void)
909a747e4fSDavid du Colombier {
919a747e4fSDavid du Colombier Sect *t;
929a747e4fSDavid du Colombier
939a747e4fSDavid du Colombier t = freehead;
949a747e4fSDavid du Colombier freehead = t->next;
959a747e4fSDavid du Colombier if(freehead == nil)
969a747e4fSDavid du Colombier freetail = nil;
979a747e4fSDavid du Colombier nfree--;
989a747e4fSDavid du Colombier return t;
999a747e4fSDavid du Colombier }
1009a747e4fSDavid du Colombier
1019a747e4fSDavid du Colombier static void
newsect(Gen * g,Sect * s)1029a747e4fSDavid du Colombier newsect(Gen *g, Sect *s)
1039a747e4fSDavid du Colombier {
1049a747e4fSDavid du Colombier int m, n, err;
1059a747e4fSDavid du Colombier uchar hdr[2*3];
1069a747e4fSDavid du Colombier
1079a747e4fSDavid du Colombier if(debug)
1089a747e4fSDavid du Colombier fprint(2, "new %d %ld\n", g->gnum, s->seq);
1099a747e4fSDavid du Colombier if(g->tail == nil)
1109a747e4fSDavid du Colombier g->head = s;
1119a747e4fSDavid du Colombier else
1129a747e4fSDavid du Colombier g->tail->next = s;
1139a747e4fSDavid du Colombier g->tail = s;
1149a747e4fSDavid du Colombier s->next = nil;
1159a747e4fSDavid du Colombier m = putc3(&hdr[0], g->gnum);
1169a747e4fSDavid du Colombier n = putc3(&hdr[m], s->seq);
1179a747e4fSDavid du Colombier s->toff = MAGSIZE + m + n;
1189a747e4fSDavid du Colombier s->coff = s->toff + 4;
1199a747e4fSDavid du Colombier s->time = NOTIME;
1209a747e4fSDavid du Colombier s->sum = 0;
1219a747e4fSDavid du Colombier err = 1;
1229a747e4fSDavid du Colombier for(;;) {
1239a747e4fSDavid du Colombier if(writedata(err, s->sect, hdr, m + n, MAGSIZE)
1249a747e4fSDavid du Colombier && writedata(err, s->sect, magic, MAGSIZE, 0))
1259a747e4fSDavid du Colombier break;
1269a747e4fSDavid du Colombier clearsect(s->sect);
1279a747e4fSDavid du Colombier err = 0;
1289a747e4fSDavid du Colombier }
1299a747e4fSDavid du Colombier }
1309a747e4fSDavid du Colombier
1319a747e4fSDavid du Colombier static Sect *
newsum(Gen * g,ulong seq)1329a747e4fSDavid du Colombier newsum(Gen *g, ulong seq)
1339a747e4fSDavid du Colombier {
1349a747e4fSDavid du Colombier Sect *t;
1359a747e4fSDavid du Colombier
1369a747e4fSDavid du Colombier if(nfree == 0)
1379a747e4fSDavid du Colombier damaged("no free sector for summary");
1389a747e4fSDavid du Colombier t = getsect();
1399a747e4fSDavid du Colombier t->seq = seq;
1409a747e4fSDavid du Colombier newsect(g, t);
1419a747e4fSDavid du Colombier return t;
1429a747e4fSDavid du Colombier }
1439a747e4fSDavid du Colombier
1449a747e4fSDavid du Colombier static void
freesect(Sect * s)1459a747e4fSDavid du Colombier freesect(Sect *s)
1469a747e4fSDavid du Colombier {
1479a747e4fSDavid du Colombier clearsect(s->sect);
1489a747e4fSDavid du Colombier if(freetail == nil)
1499a747e4fSDavid du Colombier freehead = s;
1509a747e4fSDavid du Colombier else
1519a747e4fSDavid du Colombier freetail->next = s;
1529a747e4fSDavid du Colombier freetail = s;
1539a747e4fSDavid du Colombier s->next = nil;
1549a747e4fSDavid du Colombier nfree++;
1559a747e4fSDavid du Colombier }
1569a747e4fSDavid du Colombier
1579a747e4fSDavid du Colombier static void
dupsect(Sect * s,int renum)1589a747e4fSDavid du Colombier dupsect(Sect *s, int renum)
1599a747e4fSDavid du Colombier {
1609a747e4fSDavid du Colombier Sect *t;
1619a747e4fSDavid du Colombier Renum r;
1629a747e4fSDavid du Colombier uchar *b;
1639a747e4fSDavid du Colombier int err, n;
1649a747e4fSDavid du Colombier ulong doff, off;
1659a747e4fSDavid du Colombier
1669a747e4fSDavid du Colombier if(nfree == 0)
1679a747e4fSDavid du Colombier damaged("no free for copy");
1689a747e4fSDavid du Colombier t = getsect();
1699a747e4fSDavid du Colombier b = sectbuff;
1709a747e4fSDavid du Colombier off = s->coff;
1719a747e4fSDavid du Colombier readdata(s->sect, b, off, 0);
1729a747e4fSDavid du Colombier doff = s->toff;
1739a747e4fSDavid du Colombier if(s->time == NOTIME)
1749a747e4fSDavid du Colombier doff += 4;
1759a747e4fSDavid du Colombier // Window 5
1769a747e4fSDavid du Colombier err = 1;
1779a747e4fSDavid du Colombier for(;;) {
1789a747e4fSDavid du Colombier if(writedata(err, t->sect, b + 1, s->toff - 1, 1)
1799a747e4fSDavid du Colombier && writedata(err, t->sect, b + doff, off - doff, doff)
1809a747e4fSDavid du Colombier && writedata(err, t->sect, b, 1, 0))
1819a747e4fSDavid du Colombier break;
1829a747e4fSDavid du Colombier clearsect(t->sect);
1839a747e4fSDavid du Colombier err = 0;
1849a747e4fSDavid du Colombier }
1859a747e4fSDavid du Colombier if(renum) {
1869a747e4fSDavid du Colombier r.old = s->sect;
1879a747e4fSDavid du Colombier r.new = t->sect;
1889a747e4fSDavid du Colombier erenum(&r);
1899a747e4fSDavid du Colombier }
1909a747e4fSDavid du Colombier n = s->sect;
1919a747e4fSDavid du Colombier s->sect = t->sect;
1929a747e4fSDavid du Colombier t->sect = n;
1939a747e4fSDavid du Colombier freesect(t);
1949a747e4fSDavid du Colombier if(cursect >= 0)
1959a747e4fSDavid du Colombier readdata(cursect, b, sectsize, 0);
1969a747e4fSDavid du Colombier }
1979a747e4fSDavid du Colombier
1989a747e4fSDavid du Colombier static void
gswap(void)1999a747e4fSDavid du Colombier gswap(void)
2009a747e4fSDavid du Colombier {
2019a747e4fSDavid du Colombier Gen t;
2029a747e4fSDavid du Colombier
2039a747e4fSDavid du Colombier t = gens[0];
2049a747e4fSDavid du Colombier gens[0] = gens[1];
2059a747e4fSDavid du Colombier gens[1] = t;
2069a747e4fSDavid du Colombier }
2079a747e4fSDavid du Colombier
2089a747e4fSDavid du Colombier static void
checkdata(void)2099a747e4fSDavid du Colombier checkdata(void)
2109a747e4fSDavid du Colombier {
2119a747e4fSDavid du Colombier Gen *g;
2129a747e4fSDavid du Colombier
2139a747e4fSDavid du Colombier g = &gens[0];
2149a747e4fSDavid du Colombier if(g->dup != nil) { // Window 5 damage
2159a747e4fSDavid du Colombier if(diags)
2169a747e4fSDavid du Colombier fprint(2, "%s: window 5 damage\n", argv0);
2179a747e4fSDavid du Colombier freesect(g->dup);
2189a747e4fSDavid du Colombier g->dup = nil;
2199a747e4fSDavid du Colombier }
2209a747e4fSDavid du Colombier }
2219a747e4fSDavid du Colombier
2229a747e4fSDavid du Colombier static void
checksweep(void)2239a747e4fSDavid du Colombier checksweep(void)
2249a747e4fSDavid du Colombier {
2259a747e4fSDavid du Colombier Gen *g;
2269a747e4fSDavid du Colombier Jrec j;
2279a747e4fSDavid du Colombier uchar *b;
2289a747e4fSDavid du Colombier int n, op;
2299a747e4fSDavid du Colombier Sect *s, *t, *u;
2309a747e4fSDavid du Colombier long off, seq, soff;
2319a747e4fSDavid du Colombier
2329a747e4fSDavid du Colombier g = &gens[1];
2339a747e4fSDavid du Colombier if(g->dup != nil) { // Window 5 damage
2349a747e4fSDavid du Colombier if(diags)
2359a747e4fSDavid du Colombier fprint(2, "%s: window 5 damage\n", argv0);
2369a747e4fSDavid du Colombier freesect(g->dup);
2379a747e4fSDavid du Colombier g->dup = nil;
2389a747e4fSDavid du Colombier }
2399a747e4fSDavid du Colombier
2409a747e4fSDavid du Colombier s = g->head;
2419a747e4fSDavid du Colombier if(s != g->tail) {
2429a747e4fSDavid du Colombier while(s->next != g->tail)
2439a747e4fSDavid du Colombier s = s->next;
2449a747e4fSDavid du Colombier }
2459a747e4fSDavid du Colombier
2469a747e4fSDavid du Colombier b = sectbuff;
2479a747e4fSDavid du Colombier op = -1;
2489a747e4fSDavid du Colombier seq = -1;
2499a747e4fSDavid du Colombier soff = 0;
2509a747e4fSDavid du Colombier u = nil;
2519a747e4fSDavid du Colombier t = s;
2529a747e4fSDavid du Colombier for(;;) {
2539a747e4fSDavid du Colombier readdata(t->sect, b, sectsize, 0);
2549a747e4fSDavid du Colombier off = t->toff + 4;
2559a747e4fSDavid du Colombier for(;;) {
2569a747e4fSDavid du Colombier n = convM2J(&j, &b[off]);
2579a747e4fSDavid du Colombier if(n < 0) {
2589a747e4fSDavid du Colombier if(j.type != 0xFF) {
2599a747e4fSDavid du Colombier if(debug)
2609a747e4fSDavid du Colombier fprint(2, "s[%d] @ %d %ld\n", j.type, t->sect, off);
2619a747e4fSDavid du Colombier damaged("bad Jrec");
2629a747e4fSDavid du Colombier }
2639a747e4fSDavid du Colombier break;
2649a747e4fSDavid du Colombier }
2659a747e4fSDavid du Colombier switch(j.type) {
2669a747e4fSDavid du Colombier case FT_SUMMARY:
2679a747e4fSDavid du Colombier case FT_SUMBEG:
2689a747e4fSDavid du Colombier seq = j.seq;
2699a747e4fSDavid du Colombier case FT_SUMEND:
2709a747e4fSDavid du Colombier op = j.type;
2719a747e4fSDavid du Colombier soff = off;
2729a747e4fSDavid du Colombier u = t;
2739a747e4fSDavid du Colombier break;
2749a747e4fSDavid du Colombier case FT_WRITE:
2759a747e4fSDavid du Colombier case FT_AWRITE:
2769a747e4fSDavid du Colombier off += j.size;
2779a747e4fSDavid du Colombier }
2789a747e4fSDavid du Colombier off += n;
2799a747e4fSDavid du Colombier }
2809a747e4fSDavid du Colombier t = t->next;
2819a747e4fSDavid du Colombier if(t == nil)
2829a747e4fSDavid du Colombier break;
2839a747e4fSDavid du Colombier }
2849a747e4fSDavid du Colombier
2859a747e4fSDavid du Colombier if(op == FT_SUMBEG) { // Window 1 damage
2869a747e4fSDavid du Colombier if(diags)
2879a747e4fSDavid du Colombier fprint(2, "%s: window 1 damage\n", argv0);
2889a747e4fSDavid du Colombier if(u != s) {
2899a747e4fSDavid du Colombier freesect(u);
2909a747e4fSDavid du Colombier s->next = nil;
2919a747e4fSDavid du Colombier g->tail = s;
2929a747e4fSDavid du Colombier }
2939a747e4fSDavid du Colombier s->coff = soff;
2949a747e4fSDavid du Colombier dupsect(s, 0);
2959a747e4fSDavid du Colombier seq--;
2969a747e4fSDavid du Colombier }
2979a747e4fSDavid du Colombier
2989a747e4fSDavid du Colombier if(seq >= 0) {
2999a747e4fSDavid du Colombier g = &gens[0];
3009a747e4fSDavid du Colombier if(seq > g->low)
3019a747e4fSDavid du Colombier damaged("high sweep");
3029a747e4fSDavid du Colombier if(seq == g->low) { // Window 2 damage
3039a747e4fSDavid du Colombier if(diags)
3049a747e4fSDavid du Colombier fprint(2, "%s: window 2 damage\n", argv0);
3059a747e4fSDavid du Colombier s = g->head;
3069a747e4fSDavid du Colombier g->head = s->next;
3079a747e4fSDavid du Colombier freesect(s);
3089a747e4fSDavid du Colombier if(g->head == nil) {
3099a747e4fSDavid du Colombier g->tail = nil;
3109a747e4fSDavid du Colombier g->gnum += 2;
3119a747e4fSDavid du Colombier newsum(g, 0);
3129a747e4fSDavid du Colombier gswap();
3139a747e4fSDavid du Colombier }
3149a747e4fSDavid du Colombier }
3159a747e4fSDavid du Colombier }
3169a747e4fSDavid du Colombier }
3179a747e4fSDavid du Colombier
3189a747e4fSDavid du Colombier void
load1(Sect * s,int parity)3199a747e4fSDavid du Colombier load1(Sect *s, int parity)
3209a747e4fSDavid du Colombier {
3219a747e4fSDavid du Colombier int n;
3229a747e4fSDavid du Colombier Jrec j;
3239a747e4fSDavid du Colombier uchar *b;
3249a747e4fSDavid du Colombier char *err;
3259a747e4fSDavid du Colombier Extent *x;
3269a747e4fSDavid du Colombier Entry *d, *e;
3279a747e4fSDavid du Colombier ulong ctime, off, mtime;
3289a747e4fSDavid du Colombier
3299a747e4fSDavid du Colombier if(s->sect < 0 && readonly) // readonly damaged
3309a747e4fSDavid du Colombier return;
3319a747e4fSDavid du Colombier
3329a747e4fSDavid du Colombier b = sectbuff;
3339a747e4fSDavid du Colombier readdata(s->sect, b, sectsize, 0);
3349a747e4fSDavid du Colombier s->sum = 0;
3359a747e4fSDavid du Colombier off = s->toff;
3369a747e4fSDavid du Colombier ctime = get4(&b[off]);
3379a747e4fSDavid du Colombier off += 4;
3389a747e4fSDavid du Colombier
3399a747e4fSDavid du Colombier for(;;) {
3409a747e4fSDavid du Colombier n = convM2J(&j, &b[off]);
3419a747e4fSDavid du Colombier if(n < 0) {
3429a747e4fSDavid du Colombier if(j.type != 0xFF) {
3439a747e4fSDavid du Colombier if(debug)
3449a747e4fSDavid du Colombier fprint(2, "l[%d] @ %d %ld\n", j.type, s->sect, off);
3459a747e4fSDavid du Colombier damaged("bad Jrec");
3469a747e4fSDavid du Colombier }
3479a747e4fSDavid du Colombier s->coff = off;
3489a747e4fSDavid du Colombier break;
3499a747e4fSDavid du Colombier }
3509a747e4fSDavid du Colombier off += n;
3519a747e4fSDavid du Colombier if(debug)
3529a747e4fSDavid du Colombier fprint(2, "get %J\n", &j);
3539a747e4fSDavid du Colombier switch(j.type) {
3549a747e4fSDavid du Colombier case FT_create:
3559a747e4fSDavid du Colombier ctime += j.mtime;
3569a747e4fSDavid du Colombier create:
3579a747e4fSDavid du Colombier d = elookup(j.parent);
3589a747e4fSDavid du Colombier if(d == nil) {
3599a747e4fSDavid du Colombier lddisc("parent");
3609a747e4fSDavid du Colombier break;
3619a747e4fSDavid du Colombier }
3629a747e4fSDavid du Colombier d->ref++;
3639a747e4fSDavid du Colombier e = ecreate(d, j.name, j.fnum, j.mode, ctime, &err);
3649a747e4fSDavid du Colombier if(e == nil) {
3659a747e4fSDavid du Colombier d->ref--;
3669a747e4fSDavid du Colombier lddisc("create");
3679a747e4fSDavid du Colombier break;
3689a747e4fSDavid du Colombier }
3699a747e4fSDavid du Colombier e->ref--;
3709a747e4fSDavid du Colombier if(j.type == FT_trunc)
3719a747e4fSDavid du Colombier e->mode = j.mode;
3729a747e4fSDavid du Colombier break;
3739a747e4fSDavid du Colombier case FT_chmod:
3749a747e4fSDavid du Colombier e = elookup(j.fnum);
3759a747e4fSDavid du Colombier if(e == nil) {
3769a747e4fSDavid du Colombier lddisc("lookup");
3779a747e4fSDavid du Colombier break;
3789a747e4fSDavid du Colombier }
3799a747e4fSDavid du Colombier echmod(e, j.mode, j.mnum);
3809a747e4fSDavid du Colombier break;
3819a747e4fSDavid du Colombier case FT_REMOVE:
3829a747e4fSDavid du Colombier e = elookup(j.fnum);
3839a747e4fSDavid du Colombier if(e == nil) {
3849a747e4fSDavid du Colombier lddisc("lookup");
3859a747e4fSDavid du Colombier break;
3869a747e4fSDavid du Colombier }
3879a747e4fSDavid du Colombier if(eremove(e) != nil) {
3889a747e4fSDavid du Colombier lddisc("remove");
3899a747e4fSDavid du Colombier break;
3909a747e4fSDavid du Colombier }
3919a747e4fSDavid du Colombier break;
3929a747e4fSDavid du Colombier case FT_AWRITE:
3939a747e4fSDavid du Colombier mtime = 0;
3949a747e4fSDavid du Colombier goto write;
3959a747e4fSDavid du Colombier case FT_WRITE:
3969a747e4fSDavid du Colombier ctime += j.mtime;
3979a747e4fSDavid du Colombier mtime = ctime;
3989a747e4fSDavid du Colombier write:
3999a747e4fSDavid du Colombier x = emalloc9p(sizeof(Extent));
4009a747e4fSDavid du Colombier x->sect = s->sect;
4019a747e4fSDavid du Colombier x->addr = off;
4029a747e4fSDavid du Colombier x->off = j.offset;
4039a747e4fSDavid du Colombier x->size = j.size;
4049a747e4fSDavid du Colombier off += j.size;
4059a747e4fSDavid du Colombier e = elookup(j.fnum);
4069a747e4fSDavid du Colombier if(e == nil) {
4079a747e4fSDavid du Colombier lddisc("lookup");
4089a747e4fSDavid du Colombier break;
4099a747e4fSDavid du Colombier }
4109a747e4fSDavid du Colombier ewrite(e, x, parity, mtime);
4119a747e4fSDavid du Colombier break;
4129a747e4fSDavid du Colombier case FT_trunc:
4139a747e4fSDavid du Colombier ctime += j.mtime;
4149a747e4fSDavid du Colombier e = elookup(j.tnum);
4159a747e4fSDavid du Colombier if(e == nil) {
4169a747e4fSDavid du Colombier if(debug)
4179a747e4fSDavid du Colombier fprint(2, "-> create\n");
4189a747e4fSDavid du Colombier goto create;
4199a747e4fSDavid du Colombier }
4209a747e4fSDavid du Colombier etrunc(e, j.fnum, ctime);
4219a747e4fSDavid du Colombier break;
4229a747e4fSDavid du Colombier case FT_SUMMARY:
4239a747e4fSDavid du Colombier case FT_SUMBEG:
4249a747e4fSDavid du Colombier case FT_SUMEND:
4259a747e4fSDavid du Colombier s->sum += n;
4269a747e4fSDavid du Colombier break;
4279a747e4fSDavid du Colombier default:
4289a747e4fSDavid du Colombier damaged("load1 botch");
4299a747e4fSDavid du Colombier }
4309a747e4fSDavid du Colombier }
4319a747e4fSDavid du Colombier
4329a747e4fSDavid du Colombier if(s->sum > Nsum)
4339a747e4fSDavid du Colombier s->sum = Nsum;
4349a747e4fSDavid du Colombier
4359a747e4fSDavid du Colombier s->time = ctime;
4369a747e4fSDavid du Colombier if(ctime != NOTIME && ctime > ltime)
4379a747e4fSDavid du Colombier ltime = ctime;
4389a747e4fSDavid du Colombier }
4399a747e4fSDavid du Colombier
4409a747e4fSDavid du Colombier void
load0(int parity)4419a747e4fSDavid du Colombier load0(int parity)
4429a747e4fSDavid du Colombier {
4439a747e4fSDavid du Colombier Sect *s;
4449a747e4fSDavid du Colombier
4459a747e4fSDavid du Colombier if(debug)
4469a747e4fSDavid du Colombier fprint(2, "load %d\n", parity);
4479a747e4fSDavid du Colombier for(s = gens[parity].head; s != nil; s = s->next)
4489a747e4fSDavid du Colombier load1(s, parity);
4499a747e4fSDavid du Colombier }
4509a747e4fSDavid du Colombier
4519a747e4fSDavid du Colombier void
loadfs(int ro)4529a747e4fSDavid du Colombier loadfs(int ro)
4539a747e4fSDavid du Colombier {
4549a747e4fSDavid du Colombier Gen *g;
4559a747e4fSDavid du Colombier Sect *s;
4569a747e4fSDavid du Colombier ulong u, v;
4579a747e4fSDavid du Colombier int i, j, n;
4589a747e4fSDavid du Colombier uchar hdr[MAXHDR];
4599a747e4fSDavid du Colombier
4609a747e4fSDavid du Colombier readonly = ro;
4619a747e4fSDavid du Colombier fmtinstall('J', Jconv);
4629a747e4fSDavid du Colombier
4639a747e4fSDavid du Colombier for(i = 0; i < 2; i++) {
4649a747e4fSDavid du Colombier g = &gens[i];
4659a747e4fSDavid du Colombier g->gnum = -1;
4669a747e4fSDavid du Colombier g->low = nsects;
4679a747e4fSDavid du Colombier g->high = -1;
4689a747e4fSDavid du Colombier g->count = 0;
4699a747e4fSDavid du Colombier g->head = nil;
4709a747e4fSDavid du Colombier g->tail = nil;
4719a747e4fSDavid du Colombier }
4729a747e4fSDavid du Colombier
4739a747e4fSDavid du Colombier for(i = 0; i < nsects; i++) {
4749a747e4fSDavid du Colombier readdata(i, hdr, MAXHDR, 0);
4759a747e4fSDavid du Colombier if(memcmp(hdr, magic, MAGSIZE) == 0) {
4769a747e4fSDavid du Colombier n = MAGSIZE + getc3(&hdr[MAGSIZE], &u);
4779a747e4fSDavid du Colombier getc3(&hdr[n], &v);
4789a747e4fSDavid du Colombier if(debug)
4799a747e4fSDavid du Colombier fprint(2, "%d: %ld %ld\n", i, u, v);
4809a747e4fSDavid du Colombier for(j = 0; j < 2; j++) {
4819a747e4fSDavid du Colombier g = &gens[j];
4829a747e4fSDavid du Colombier if(g->gnum == u) {
4839a747e4fSDavid du Colombier g->count++;
4849a747e4fSDavid du Colombier if(v < g->low)
4859a747e4fSDavid du Colombier g->low = v;
4869a747e4fSDavid du Colombier if(v > g->high)
4879a747e4fSDavid du Colombier g->high = v;
4889a747e4fSDavid du Colombier break;
4899a747e4fSDavid du Colombier }
4909a747e4fSDavid du Colombier else if(g->gnum < 0) {
4919a747e4fSDavid du Colombier g->gnum = u;
4929a747e4fSDavid du Colombier g->count = 1;
4939a747e4fSDavid du Colombier g->low = v;
4949a747e4fSDavid du Colombier g->high = v;
4959a747e4fSDavid du Colombier break;
4969a747e4fSDavid du Colombier }
4979a747e4fSDavid du Colombier }
4989a747e4fSDavid du Colombier if(j == 2)
4999a747e4fSDavid du Colombier damaged("unexpected generation");
5009a747e4fSDavid du Colombier }
5019a747e4fSDavid du Colombier else if(hdr[0] == 0xFF) {
5029a747e4fSDavid du Colombier nfree++;
5039a747e4fSDavid du Colombier s = emalloc9p(sizeof(Sect));
5049a747e4fSDavid du Colombier s->sect = i;
5059a747e4fSDavid du Colombier s->next = freehead;
5069a747e4fSDavid du Colombier freehead = s;
5079a747e4fSDavid du Colombier if(freetail == nil)
5089a747e4fSDavid du Colombier freetail = s;
5099a747e4fSDavid du Colombier }
5109a747e4fSDavid du Colombier else
5119a747e4fSDavid du Colombier nbad++;
5129a747e4fSDavid du Colombier }
5139a747e4fSDavid du Colombier
5149a747e4fSDavid du Colombier if(nbad > 0)
5159a747e4fSDavid du Colombier damaged("bad sectors");
5169a747e4fSDavid du Colombier
5179a747e4fSDavid du Colombier if(gens[0].gnum < 0)
5189a747e4fSDavid du Colombier damaged("no data");
5199a747e4fSDavid du Colombier
5209a747e4fSDavid du Colombier if(gens[1].gnum < 0) { // Window 3 death
5219a747e4fSDavid du Colombier if(diags)
5229a747e4fSDavid du Colombier fprint(2, "%s: window 3 damage\n", argv0);
5239a747e4fSDavid du Colombier g = &gens[1];
5249a747e4fSDavid du Colombier g->gnum = gens[0].gnum + 1;
5259a747e4fSDavid du Colombier g->low = 0;
5269a747e4fSDavid du Colombier g->high = 0;
5279a747e4fSDavid du Colombier g->count = 1;
5289a747e4fSDavid du Colombier if(!readonly)
5299a747e4fSDavid du Colombier newsum(g, 0);
5309a747e4fSDavid du Colombier }
5319a747e4fSDavid du Colombier
5329a747e4fSDavid du Colombier if(gens[0].gnum > gens[1].gnum)
5339a747e4fSDavid du Colombier gswap();
5349a747e4fSDavid du Colombier
5359a747e4fSDavid du Colombier for(i = 0; i < 2; i++) {
5369a747e4fSDavid du Colombier g = &gens[i];
5379a747e4fSDavid du Colombier n = g->count;
5389a747e4fSDavid du Colombier if(n <= g->high - g->low)
5399a747e4fSDavid du Colombier damaged("missing sectors");
5409a747e4fSDavid du Colombier g->vect = emalloc9p(n * sizeof(Sect *));
5419a747e4fSDavid du Colombier for(j = 0; j < n; j++) {
5429a747e4fSDavid du Colombier s = emalloc9p(sizeof(Sect));
5439a747e4fSDavid du Colombier s->sect = -1;
5449a747e4fSDavid du Colombier g->vect[j] = s;
5459a747e4fSDavid du Colombier }
5469a747e4fSDavid du Colombier }
5479a747e4fSDavid du Colombier
5489a747e4fSDavid du Colombier if(debug) {
5499a747e4fSDavid du Colombier for(j = 0; j < 2; j++) {
5509a747e4fSDavid du Colombier g = &gens[j];
5519a747e4fSDavid du Colombier print("%d\t%d\t%d-%d\n", g->gnum, g->count, g->low, g->high);
5529a747e4fSDavid du Colombier }
5539a747e4fSDavid du Colombier }
5549a747e4fSDavid du Colombier
5559a747e4fSDavid du Colombier for(i = 0; i < nsects; i++) {
5569a747e4fSDavid du Colombier readdata(i, hdr, MAXHDR, 0);
5579a747e4fSDavid du Colombier if(memcmp(hdr, magic, MAGSIZE) == 0) {
5589a747e4fSDavid du Colombier n = MAGSIZE + getc3(&hdr[MAGSIZE], &u);
5599a747e4fSDavid du Colombier n += getc3(&hdr[n], &v);
5609a747e4fSDavid du Colombier g = nil;
5619a747e4fSDavid du Colombier for(j = 0; j < 2; j++) {
5629a747e4fSDavid du Colombier g = &gens[j];
5639a747e4fSDavid du Colombier if(g->gnum == u)
5649a747e4fSDavid du Colombier break;
5659a747e4fSDavid du Colombier }
5669a747e4fSDavid du Colombier if(j == 2)
5679a747e4fSDavid du Colombier damaged("generation botch");
5689a747e4fSDavid du Colombier s = g->vect[v - g->low];
5699a747e4fSDavid du Colombier s->seq = v;
5709a747e4fSDavid du Colombier s->toff = n;
5719a747e4fSDavid du Colombier if(s->sect < 0)
5729a747e4fSDavid du Colombier s->sect = i;
5739a747e4fSDavid du Colombier else if(v == g->high && g->dup == nil) {
5749a747e4fSDavid du Colombier s = emalloc9p(sizeof(Sect));
5759a747e4fSDavid du Colombier s->sect = i;
5769a747e4fSDavid du Colombier g->dup = s;
5779a747e4fSDavid du Colombier }
5789a747e4fSDavid du Colombier else
5799a747e4fSDavid du Colombier damaged("dup block");
5809a747e4fSDavid du Colombier }
5819a747e4fSDavid du Colombier }
5829a747e4fSDavid du Colombier
5839a747e4fSDavid du Colombier for(j = 0; j < 2; j++) {
5849a747e4fSDavid du Colombier g = &gens[j];
5859a747e4fSDavid du Colombier for(i = 0; i < g->count; i++) {
5869a747e4fSDavid du Colombier s = g->vect[i];
5879a747e4fSDavid du Colombier if(g->tail == nil)
5889a747e4fSDavid du Colombier g->head = s;
5899a747e4fSDavid du Colombier else
5909a747e4fSDavid du Colombier g->tail->next = s;
5919a747e4fSDavid du Colombier g->tail = s;
5929a747e4fSDavid du Colombier s->next = nil;
5939a747e4fSDavid du Colombier }
5949a747e4fSDavid du Colombier free(g->vect);
5959a747e4fSDavid du Colombier }
5969a747e4fSDavid du Colombier
5979a747e4fSDavid du Colombier cursect = -1;
5989a747e4fSDavid du Colombier
5999a747e4fSDavid du Colombier if(!readonly) {
6009a747e4fSDavid du Colombier checkdata();
6019a747e4fSDavid du Colombier checksweep();
6029a747e4fSDavid du Colombier }
6039a747e4fSDavid du Colombier
6049a747e4fSDavid du Colombier load0(1);
6059a747e4fSDavid du Colombier load0(0);
6069a747e4fSDavid du Colombier
6079a747e4fSDavid du Colombier if(ltime != 0) {
6089a747e4fSDavid du Colombier u = now();
6099a747e4fSDavid du Colombier if(u < ltime) {
6109a747e4fSDavid du Colombier delta = ltime - u;
6119a747e4fSDavid du Colombier if(diags)
6129a747e4fSDavid du Colombier fprint(2, "%s: check clock: delta = %lud\n", argv0, delta);
6139a747e4fSDavid du Colombier }
6149a747e4fSDavid du Colombier }
6159a747e4fSDavid du Colombier
6169a747e4fSDavid du Colombier limit = 80 * nsects * sectsize / 100;
6179a747e4fSDavid du Colombier maxwrite = sectsize - MAXHDR - Nwrite - Nsum;
6189a747e4fSDavid du Colombier if(maxwrite > WRSIZE)
6199a747e4fSDavid du Colombier maxwrite = WRSIZE;
6209a747e4fSDavid du Colombier }
6219a747e4fSDavid du Colombier
6229a747e4fSDavid du Colombier static int
sputw(Sect * s,Jrec * j,int mtime,Extent * x,void * a)6239a747e4fSDavid du Colombier sputw(Sect *s, Jrec *j, int mtime, Extent *x, void *a)
6249a747e4fSDavid du Colombier {
6259a747e4fSDavid du Colombier ulong t;
6269a747e4fSDavid du Colombier int err, n, r;
6279a747e4fSDavid du Colombier uchar buff[Nmax], type[1];
6289a747e4fSDavid du Colombier
6299a747e4fSDavid du Colombier if(debug)
6309a747e4fSDavid du Colombier fprint(2, "put %J\n", j);
6319a747e4fSDavid du Colombier
6329a747e4fSDavid du Colombier if(mtime) {
6339a747e4fSDavid du Colombier t = j->mtime;
6349a747e4fSDavid du Colombier if(s->time == NOTIME) {
6359a747e4fSDavid du Colombier put4(buff, t);
6369a747e4fSDavid du Colombier if(!writedata(1, s->sect, buff, 4, s->toff)) {
6379a747e4fSDavid du Colombier dupsect(s, 1);
6389a747e4fSDavid du Colombier writedata(0, s->sect, buff, 4, s->toff);
6399a747e4fSDavid du Colombier }
6409a747e4fSDavid du Colombier s->time = t;
6419a747e4fSDavid du Colombier j->mtime = 0;
6429a747e4fSDavid du Colombier }
6439a747e4fSDavid du Colombier else {
6449a747e4fSDavid du Colombier j->mtime = t - s->time;
6459a747e4fSDavid du Colombier s->time = t;
6469a747e4fSDavid du Colombier }
6479a747e4fSDavid du Colombier }
6489a747e4fSDavid du Colombier
6499a747e4fSDavid du Colombier n = convJ2M(j, buff);
6509a747e4fSDavid du Colombier if(n < 0)
6519a747e4fSDavid du Colombier damaged("convJ2M");
6529a747e4fSDavid du Colombier
6539a747e4fSDavid du Colombier // Window 4
6549a747e4fSDavid du Colombier err = 2;
6559a747e4fSDavid du Colombier for(;;) {
6569a747e4fSDavid du Colombier err--;
6579a747e4fSDavid du Colombier if(!err)
6589a747e4fSDavid du Colombier dupsect(s, 1); // Window 4 damage
6599a747e4fSDavid du Colombier t = s->coff + 1;
6609a747e4fSDavid du Colombier if(!writedata(err, s->sect, buff, n, t))
6619a747e4fSDavid du Colombier continue;
6629a747e4fSDavid du Colombier
6639a747e4fSDavid du Colombier t += n;
6649a747e4fSDavid du Colombier r = n;
6659a747e4fSDavid du Colombier if(x != nil) {
6669a747e4fSDavid du Colombier x->sect = s->sect;
6679a747e4fSDavid du Colombier x->addr = t;
6689a747e4fSDavid du Colombier if(!writedata(err, s->sect, a, j->size, t))
6699a747e4fSDavid du Colombier continue;
6709a747e4fSDavid du Colombier t += j->size;
6719a747e4fSDavid du Colombier r += j->size;
6729a747e4fSDavid du Colombier }
6739a747e4fSDavid du Colombier
6749a747e4fSDavid du Colombier type[0] = j->type;
6759a747e4fSDavid du Colombier if(!writedata(err, s->sect, type, 1, s->coff))
6769a747e4fSDavid du Colombier continue;
6779a747e4fSDavid du Colombier r++;
6789a747e4fSDavid du Colombier break;
6799a747e4fSDavid du Colombier }
6809a747e4fSDavid du Colombier s->coff = t;
6819a747e4fSDavid du Colombier return r;
6829a747e4fSDavid du Colombier }
6839a747e4fSDavid du Colombier
6849a747e4fSDavid du Colombier static void
summarize(void)6859a747e4fSDavid du Colombier summarize(void)
6869a747e4fSDavid du Colombier {
6879a747e4fSDavid du Colombier Gen *g;
6889a747e4fSDavid du Colombier uchar *b;
6899a747e4fSDavid du Colombier Entry *e;
6909a747e4fSDavid du Colombier Extent *x;
6919a747e4fSDavid du Colombier Jrec j, sum;
6929a747e4fSDavid du Colombier Sect *s, *t;
6939a747e4fSDavid du Colombier ulong off, ctime;
6949a747e4fSDavid du Colombier int n, bytes, more, mtime, sumd;
6959a747e4fSDavid du Colombier
6969a747e4fSDavid du Colombier g = &gens[eparity];
6979a747e4fSDavid du Colombier s = g->head;
6989a747e4fSDavid du Colombier g->head = s->next;
6999a747e4fSDavid du Colombier if(g->head == nil)
7009a747e4fSDavid du Colombier g->tail = nil;
7019a747e4fSDavid du Colombier g = &gens[eparity^1];
7029a747e4fSDavid du Colombier t = g->tail;
7039a747e4fSDavid du Colombier b = sectbuff;
7049a747e4fSDavid du Colombier x = nil;
7059a747e4fSDavid du Colombier
7069a747e4fSDavid du Colombier if(debug)
7079a747e4fSDavid du Colombier fprint(2, "summarize\n");
7089a747e4fSDavid du Colombier
7099a747e4fSDavid du Colombier for(;;) { // Window 1
7109a747e4fSDavid du Colombier readdata(s->sect, b, sectsize, 0);
7119a747e4fSDavid du Colombier off = s->toff;
7129a747e4fSDavid du Colombier ctime = get4(&b[off]);
7139a747e4fSDavid du Colombier off += 4;
7149a747e4fSDavid du Colombier sumd = 0;
7159a747e4fSDavid du Colombier
7169a747e4fSDavid du Colombier cursect = s->sect;
7179a747e4fSDavid du Colombier while(b[off] != 0xFF) {
7189a747e4fSDavid du Colombier n = convM2J(&j, &b[off]);
7199a747e4fSDavid du Colombier if(n < 0)
7209a747e4fSDavid du Colombier damaged("bad Jrec");
7219a747e4fSDavid du Colombier if(debug)
7229a747e4fSDavid du Colombier fprint(2, "read %J\n", &j);
7239a747e4fSDavid du Colombier off += n;
7249a747e4fSDavid du Colombier bytes = n;
7259a747e4fSDavid du Colombier mtime = 0;
7269a747e4fSDavid du Colombier switch(j.type) {
7279a747e4fSDavid du Colombier case FT_create:
7289a747e4fSDavid du Colombier ctime += j.mtime;
7299a747e4fSDavid du Colombier mtime = 1;
7309a747e4fSDavid du Colombier create:
7319a747e4fSDavid du Colombier e = elookup(j.fnum);
7329a747e4fSDavid du Colombier if(e == nil)
7339a747e4fSDavid du Colombier continue;
7349a747e4fSDavid du Colombier break;
7359a747e4fSDavid du Colombier case FT_chmod:
7369a747e4fSDavid du Colombier e = elookup(j.fnum);
7379a747e4fSDavid du Colombier if(e == nil || j.mnum != e->mnum)
7389a747e4fSDavid du Colombier continue;
7399a747e4fSDavid du Colombier break;
7409a747e4fSDavid du Colombier case FT_REMOVE:
7419a747e4fSDavid du Colombier e = elookup(j.fnum);
7429a747e4fSDavid du Colombier if(e == nil)
7439a747e4fSDavid du Colombier continue;
7449a747e4fSDavid du Colombier break;
7459a747e4fSDavid du Colombier case FT_trunc:
7469a747e4fSDavid du Colombier ctime += j.mtime;
7479a747e4fSDavid du Colombier mtime = 1;
7489a747e4fSDavid du Colombier e = elookup(j.tnum);
7499a747e4fSDavid du Colombier if(e == nil) {
7509a747e4fSDavid du Colombier if(debug)
7519a747e4fSDavid du Colombier fprint(2, "-> create\n");
7529a747e4fSDavid du Colombier j.type = FT_create;
7539a747e4fSDavid du Colombier goto create;
7549a747e4fSDavid du Colombier }
7559a747e4fSDavid du Colombier break;
7569a747e4fSDavid du Colombier case FT_AWRITE:
7579a747e4fSDavid du Colombier goto write;
7589a747e4fSDavid du Colombier case FT_WRITE:
7599a747e4fSDavid du Colombier ctime += j.mtime;
7609a747e4fSDavid du Colombier mtime = 1;
7619a747e4fSDavid du Colombier write:
7629a747e4fSDavid du Colombier e = elookup(j.fnum);
7639a747e4fSDavid du Colombier if(e == nil) {
7649a747e4fSDavid du Colombier off += j.size;
7659a747e4fSDavid du Colombier continue;
7669a747e4fSDavid du Colombier }
7679a747e4fSDavid du Colombier x = esum(e, s->sect, off, &more);
7689a747e4fSDavid du Colombier if(x == nil) {
7699a747e4fSDavid du Colombier damaged("missing extent");
7709a747e4fSDavid du Colombier off += j.size;
7719a747e4fSDavid du Colombier continue;
7729a747e4fSDavid du Colombier }
7739a747e4fSDavid du Colombier if(more) {
7749a747e4fSDavid du Colombier j.type = FT_AWRITE;
7759a747e4fSDavid du Colombier mtime = 0;
7769a747e4fSDavid du Colombier }
7779a747e4fSDavid du Colombier bytes += j.size;
7789a747e4fSDavid du Colombier break;
7799a747e4fSDavid du Colombier case FT_SUMMARY:
7809a747e4fSDavid du Colombier case FT_SUMBEG:
7819a747e4fSDavid du Colombier case FT_SUMEND:
7829a747e4fSDavid du Colombier continue;
7839a747e4fSDavid du Colombier default:
7849a747e4fSDavid du Colombier damaged("summarize botch");
7859a747e4fSDavid du Colombier }
7869a747e4fSDavid du Colombier
7879a747e4fSDavid du Colombier if(!sumd) {
7889a747e4fSDavid du Colombier if(t->coff + Nsumbeg >= sectsize - 1)
7899a747e4fSDavid du Colombier t = newsum(g, t->seq + 1);
7909a747e4fSDavid du Colombier sum.type = FT_SUMBEG;
7919a747e4fSDavid du Colombier sum.seq = s->seq;
7929a747e4fSDavid du Colombier if(debug)
7939a747e4fSDavid du Colombier fprint(2, "+ %J\n", &sum);
7949a747e4fSDavid du Colombier t->sum += sputw(t, &sum, 0, nil, nil);
7959a747e4fSDavid du Colombier if(t->sum >= Nsum)
7969a747e4fSDavid du Colombier t->sum = Nsum;
7979a747e4fSDavid du Colombier sumd = 1;
7989a747e4fSDavid du Colombier }
7999a747e4fSDavid du Colombier
8009a747e4fSDavid du Colombier if(t->coff + bytes >= sectsize - Nsum + t->sum - 1)
8019a747e4fSDavid du Colombier t = newsum(g, t->seq + 1);
8029a747e4fSDavid du Colombier
8039a747e4fSDavid du Colombier if(mtime)
8049a747e4fSDavid du Colombier j.mtime = ctime;
8059a747e4fSDavid du Colombier
8069a747e4fSDavid du Colombier switch(j.type) {
8079a747e4fSDavid du Colombier case FT_AWRITE:
8089a747e4fSDavid du Colombier case FT_WRITE:
8099a747e4fSDavid du Colombier sputw(t, &j, mtime, x, &b[off]);
8109a747e4fSDavid du Colombier off += j.size;
8119a747e4fSDavid du Colombier break;
8129a747e4fSDavid du Colombier default:
8139a747e4fSDavid du Colombier sputw(t, &j, mtime, nil, nil);
8149a747e4fSDavid du Colombier }
8159a747e4fSDavid du Colombier }
8169a747e4fSDavid du Colombier cursect = -1;
8179a747e4fSDavid du Colombier
8189a747e4fSDavid du Colombier if(t->coff + Nsumbeg >= sectsize - 1)
8199a747e4fSDavid du Colombier t = newsum(g, t->seq + 1);
8209a747e4fSDavid du Colombier if(sumd)
8219a747e4fSDavid du Colombier sum.type = FT_SUMEND;
8229a747e4fSDavid du Colombier else {
8239a747e4fSDavid du Colombier sum.type = FT_SUMMARY;
8249a747e4fSDavid du Colombier sum.seq = s->seq;
8259a747e4fSDavid du Colombier }
8269a747e4fSDavid du Colombier if(debug)
8279a747e4fSDavid du Colombier fprint(2, "+ %J\n", &sum);
8289a747e4fSDavid du Colombier t->sum += sputw(t, &sum, 0, nil, nil);
8299a747e4fSDavid du Colombier if(t->sum >= Nsum)
8309a747e4fSDavid du Colombier t->sum = Nsum;
8319a747e4fSDavid du Colombier
8329a747e4fSDavid du Colombier // Window 2
8339a747e4fSDavid du Colombier freesect(s);
8349a747e4fSDavid du Colombier g = &gens[eparity];
8359a747e4fSDavid du Colombier s = g->head;
8369a747e4fSDavid du Colombier if(s == nil) {
8379a747e4fSDavid du Colombier // Window 3
8389a747e4fSDavid du Colombier g->gnum += 2;
8399a747e4fSDavid du Colombier newsum(g, 0);
8409a747e4fSDavid du Colombier eparity ^= 1;
8419a747e4fSDavid du Colombier return;
8429a747e4fSDavid du Colombier }
8439a747e4fSDavid du Colombier
8449a747e4fSDavid du Colombier if(nfree >= Nfree)
8459a747e4fSDavid du Colombier return;
8469a747e4fSDavid du Colombier
8479a747e4fSDavid du Colombier g->head = s->next;
8489a747e4fSDavid du Colombier if(g->head == nil)
8499a747e4fSDavid du Colombier g->tail = nil;
8509a747e4fSDavid du Colombier g = &gens[eparity^1];
8519a747e4fSDavid du Colombier }
8529a747e4fSDavid du Colombier }
8539a747e4fSDavid du Colombier
8549a747e4fSDavid du Colombier char *
need(int bytes)8559a747e4fSDavid du Colombier need(int bytes)
8569a747e4fSDavid du Colombier {
8579a747e4fSDavid du Colombier Gen *g;
8589a747e4fSDavid du Colombier int sums;
8599a747e4fSDavid du Colombier Sect *s, *t;
8609a747e4fSDavid du Colombier
8619a747e4fSDavid du Colombier sums = 0;
8629a747e4fSDavid du Colombier for(;;) {
8639a747e4fSDavid du Colombier s = gens[eparity].tail;
8649a747e4fSDavid du Colombier if(s->coff + bytes < sectsize - Nsum + s->sum - 1)
8659a747e4fSDavid du Colombier return nil;
8669a747e4fSDavid du Colombier
8679a747e4fSDavid du Colombier if(nfree >= Nfree)
8689a747e4fSDavid du Colombier break;
8699a747e4fSDavid du Colombier
8709a747e4fSDavid du Colombier if(sums == 2) {
8719a747e4fSDavid du Colombier readonly = 1;
8729a747e4fSDavid du Colombier return "generation full";
8739a747e4fSDavid du Colombier }
8749a747e4fSDavid du Colombier
8759a747e4fSDavid du Colombier summarize();
8769a747e4fSDavid du Colombier sums++;
8779a747e4fSDavid du Colombier }
8789a747e4fSDavid du Colombier
8799a747e4fSDavid du Colombier g = &gens[eparity];
8809a747e4fSDavid du Colombier t = getsect();
8819a747e4fSDavid du Colombier t->seq = g->tail->seq + 1;
8829a747e4fSDavid du Colombier newsect(g, t);
8839a747e4fSDavid du Colombier return nil;
8849a747e4fSDavid du Colombier }
8859a747e4fSDavid du Colombier
8869a747e4fSDavid du Colombier void
putw(Jrec * j,int mtime,Extent * x,void * a)8879a747e4fSDavid du Colombier putw(Jrec *j, int mtime, Extent *x, void *a)
8889a747e4fSDavid du Colombier {
8899a747e4fSDavid du Colombier sputw(gens[eparity].tail, j, mtime, x, a);
8909a747e4fSDavid du Colombier }
8919a747e4fSDavid du Colombier
8929a747e4fSDavid du Colombier void
put(Jrec * j,int mtime)8939a747e4fSDavid du Colombier put(Jrec *j, int mtime)
8949a747e4fSDavid du Colombier {
8959a747e4fSDavid du Colombier sputw(gens[eparity].tail, j, mtime, nil, nil);
8969a747e4fSDavid du Colombier }
897