--- /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;