Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lib/bitmap.c: conversion routines to/from u32 array

Aimed at transferring bitmaps to/from user-space in a 32/64-bit agnostic
way.

Tested:
unit tests (next patch) on qemu i386, x86_64, ppc, ppc64 BE and LE,
ARM.

Signed-off-by: David Decotigny <decot@googlers.com>
Reviewed-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

David Decotigny and committed by
David S. Miller
e52bc7c2 76d13b56

+99
+10
include/linux/bitmap.h
··· 59 59 * bitmap_find_free_region(bitmap, bits, order) Find and allocate bit region 60 60 * bitmap_release_region(bitmap, pos, order) Free specified bit region 61 61 * bitmap_allocate_region(bitmap, pos, order) Allocate specified bit region 62 + * bitmap_from_u32array(dst, nbits, buf, nwords) *dst = *buf (nwords 32b words) 63 + * bitmap_to_u32array(buf, nwords, src, nbits) *buf = *dst (nwords 32b words) 62 64 */ 63 65 64 66 /* ··· 165 163 extern int bitmap_find_free_region(unsigned long *bitmap, unsigned int bits, int order); 166 164 extern void bitmap_release_region(unsigned long *bitmap, unsigned int pos, int order); 167 165 extern int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order); 166 + extern unsigned int bitmap_from_u32array(unsigned long *bitmap, 167 + unsigned int nbits, 168 + const u32 *buf, 169 + unsigned int nwords); 170 + extern unsigned int bitmap_to_u32array(u32 *buf, 171 + unsigned int nwords, 172 + const unsigned long *bitmap, 173 + unsigned int nbits); 168 174 #ifdef __BIG_ENDIAN 169 175 extern void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int nbits); 170 176 #else
+89
lib/bitmap.c
··· 12 12 #include <linux/bitmap.h> 13 13 #include <linux/bitops.h> 14 14 #include <linux/bug.h> 15 + #include <linux/kernel.h> 16 + #include <linux/string.h> 15 17 16 18 #include <asm/page.h> 17 19 #include <asm/uaccess.h> ··· 1060 1058 return __reg_op(bitmap, pos, order, REG_OP_ALLOC); 1061 1059 } 1062 1060 EXPORT_SYMBOL(bitmap_allocate_region); 1061 + 1062 + /** 1063 + * bitmap_from_u32array - copy the contents of a u32 array of bits to bitmap 1064 + * @bitmap: array of unsigned longs, the destination bitmap, non NULL 1065 + * @nbits: number of bits in @bitmap 1066 + * @buf: array of u32 (in host byte order), the source bitmap, non NULL 1067 + * @nwords: number of u32 words in @buf 1068 + * 1069 + * copy min(nbits, 32*nwords) bits from @buf to @bitmap, remaining 1070 + * bits between nword and nbits in @bitmap (if any) are cleared. In 1071 + * last word of @bitmap, the bits beyond nbits (if any) are kept 1072 + * unchanged. 1073 + * 1074 + * Return the number of bits effectively copied. 1075 + */ 1076 + unsigned int 1077 + bitmap_from_u32array(unsigned long *bitmap, unsigned int nbits, 1078 + const u32 *buf, unsigned int nwords) 1079 + { 1080 + unsigned int dst_idx, src_idx; 1081 + 1082 + for (src_idx = dst_idx = 0; dst_idx < BITS_TO_LONGS(nbits); ++dst_idx) { 1083 + unsigned long part = 0; 1084 + 1085 + if (src_idx < nwords) 1086 + part = buf[src_idx++]; 1087 + 1088 + #if BITS_PER_LONG == 64 1089 + if (src_idx < nwords) 1090 + part |= ((unsigned long) buf[src_idx++]) << 32; 1091 + #endif 1092 + 1093 + if (dst_idx < nbits/BITS_PER_LONG) 1094 + bitmap[dst_idx] = part; 1095 + else { 1096 + unsigned long mask = BITMAP_LAST_WORD_MASK(nbits); 1097 + 1098 + bitmap[dst_idx] = (bitmap[dst_idx] & ~mask) 1099 + | (part & mask); 1100 + } 1101 + } 1102 + 1103 + return min_t(unsigned int, nbits, 32*nwords); 1104 + } 1105 + EXPORT_SYMBOL(bitmap_from_u32array); 1106 + 1107 + /** 1108 + * bitmap_to_u32array - copy the contents of bitmap to a u32 array of bits 1109 + * @buf: array of u32 (in host byte order), the dest bitmap, non NULL 1110 + * @nwords: number of u32 words in @buf 1111 + * @bitmap: array of unsigned longs, the source bitmap, non NULL 1112 + * @nbits: number of bits in @bitmap 1113 + * 1114 + * copy min(nbits, 32*nwords) bits from @bitmap to @buf. Remaining 1115 + * bits after nbits in @buf (if any) are cleared. 1116 + * 1117 + * Return the number of bits effectively copied. 1118 + */ 1119 + unsigned int 1120 + bitmap_to_u32array(u32 *buf, unsigned int nwords, 1121 + const unsigned long *bitmap, unsigned int nbits) 1122 + { 1123 + unsigned int dst_idx = 0, src_idx = 0; 1124 + 1125 + while (dst_idx < nwords) { 1126 + unsigned long part = 0; 1127 + 1128 + if (src_idx < BITS_TO_LONGS(nbits)) { 1129 + part = bitmap[src_idx]; 1130 + if (src_idx >= nbits/BITS_PER_LONG) 1131 + part &= BITMAP_LAST_WORD_MASK(nbits); 1132 + src_idx++; 1133 + } 1134 + 1135 + buf[dst_idx++] = part & 0xffffffffUL; 1136 + 1137 + #if BITS_PER_LONG == 64 1138 + if (dst_idx < nwords) { 1139 + part >>= 32; 1140 + buf[dst_idx++] = part & 0xffffffffUL; 1141 + } 1142 + #endif 1143 + } 1144 + 1145 + return min_t(unsigned int, nbits, 32*nwords); 1146 + } 1147 + EXPORT_SYMBOL(bitmap_to_u32array); 1063 1148 1064 1149 /** 1065 1150 * bitmap_copy_le - copy a bitmap, putting the bits into little-endian order.