summaryrefslogtreecommitdiffstats
path: root/lib/bitmap.c
diff options
context:
space:
mode:
authorYury Norov <ynorov@caviumnetworks.com>2018-02-06 18:38:02 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-02-06 21:32:44 -0500
commitc724f193619c896621bf5818d71ce77437f49a06 (patch)
treebf6a91db63c1543dcf4b8b0e46fcbcbe55d3efda /lib/bitmap.c
parenteed9c249f7f137bceaebfd69bc9544ea09be9180 (diff)
bitmap: new bitmap_copy_safe and bitmap_{from,to}_arr32
This patchset replaces bitmap_{to,from}_u32array with more simple and standard looking copy-like functions. bitmap_from_u32array() takes 4 arguments (bitmap_to_u32array is similar): - unsigned long *bitmap, which is destination; - unsigned int nbits, the length of destination bitmap, in bits; - const u32 *buf, the source; and - unsigned int nwords, the length of source buffer in ints. In description to the function it is detailed like: * copy min(nbits, 32*nwords) bits from @buf to @bitmap, remaining * bits between nword and nbits in @bitmap (if any) are cleared. Having two size arguments looks unneeded and potentially dangerous. It is unneeded because normally user of copy-like function should take care of the size of destination and make it big enough to fit source data. And it is dangerous because function may hide possible error if user doesn't provide big enough bitmap, and data becomes silently dropped. That's why all copy-like functions have 1 argument for size of copying data, and I don't see any reason to make bitmap_from_u32array() different. One exception that comes in mind is strncpy() which also provides size of destination in arguments, but it's strongly argued by the possibility of taking broken strings in source. This is not the case of bitmap_{from,to}_u32array(). There is no many real users of bitmap_{from,to}_u32array(), and they all very clearly provide size of destination matched with the size of source, so additional functionality is not used in fact. Like this: bitmap_from_u32array(to->link_modes.supported, __ETHTOOL_LINK_MODE_MASK_NBITS, link_usettings.link_modes.supported, __ETHTOOL_LINK_MODE_MASK_NU32); Where: #define __ETHTOOL_LINK_MODE_MASK_NU32 \ DIV_ROUND_UP(__ETHTOOL_LINK_MODE_MASK_NBITS, 32) In this patch, bitmap_copy_safe and bitmap_{from,to}_arr32 are introduced. 'Safe' in bitmap_copy_safe() stands for clearing unused bits in bitmap beyond last bit till the end of last word. It is useful for hardening API when bitmap is assumed to be exposed to userspace. bitmap_{from,to}_arr32 functions are replacements for bitmap_{from,to}_u32array. They don't take unneeded nwords argument, and so simpler in implementation and understanding. This patch suggests optimization for 32-bit systems - aliasing bitmap_{from,to}_arr32 to bitmap_copy_safe. Other possible optimization is aliasing 64-bit LE bitmap_{from,to}_arr32 to more generic function(s). But I didn't end up with the function that would be helpful by itself, and can be used to alias 64-bit LE bitmap_{from,to}_arr32, like bitmap_copy_safe() does. So I preferred to leave things as is. The following patch switches kernel to new API and introduces test for it. Discussion is here: https://lkml.org/lkml/2017/11/15/592 [ynorov@caviumnetworks.com: rename bitmap_copy_safe to bitmap_copy_clear_tail] Link: http://lkml.kernel.org/r/20180201172508.5739-3-ynorov@caviumnetworks.com Link: http://lkml.kernel.org/r/20171228150019.27953-1-ynorov@caviumnetworks.com Signed-off-by: Yury Norov <ynorov@caviumnetworks.com> Cc: Ben Hutchings <ben@decadent.org.uk> Cc: David Decotigny <decot@googlers.com>, Cc: David S. Miller <davem@davemloft.net>, Cc: Geert Uytterhoeven <geert@linux-m68k.org> Cc: Matthew Wilcox <mawilcox@microsoft.com> Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib/bitmap.c')
-rw-r--r--lib/bitmap.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c
index d8f0c094b18e..47fe6441562c 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -1214,3 +1214,59 @@ void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int n
1214} 1214}
1215EXPORT_SYMBOL(bitmap_copy_le); 1215EXPORT_SYMBOL(bitmap_copy_le);
1216#endif 1216#endif
1217
1218#if BITS_PER_LONG == 64
1219/**
1220 * bitmap_from_arr32 - copy the contents of u32 array of bits to bitmap
1221 * @bitmap: array of unsigned longs, the destination bitmap
1222 * @buf: array of u32 (in host byte order), the source bitmap
1223 * @nbits: number of bits in @bitmap
1224 */
1225void bitmap_from_arr32(unsigned long *bitmap, const u32 *buf,
1226 unsigned int nbits)
1227{
1228 unsigned int i, halfwords;
1229
1230 if (!nbits)
1231 return;
1232
1233 halfwords = DIV_ROUND_UP(nbits, 32);
1234 for (i = 0; i < halfwords; i++) {
1235 bitmap[i/2] = (unsigned long) buf[i];
1236 if (++i < halfwords)
1237 bitmap[i/2] |= ((unsigned long) buf[i]) << 32;
1238 }
1239
1240 /* Clear tail bits in last word beyond nbits. */
1241 if (nbits % BITS_PER_LONG)
1242 bitmap[(halfwords - 1) / 2] &= BITMAP_LAST_WORD_MASK(nbits);
1243}
1244EXPORT_SYMBOL(bitmap_from_arr32);
1245
1246/**
1247 * bitmap_to_arr32 - copy the contents of bitmap to a u32 array of bits
1248 * @buf: array of u32 (in host byte order), the dest bitmap
1249 * @bitmap: array of unsigned longs, the source bitmap
1250 * @nbits: number of bits in @bitmap
1251 */
1252void bitmap_to_arr32(u32 *buf, const unsigned long *bitmap, unsigned int nbits)
1253{
1254 unsigned int i, halfwords;
1255
1256 if (!nbits)
1257 return;
1258
1259 halfwords = DIV_ROUND_UP(nbits, 32);
1260 for (i = 0; i < halfwords; i++) {
1261 buf[i] = (u32) (bitmap[i/2] & UINT_MAX);
1262 if (++i < halfwords)
1263 buf[i] = (u32) (bitmap[i/2] >> 32);
1264 }
1265
1266 /* Clear tail bits in last element of array beyond nbits. */
1267 if (nbits % BITS_PER_LONG)
1268 buf[halfwords - 1] &= (u32) (UINT_MAX >> ((-nbits) & 31));
1269}
1270EXPORT_SYMBOL(bitmap_to_arr32);
1271
1272#endif