syncarena.c 5.1 KB

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