Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 72e02075 authored by NeilBrown's avatar NeilBrown
Browse files

md: factor out parsing of fixed-point numbers



safe_delay_store can parse fixed point numbers (for fractions
of a second).  We will want to do that for another sysfs
file soon, so factor out the code.

Signed-off-by: default avatarNeilBrown <neilb@suse.de>
parent f6af949c
Loading
Loading
Loading
Loading
+42 −22
Original line number Original line Diff line number Diff line
@@ -2763,6 +2763,47 @@ static void analyze_sbs(mddev_t * mddev)
	}
	}
}
}


/* Read a fixed-point number.
 * Numbers in sysfs attributes should be in "standard" units where
 * possible, so time should be in seconds.
 * However we internally use a a much smaller unit such as 
 * milliseconds or jiffies.
 * This function takes a decimal number with a possible fractional
 * component, and produces an integer which is the result of
 * multiplying that number by 10^'scale'.
 * all without any floating-point arithmetic.
 */
int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale)
{
	unsigned long result = 0;
	long decimals = -1;
	while (isdigit(*cp) || (*cp == '.' && decimals < 0)) {
		if (*cp == '.')
			decimals = 0;
		else if (decimals < scale) {
			unsigned int value;
			value = *cp - '0';
			result = result * 10 + value;
			if (decimals >= 0)
				decimals++;
		}
		cp++;
	}
	if (*cp == '\n')
		cp++;
	if (*cp)
		return -EINVAL;
	if (decimals < 0)
		decimals = 0;
	while (decimals < scale) {
		result *= 10;
		decimals ++;
	}
	*res = result;
	return 0;
}


static void md_safemode_timeout(unsigned long data);
static void md_safemode_timeout(unsigned long data);


static ssize_t
static ssize_t
@@ -2774,31 +2815,10 @@ safe_delay_show(mddev_t *mddev, char *page)
static ssize_t
static ssize_t
safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len)
safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len)
{
{
	int scale=1;
	int dot=0;
	int i;
	unsigned long msec;
	unsigned long msec;
	char buf[30];


	/* remove a period, and count digits after it */
	if (strict_strtoul_scaled(cbuf, &msec, 3) < 0)
	if (len >= sizeof(buf))
		return -EINVAL;
	strlcpy(buf, cbuf, sizeof(buf));
	for (i=0; i<len; i++) {
		if (dot) {
			if (isdigit(buf[i])) {
				buf[i-1] = buf[i];
				scale *= 10;
			}
			buf[i] = 0;
		} else if (buf[i] == '.') {
			dot=1;
			buf[i] = 0;
		}
	}
	if (strict_strtoul(buf, 10, &msec) < 0)
		return -EINVAL;
		return -EINVAL;
	msec = (msec * 1000) / scale;
	if (msec == 0)
	if (msec == 0)
		mddev->safemode_delay = 0;
		mddev->safemode_delay = 0;
	else {
	else {
+2 −1
Original line number Original line Diff line number Diff line
@@ -463,6 +463,7 @@ extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors);
extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors);
extern int md_check_no_bitmap(mddev_t *mddev);
extern int md_check_no_bitmap(mddev_t *mddev);
extern int md_integrity_register(mddev_t *mddev);
extern int md_integrity_register(mddev_t *mddev);
void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
extern void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale);


#endif /* _MD_MD_H */
#endif /* _MD_MD_H */