summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-16 19:02:04 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-16 19:02:04 -0400
commit7d69cff26ceadce8638cb65191285932a3de3d4c (patch)
tree7a23eb561e6a25fbd111af2d0152cc6f34c2cecd /lib
parent8fa6f4974d55ad1fb0a9522c5a5cfd050a517048 (diff)
parent0351b8f81392c6dbbbb036e5c8f73ceff68726e9 (diff)
downloadlinux-7d69cff26ceadce8638cb65191285932a3de3d4c.tar.gz
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
 "This is the usual grab bag of driver updates (lpfc, qla2xxx, storvsc,
  aacraid, ipr) plus an assortment of minor updates.  There's also a
  major update to aic1542 which moves the driver into this millenium"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (106 commits)
  change SCSI Maintainer email
  sd, mmc, virtio_blk, string_helpers: fix block size units
  ufs: add support to allow non standard behaviours (quirks)
  ufs-qcom: save controller revision info in internal structure
  qla2xxx: Update driver version to 8.07.00.18-k
  qla2xxx: Restore physical port WWPN only, when port down detected for FA-WWPN port.
  qla2xxx: Fix virtual port configuration, when switch port is disabled/enabled.
  qla2xxx: Prevent multiple firmware dump collection for ISP27XX.
  qla2xxx: Disable Interrupt handshake for ISP27XX.
  qla2xxx: Add debugging info for MBX timeout.
  qla2xxx: Add serdes read/write support for ISP27XX
  qla2xxx: Add udev notification to save fw dump for ISP27XX
  qla2xxx: Add message for sucessful FW dump collected for ISP27XX.
  qla2xxx: Add support to load firmware from file for ISP 26XX/27XX.
  qla2xxx: Fix beacon blink for ISP27XX.
  qla2xxx: Increase the wait time for firmware to be ready for P3P.
  qla2xxx: Fix crash due to wrong casting of reg for ISP27XX.
  qla2xxx: Fix warnings reported by static checker.
  lpfc: Update version to 10.5.0.0 for upstream patch set
  lpfc: Update copyright to 2015
  ...
Diffstat (limited to 'lib')
-rw-r--r--lib/string_helpers.c68
1 files changed, 48 insertions, 20 deletions
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 1826c7407258..c98ae818eb4e 100644
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -4,6 +4,7 @@
  * Copyright 31 August 2008 James Bottomley
  * Copyright (C) 2013, Intel Corporation
  */
+#include <linux/bug.h>
 #include <linux/kernel.h>
 #include <linux/math64.h>
 #include <linux/export.h>
@@ -14,7 +15,8 @@
 
 /**
  * string_get_size - get the size in the specified units
- * @size:	The size to be converted
+ * @size:	The size to be converted in blocks
+ * @blk_size:	Size of the block (use 1 for size in bytes)
  * @units:	units to use (powers of 1000 or 1024)
  * @buf:	buffer to format to
  * @len:	length of buffer
@@ -24,14 +26,14 @@
  * at least 9 bytes and will always be zero terminated.
  *
  */
-void string_get_size(u64 size, const enum string_size_units units,
+void string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
 		     char *buf, int len)
 {
 	static const char *const units_10[] = {
-		"B", "kB", "MB", "GB", "TB", "PB", "EB"
+		"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
 	};
 	static const char *const units_2[] = {
-		"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"
+		"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"
 	};
 	static const char *const *const units_str[] = {
 		[STRING_UNITS_10] = units_10,
@@ -42,31 +44,57 @@ void string_get_size(u64 size, const enum string_size_units units,
 		[STRING_UNITS_2] = 1024,
 	};
 	int i, j;
-	u32 remainder = 0, sf_cap;
+	u32 remainder = 0, sf_cap, exp;
 	char tmp[8];
+	const char *unit;
 
 	tmp[0] = '\0';
 	i = 0;
-	if (size >= divisor[units]) {
-		while (size >= divisor[units]) {
-			remainder = do_div(size, divisor[units]);
-			i++;
-		}
+	if (!size)
+		goto out;
 
-		sf_cap = size;
-		for (j = 0; sf_cap*10 < 1000; j++)
-			sf_cap *= 10;
+	while (blk_size >= divisor[units]) {
+		remainder = do_div(blk_size, divisor[units]);
+		i++;
+	}
 
-		if (j) {
-			remainder *= 1000;
-			remainder /= divisor[units];
-			snprintf(tmp, sizeof(tmp), ".%03u", remainder);
-			tmp[j+1] = '\0';
-		}
+	exp = divisor[units] / (u32)blk_size;
+	if (size >= exp) {
+		remainder = do_div(size, divisor[units]);
+		remainder *= blk_size;
+		i++;
+	} else {
+		remainder *= size;
+	}
+
+	size *= blk_size;
+	size += remainder / divisor[units];
+	remainder %= divisor[units];
+
+	while (size >= divisor[units]) {
+		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;
+		remainder /= divisor[units];
+		snprintf(tmp, sizeof(tmp), ".%03u", remainder);
+		tmp[j+1] = '\0';
+	}
+
+ out:
+	if (i >= ARRAY_SIZE(units_2))
+		unit = "UNK";
+	else
+		unit = units_str[units][i];
+
 	snprintf(buf, len, "%u%s %s", (u32)size,
-		 tmp, units_str[units][i]);
+		 tmp, unit);
 }
 EXPORT_SYMBOL(string_get_size);