]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From a8659597bf744b0f8d2560e2a734b5c941569e0e Mon Sep 17 00:00:00 2001 |
2 | From: H. Peter Anvin <hpa@zytor.com> | |
3 | Date: Tue, 14 Oct 2008 11:34:21 -0700 | |
4 | Subject: SCSI lib: string_get_size(): don't hang on zero; no decimals on exact | |
5 | Patch-mainline: 2.6.28 | |
6 | References: bnc#500429 | |
7 | ||
8 | From: H. Peter Anvin <hpa@zytor.com> | |
9 | ||
10 | commit a8659597bf744b0f8d2560e2a734b5c941569e0e upstream. | |
11 | ||
12 | We would hang forever when passing a zero to string_get_size(). | |
13 | Furthermore, string_get_size() would produce decimals on a value small | |
14 | enough to be exact. Finally, a few formatting issues are inconsistent | |
15 | with standard SI style guidelines. | |
16 | ||
17 | - If the value is less than the divisor, skip the entire rounding | |
18 | step. This prints out all small values including zero as integers, | |
19 | without decimals. | |
20 | - Add a space between the value and the symbol for the unit, | |
21 | consistent with standard SI practice. | |
22 | - Lower case k in kB since we are talking about powers of 10. | |
23 | - Finally, change "int" to "unsigned int" in one place to shut up a | |
24 | gcc warning when compiling the code out-of-kernel for testing. | |
25 | ||
26 | Signed-off-by: H. Peter Anvin <hpa@zytor.com> | |
27 | Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> | |
28 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
29 | ||
30 | --- | |
31 | lib/string_helpers.c | 38 +++++++++++++++++++++----------------- | |
32 | 1 file changed, 21 insertions(+), 17 deletions(-) | |
33 | ||
34 | --- a/lib/string_helpers.c | |
35 | +++ b/lib/string_helpers.c | |
36 | @@ -23,7 +23,7 @@ | |
37 | int string_get_size(u64 size, const enum string_size_units units, | |
38 | char *buf, int len) | |
39 | { | |
40 | - const char *units_10[] = { "B", "KB", "MB", "GB", "TB", "PB", | |
41 | + const char *units_10[] = { "B", "kB", "MB", "GB", "TB", "PB", | |
42 | "EB", "ZB", "YB", NULL}; | |
43 | const char *units_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", | |
44 | "EiB", "ZiB", "YiB", NULL }; | |
45 | @@ -31,7 +31,7 @@ int string_get_size(u64 size, const enum | |
46 | [STRING_UNITS_10] = units_10, | |
47 | [STRING_UNITS_2] = units_2, | |
48 | }; | |
49 | - const int divisor[] = { | |
50 | + const unsigned int divisor[] = { | |
51 | [STRING_UNITS_10] = 1000, | |
52 | [STRING_UNITS_2] = 1024, | |
53 | }; | |
54 | @@ -40,23 +40,27 @@ int string_get_size(u64 size, const enum | |
55 | char tmp[8]; | |
56 | ||
57 | tmp[0] = '\0'; | |
58 | - | |
59 | - for (i = 0; size > divisor[units] && units_str[units][i]; i++) | |
60 | - remainder = do_div(size, divisor[units]); | |
61 | - | |
62 | - sf_cap = size; | |
63 | - for (j = 0; sf_cap*10 < 1000; j++) | |
64 | - sf_cap *= 10; | |
65 | - | |
66 | - if (j) { | |
67 | - remainder *= 1000; | |
68 | - do_div(remainder, divisor[units]); | |
69 | - snprintf(tmp, sizeof(tmp), ".%03lld", | |
70 | - (unsigned long long)remainder); | |
71 | - tmp[j+1] = '\0'; | |
72 | + i = 0; | |
73 | + if (size >= divisor[units]) { | |
74 | + while (size >= divisor[units] && units_str[units][i]) { | |
75 | + remainder = do_div(size, divisor[units]); | |
76 | + i++; | |
77 | + } | |
78 | + | |
79 | + sf_cap = size; | |
80 | + for (j = 0; sf_cap*10 < 1000; j++) | |
81 | + sf_cap *= 10; | |
82 | + | |
83 | + if (j) { | |
84 | + remainder *= 1000; | |
85 | + do_div(remainder, divisor[units]); | |
86 | + snprintf(tmp, sizeof(tmp), ".%03lld", | |
87 | + (unsigned long long)remainder); | |
88 | + tmp[j+1] = '\0'; | |
89 | + } | |
90 | } | |
91 | ||
92 | - snprintf(buf, len, "%lld%s%s", (unsigned long long)size, | |
93 | + snprintf(buf, len, "%lld%s %s", (unsigned long long)size, | |
94 | tmp, units_str[units][i]); | |
95 | ||
96 | return 0; |