Commit 3c9f3681d0b4af09c1cbf04f92fdfb72bd81ad7b

Authored by James Bottomley
1 parent 114f1ea408

[SCSI] lib: add generic helper to print sizes rounded to the correct SI range

This patch adds the ability to print sizes in either units of 10^3 (SI)
or 2^10 (Binary) units.  It rounds up to three significant figures and
can be used for either memory or storage capacities.

Oh, and I'm fully aware that 64 bits is only 16EiB ... the Zetta and
Yotta units are added for future proofing against the day we have 128
bit computers ...

[fujita.tomonori@lab.ntt.co.jp: fix missed unsigned long long cast]
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>

Showing 3 changed files with 82 additions and 1 deletions Side-by-side Diff

include/linux/string_helpers.h
  1 +#ifndef _LINUX_STRING_HELPERS_H_
  2 +#define _LINUX_STRING_HELPERS_H_
  3 +
  4 +#include <linux/types.h>
  5 +
  6 +/* Descriptions of the types of units to
  7 + * print in */
  8 +enum string_size_units {
  9 + STRING_UNITS_10, /* use powers of 10^3 (standard SI) */
  10 + STRING_UNITS_2, /* use binary powers of 2^10 */
  11 +};
  12 +
  13 +int string_get_size(u64 size, enum string_size_units units,
  14 + char *buf, int len);
  15 +
  16 +#endif
... ... @@ -19,7 +19,8 @@
19 19 lib-y += kobject.o kref.o klist.o
20 20  
21 21 obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
22   - bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o
  22 + bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
  23 + string_helpers.o
23 24  
24 25 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
25 26 CFLAGS_kobject.o += -DDEBUG
lib/string_helpers.c
  1 +/*
  2 + * Helpers for formatting and printing strings
  3 + *
  4 + * Copyright 31 August 2008 James Bottomley
  5 + */
  6 +#include <linux/kernel.h>
  7 +#include <linux/math64.h>
  8 +#include <linux/module.h>
  9 +#include <linux/string_helpers.h>
  10 +
  11 +/**
  12 + * string_get_size - get the size in the specified units
  13 + * @size: The size to be converted
  14 + * @units: units to use (powers of 1000 or 1024)
  15 + * @buf: buffer to format to
  16 + * @len: length of buffer
  17 + *
  18 + * This function returns a string formatted to 3 significant figures
  19 + * giving the size in the required units. Returns 0 on success or
  20 + * error on failure. @buf is always zero terminated.
  21 + *
  22 + */
  23 +int string_get_size(u64 size, const enum string_size_units units,
  24 + char *buf, int len)
  25 +{
  26 + const char *units_10[] = { "B", "KB", "MB", "GB", "TB", "PB",
  27 + "EB", "ZB", "YB", NULL};
  28 + const char *units_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB",
  29 + "EiB", "ZiB", "YiB", NULL };
  30 + const char **units_str[] = {
  31 + [STRING_UNITS_10] = units_10,
  32 + [STRING_UNITS_2] = units_2,
  33 + };
  34 + const int divisor[] = {
  35 + [STRING_UNITS_10] = 1000,
  36 + [STRING_UNITS_2] = 1024,
  37 + };
  38 + int i, j;
  39 + u64 remainder = 0, sf_cap;
  40 + char tmp[8];
  41 +
  42 + tmp[0] = '\0';
  43 +
  44 + for (i = 0; size > divisor[units] && units_str[units][i]; i++)
  45 + remainder = do_div(size, divisor[units]);
  46 +
  47 + sf_cap = size;
  48 + for (j = 0; sf_cap*10 < 1000; j++)
  49 + sf_cap *= 10;
  50 +
  51 + if (j) {
  52 + remainder *= 1000;
  53 + do_div(remainder, divisor[units]);
  54 + snprintf(tmp, sizeof(tmp), ".%03lld",
  55 + (unsigned long long)remainder);
  56 + tmp[j+1] = '\0';
  57 + }
  58 +
  59 + snprintf(buf, len, "%lld%s%s", (unsigned long long)size,
  60 + tmp, units_str[units][i]);
  61 +
  62 + return 0;
  63 +}
  64 +EXPORT_SYMBOL(string_get_size);