Following the call stack of sysfs_strtoul_clamp appears to lead to _parse_integer:
_parse_integer has the comment “Don’t you dare use this function” and appears to stop parsing at any value outside of the range 0-f. It doesn’t appear to handle “M”.
/*
* Convert non-negative integer string representation in explicitly given radix
* to an integer.
* Return number of characters consumed maybe or-ed with overflow bit.
* If overflow occurs, result integer (incorrect) is still returned.
*
* Don't you dare use this function.
*/
unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)
{
unsigned long long res;
unsigned int rv;
res = 0;
rv = 0;
while (1) {
unsigned int c = *s;
unsigned int lc = c | 0x20; /* don't tolower() this line */
unsigned int val;
if ('0' <= c && c <= '9')
val = c - '0';
else if ('a' <= lc && lc <= 'f')
val = lc - 'a' + 10;
else
break;
if (val >= base)
break;
/*
* Check for overflow only if we are within range of
* it in the max base we support (16)
*/
if (unlikely(res & (~0ull << 60))) {
if (res > div_u64(ULLONG_MAX - val, base))
rv |= KSTRTOX_OVERFLOW;
}
res = res * base + val;
rv++;
s++;
}
*p = res;
return rv;
}
Since “M” is unparsed, The calling function (_kstrtoull) sees that there is still data in the string (*s) and returns “EINVAL”:
static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
{
unsigned long long _res;
unsigned int rv;
s = _parse_integer_fixup_radix(s, &base);
rv = _parse_integer(s, base, &_res);
if (rv & KSTRTOX_OVERFLOW)
return -ERANGE;
if (rv == 0)
return -EINVAL;
s += rv;
if (*s == '\n')
s++;
if (*s)
return -EINVAL;
*res = _res;
return 0;
}
P.S. As a workaround, it looks like there is a numfmt command that will do the conversion for you:
Just FYI, you don’t need to embed it in echo like that since numfmt outputs to standard out anyway. Also, if it is something you think you might need from time-to-time, you can make an alias so you don’t have to remember the options:
alias nf='numfmt --from=iec'
Put the above line in a new file named /etc/profile.d/nf.sh and then all users on your system (including root) should have an nf command that will convert parameters like 64M (i.e. nf 64M).