aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-12-13 20:49:55 -0500
committerNeilBrown <neilb@suse.de>2009-12-13 20:51:41 -0500
commit72e02075a33f739e21430262f71da8e82db9dbb3 (patch)
tree04a87a16751b714fe0fb41f28ccc54af9f820de1 /drivers/md/md.c
parentf6af949c5672115313cc3c976d85b0533f607d7e (diff)
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: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c64
1 files changed, 42 insertions, 22 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index c56c64d13075..93287f88f1f4 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2763,6 +2763,47 @@ static void analyze_sbs(mddev_t * mddev)
2763 } 2763 }
2764} 2764}
2765 2765
2766/* Read a fixed-point number.
2767 * Numbers in sysfs attributes should be in "standard" units where
2768 * possible, so time should be in seconds.
2769 * However we internally use a a much smaller unit such as
2770 * milliseconds or jiffies.
2771 * This function takes a decimal number with a possible fractional
2772 * component, and produces an integer which is the result of
2773 * multiplying that number by 10^'scale'.
2774 * all without any floating-point arithmetic.
2775 */
2776int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale)
2777{
2778 unsigned long result = 0;
2779 long decimals = -1;
2780 while (isdigit(*cp) || (*cp == '.' && decimals < 0)) {
2781 if (*cp == '.')
2782 decimals = 0;
2783 else if (decimals < scale) {
2784 unsigned int value;
2785 value = *cp - '0';
2786 result = result * 10 + value;
2787 if (decimals >= 0)
2788 decimals++;
2789 }
2790 cp++;
2791 }
2792 if (*cp == '\n')
2793 cp++;
2794 if (*cp)
2795 return -EINVAL;
2796 if (decimals < 0)
2797 decimals = 0;
2798 while (decimals < scale) {
2799 result *= 10;
2800 decimals ++;
2801 }
2802 *res = result;
2803 return 0;
2804}
2805
2806
2766static void md_safemode_timeout(unsigned long data); 2807static void md_safemode_timeout(unsigned long data);
2767 2808
2768static ssize_t 2809static ssize_t
@@ -2774,31 +2815,10 @@ safe_delay_show(mddev_t *mddev, char *page)
2774static ssize_t 2815static ssize_t
2775safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len) 2816safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len)
2776{ 2817{
2777 int scale=1;
2778 int dot=0;
2779 int i;
2780 unsigned long msec; 2818 unsigned long msec;
2781 char buf[30];
2782 2819
2783 /* remove a period, and count digits after it */ 2820 if (strict_strtoul_scaled(cbuf, &msec, 3) < 0)
2784 if (len >= sizeof(buf))
2785 return -EINVAL;
2786 strlcpy(buf, cbuf, sizeof(buf));
2787 for (i=0; i<len; i++) {
2788 if (dot) {
2789 if (isdigit(buf[i])) {
2790 buf[i-1] = buf[i];
2791 scale *= 10;
2792 }
2793 buf[i] = 0;
2794 } else if (buf[i] == '.') {
2795 dot=1;
2796 buf[i] = 0;
2797 }
2798 }
2799 if (strict_strtoul(buf, 10, &msec) < 0)
2800 return -EINVAL; 2821 return -EINVAL;
2801 msec = (msec * 1000) / scale;
2802 if (msec == 0) 2822 if (msec == 0)
2803 mddev->safemode_delay = 0; 2823 mddev->safemode_delay = 0;
2804 else { 2824 else {