+++ /dev/null
-From a8659597bf744b0f8d2560e2a734b5c941569e0e Mon Sep 17 00:00:00 2001
-From: H. Peter Anvin <hpa@zytor.com>
-Date: Tue, 14 Oct 2008 11:34:21 -0700
-Subject: SCSI lib: string_get_size(): don't hang on zero; no decimals on exact
-Patch-mainline: 2.6.28
-References: bnc#500429
-
-From: H. Peter Anvin <hpa@zytor.com>
-
-commit a8659597bf744b0f8d2560e2a734b5c941569e0e upstream.
-
-We would hang forever when passing a zero to string_get_size().
-Furthermore, string_get_size() would produce decimals on a value small
-enough to be exact. Finally, a few formatting issues are inconsistent
-with standard SI style guidelines.
-
-- If the value is less than the divisor, skip the entire rounding
- step. This prints out all small values including zero as integers,
- without decimals.
-- Add a space between the value and the symbol for the unit,
- consistent with standard SI practice.
-- Lower case k in kB since we are talking about powers of 10.
-- Finally, change "int" to "unsigned int" in one place to shut up a
- gcc warning when compiling the code out-of-kernel for testing.
-
-Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-
----
- lib/string_helpers.c | 38 +++++++++++++++++++++-----------------
- 1 file changed, 21 insertions(+), 17 deletions(-)
-
---- a/lib/string_helpers.c
-+++ b/lib/string_helpers.c
-@@ -23,7 +23,7 @@
- int string_get_size(u64 size, const enum string_size_units units,
- char *buf, int len)
- {
-- const char *units_10[] = { "B", "KB", "MB", "GB", "TB", "PB",
-+ const char *units_10[] = { "B", "kB", "MB", "GB", "TB", "PB",
- "EB", "ZB", "YB", NULL};
- const char *units_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB",
- "EiB", "ZiB", "YiB", NULL };
-@@ -31,7 +31,7 @@ int string_get_size(u64 size, const enum
- [STRING_UNITS_10] = units_10,
- [STRING_UNITS_2] = units_2,
- };
-- const int divisor[] = {
-+ const unsigned int divisor[] = {
- [STRING_UNITS_10] = 1000,
- [STRING_UNITS_2] = 1024,
- };
-@@ -40,23 +40,27 @@ int string_get_size(u64 size, const enum
- char tmp[8];
-
- tmp[0] = '\0';
--
-- for (i = 0; size > divisor[units] && units_str[units][i]; i++)
-- remainder = do_div(size, divisor[units]);
--
-- sf_cap = size;
-- for (j = 0; sf_cap*10 < 1000; j++)
-- sf_cap *= 10;
--
-- if (j) {
-- remainder *= 1000;
-- do_div(remainder, divisor[units]);
-- snprintf(tmp, sizeof(tmp), ".%03lld",
-- (unsigned long long)remainder);
-- tmp[j+1] = '\0';
-+ i = 0;
-+ if (size >= divisor[units]) {
-+ while (size >= divisor[units] && units_str[units][i]) {
-+ remainder = do_div(size, divisor[units]);
-+ i++;
-+ }
-+
-+ sf_cap = size;
-+ for (j = 0; sf_cap*10 < 1000; j++)
-+ sf_cap *= 10;
-+
-+ if (j) {
-+ remainder *= 1000;
-+ do_div(remainder, divisor[units]);
-+ snprintf(tmp, sizeof(tmp), ".%03lld",
-+ (unsigned long long)remainder);
-+ tmp[j+1] = '\0';
-+ }
- }
-
-- snprintf(buf, len, "%lld%s%s", (unsigned long long)size,
-+ snprintf(buf, len, "%lld%s %s", (unsigned long long)size,
- tmp, units_str[units][i]);
-
- return 0;