backport to buster
[hcoop/debian/openafs.git] / src / ptserver / map.c
CommitLineData
805e021f
CE
1/*
2 * bit map routines (in-core).
3 */
4/*
5 * Copyright (c) 1995, 1996, 2007 Marcus D. Watts All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the developer may not be used to endorse or promote
16 * products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
21 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 * MARCUS D. WATTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
28 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <afsconfig.h>
32#include <afs/param.h>
33
34#include <roken.h>
35
36#ifdef SUPERGROUPS
37#include "map.h"
38
39#undef PRINT_MAP_ERROR
40/* #define MAP_DEBUG */
41/* #define NEED_READ_WRITE */
42
43#define LSHIFT 5
44#define MSHIFT 8 /* XXX make this 8 in the production version... */
45#define MDATA (1<<MSHIFT)
46struct bitmap {
47 struct bitmap *m_next;
48 int m_page;
49 int m_data[MDATA];
50};
51
52#define MAP(p) ((struct bitmap*)((intptr_t)(p)&~1))
53#define NEGMAP(p) (((intptr_t)(p))&1)
54#define POSMAP(p) (!NEGMAP(p))
55#define NOT_MAP(mp) ((struct map *) (((intptr_t)(mp)) ^ 1))
56
57#define NUMBERTOBIT(n) ((n) & ((1<<LSHIFT)-1))
58#define NUMBERTOINDEX(n) ((n>>LSHIFT) & ((1<<MSHIFT)-1))
59#define NUMBERTOPAGE(n) ((n>>(LSHIFT+MSHIFT)))
60#define TONUMBER(p,x,b) ((b) + ((x)<<LSHIFT) + ((p)<<((LSHIFT+MSHIFT))))
61
62#define Mflag (debug_mask & (1L<<('Y'-'@')))
63#define Aflag (debug_mask & (1L<<('Z'-'@')))
64extern int debug_mask;
65
66int
67in_map(struct map *parm, int node)
68{
69 struct bitmap *map;
70 int bit;
71 int x, page;
72 int result;
73
74#ifdef MAP_DEBUG
75 if (Aflag) {
76 printf("in_map: is %d in [", node);
77 print_map(parm);
78 printf(" ]");
79 }
80#endif
81 bit = NUMBERTOBIT(node);
82 x = NUMBERTOINDEX(node);
83 page = NUMBERTOPAGE(node);
84#ifdef MAP_DEBUG
85 if (Aflag)
86 if (TONUMBER(page, x, bit) != node) {
87 printf
88 ("bxp mixup: node=%d -> p=%d x=%d b=%d -> %d, %d, %d = %d\n",
89 node, page, x, bit, TONUMBER(page, 0, 0), TONUMBER(0, x, 0),
90 TONUMBER(0, 0, bit), TONUMBER(page, x, bit));
91 }
92#endif
93 bit = 1L << bit;;
94
95 for (map = MAP(parm); map; map = map->m_next)
96 if (map->m_page == page)
97 return NEGMAP(parm) ^ (!!(map->m_data[x] & bit));
98 result = !POSMAP(parm);
99#ifdef MAP_DEBUG
100 if (Aflag)
101 printf(" -> %s\n", result ? "yes" : "no");
102#endif
103 return result;
104}
105
106void
107free_map(struct map *parm)
108{
109 struct bitmap *map, *next;
110#ifdef MAP_DEBUG
111 if (Aflag) {
112 printf("Freeing map");
113 print_map(parm);
114 printf("\n");
115 }
116#endif
117 map = MAP(parm);
118 while (map) {
119 next = map->m_next;
120 free(map);
121 map = next;
122 }
123}
124
125struct map *
126add_map(struct map *parm, int node)
127{
128 struct bitmap *map;
129 int bit;
130 int x, page;
131
132#ifdef MAP_DEBUG
133 if (Aflag) {
134 printf("add_map: adding %d to [", node);
135 print_map(parm);
136 printf(" ] ");
137 }
138#endif
139 bit = NUMBERTOBIT(node);
140 x = NUMBERTOINDEX(node);
141 page = NUMBERTOPAGE(node);
142
143 bit = 1L << bit;;
144
145 for (map = MAP(parm); map; map = map->m_next)
146 if (map->m_page == page)
147 break;
148 if (!map) {
149 map = malloc(sizeof *map);
150 if (!map) {
151#ifdef PRINT_MAP_ERROR
152 printf("No memory!\n");
153#endif
154 free_map((struct map *)map);
155 return 0;
156 }
157 map->m_page = page;
158 memset( map->m_data, 0, sizeof map->m_data);
159 if (NEGMAP(parm)) {
160 int i;
161 for (i = 0; i < MDATA; ++i)
162 map->m_data[i] = ~0;
163 }
164 map->m_next = MAP(parm);
165 if (POSMAP(parm))
166 parm = (struct map *)map;
167 else
168 parm = NOT_MAP(map);
169 }
170 if (POSMAP(parm))
171 map->m_data[x] |= bit;
172 else
173 map->m_data[x] &= ~bit;
174#ifdef MAP_DEBUG
175 if (Aflag) {
176 printf(" ->");
177 print_map(parm);
178 printf("\n");
179 }
180#endif
181 return (struct map *)parm;
182}
183
184struct bitmap *
185simplify_bitmap(struct bitmap *map)
186{
187 struct bitmap **mpp, *mp2;
188 int i;
189 for (mpp = &map; (mp2 = *mpp);) {
190 for (i = 0; i < MDATA; ++i)
191 if (mp2->m_data[i])
192 break;
193 if (i == MDATA) {
194#ifdef PRINT_MAP_ERROR
195 printf("simplify_bitmap: failed to eliminate zero page %d\n",
196 mp2->m_page);
197#endif
198 *mpp = mp2->m_next;
199 free(mp2);
200 } else
201 mpp = &mp2->m_next;
202 }
203 return map;
204}
205
206struct bitmap *
207or_bitmap(struct bitmap *left, struct bitmap *right)
208{
209 struct bitmap **rightmp, *lmap, *rmap;
210 int i;
211 for (lmap = left; lmap; lmap = lmap->m_next) {
212 for (rightmp = &right; (rmap = *rightmp); rightmp = &rmap->m_next)
213 if (rmap->m_page == lmap->m_page) {
214 for (i = 0; i < MDATA; ++i)
215 lmap->m_data[i] |= rmap->m_data[i];
216 *rightmp = rmap->m_next;
217 free(rmap);
218 break;
219 }
220 }
221 for (rightmp = &left; *rightmp; rightmp = &(*rightmp)->m_next)
222 ;
223 *rightmp = right;
224 return left;
225}
226
227struct bitmap *
228and_bitmap(struct bitmap *left, struct bitmap *right)
229{
230 struct bitmap **rightmp, *lmap, *rmap, **leftmp;
231 int i;
232 int sig;
233 for (leftmp = &left; (lmap = *leftmp);) {
234 sig = 0;
235 for (rightmp = &right; (rmap = *rightmp); rightmp = &rmap->m_next)
236 if (rmap->m_page == lmap->m_page) {
237 for (i = 0; i < MDATA; ++i)
238 sig |= (lmap->m_data[i] &= rmap->m_data[i]);
239 *rightmp = rmap->m_next;
240 free(rmap);
241 break;
242 }
243 if (rmap && sig) {
244 leftmp = &lmap->m_next;
245 } else {
246 *leftmp = lmap->m_next;
247 free(lmap);
248 }
249 }
250 free_map((struct map *)right);
251 return simplify_bitmap(left);
252}
253
254/* bit set in left, but not in right */
255struct bitmap *
256bic_bitmap(struct bitmap *left, struct bitmap *right)
257{
258 struct bitmap **rightmp, *lmap, *rmap, **leftmp;
259 int i;
260 int sig;
261#ifdef MAP_DEBUG
262 if (Mflag) {
263 printf("bic_bitmap: left=%#lx right=%#lx\n", (long)left, (long)right);
264 }
265#endif
266 for (leftmp = &left; (lmap = *leftmp);) {
267 sig = 0;
268 for (rightmp = &right; (rmap = *rightmp); rightmp = &rmap->m_next)
269 if (rmap->m_page == lmap->m_page) {
270 for (i = 0; i < MDATA; ++i)
271 sig |= (lmap->m_data[i] &= ~rmap->m_data[i]);
272 *rightmp = rmap->m_next;
273 free(rmap);
274 break;
275 }
276 if (!rmap || sig) {
277 leftmp = &lmap->m_next;
278 } else {
279 *leftmp = lmap->m_next;
280 free(lmap);
281 }
282 }
283 free_map((struct map *)right);
284 left = simplify_bitmap(left);
285#ifdef MAP_DEBUG
286 if (Mflag) {
287 printf("bic_bitmap: result=%#lx\n", (long) left);
288 }
289#endif
290 return left;
291}
292
293struct map *
294and_map(struct map *mp1, struct map *mp2)
295{
296#ifdef MAP_DEBUG
297 if (Mflag) {
298 printf("Anding maps");
299 print_map(mp1);
300 printf(" and");
301 print_map(mp2);
302 }
303#endif
304 if (POSMAP(mp1))
305 if (POSMAP(mp2))
306 mp1 = (struct map *)and_bitmap((struct bitmap *) mp1,
307 (struct bitmap *) mp2);
308 else
309 mp1 = (struct map *)bic_bitmap((struct bitmap *) mp1, MAP(mp2));
310 else if (POSMAP(mp2))
311 mp1 = (struct map *)bic_bitmap((struct bitmap *) mp2, MAP(mp1));
312 else
313 mp1 = NOT_MAP(or_bitmap(MAP(mp1), MAP(mp2)));
314#ifdef MAP_DEBUG
315 if (Mflag) {
316 printf(" ->");
317 print_map(mp1);
318 printf("\n");
319 }
320#endif
321 return mp1;
322}
323
324struct map *
325or_map(struct map *mp1, struct map *mp2)
326{
327#ifdef MAP_DEBUG
328 if (Mflag) {
329 printf("Oring maps");
330 print_map(mp1);
331 printf(" and");
332 print_map(mp2);
333 }
334#endif
335 if (POSMAP(mp1))
336 if (POSMAP(mp2))
337 mp1 = (struct map *)or_bitmap((struct bitmap *) mp1,
338 (struct bitmap *) mp2);
339 else
340 mp1 = NOT_MAP(bic_bitmap(MAP(mp2), (struct bitmap *) mp1));
341 else if (POSMAP(mp2))
342 mp1 = NOT_MAP(bic_bitmap(MAP(mp1), (struct bitmap *) mp2));
343 else
344 mp1 = NOT_MAP(and_bitmap(MAP(mp1), MAP(mp2)));
345#ifdef MAP_DEBUG
346 if (Mflag) {
347 printf(" ->");
348 print_map(mp1);
349 printf("\n");
350 }
351#endif
352 return mp1;
353}
354
355struct map *
356not_map(struct map *map)
357{
358#ifdef MAP_DEBUG
359 if (Mflag) {
360 printf("Notting map");
361 print_map(map);
362 printf("\n");
363 }
364#endif
365 return NOT_MAP(map);
366}
367
368struct map *
369copy_map(struct map *parm)
370{
371 struct bitmap *result, **mpp, *map;
372#ifdef MAP_DEBUG
373 if (Mflag) {
374 printf("copymap:");
375 print_map(parm);
376 printf("\n");
377 }
378#endif
379 map = MAP(parm);
380 for (mpp = &result; (*mpp = 0), map; map = map->m_next) {
381 *mpp = malloc(sizeof **mpp);
382 if (!*mpp) {
383#ifdef MAP_DEBUG
384 if (Mflag)
385 printf("copy_map: out of memory\n");
386#endif
387 free_map((struct map *)result);
388 result = 0;
389 break;
390 }
391 **mpp = *map;
392 mpp = &(*mpp)->m_next;
393 }
394 if (NEGMAP(parm))
395 return NOT_MAP(result);
396 else
397 return (struct map *)result;
398}
399
400int
401count_map(struct map *parm)
402{
403 int nf;
404 struct bitmap *map;
405 int i, j;
406
407 nf = 0;
408 for (map = MAP(parm); map; map = map->m_next) {
409 for (i = 0; i < MDATA; ++i) {
410 if (!map->m_data[i])
411 ;
412 else if (!~map->m_data[i])
413 nf += (1 << LSHIFT);
414 else
415 for (j = 0; j < (1L << LSHIFT); ++j)
416 if (map->m_data[i] & (1L << j))
417 ++nf;
418 }
419 }
420 if (NEGMAP(parm))
421 nf = ~nf; /* note 1's complement */
422#ifdef MAP_DEBUG
423 if (Mflag) {
424 printf("countmap:");
425 print_map(parm);
426 printf(" -> %d\n", nf);
427 }
428#endif
429 return nf;
430}
431
432int
433next_map(struct map *parm, int node)
434{
435 struct bitmap *map, *lowest;
436 int bit, mask;
437 int x, page;
438 int best;
439 int i;
440 int bn;
441
442#ifdef MAP_DEBUG
443 if (Aflag) {
444 printf("next_map: selecting next after %d from", node);
445 print_map(parm);
446 }
447#endif
448 if (NEGMAP(parm)) {
449#ifdef MAP_DEBUG
450 if (Aflag)
451 printf("next_map failed; negative map\n");
452#endif
453 return -1;
454 }
455
456 ++node;
457 bit = NUMBERTOBIT(node);
458 x = NUMBERTOINDEX(node);
459 page = NUMBERTOPAGE(node);
460 bit = 1L << bit;
461 best = -1;
462 lowest = 0;
463 for (map = MAP(parm); map; map = map->m_next)
464 if (map->m_page >= page && (!lowest || lowest->m_page > map->m_page)) {
465 i = 0;
466 mask = ~0;
467 if (page == map->m_page)
468 i = x, mask = -bit;
469 for (; i < MDATA; ++i, mask = ~0)
470 if (map->m_data[i] & mask)
471 break;
472 if (i < MDATA) {
473 for (bn = 0; bn < (1 << LSHIFT); ++bn)
474 if (map->m_data[i] & mask & (1L << bn)) {
475 break;
476 }
477#ifdef MAP_DEBUG
478 if (Aflag) {
479 if (bn == (1 << LSHIFT)) {
480 printf
481 ("next_map: botch; pageno %d index %d data %#x mask %#x x,bit %d,%#x\n",
482 map->m_page, i, map->m_data[i], mask, x, bit);
483 continue;
484 }
485 }
486#endif
487 best = bn + ((i + ((map->m_page) << MSHIFT)
488 ) << LSHIFT);
489 lowest = map;
490 }
491 }
492#ifdef MAP_DEBUG
493 if (Aflag) {
494 printf(" -> %d\n", best);
495 if (best >= 0 && !in_map(parm, best)) {
496 printf("next_map: botch; %d not in map\n", best);
497 return -1;
498 }
499 }
500#endif
501 return best;
502}
503
504int
505first_map(struct map *parm)
506{
507 return next_map(parm, -9999);
508}
509
510int
511prev_map(struct map *parm, int node)
512{
513 struct bitmap *map, *lowest;
514 int bit, mask;
515 int x, page;
516 int best;
517 int i;
518 int bn;
519
520#ifdef MAP_DEBUG
521 if (Aflag) {
522 printf("prev_map: selecting previous before %d from", node);
523 print_map(parm);
524 }
525#endif
526 if (NEGMAP(parm)) {
527#ifdef MAP_DEBUG
528 if (Aflag)
529 printf("prev_map failed; negative map\n");
530#endif
531 return -1;
532 }
533
534 if (node < 0)
535 node = ((unsigned int)~0) >> 1;
536
537 --node;
538 bit = NUMBERTOBIT(node);
539 x = NUMBERTOINDEX(node);
540 page = NUMBERTOPAGE(node);
541 bit = 1L << bit;
542 best = -1;
543 lowest = 0;
544 for (map = MAP(parm); map; map = map->m_next)
545 if (map->m_page <= page && (!lowest || lowest->m_page < map->m_page)) {
546 i = MDATA - 1;
547 mask = ~0;
548 if (page == map->m_page)
549 i = x, mask = (bit << 1) - 1;
550 for (; i >= 0; --i, mask = ~0)
551 if (map->m_data[i] & mask)
552 break;
553 if (i >= 0) {
554 for (bn = (1 << LSHIFT) - 1; bn >= 0; --bn)
555 if (map->m_data[i] & mask & (1L << bn)) {
556 break;
557 }
558#ifdef MAP_DEBUG
559 if (Aflag) {
560 if (bn < 0) {
561 printf
562 ("prev_map: botch; pageno %d index %d data %#x mask %#x x,bit %d,%#x\n",
563 map->m_page, i, map->m_data[i], mask, x, bit);
564 continue;
565 }
566 }
567#endif
568 best = bn + ((i + ((map->m_page) << MSHIFT)
569 ) << LSHIFT);
570 lowest = map;
571 }
572 }
573#ifdef MAP_DEBUG
574 if (Aflag) {
575 printf(" -> %d\n", best);
576 if (best >= 0 && !in_map(parm, best)) {
577 printf("prev_map: botch; %d not in map\n", best);
578 return -1;
579 }
580 }
581#endif
582 return best;
583}
584
585int
586last_map(struct map *parm)
587{
588 return prev_map(parm, 0x7fffffff);
589}
590
591struct map *
592negative_map(struct map *map)
593{
594 return (struct map *)NEGMAP(map);
595}
596
597struct map *
598bic_map(struct map *mp1, struct map *mp2)
599{
600#ifdef MAP_DEBUG
601 if (Mflag) {
602 printf("Bic maps");
603 print_map(mp1);
604 printf(" minus");
605 print_map(mp2);
606 }
607#endif
608 mp1 = and_map(mp1, NOT_MAP(mp2));
609#ifdef MAP_DEBUG
610 if (Mflag) {
611 printf(" ->");
612 print_map(mp1);
613 printf("\n");
614 }
615#endif
616 return mp1;
617}
618
619#ifdef PRINT_MAP_ERROR
620void
621print_map(struct map *parm)
622{
623 struct bitmap *map;
624 int i, j;
625 int bitno, firstbitno, lastbitno;
626 if (NEGMAP(parm)) {
627 printf(" NOT");
628 }
629 map = MAP(parm);
630 if (!map)
631 printf(" nil(%lx)", (long)parm);
632 else
633 printf(" %lx", (long)parm);
634 lastbitno = -100;
635 firstbitno = -100;
636 for (; map; map = map->m_next)
637 for (i = 0; i < MDATA; ++i)
638 if (map->m_data[i])
639 for (j = 0; j < (1 << LSHIFT); ++j) {
640 bitno =
641 j + (i << LSHIFT) +
642 ((map->m_page) << (LSHIFT + MSHIFT));
643 if (map->m_data[i] & (1 << j)) {
644 if (bitno == lastbitno + 1) {
645 ++lastbitno;
646 continue;
647 }
648 if (bitno != (lastbitno + 1)) {
649 if (firstbitno >= 0 && firstbitno != lastbitno)
650 printf("-%d", lastbitno);
651 firstbitno = -100;
652 }
653 printf(" %d", bitno);
654 firstbitno = lastbitno = bitno;
655 } else {
656 if (firstbitno >= 0 && firstbitno != lastbitno)
657 printf("-%d", lastbitno);
658 firstbitno = -100;
659 }
660 }
661 if (firstbitno >= 0 && firstbitno != lastbitno)
662 printf("-%d", lastbitno);
663}
664#endif
665
666#ifdef NEED_READ_WRITE
667struct map *
668read_map(int (*f) (void *), char *arg)
669{
670 struct bitmap *map, *result, **mp;
671 int page;
672 int bitno, lastno;
673 int data;
674
675/* count, then startbitno, then bits. */
676 lastno = ((*f) (arg));
677 if (lastno == -1)
678 return 0;
679 if (lastno & ((1 << LSHIFT) - 1)) {
680#ifdef PRINT_MAP_ERROR
681 printf("read_map: bad count\n");
682#endif
683 return 0;
684 }
685 bitno = ((*f) (arg));
686 if (bitno & ((1 << LSHIFT) - 1)) {
687#ifdef PRINT_MAP_ERROR
688 printf("read_map: bad start\n");
689#endif
690 return 0;
691 }
692 lastno += bitno;
693 map = result = 0;
694 for (; bitno < lastno; bitno += (1 << LSHIFT)) {
695 data = (*f) (arg);
696 if (!data)
697 continue;
698 page = NUMBERTOPAGE(bitno);
699 if (!map || map->m_page != page)
700 for (mp = &result; (map = *mp); mp = &map->m_next)
701 if (map->m_page == page)
702 break;
703 if (!map) {
704 map = malloc(sizeof *map);
705 if (!map) {
706#ifdef PRINT_MAP_ERROR
707 printf("No memory!\n");
708#endif
709 if (result)
710 free_map((struct map *)result);
711 return 0;
712 }
713 memset( map->m_data, 0, sizeof map->m_data);
714 map->m_page = page;
715 map->m_next = 0;
716 *mp = map;
717 }
718 map->m_data[NUMBERTOINDEX(bitno)] = data;
719 }
720 return (struct map *)result;
721}
722
723int
724write_map(struct map *parm, int (*f) (void *, int), char *arg)
725{
726 struct bitmap *map;
727 int page;
728 int bitno, lastno, thisno, prevno;
729 int i, j;
730
731 bitno = first_map(parm);
732 bitno &= ~((1 << LSHIFT) - 1);
733
734 lastno = last_map(parm);
735 lastno -= bitno;
736 lastno += ((1 << LSHIFT));
737 lastno &= ~((1 << LSHIFT) - 1);
738/* count, then startbitno, then bits. */
739 if ((*f) (arg, lastno) == -1)
740 return -1;
741 /* word: number of bits */
742 if ((*f) (arg, bitno) == -1)
743 return -1;
744 lastno += bitno;
745 prevno = bitno;
746 for (bitno = first_map(parm); bitno >= 0; bitno = next_map(parm, bitno)) {
747 page = NUMBERTOPAGE(bitno);
748 for (map = MAP(parm); map; map = map->m_next)
749 if (map->m_page == page)
750 break;
751 if (!map) {
752#ifdef PRINT_MAP_ERROR
753 printf("write_map: botch #1: can't find page %d\n", page);
754#endif
755 continue;
756 }
757 for (i = 0; i < MDATA; ++i) {
758 if (!map->m_data[i])
759 continue;
760 thisno = TONUMBER(page, i, 0);
761 for (j = thisno - prevno; j > 0; j -= (1 << LSHIFT))
762 if ((*f) (arg, 0) == -1)
763 return -1;
764 prevno = thisno;
765 for (;;) {
766 if ((*f) (arg, map->m_data[i]) == -1)
767 return -1;
768 prevno += (1 << LSHIFT);
769 ++i;
770 if (i >= MDATA || !map->m_data[i])
771 break;
772 }
773 --i;
774 }
775 bitno = TONUMBER(page, i, 0) - 1;
776 }
777#ifdef PRINT_MAP_ERROR
778 if (prevno != lastno)
779 printf("write_map: botch #2: bitno=%d prevno=%d lastno=%d\n", bitno,
780 prevno, lastno);
781#endif
782 return 0;
783}
784#endif
785
786#endif