summaryrefslogtreecommitdiffstats
path: root/src/cmd/venti/srv/syncindex0.c
diff options
context:
space:
mode:
authorRuss Cox <rsc@swtch.com>2007-10-29 14:33:17 -0400
committerRuss Cox <rsc@swtch.com>2007-10-29 14:33:17 -0400
commit45ac814c8609174199cadb6f1bbb4baf7c12c94a (patch)
tree49f4b2120a36b080a0ffe8f9988c21db7b97656c /src/cmd/venti/srv/syncindex0.c
parentc5a183de108e5685305734d5cf984b58bb0d614a (diff)
downloadplan9port-45ac814c8609174199cadb6f1bbb4baf7c12c94a.tar.gz
plan9port-45ac814c8609174199cadb6f1bbb4baf7c12c94a.zip
venti: fix sync deadlock, add /proc stub
Diffstat (limited to 'src/cmd/venti/srv/syncindex0.c')
-rw-r--r--src/cmd/venti/srv/syncindex0.c210
1 files changed, 59 insertions, 151 deletions
diff --git a/src/cmd/venti/srv/syncindex0.c b/src/cmd/venti/srv/syncindex0.c
index 98f6adf1..be3a2ea0 100644
--- a/src/cmd/venti/srv/syncindex0.c
+++ b/src/cmd/venti/srv/syncindex0.c
@@ -2,184 +2,92 @@
#include "dat.h"
#include "fns.h"
-enum
+static int
+syncarenaindex(Arena *arena, u64int a0)
{
- ClumpChunks = 32*1024
-};
-
-static int missing, wrong;
-
-/*
- * shell sort is plenty good enough
- * because we're going to do a bunch of disk i/o's
- */
-static void
-sortclumpinfo(ClumpInfo *ci, int *s, int n)
-{
- int i, j, m, t;
-
- for(m = (n + 3) / 5; m > 0; m = (m + 1) / 3){
- for(i = n - m; i-- > 0;){
- for(j = i + m; j < n; j += m){
- if(memcmp(ci[s[j - m]].score, ci[s[j]].score, VtScoreSize) <= 0)
- break;
- t = s[j];
- s[j] = s[j - m];
- s[j - m] = t;
- }
- }
- }
-}
-
-int
-syncarenaindex(Index *ix, Arena *arena, u32int clump, u64int a, int fix, int *pflush, int check)
-{
- Packet *pack;
- IEntry ie;
+ int ok;
+ u32int clump;
+ u64int a;
+ ClumpInfo ci;
IAddr ia;
- ClumpInfo *ci, *cis;
- u64int *addrs;
- int i, n, ok, *s, flush;
-
- trace(TraceProc, "syncarenaindex enter");
+ AState as;
+
+ if(arena->diskstats.clumps == arena->memstats.clumps)
+ return 0;
+
+ memset(&as, 0, sizeof as);
+ as.arena = arena;
+ as.stats = arena->diskstats;
- flush = 0;
- cis = MKN(ClumpInfo, ClumpChunks);
- addrs = MKN(u64int, ClumpChunks);
- s = MKN(int, ClumpChunks);
ok = 0;
- for(; clump < arena->memstats.clumps; clump += n){
- n = ClumpChunks;
- if(n > arena->memstats.clumps - clump)
- n = arena->memstats.clumps - clump;
- n = readclumpinfos(arena, clump, cis, n);
- if(n <= 0){
- fprint(2, "arena directory read failed\n");
+ a = a0 + arena->diskstats.used;
+ for(clump=arena->diskstats.clumps; clump < arena->memstats.clumps; clump++){
+ if(readclumpinfo(arena, clump, &ci) < 0){
+ fprint(2, "%s: clump %d: cannot read clumpinfo\n",
+ arena->name, clump);
ok = -1;
break;
}
- for(i = 0; i < n; i++){
- addrs[i] = a;
- a += cis[i].size + ClumpSize;
- s[i] = i;
- }
-
- sortclumpinfo(cis, s, n);
+ ia.type = ci.type;
+ ia.size = ci.uncsize;
+ ia.addr = a;
+ ia.blocks = (ClumpSize + ci.size + (1 << ABlockLog) - 1) >> ABlockLog;
+ a += ClumpSize + ci.size;
- for(i = 0; i < n; i++){
- ci = &cis[s[i]];
- ia.type = ci->type;
- ia.size = ci->uncsize;
- ia.addr = addrs[s[i]];
- ia.blocks = (ci->size + ClumpSize + (1 << ABlockLog) - 1) >> ABlockLog;
-
- if(!check)
- goto Add;
- if(loadientry(ix, ci->score, ci->type, &ie) < 0){
- trace(TraceProc, "syncarenaindex missing block %V.%d", ci->score, ci->type);
- missing++;
- if(0) fprint(2, "missing block type=%d score=%V\n", ci->type, ci->score);
- }else if(iaddrcmp(&ia, &ie.ia) != 0){
- trace(TraceProc, "syncarenaindex mismatched entry");
- fprint(2, "\nmismatched index entry and clump at %d\n", clump + i);
- fprint(2, "\tclump: type=%d size=%d blocks=%d addr=%lld\n", ia.type, ia.size, ia.blocks, ia.addr);
- fprint(2, "\tindex: type=%d size=%d block=%d addr=%lld\n", ie.ia.type, ie.ia.size, ie.ia.blocks, ie.ia.addr);
- pack = readlump(ie.score, ie.ia.type, ie.ia.size, nil);
- packetfree(pack);
- if(pack != nil){
- fprint(2, "duplicated lump\n");
- continue;
- }
- wrong++;
- }else
- continue;
- Add:
- if(!fix){
- ok = -1;
- continue;
- }
- flush = 1;
- trace(TraceProc, "syncarenaindex insert %V", ci->score);
- insertscore(ci->score, &ia, IEDirty);
- }
-
- if(0 && clump / 1000 != (clump + n) / 1000)
- fprint(2, ".");
- }
- free(cis);
- free(addrs);
- free(s);
- if(flush){
- flushdcache();
- *pflush = 1;
+ as.stats.used += ClumpSize + ci.size;
+ as.stats.uncsize += ia.size;
+ as.stats.clumps++;
+ if(ci.uncsize > ci.size)
+ as.stats.cclumps++;
+ as.aa = a;
+ insertscore(ci.score, &ia, IEDirty, &as);
}
+ flushdcache();
return ok;
}
int
-syncindex(Index *ix, int fix, int mustflush, int check)
+syncindex(Index *ix)
{
Arena *arena;
- AState as;
- u64int a;
- int i, e, e1, ok, ok1, flush;
+ int i, e, e1, ok;
ok = 0;
- flush = 0;
for(i = 0; i < ix->narenas; i++){
trace(TraceProc, "syncindex start %d", i);
arena = ix->arenas[i];
- /*
- * Syncarena will scan through the arena looking for blocks
- * that have been forgotten. It will update arena->memstats.used,
- * so save the currenct copy as the place to start the
- * syncarenaindex scan.
- */
- a = arena->memstats.used;
- e = syncarena(arena, ix->amap[i].start, TWID32, fix, fix);
+ e = syncarena(arena, TWID32, 1, 1);
e1 = e;
- if(fix)
- e1 &= ~(SyncHeader|SyncCIZero|SyncCIErr);
- if(e1 == SyncHeader)
+ e1 &= ~(SyncHeader|SyncCIZero|SyncCIErr);
+ if(e & SyncHeader)
fprint(2, "arena %s: header is out-of-date\n", arena->name);
- if(e1)
+ if(e1){
+ fprint(2, "arena %s: %x\n", arena->name, e1);
ok = -1;
- else{
- /*
- * use diskstats not memstats here, because diskstats
- * is what has been indexed; memstats is what has
- * made it to disk (confusing names).
- */
- ok1 = syncarenaindex(ix, arena,
- arena->diskstats.clumps,
- ix->amap[i].start + arena->diskstats.used,
- fix, &flush, check);
- if(ok1 < 0)
- fprint(2, "syncarenaindex: %r\n");
- if(fix && ok1==0 && (e & SyncHeader) && wbarena(arena) < 0)
- fprint(2, "arena=%s header write failed: %r\n", arena->name);
- ok |= ok1;
+ continue;
+ }
+ flushdcache();
+
+ if(arena->memstats.clumps == arena->diskstats.clumps)
+ continue;
+
+ fprint(2, "%T %s: indexing %d clumps...\n",
+ arena->name,
+ arena->memstats.clumps - arena->diskstats.clumps);
- as.arena = arena;
- as.aa = ix->amap[i].start + arena->memstats.used;
- as.stats = arena->memstats;
- setdcachestate(&as);
+ if(syncarenaindex(arena, ix->amap[i].start) < 0){
+ fprint(2, "arena %s: syncarenaindex: %r\n", arena->name);
+ ok = -1;
+ continue;
+ }
+ if(wbarena(arena) < 0){
+ fprint(2, "arena %s: wbarena: %r\n", arena->name);
+ ok = -1;
+ continue;
}
- }
- if(missing || wrong)
- fprint(2, "syncindex: %d missing entries, %d wrong entries (flush=%d)\n", missing, wrong, flush);
- if(fix && wbindex(ix) < 0){
- fprint(2, "can't write back index header for %s: %r\n", ix->name);
- return -1;
- }
- if(fix && flush){
flushdcache();
- if(mustflush){
- flushicache();
- flushdcache();
- }else
- kickicache();
+ delaykickicache();
}
return ok;
}