syncarena.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #include "stdinc.h"
  2. #include "dat.h"
  3. #include "fns.h"
  4. static int writeclumphead(Arena *arena, u64int aa, Clump *cl);
  5. static int writeclumpmagic(Arena *arena, u64int aa, u32int magic);
  6. int
  7. clumpinfocmp(ClumpInfo *c, ClumpInfo *d)
  8. {
  9. return c->type != d->type
  10. || c->size != d->size
  11. || c->uncsize != d->uncsize
  12. || scorecmp(c->score, d->score)!=0;
  13. }
  14. /*
  15. * synchronize the clump info directory with
  16. * with the clumps actually stored in the arena.
  17. * the directory should be at least as up to date
  18. * as the arena's trailer.
  19. *
  20. * checks/updates at most n clumps.
  21. *
  22. * returns 0 if ok, flags if error occurred
  23. */
  24. int
  25. syncarena(Arena *arena, u32int n, int zok, int fix)
  26. {
  27. ZBlock *lump;
  28. Clump cl;
  29. ClumpInfo ci;
  30. static ClumpInfo zci = { .type = -1 };
  31. u8int score[VtScoreSize];
  32. u64int uncsize, used, aa;
  33. u32int clump, clumps, cclumps, magic;
  34. int err, flush, broken;
  35. used = arena->memstats.used;
  36. clumps = arena->memstats.clumps;
  37. cclumps = arena->memstats.cclumps;
  38. uncsize = arena->memstats.uncsize;
  39. trace(TraceProc, "syncarena start");
  40. flush = 0;
  41. err = 0;
  42. for(; n; n--){
  43. aa = arena->memstats.used;
  44. clump = arena->memstats.clumps;
  45. magic = clumpmagic(arena, aa);
  46. if(magic == ClumpFreeMagic)
  47. break;
  48. if(magic != arena->clumpmagic){
  49. fprint(2, "%s: illegal clump magic number=%#8.8ux at clump=%d\n", arena->name, magic, clump);
  50. /* err |= SyncDataErr; */
  51. if(fix && writeclumpmagic(arena, aa, ClumpFreeMagic) < 0){
  52. fprint(2, "%s: can't write corrected clump free magic: %r", arena->name);
  53. err |= SyncFixErr;
  54. }
  55. break;
  56. }
  57. broken = 0;
  58. lump = loadclump(arena, aa, 0, &cl, score, 0);
  59. if(lump == nil){
  60. fprint(2, "%s: clump=%d failed to read correctly: %r\n", arena->name, clump);
  61. break;
  62. }else if(cl.info.type != VtCorruptType){
  63. scoremem(score, lump->data, cl.info.uncsize);
  64. if(scorecmp(cl.info.score, score) != 0){
  65. /* ignore partially written block */
  66. if(cl.encoding == ClumpENone)
  67. break;
  68. fprint(2, "%s: clump=%d has mismatched score\n", arena->name, clump);
  69. err |= SyncDataErr;
  70. broken = 1;
  71. }else if(vttypevalid(cl.info.type) < 0){
  72. fprint(2, "%s: clump=%d has invalid type %d", arena->name, clump, cl.info.type);
  73. err |= SyncDataErr;
  74. broken = 1;
  75. }
  76. if(broken && fix){
  77. cl.info.type = VtCorruptType;
  78. if(writeclumphead(arena, aa, &cl) < 0){
  79. fprint(2, "%s: can't write corrected clump header: %r", arena->name);
  80. err |= SyncFixErr;
  81. }
  82. }
  83. }
  84. freezblock(lump);
  85. arena->memstats.used += ClumpSize + cl.info.size;
  86. arena->memstats.clumps++;
  87. if(!broken && readclumpinfo(arena, clump, &ci)<0){
  88. fprint(2, "%s: arena directory read failed\n", arena->name);
  89. broken = 1;
  90. }else if(!broken && clumpinfocmp(&ci, &cl.info)!=0){
  91. if(clumpinfocmp(&ci, &zci) == 0){
  92. err |= SyncCIZero;
  93. if(!zok)
  94. fprint(2, "%s: unwritten clump info for clump=%d\n", arena->name, clump);
  95. }else{
  96. err |= SyncCIErr;
  97. fprint(2, "%s: bad clump info for clump=%d\n", arena->name, clump);
  98. fprint(2, "\texpected score=%V type=%d size=%d uncsize=%d\n",
  99. cl.info.score, cl.info.type, cl.info.size, cl.info.uncsize);
  100. fprint(2, "\tfound score=%V type=%d size=%d uncsize=%d\n",
  101. ci.score, ci.type, ci.size, ci.uncsize);
  102. }
  103. broken = 1;
  104. }
  105. if(broken && fix){
  106. flush = 1;
  107. ci = cl.info;
  108. if(writeclumpinfo(arena, clump, &ci) < 0){
  109. fprint(2, "%s: can't write correct clump directory: %r\n", arena->name);
  110. err |= SyncFixErr;
  111. }
  112. }
  113. trace(TraceProc, "syncarena unindexed clump %V %d", cl.info.score, arena->memstats.clumps);
  114. arena->memstats.uncsize += cl.info.uncsize;
  115. if(cl.info.size < cl.info.uncsize)
  116. arena->memstats.cclumps++;
  117. }
  118. if(flush){
  119. trace(TraceProc, "syncarena flush");
  120. arena->wtime = now();
  121. if(arena->ctime == 0 && arena->memstats.clumps)
  122. arena->ctime = arena->wtime;
  123. flushdcache();
  124. }
  125. if(used != arena->memstats.used
  126. || clumps != arena->memstats.clumps
  127. || cclumps != arena->memstats.cclumps
  128. || uncsize != arena->memstats.uncsize){
  129. err |= SyncHeader;
  130. fprint(2, "arena %s: fix=%d flush=%d %lld->%lld %ud->%ud %ud->%ud %lld->%lld\n",
  131. arena->name,
  132. fix,
  133. flush,
  134. used, arena->memstats.used,
  135. clumps, arena->memstats.clumps,
  136. cclumps, arena->memstats.cclumps,
  137. uncsize, arena->memstats.uncsize);
  138. }
  139. return err;
  140. }
  141. static int
  142. writeclumphead(Arena *arena, u64int aa, Clump *cl)
  143. {
  144. ZBlock *zb;
  145. int bad;
  146. zb = alloczblock(ClumpSize, 0, arena->blocksize);
  147. if(zb == nil)
  148. return -1;
  149. bad = packclump(cl, zb->data, arena->clumpmagic)<0
  150. || writearena(arena, aa, zb->data, ClumpSize) != ClumpSize;
  151. freezblock(zb);
  152. return bad ? -1 : 0;
  153. }
  154. static int
  155. writeclumpmagic(Arena *arena, u64int aa, u32int magic)
  156. {
  157. u8int buf[U32Size];
  158. packmagic(magic, buf);
  159. return writearena(arena, aa, buf, U32Size) == U32Size;
  160. }