linux-bk/lib/mask.c
<<
>>
Prefs
   1/*
   2 * lib/mask.c
   3 *
   4 * This file is subject to the terms and conditions of the GNU General Public
   5 * License.  See the file "COPYING" in the main directory of this archive
   6 * for more details.
   7 *
   8 * Copyright (C) 2003 Silicon Graphics, Inc.  All Rights Reserved.
   9 */
  10
  11/*
  12 * Routines to manipulate multi-word bit masks, such as cpumasks.
  13 *
  14 * The ascii representation of multi-word bit masks displays each
  15 * 32bit word in hex (not zero filled), and for masks longer than
  16 * one word, uses a comma separator between words.  Words are
  17 * displayed in big-endian order most significant first.  And hex
  18 * digits within a word are also in big-endian order, of course.
  19 *
  20 * Examples:
  21 *   A mask with just bit 0 set displays as "1".
  22 *   A mask with just bit 127 set displays as "80000000,0,0,0".
  23 *   A mask with just bit 64 set displays as "1,0,0".
  24 *   A mask with bits 0, 1, 2, 4, 8, 16, 32 and 64 set displays
  25 *     as "1,1,10117".  The first "1" is for bit 64, the second
  26 *     for bit 32, the third for bit 16, and so forth, to the
  27 *     "7", which is for bits 2, 1 and 0.
  28 *   A mask with bits 32 through 39 set displays as "ff,0".
  29 *
  30 * The internal binary representation of masks is as one or
  31 * an array of unsigned longs, perhaps wrapped in a struct for
  32 * convenient use as an lvalue.  The following code doesn't know
  33 * about any such struct details, relying on inline macros in
  34 * files such as cpumask.h to pass in an unsigned long pointer
  35 * and a length (in bytes), describing the mask contents.
  36 * The 32bit words in the array are in little-endian order,
  37 * low order word first.  Beware that this is the reverse order
  38 * of the ascii representation.
  39 *
  40 * Even though the size of the input mask is provided in bytes,
  41 * the following code may assume that the mask is a multiple of
  42 * 32 or 64 bit words long, and ignore any fractional portion
  43 * of a word at the end.  The main reason the size is passed in
  44 * bytes is because it is so easy to write 'sizeof(somemask_t)'
  45 * in the macros.
  46 *
  47 * Masks are not a single,simple type, like classic 'C'
  48 * nul-term strings.  Rather they are a family of types, one
  49 * for each different length.  Inline macros are used to pick
  50 * up the actual length, where it is known to the compiler, and
  51 * pass it down to these routines, which work on any specified
  52 * length array of unsigned longs.  Poor man's templates.
  53 *
  54 * Many of the inline macros don't call into the following
  55 * routines.  Some of them call into other kernel routines,
  56 * such as memset(), set_bit() or ffs().  Some of them can
  57 * accomplish their task right inline, such as returning the
  58 * size or address of the unsigned long array, or optimized
  59 * versions of the macros for the most common case of an array
  60 * of a single unsigned long.
  61 */
  62
  63#include <linux/kernel.h>
  64#include <linux/string.h>
  65#include <linux/ctype.h>
  66#include <linux/slab.h>
  67#include <linux/errno.h>
  68#include <linux/gfp.h>
  69#include <asm/uaccess.h>
  70
  71#define MAX_HEX_PER_BYTE 4      /* dont need > 4 hex chars to encode byte */
  72#define BASE 16                 /* masks are input in hex (base 16) */
  73#define NUL ((char)'\0')        /* nul-terminator */
  74
  75/**
  76 * __mask_snprintf_len - represent multi-word bit mask as string.
  77 * @buf: The buffer to place the result into
  78 * @buflen: The size of the buffer, including the trailing null space
  79 * @maskp: Points to beginning of multi-word bit mask.
  80 * @maskbytes: Number of bytes in bit mask at maskp.
  81 *
  82 * This routine is expected to be called from a macro such as:
  83 *
  84 * #define cpumask_snprintf(buf, buflen, mask) \
  85 *   __mask_snprintf_len(buf, buflen, cpus_addr(mask), sizeof(mask))
  86 */
  87
  88int __mask_snprintf_len(char *buf, unsigned int buflen,
  89        const unsigned long *maskp, unsigned int maskbytes)
  90{
  91        u32 *wordp = (u32 *)maskp;
  92        int i = maskbytes/sizeof(u32) - 1;
  93        int len = 0;
  94        char *sep = "";
  95
  96        while (i >= 1 && wordp[i] == 0)
  97                i--;
  98        while (i >= 0) {
  99                len += snprintf(buf+len, buflen-len, "%s%x", sep, wordp[i]);
 100                sep = ",";
 101                i--;
 102        }
 103        return len;
 104}
 105
 106/**
 107 * __mask_parse_len - parse user string into maskbytes mask at maskp
 108 * @ubuf: The user buffer from which to take the string
 109 * @ubuflen: The size of this buffer, including the terminating char
 110 * @maskp: Place resulting mask (array of unsigned longs) here
 111 * @masklen: Construct mask at @maskp to have exactly @masklen bytes
 112 *
 113 * @masklen is a multiple of sizeof(unsigned long).  A mask of
 114 * @masklen bytes is constructed starting at location @maskp.
 115 * The value of this mask is specified by the user provided
 116 * string starting at address @ubuf.  Only bytes in the range
 117 * [@ubuf, @ubuf+@ubuflen) can be read from user space, and
 118 * reading will stop after the first byte that is not a comma
 119 * or valid hex digit in the characters [,0-9a-fA-F], or at
 120 * the point @ubuf+@ubuflen, whichever comes first.
 121 *
 122 * Since the user only needs about 2.25 chars per byte to encode
 123 * a mask (one char per nibble plus one comma separator or nul
 124 * terminator per byte), we blow them off with -EINVAL if they
 125 * claim a @ubuflen more than 4 (MAX_HEX_PER_BYTE) times maskbytes.
 126 * An empty word (delimited by two consecutive commas, for example)
 127 * is taken as zero.  If @buflen is zero, the entire @maskp is set
 128 * to zero.
 129 *
 130 * If the user provides fewer comma-separated ascii words
 131 * than there are 32 bit words in maskbytes, we zero fill the
 132 * remaining high order words.  If they provide more, they fail
 133 * with -EINVAL.  Each comma-separate ascii word is taken as
 134 * a hex representation; leading zeros are ignored, and do not
 135 * imply octal.  '00e1', 'e1', '00E1', 'E1' are all the same.
 136 * If user passes a word that is larger than fits in a u32,
 137 * they fail with -EOVERFLOW.
 138 */
 139
 140int __mask_parse_len(const char __user *ubuf, unsigned int ubuflen,
 141        unsigned long *maskp, unsigned int maskbytes)
 142{
 143        char buf[maskbytes * MAX_HEX_PER_BYTE + sizeof(NUL)];
 144        char *bp = buf;
 145        u32 *wordp = (u32 *)maskp;
 146        char *p;
 147        int i, j;
 148
 149        if (ubuflen > maskbytes * MAX_HEX_PER_BYTE)
 150                return -EINVAL;
 151        if (copy_from_user(buf, ubuf, ubuflen))
 152                return -EFAULT;
 153        buf[ubuflen] = NUL;
 154
 155        /*
 156         * Put the words into wordp[] in big-endian order,
 157         * then go back and reverse them.
 158         */
 159        memset(wordp, 0, maskbytes);
 160        i = j = 0;
 161        while ((p = strsep(&bp, ",")) != NULL) {
 162                unsigned long long t;
 163                if (j == maskbytes/sizeof(u32))
 164                        return -EINVAL;
 165                t = simple_strtoull(p, 0, BASE);
 166                if (t != (u32)t)
 167                        return -EOVERFLOW;
 168                wordp[j++] = t;
 169        }
 170        --j;
 171        while (i < j) {
 172                u32 t = wordp[i];
 173                wordp[i] = wordp[j];
 174                wordp[j] = t;
 175                i++, --j;
 176        }
 177        return 0;
 178}
 179
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.