extentlist.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. #include "logfsos.h"
  2. #include "logfs.h"
  3. #include "local.h"
  4. typedef struct ExtentNode ExtentNode;
  5. struct ExtentNode {
  6. Extent e;
  7. ExtentNode *next;
  8. };
  9. struct ExtentList {
  10. ExtentNode *head;
  11. };
  12. char *
  13. logfsextentlistnew(ExtentList **ep)
  14. {
  15. ExtentList *l;
  16. l = logfsrealloc(nil, sizeof(*l));
  17. if(l == nil)
  18. return Enomem;
  19. *ep = l;
  20. return nil;
  21. }
  22. void
  23. logfsextentlistreset(ExtentList *l)
  24. {
  25. ExtentNode *n;
  26. n = l->head;
  27. while(n) {
  28. ExtentNode *next;
  29. next = n->next;
  30. logfsfreemem(n);
  31. n = next;
  32. }
  33. l->head = nil;
  34. }
  35. void
  36. logfsextentlistfree(ExtentList **lp)
  37. {
  38. ExtentList *l;
  39. if(lp == nil || (l = *lp) == nil)
  40. return;
  41. logfsextentlistreset(l);
  42. logfsfreemem(l);
  43. *lp = nil;
  44. }
  45. char *
  46. logfsextentlistinsert(ExtentList *l, Extent *add, Extent **new)
  47. {
  48. ExtentNode *old, *prev;
  49. ExtentNode *saved = nil;
  50. if(l == nil)
  51. return "nil extentlist";
  52. /* initially a's extents are non-empty, disjoint and sorted */
  53. old = l->head;
  54. prev = nil;
  55. while(old) {
  56. ExtentNode *next = old->next;
  57. if(add->max <= old->e.min)
  58. break;
  59. if(old->e.min < add->max && add->min < old->e.max) { /* they intersect */
  60. if(add->min <= old->e.min) {
  61. /* add overlaps front of old */
  62. if(add->max < old->e.max) {
  63. int trimmed;
  64. /* but doesn't overlap end */
  65. /* retain tail of old */
  66. if(saved == nil){
  67. saved = logfsrealloc(nil, sizeof(*saved));
  68. if(saved == nil)
  69. return Enomem;
  70. }
  71. trimmed = add->max - old->e.min;
  72. old->e.min += trimmed;
  73. old->e.flashaddr += trimmed;
  74. /* can't touch any further extents, so... */
  75. break;
  76. }
  77. /* add.min ≤ old.min < old.max ≤ add.max ⇒ add completely covers old */
  78. /* delete old */
  79. if(prev)
  80. prev->next = next;
  81. else
  82. l->head = next;
  83. /* stash the deleted extent, so we can reuse it */
  84. if(saved == nil)
  85. saved = old;
  86. else
  87. logfsfreemem(old);
  88. old = next;
  89. continue;
  90. }
  91. else {
  92. /* add.min > old.min, so overlaps end of old or splits it */
  93. if(add->max < old->e.max) { /* add inside old, splitting it */
  94. ExtentNode *frag;
  95. /*
  96. * will need at most two add extents, so ensure
  97. * enough store exists before changing data structures
  98. */
  99. if(saved == nil)
  100. saved = logfsrealloc(nil, sizeof(*saved));
  101. frag = logfsrealloc(nil, sizeof(*frag));
  102. if(saved == nil || frag == nil)
  103. return Enomem;
  104. frag->next = next;
  105. old->next = frag;
  106. frag->e.min = add->max;
  107. frag->e.max = old->e.max;
  108. frag->e.flashaddr = old->e.flashaddr + (add->max - old->e.min);
  109. old->e.max = add->min;
  110. prev = old;
  111. break;
  112. }
  113. else {
  114. /*
  115. * will need at most one add extent, so create one
  116. * now before changing data structures
  117. */
  118. if(saved == nil){
  119. saved = logfsrealloc(nil, sizeof(*saved));
  120. if(saved == nil)
  121. return Enomem;
  122. }
  123. old->e.max = add->min; /* retain start of old */
  124. }
  125. /* old.max <= add.max ⇒ add covers tail of old */
  126. }
  127. }
  128. prev = old;
  129. old = next;
  130. }
  131. /*
  132. * if here, and saved == nil, then there was no overlap
  133. */
  134. if(saved == nil){
  135. saved = logfsrealloc(nil, sizeof(*saved));
  136. if(saved == nil)
  137. return Enomem;
  138. }
  139. saved->e = *add;
  140. if(prev) {
  141. saved->next = prev->next;
  142. prev->next = saved;
  143. }
  144. else {
  145. saved->next = l->head;
  146. l->head = saved;
  147. }
  148. if(new)
  149. *new = &saved->e;
  150. return nil;
  151. }
  152. Extent *
  153. logfsextentlistmatch(ExtentList *l, Extent *e)
  154. {
  155. ExtentNode *m;
  156. u32int flashmax;
  157. if(l == nil)
  158. return nil;
  159. flashmax = e->flashaddr + (e->max - e->min);
  160. for(m = l->head; m; m = m->next) {
  161. u32int l = m->e.max - m->e.min;
  162. if(e->min < m->e.max && m->e.min < e->max /* they intersect */
  163. && m->e.flashaddr < flashmax && e->flashaddr < m->e.flashaddr + l) /* the store intersects */
  164. return &(m->e);
  165. }
  166. return nil;
  167. }
  168. int
  169. logfsextentlistmatchall(ExtentList *l, int (*func)(void *magic, Extent *), void *magic, Extent *e)
  170. {
  171. ExtentNode *m;
  172. u32int flashmax;
  173. if(l == nil)
  174. return 1;
  175. flashmax = e->flashaddr + (e->max - e->min);
  176. for(m = l->head; m; m = m->next) {
  177. u32int l;
  178. if(m->e.min >= e->max)
  179. return 1;
  180. l = m->e.max - m->e.min;
  181. if(e->min < m->e.max /* they intersect */
  182. && m->e.flashaddr < flashmax && e->flashaddr < m->e.flashaddr + l) {
  183. /* the store intersects */
  184. int rv = (*func)(magic, &(m->e));
  185. if(rv <= 0)
  186. return rv;
  187. }
  188. }
  189. return 1;
  190. }
  191. int
  192. logfsextentlistwalk(ExtentList *l, int (*func)(void *magic, Extent *, int hole), void *magic)
  193. {
  194. ExtentNode *n;
  195. u32int last = 0;
  196. if(l == nil)
  197. return 1;
  198. for(n = l->head; n; n = n->next) {
  199. int rv;
  200. if(last < n->e.min) {
  201. Extent hole;
  202. hole.min = last;
  203. hole.max = n->e.min;
  204. hole.flashaddr = ~0;
  205. rv = (*func)(magic, &hole, 1);
  206. if(rv <= 0)
  207. return rv;
  208. }
  209. rv = (*func)(magic, &n->e, 0);
  210. if(rv <= 0)
  211. return rv;
  212. last = n->e.max;
  213. }
  214. return 1;
  215. }
  216. int
  217. logfsextentlistwalkrange(ExtentList *l, int (*func)(void *magic, u32int baseoffset, u32int limitoffset, Extent *, u32int extentoffset), void *magic, u32int base, u32int limit)
  218. {
  219. ExtentNode *n;
  220. u32int last = 0;
  221. if(l == nil)
  222. return 1;
  223. for(n = l->head; n; n = n->next) {
  224. Extent hole;
  225. Extent *e;
  226. if(last < n->e.min) {
  227. hole.min = last;
  228. hole.max = n->e.min;
  229. e = &hole;
  230. }
  231. else {
  232. again:
  233. e = &n->e;
  234. }
  235. if(e->min >= limit)
  236. return 1;
  237. //print("walkrange %ud .. %ud\n", e->min, e->max);
  238. if(e->max > base) {
  239. ulong rangebase, rangelimit, extentoffset;
  240. int rv;
  241. rangebase = e->min;
  242. if(rangebase < base) {
  243. extentoffset = base - rangebase;
  244. rangebase += extentoffset;
  245. }
  246. else
  247. extentoffset = 0;
  248. rangelimit = e->max;
  249. if(rangelimit > limit)
  250. rangelimit = limit;
  251. rv = (*func)(magic, rangebase - base, rangelimit - base, e == &hole ? nil : e, extentoffset);
  252. if(rv <= 0)
  253. return rv;
  254. }
  255. last = e->max;
  256. if(e == &hole)
  257. goto again;
  258. }
  259. return 1;
  260. }