1
2
3
4
5
6
7
8#include <linux/module.h>
9#include <linux/ctype.h>
10#include <linux/errno.h>
11#include <linux/bitmap.h>
12#include <linux/bitops.h>
13#include <asm/uaccess.h>
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41int __bitmap_empty(const unsigned long *bitmap, int bits)
42{
43 int k, lim = bits/BITS_PER_LONG;
44 for (k = 0; k < lim; ++k)
45 if (bitmap[k])
46 return 0;
47
48 if (bits % BITS_PER_LONG)
49 if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
50 return 0;
51
52 return 1;
53}
54EXPORT_SYMBOL(__bitmap_empty);
55
56int __bitmap_full(const unsigned long *bitmap, int bits)
57{
58 int k, lim = bits/BITS_PER_LONG;
59 for (k = 0; k < lim; ++k)
60 if (~bitmap[k])
61 return 0;
62
63 if (bits % BITS_PER_LONG)
64 if (~bitmap[k] & BITMAP_LAST_WORD_MASK(bits))
65 return 0;
66
67 return 1;
68}
69EXPORT_SYMBOL(__bitmap_full);
70
71int __bitmap_equal(const unsigned long *bitmap1,
72 const unsigned long *bitmap2, int bits)
73{
74 int k, lim = bits/BITS_PER_LONG;
75 for (k = 0; k < lim; ++k)
76 if (bitmap1[k] != bitmap2[k])
77 return 0;
78
79 if (bits % BITS_PER_LONG)
80 if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
81 return 0;
82
83 return 1;
84}
85EXPORT_SYMBOL(__bitmap_equal);
86
87void __bitmap_complement(unsigned long *dst, const unsigned long *src, int bits)
88{
89 int k, lim = bits/BITS_PER_LONG;
90 for (k = 0; k < lim; ++k)
91 dst[k] = ~src[k];
92
93 if (bits % BITS_PER_LONG)
94 dst[k] = ~src[k] & BITMAP_LAST_WORD_MASK(bits);
95}
96EXPORT_SYMBOL(__bitmap_complement);
97
98
99
100
101
102
103
104
105
106
107
108
109void __bitmap_shift_right(unsigned long *dst,
110 const unsigned long *src, int shift, int bits)
111{
112 int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
113 int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
114 unsigned long mask = (1UL << left) - 1;
115 for (k = 0; off + k < lim; ++k) {
116 unsigned long upper, lower;
117
118
119
120
121
122 if (!rem || off + k + 1 >= lim)
123 upper = 0;
124 else {
125 upper = src[off + k + 1];
126 if (off + k + 1 == lim - 1 && left)
127 upper &= mask;
128 }
129 lower = src[off + k];
130 if (left && off + k == lim - 1)
131 lower &= mask;
132 dst[k] = upper << (BITS_PER_LONG - rem) | lower >> rem;
133 if (left && k == lim - 1)
134 dst[k] &= mask;
135 }
136 if (off)
137 memset(&dst[lim - off], 0, off*sizeof(unsigned long));
138}
139EXPORT_SYMBOL(__bitmap_shift_right);
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154void __bitmap_shift_left(unsigned long *dst,
155 const unsigned long *src, int shift, int bits)
156{
157 int k, lim = BITS_TO_LONGS(bits), left = bits % BITS_PER_LONG;
158 int off = shift/BITS_PER_LONG, rem = shift % BITS_PER_LONG;
159 for (k = lim - off - 1; k >= 0; --k) {
160 unsigned long upper, lower;
161
162
163
164
165
166 if (rem && k > 0)
167 lower = src[k - 1];
168 else
169 lower = 0;
170 upper = src[k];
171 if (left && k == lim - 1)
172 upper &= (1UL << left) - 1;
173 dst[k + off] = lower >> (BITS_PER_LONG - rem) | upper << rem;
174 if (left && k + off == lim - 1)
175 dst[k + off] &= (1UL << left) - 1;
176 }
177 if (off)
178 memset(dst, 0, off*sizeof(unsigned long));
179}
180EXPORT_SYMBOL(__bitmap_shift_left);
181
182void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
183 const unsigned long *bitmap2, int bits)
184{
185 int k;
186 int nr = BITS_TO_LONGS(bits);
187
188 for (k = 0; k < nr; k++)
189 dst[k] = bitmap1[k] & bitmap2[k];
190}
191EXPORT_SYMBOL(__bitmap_and);
192
193void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
194 const unsigned long *bitmap2, int bits)
195{
196 int k;
197 int nr = BITS_TO_LONGS(bits);
198
199 for (k = 0; k < nr; k++)
200 dst[k] = bitmap1[k] | bitmap2[k];
201}
202EXPORT_SYMBOL(__bitmap_or);
203
204void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
205 const unsigned long *bitmap2, int bits)
206{
207 int k;
208 int nr = BITS_TO_LONGS(bits);
209
210 for (k = 0; k < nr; k++)
211 dst[k] = bitmap1[k] ^ bitmap2[k];
212}
213EXPORT_SYMBOL(__bitmap_xor);
214
215void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
216 const unsigned long *bitmap2, int bits)
217{
218 int k;
219 int nr = BITS_TO_LONGS(bits);
220
221 for (k = 0; k < nr; k++)
222 dst[k] = bitmap1[k] & ~bitmap2[k];
223}
224EXPORT_SYMBOL(__bitmap_andnot);
225
226int __bitmap_intersects(const unsigned long *bitmap1,
227 const unsigned long *bitmap2, int bits)
228{
229 int k, lim = bits/BITS_PER_LONG;
230 for (k = 0; k < lim; ++k)
231 if (bitmap1[k] & bitmap2[k])
232 return 1;
233
234 if (bits % BITS_PER_LONG)
235 if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
236 return 1;
237 return 0;
238}
239EXPORT_SYMBOL(__bitmap_intersects);
240
241int __bitmap_subset(const unsigned long *bitmap1,
242 const unsigned long *bitmap2, int bits)
243{
244 int k, lim = bits/BITS_PER_LONG;
245 for (k = 0; k < lim; ++k)
246 if (bitmap1[k] & ~bitmap2[k])
247 return 0;
248
249 if (bits % BITS_PER_LONG)
250 if ((bitmap1[k] & ~bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
251 return 0;
252 return 1;
253}
254EXPORT_SYMBOL(__bitmap_subset);
255
256int __bitmap_weight(const unsigned long *bitmap, int bits)
257{
258 int k, w = 0, lim = bits/BITS_PER_LONG;
259
260 for (k = 0; k < lim; k++)
261 w += hweight_long(bitmap[k]);
262
263 if (bits % BITS_PER_LONG)
264 w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
265
266 return w;
267}
268EXPORT_SYMBOL(__bitmap_weight);
269
270
271
272
273
274
275#define CHUNKSZ 32
276#define nbits_to_hold_value(val) fls(val)
277#define unhex(c) (isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
278#define BASEDEC 10
279
280
281
282
283
284
285
286
287
288
289
290int bitmap_scnprintf(char *buf, unsigned int buflen,
291 const unsigned long *maskp, int nmaskbits)
292{
293 int i, word, bit, len = 0;
294 unsigned long val;
295 const char *sep = "";
296 int chunksz;
297 u32 chunkmask;
298
299 chunksz = nmaskbits & (CHUNKSZ - 1);
300 if (chunksz == 0)
301 chunksz = CHUNKSZ;
302
303 i = ALIGN(nmaskbits, CHUNKSZ) - CHUNKSZ;
304 for (; i >= 0; i -= CHUNKSZ) {
305 chunkmask = ((1ULL << chunksz) - 1);
306 word = i / BITS_PER_LONG;
307 bit = i % BITS_PER_LONG;
308 val = (maskp[word] >> bit) & chunkmask;
309 len += scnprintf(buf+len, buflen-len, "%s%0*lx", sep,
310 (chunksz+3)/4, val);
311 chunksz = CHUNKSZ;
312 sep = ",";
313 }
314 return len;
315}
316EXPORT_SYMBOL(bitmap_scnprintf);
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334int __bitmap_parse(const char *buf, unsigned int buflen,
335 int is_user, unsigned long *maskp,
336 int nmaskbits)
337{
338 int c, old_c, totaldigits, ndigits, nchunks, nbits;
339 u32 chunk;
340 const char __user *ubuf = buf;
341
342 bitmap_zero(maskp, nmaskbits);
343
344 nchunks = nbits = totaldigits = c = 0;
345 do {
346 chunk = ndigits = 0;
347
348
349 while (buflen) {
350 old_c = c;
351 if (is_user) {
352 if (__get_user(c, ubuf++))
353 return -EFAULT;
354 }
355 else
356 c = *buf++;
357 buflen--;
358 if (isspace(c))
359 continue;
360
361
362
363
364
365
366 if (totaldigits && c && isspace(old_c))
367 return -EINVAL;
368
369
370 if (c == '\0' || c == ',')
371 break;
372
373 if (!isxdigit(c))
374 return -EINVAL;
375
376
377
378
379
380
381 if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1))
382 return -EOVERFLOW;
383
384 chunk = (chunk << 4) | unhex(c);
385 ndigits++; totaldigits++;
386 }
387 if (ndigits == 0)
388 return -EINVAL;
389 if (nchunks == 0 && chunk == 0)
390 continue;
391
392 __bitmap_shift_left(maskp, maskp, CHUNKSZ, nmaskbits);
393 *maskp |= chunk;
394 nchunks++;
395 nbits += (nchunks == 1) ? nbits_to_hold_value(chunk) : CHUNKSZ;
396 if (nbits > nmaskbits)
397 return -EOVERFLOW;
398 } while (buflen && c == ',');
399
400 return 0;
401}
402EXPORT_SYMBOL(__bitmap_parse);
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419int bitmap_parse_user(const char __user *ubuf,
420 unsigned int ulen, unsigned long *maskp,
421 int nmaskbits)
422{
423 if (!access_ok(VERIFY_READ, ubuf, ulen))
424 return -EFAULT;
425 return __bitmap_parse((const char *)ubuf, ulen, 1, maskp, nmaskbits);
426}
427EXPORT_SYMBOL(bitmap_parse_user);
428
429
430
431
432
433
434
435
436
437static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len)
438{
439 if (len > 0)
440 len += scnprintf(buf + len, buflen - len, ",");
441 if (rbot == rtop)
442 len += scnprintf(buf + len, buflen - len, "%d", rbot);
443 else
444 len += scnprintf(buf + len, buflen - len, "%d-%d", rbot, rtop);
445 return len;
446}
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465int bitmap_scnlistprintf(char *buf, unsigned int buflen,
466 const unsigned long *maskp, int nmaskbits)
467{
468 int len = 0;
469
470 int cur, rbot, rtop;
471
472 if (buflen == 0)
473 return 0;
474 buf[0] = 0;
475
476 rbot = cur = find_first_bit(maskp, nmaskbits);
477 while (cur < nmaskbits) {
478 rtop = cur;
479 cur = find_next_bit(maskp, nmaskbits, cur+1);
480 if (cur >= nmaskbits || cur > rtop + 1) {
481 len = bscnl_emit(buf, buflen, rbot, rtop, len);
482 rbot = cur;
483 }
484 }
485 return len;
486}
487EXPORT_SYMBOL(bitmap_scnlistprintf);
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits)
507{
508 unsigned a, b;
509
510 bitmap_zero(maskp, nmaskbits);
511 do {
512 if (!isdigit(*bp))
513 return -EINVAL;
514 b = a = simple_strtoul(bp, (char **)&bp, BASEDEC);
515 if (*bp == '-') {
516 bp++;
517 if (!isdigit(*bp))
518 return -EINVAL;
519 b = simple_strtoul(bp, (char **)&bp, BASEDEC);
520 }
521 if (!(a <= b))
522 return -EINVAL;
523 if (b >= nmaskbits)
524 return -ERANGE;
525 while (a <= b) {
526 set_bit(a, maskp);
527 a++;
528 }
529 if (*bp == ',')
530 bp++;
531 } while (*bp != '\0' && *bp != '\n');
532 return 0;
533}
534EXPORT_SYMBOL(bitmap_parselist);
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits)
555{
556 int i, ord;
557
558 if (pos < 0 || pos >= bits || !test_bit(pos, buf))
559 return -1;
560
561 i = find_first_bit(buf, bits);
562 ord = 0;
563 while (i < pos) {
564 i = find_next_bit(buf, bits, i + 1);
565 ord++;
566 }
567 BUG_ON(i != pos);
568
569 return ord;
570}
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590static int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
591{
592 int pos = 0;
593
594 if (ord >= 0 && ord < bits) {
595 int i;
596
597 for (i = find_first_bit(buf, bits);
598 i < bits && ord > 0;
599 i = find_next_bit(buf, bits, i + 1))
600 ord--;
601 if (i < bits && ord == 0)
602 pos = i;
603 }
604
605 return pos;
606}
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640void bitmap_remap(unsigned long *dst, const unsigned long *src,
641 const unsigned long *old, const unsigned long *new,
642 int bits)
643{
644 int oldbit, w;
645
646 if (dst == src)
647 return;
648 bitmap_zero(dst, bits);
649
650 w = bitmap_weight(new, bits);
651 for (oldbit = find_first_bit(src, bits);
652 oldbit < bits;
653 oldbit = find_next_bit(src, bits, oldbit + 1)) {
654 int n = bitmap_pos_to_ord(old, oldbit, bits);
655 if (n < 0 || w == 0)
656 set_bit(oldbit, dst);
657 else
658 set_bit(bitmap_ord_to_pos(new, n % w, bits), dst);
659 }
660}
661EXPORT_SYMBOL(bitmap_remap);
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689int bitmap_bitremap(int oldbit, const unsigned long *old,
690 const unsigned long *new, int bits)
691{
692 int w = bitmap_weight(new, bits);
693 int n = bitmap_pos_to_ord(old, oldbit, bits);
694 if (n < 0 || w == 0)
695 return oldbit;
696 else
697 return bitmap_ord_to_pos(new, n % w, bits);
698}
699EXPORT_SYMBOL(bitmap_bitremap);
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719enum {
720 REG_OP_ISFREE,
721 REG_OP_ALLOC,
722 REG_OP_RELEASE,
723};
724
725static int __reg_op(unsigned long *bitmap, int pos, int order, int reg_op)
726{
727 int nbits_reg;
728 int index;
729 int offset;
730 int nlongs_reg;
731 int nbitsinlong;
732 unsigned long mask;
733 int i;
734 int ret = 0;
735
736
737
738
739
740 nbits_reg = 1 << order;
741 index = pos / BITS_PER_LONG;
742 offset = pos - (index * BITS_PER_LONG);
743 nlongs_reg = BITS_TO_LONGS(nbits_reg);
744 nbitsinlong = min(nbits_reg, BITS_PER_LONG);
745
746
747
748
749
750 mask = (1UL << (nbitsinlong - 1));
751 mask += mask - 1;
752 mask <<= offset;
753
754 switch (reg_op) {
755 case REG_OP_ISFREE:
756 for (i = 0; i < nlongs_reg; i++) {
757 if (bitmap[index + i] & mask)
758 goto done;
759 }
760 ret = 1;
761 break;
762
763 case REG_OP_ALLOC:
764 for (i = 0; i < nlongs_reg; i++)
765 bitmap[index + i] |= mask;
766 break;
767
768 case REG_OP_RELEASE:
769 for (i = 0; i < nlongs_reg; i++)
770 bitmap[index + i] &= ~mask;
771 break;
772 }
773done:
774 return ret;
775}
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791int bitmap_find_free_region(unsigned long *bitmap, int bits, int order)
792{
793 int pos;
794
795 for (pos = 0; pos < bits; pos += (1 << order))
796 if (__reg_op(bitmap, pos, order, REG_OP_ISFREE))
797 break;
798 if (pos == bits)
799 return -ENOMEM;
800 __reg_op(bitmap, pos, order, REG_OP_ALLOC);
801 return pos;
802}
803EXPORT_SYMBOL(bitmap_find_free_region);
804
805
806
807
808
809
810
811
812
813
814
815
816void bitmap_release_region(unsigned long *bitmap, int pos, int order)
817{
818 __reg_op(bitmap, pos, order, REG_OP_RELEASE);
819}
820EXPORT_SYMBOL(bitmap_release_region);
821
822
823
824
825
826
827
828
829
830
831
832
833int bitmap_allocate_region(unsigned long *bitmap, int pos, int order)
834{
835 if (!__reg_op(bitmap, pos, order, REG_OP_ISFREE))
836 return -EBUSY;
837 __reg_op(bitmap, pos, order, REG_OP_ALLOC);
838 return 0;
839}
840EXPORT_SYMBOL(bitmap_allocate_region);
841