mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
libdm: add dm_bitset_parse_list()
Add a function to parse a list of integer values and ranges into a dm_bitset representation. Individual values signify that that bit is set in the resulting mask and ranges are given as a pair of start and end values, M-N, such that M and N are the first and last members of the range (inclusive). The implementation is based on the kernel's __bitmap_parselist() that is used for cpumasks and other set configuration passed in string form from user space.
This commit is contained in:
parent
d382e66035
commit
81fad9e853
@ -1,5 +1,6 @@
|
|||||||
Version 1.02.129 -
|
Version 1.02.129 -
|
||||||
=================================
|
=================================
|
||||||
|
Add dm_bitset_parse_list() to parse a string representation of a bitset.
|
||||||
Thin dmeventd plugin umounts lvm2 volume only when pool is 95% or more.
|
Thin dmeventd plugin umounts lvm2 volume only when pool is 95% or more.
|
||||||
|
|
||||||
Version 1.02.128 - 25th June 2016
|
Version 1.02.128 - 25th June 2016
|
||||||
|
1
libdm/.exported_symbols.DM_1_02_129
Normal file
1
libdm/.exported_symbols.DM_1_02_129
Normal file
@ -0,0 +1 @@
|
|||||||
|
dm_bitset_parse_list
|
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
#include "dmlib.h"
|
#include "dmlib.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
/* FIXME: calculate this. */
|
/* FIXME: calculate this. */
|
||||||
#define INT_SHIFT 5
|
#define INT_SHIFT 5
|
||||||
|
|
||||||
@ -103,3 +105,99 @@ int dm_bit_get_first(dm_bitset_t bs)
|
|||||||
{
|
{
|
||||||
return dm_bit_get_next(bs, -1);
|
return dm_bit_get_next(bs, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Based on the Linux kernel __bitmap_parselist from lib/bitmap.c
|
||||||
|
*/
|
||||||
|
dm_bitset_t dm_bitset_parse_list(const char *str, struct dm_pool *mem)
|
||||||
|
{
|
||||||
|
unsigned a, b;
|
||||||
|
int c, old_c, totaldigits, ndigits, nmaskbits;
|
||||||
|
int at_start, in_range;
|
||||||
|
dm_bitset_t mask = NULL;
|
||||||
|
const char *start = str;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
scan:
|
||||||
|
len = strlen(str);
|
||||||
|
totaldigits = c = 0;
|
||||||
|
nmaskbits = 0;
|
||||||
|
do {
|
||||||
|
at_start = 1;
|
||||||
|
in_range = 0;
|
||||||
|
a = b = 0;
|
||||||
|
ndigits = totaldigits;
|
||||||
|
|
||||||
|
/* Get the next value or range of values */
|
||||||
|
while (len) {
|
||||||
|
old_c = c;
|
||||||
|
c = *str++;
|
||||||
|
len--;
|
||||||
|
if (isspace(c))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* A '\0' or a ',' signal the end of a value or range */
|
||||||
|
if (c == '\0' || c == ',')
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
* whitespaces between digits are not allowed,
|
||||||
|
* but it's ok if whitespaces are on head or tail.
|
||||||
|
* when old_c is whilespace,
|
||||||
|
* if totaldigits == ndigits, whitespace is on head.
|
||||||
|
* if whitespace is on tail, it should not run here.
|
||||||
|
* as c was ',' or '\0',
|
||||||
|
* the last code line has broken the current loop.
|
||||||
|
*/
|
||||||
|
if ((totaldigits != ndigits) && isspace(old_c))
|
||||||
|
goto_bad;
|
||||||
|
|
||||||
|
if (c == '-') {
|
||||||
|
if (at_start || in_range)
|
||||||
|
return_0;
|
||||||
|
b = 0;
|
||||||
|
in_range = 1;
|
||||||
|
at_start = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isdigit(c))
|
||||||
|
goto_bad;
|
||||||
|
|
||||||
|
b = b * 10 + (c - '0');
|
||||||
|
if (!in_range)
|
||||||
|
a = b;
|
||||||
|
at_start = 0;
|
||||||
|
totaldigits++;
|
||||||
|
}
|
||||||
|
if (ndigits == totaldigits)
|
||||||
|
continue;
|
||||||
|
/* if no digit is after '-', it's wrong */
|
||||||
|
if (at_start && in_range)
|
||||||
|
goto_bad;
|
||||||
|
if (!(a <= b))
|
||||||
|
goto_bad;
|
||||||
|
if (b >= nmaskbits)
|
||||||
|
nmaskbits = b + 1;
|
||||||
|
while ((a <= b) && mask) {
|
||||||
|
dm_bit_set(mask, a);
|
||||||
|
a++;
|
||||||
|
}
|
||||||
|
} while (len && c == ',');
|
||||||
|
|
||||||
|
if (!mask) {
|
||||||
|
if (!(mask = dm_bitset_create(mem, nmaskbits)))
|
||||||
|
goto_bad;
|
||||||
|
str = start;
|
||||||
|
goto scan;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
bad:
|
||||||
|
if (mask) {
|
||||||
|
if (mem)
|
||||||
|
dm_pool_free(mem, mask);
|
||||||
|
else
|
||||||
|
dm_bitset_destroy(mask);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@ -1843,6 +1843,16 @@ int dm_bit_get_next(dm_bitset_t bs, int last_bit);
|
|||||||
#define dm_bit_copy(bs1, bs2) \
|
#define dm_bit_copy(bs1, bs2) \
|
||||||
memcpy((bs1) + 1, (bs2) + 1, ((*(bs1) / DM_BITS_PER_INT) + 1) * sizeof(int))
|
memcpy((bs1) + 1, (bs2) + 1, ((*(bs1) / DM_BITS_PER_INT) + 1) * sizeof(int))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse a string representation of a bitset into a dm_bitset_t. The
|
||||||
|
* notation used is identical to the kernel bitmap parser (cpuset etc.)
|
||||||
|
* and supports both lists ("1,2,3") and ranges ("1-2,5-8"). If the mem
|
||||||
|
* parameter is NULL memory for the bitset will be allocated using
|
||||||
|
* dm_malloc(). Otherwise the bitset will be allocated using the supplied
|
||||||
|
* dm_pool.
|
||||||
|
*/
|
||||||
|
dm_bitset_t dm_bitset_parse_list(const char *str, struct dm_pool *mem);
|
||||||
|
|
||||||
/* Returns number of set bits */
|
/* Returns number of set bits */
|
||||||
static inline unsigned hweight32(uint32_t i)
|
static inline unsigned hweight32(uint32_t i)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user