* Re: [patch 069/104] lib/string_helpers.c:string_get_size(): remove redundant prefixes
[not found] <54dd30d9.8sIvA5PVH18vSWTI%akpm@linux-foundation.org>
@ 2015-02-12 23:25 ` James Bottomley
2015-02-12 23:40 ` Andrew Morton
0 siblings, 1 reply; 7+ messages in thread
From: James Bottomley @ 2015-02-12 23:25 UTC (permalink / raw)
To: akpm; +Cc: torvalds, linux, linux-scsi
On Thu, 2015-02-12 at 15:01 -0800, akpm@linux-foundation.org wrote:
> From: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> Subject: lib/string_helpers.c:string_get_size(): remove redundant prefixes
>
> While 3c9f3681d0b4 "[SCSI] lib: add generic helper to print sizes rounded
> to the correct SI range" says that Z and Y are included in preparation for
> 128 bit computers, they just waste .text currently. If and when we get
> u128, string_get_size needs updating anyway (and ISO needs to come up with
> four more prefixes).
This is rubbish. It's nothing to do with 128 bits. This is to do with
disk sizes linux gets attached to. The current largest device clusters
are Petabytes ... I think we may have some exabyte ones somewhere in the
Academic community, so it's by no means inconcievable we'll have
Zettabyte ones within a few years. The SCSI standard, with 4k blocks
supports up to 2^76, which is well into Zettabytes. We obviously run
off the mmap possibilities a lot sooner, because of the byte offsets,
but that's fixable. Someone will probably start first by passing blocks
into that interface not bytes, so we'd like it not to be based on
assumptions that think 2^64 is the largest possible value.
> Also there's no need to include and test for the NULL sentinel; once we
> reach "E" size is at most 18. [The test is also wrong; it should be
> units_str[units][i+1]; if we've reached NULL we're already doomed.]
So fix the bug, don't set us up to run off the end of the array. And
please consult the community which keeps track of this rather than
trying to get it into Linux without review.
James
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch 069/104] lib/string_helpers.c:string_get_size(): remove redundant prefixes
2015-02-12 23:25 ` [patch 069/104] lib/string_helpers.c:string_get_size(): remove redundant prefixes James Bottomley
@ 2015-02-12 23:40 ` Andrew Morton
2015-02-12 23:45 ` James Bottomley
0 siblings, 1 reply; 7+ messages in thread
From: Andrew Morton @ 2015-02-12 23:40 UTC (permalink / raw)
To: James Bottomley; +Cc: torvalds, linux, linux-scsi
On Thu, 12 Feb 2015 15:25:08 -0800 James Bottomley <James.Bottomley@hansenpartnership.com> wrote:
> On Thu, 2015-02-12 at 15:01 -0800, akpm@linux-foundation.org wrote:
> > From: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> > Subject: lib/string_helpers.c:string_get_size(): remove redundant prefixes
> >
> > While 3c9f3681d0b4 "[SCSI] lib: add generic helper to print sizes rounded
> > to the correct SI range" says that Z and Y are included in preparation for
> > 128 bit computers, they just waste .text currently. If and when we get
> > u128, string_get_size needs updating anyway (and ISO needs to come up with
> > four more prefixes).
>
> This is rubbish. It's nothing to do with 128 bits. This is to do with
> disk sizes linux gets attached to. The current largest device clusters
> are Petabytes ... I think we may have some exabyte ones somewhere in the
> Academic community, so it's by no means inconcievable we'll have
> Zettabyte ones within a few years. The SCSI standard, with 4k blocks
> supports up to 2^76, which is well into Zettabytes. We obviously run
> off the mmap possibilities a lot sooner, because of the byte offsets,
> but that's fixable. Someone will probably start first by passing blocks
> into that interface not bytes, so we'd like it not to be based on
> assumptions that think 2^64 is the largest possible value.
I don't get it. As the man says, this is presently dead code and
string_get_size() will need to be changed to work for disks larger than
2^64 bytes. That change may be to take a u128 or it may be as you
suggest: replace the `u64 size' with `u64 size, u64 units' which is
effectively the same thing.
> > Also there's no need to include and test for the NULL sentinel; once we
> > reach "E" size is at most 18. [The test is also wrong; it should be
> > units_str[units][i+1]; if we've reached NULL we're already doomed.]
>
> So fix the bug, don't set us up to run off the end of the array. And
> please consult the community which keeps track of this rather than
> trying to get it into Linux without review.
That seems a bit harsh - you've been cc'ed on this every step of the way.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch 069/104] lib/string_helpers.c:string_get_size(): remove redundant prefixes
2015-02-12 23:40 ` Andrew Morton
@ 2015-02-12 23:45 ` James Bottomley
2015-02-12 23:55 ` Andrew Morton
0 siblings, 1 reply; 7+ messages in thread
From: James Bottomley @ 2015-02-12 23:45 UTC (permalink / raw)
To: Andrew Morton; +Cc: torvalds, linux, linux-scsi
On Thu, 2015-02-12 at 15:40 -0800, Andrew Morton wrote:
> On Thu, 12 Feb 2015 15:25:08 -0800 James Bottomley <James.Bottomley@hansenpartnership.com> wrote:
>
> > On Thu, 2015-02-12 at 15:01 -0800, akpm@linux-foundation.org wrote:
> > > From: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> > > Subject: lib/string_helpers.c:string_get_size(): remove redundant prefixes
> > >
> > > While 3c9f3681d0b4 "[SCSI] lib: add generic helper to print sizes rounded
> > > to the correct SI range" says that Z and Y are included in preparation for
> > > 128 bit computers, they just waste .text currently. If and when we get
> > > u128, string_get_size needs updating anyway (and ISO needs to come up with
> > > four more prefixes).
> >
> > This is rubbish. It's nothing to do with 128 bits. This is to do with
> > disk sizes linux gets attached to. The current largest device clusters
> > are Petabytes ... I think we may have some exabyte ones somewhere in the
> > Academic community, so it's by no means inconcievable we'll have
> > Zettabyte ones within a few years. The SCSI standard, with 4k blocks
> > supports up to 2^76, which is well into Zettabytes. We obviously run
> > off the mmap possibilities a lot sooner, because of the byte offsets,
> > but that's fixable. Someone will probably start first by passing blocks
> > into that interface not bytes, so we'd like it not to be based on
> > assumptions that think 2^64 is the largest possible value.
>
> I don't get it. As the man says, this is presently dead code and
> string_get_size() will need to be changed to work for disks larger than
> 2^64 bytes. That change may be to take a u128 or it may be as you
> suggest: replace the `u64 size' with `u64 size, u64 units' which is
> effectively the same thing.
The first thing someone's going to do is pass in blocks, because that's
the way the rest of block functions. If we're lucky the add "ZB" too,
but if not we run off the end in some obscure large cluster somewhere.
Don't set people up to make mistakes.
> > > Also there's no need to include and test for the NULL sentinel; once we
> > > reach "E" size is at most 18. [The test is also wrong; it should be
> > > units_str[units][i+1]; if we've reached NULL we're already doomed.]
> >
> > So fix the bug, don't set us up to run off the end of the array. And
> > please consult the community which keeps track of this rather than
> > trying to get it into Linux without review.
>
> That seems a bit harsh - you've been cc'ed on this every step of the way.
I think you need to check your scripts. This is the first time I've
seen this patch, which is why I'm reacting this way.
James
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch 069/104] lib/string_helpers.c:string_get_size(): remove redundant prefixes
2015-02-12 23:45 ` James Bottomley
@ 2015-02-12 23:55 ` Andrew Morton
2015-02-14 0:05 ` James Bottomley
0 siblings, 1 reply; 7+ messages in thread
From: Andrew Morton @ 2015-02-12 23:55 UTC (permalink / raw)
To: James Bottomley; +Cc: torvalds, linux, linux-scsi
On Thu, 12 Feb 2015 15:45:29 -0800 James Bottomley <James.Bottomley@hansenpartnership.com> wrote:
> ...
>
> > I don't get it. As the man says, this is presently dead code and
> > string_get_size() will need to be changed to work for disks larger than
> > 2^64 bytes. That change may be to take a u128 or it may be as you
> > suggest: replace the `u64 size' with `u64 size, u64 units' which is
> > effectively the same thing.
>
> The first thing someone's going to do is pass in blocks, because that's
> the way the rest of block functions. If we're lucky the add "ZB" too,
> but if not we run off the end in some obscure large cluster somewhere.
> Don't set people up to make mistakes.
Well maybe. A little bit. But it assumes that someone is going to
make a change then not test it.
> > > > Also there's no need to include and test for the NULL sentinel; once we
> > > > reach "E" size is at most 18. [The test is also wrong; it should be
> > > > units_str[units][i+1]; if we've reached NULL we're already doomed.]
> > >
> > > So fix the bug, don't set us up to run off the end of the array. And
> > > please consult the community which keeps track of this rather than
> > > trying to get it into Linux without review.
> >
> > That seems a bit harsh - you've been cc'ed on this every step of the way.
>
> I think you need to check your scripts. This is the first time I've
> seen this patch, which is why I'm reacting this way.
No, James.Bottomley@HansenPartnership.com was cc'ed on the original
email and on the -mm spam.
Perhaps Rasmus should should also have cc'ed linux-scsi - practice
seems to vary a lot. But he did cc the scsi maintainer and the author
of the patch he was modifying (yourself).
So I think the patch is reasonable and the way Rasmus and I handled it
is also reasonable. Going nuts at us over it isn't reasonable!
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch 069/104] lib/string_helpers.c:string_get_size(): remove redundant prefixes
2015-02-12 23:55 ` Andrew Morton
@ 2015-02-14 0:05 ` James Bottomley
2015-02-14 1:02 ` Andrew Morton
0 siblings, 1 reply; 7+ messages in thread
From: James Bottomley @ 2015-02-14 0:05 UTC (permalink / raw)
To: Andrew Morton; +Cc: torvalds, linux, linux-scsi
On Thu, 2015-02-12 at 15:55 -0800, Andrew Morton wrote:
> On Thu, 12 Feb 2015 15:45:29 -0800 James Bottomley <James.Bottomley@hansenpartnership.com> wrote:
>
> > ...
> >
> > > I don't get it. As the man says, this is presently dead code and
> > > string_get_size() will need to be changed to work for disks larger than
> > > 2^64 bytes. That change may be to take a u128 or it may be as you
> > > suggest: replace the `u64 size' with `u64 size, u64 units' which is
> > > effectively the same thing.
> >
> > The first thing someone's going to do is pass in blocks, because that's
> > the way the rest of block functions. If we're lucky the add "ZB" too,
> > but if not we run off the end in some obscure large cluster somewhere.
> > Don't set people up to make mistakes.
>
> Well maybe. A little bit. But it assumes that someone is going to
> make a change then not test it.
That would be SOP for very large devices ... very few developers have
access. However, since it's easy to fix, I'll do that instead of
complaining about the lack of analysis.
This fixes the routine and all the call sites to pass arguments in in
terms of a known block size. Given that all the callers were scaling
from blocks to bytes anyway, it fits naturally and fixes the overflow
that would occur with very large devices in the old scheme.
James
---
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index cdfbd21..26d2440 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -344,7 +344,7 @@ static void virtblk_config_changed_work(struct work_struct *work)
struct request_queue *q = vblk->disk->queue;
char cap_str_2[10], cap_str_10[10];
char *envp[] = { "RESIZE=1", NULL };
- u64 capacity, size;
+ u64 capacity;
/* Host must always specify the capacity. */
virtio_cread(vdev, struct virtio_blk_config, capacity, &capacity);
@@ -356,9 +356,10 @@ static void virtblk_config_changed_work(struct work_struct *work)
capacity = (sector_t)-1;
}
- size = capacity * queue_logical_block_size(q);
- string_get_size(size, STRING_UNITS_2, cap_str_2, sizeof(cap_str_2));
- string_get_size(size, STRING_UNITS_10, cap_str_10, sizeof(cap_str_10));
+ string_get_size(capacity, queue_logical_block_size(q),
+ STRING_UNITS_2, cap_str_2, sizeof(cap_str_2));
+ string_get_size(capacity, queue_logical_block_size(q),
+ STRING_UNITS_10, cap_str_10, sizeof(cap_str_10));
dev_notice(&vdev->dev,
"new size: %llu %d-byte logical blocks (%s/%s)\n",
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index c69afb5..2fc4269 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -2230,7 +2230,7 @@ static int mmc_blk_alloc_part(struct mmc_card *card,
part_md->part_type = part_type;
list_add(&part_md->part, &md->part);
- string_get_size((u64)get_capacity(part_md->disk) << 9, STRING_UNITS_2,
+ string_get_size((u64)get_capacity(part_md->disk), 512, STRING_UNITS_2,
cap_str, sizeof(cap_str));
pr_info("%s: %s %s partition %u %s\n",
part_md->disk->disk_name, mmc_card_id(card),
@@ -2436,7 +2436,7 @@ static int mmc_blk_probe(struct device *dev)
if (IS_ERR(md))
return PTR_ERR(md);
- string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
+ string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2,
cap_str, sizeof(cap_str));
pr_info("%s: %s %s %s %s\n",
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 6b78476..3c7fe4e 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2235,11 +2235,11 @@ got_data:
{
char cap_str_2[10], cap_str_10[10];
- u64 sz = (u64)sdkp->capacity << ilog2(sector_size);
- string_get_size(sz, STRING_UNITS_2, cap_str_2,
- sizeof(cap_str_2));
- string_get_size(sz, STRING_UNITS_10, cap_str_10,
+ string_get_size(sdkp->capacity, sector_size,
+ STRING_UNITS_2, cap_str_2, sizeof(cap_str_2));
+ string_get_size(sdkp->capacity, sector_size,
+ STRING_UNITS_10, cap_str_10,
sizeof(cap_str_10));
if (sdkp->first_scan || old_capacity != sdkp->capacity) {
diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h
index 6575718..2633280 100644
--- a/include/linux/string_helpers.h
+++ b/include/linux/string_helpers.h
@@ -10,7 +10,7 @@ enum string_size_units {
STRING_UNITS_2, /* use binary powers of 2^10 */
};
-void string_get_size(u64 size, enum string_size_units units,
+void string_get_size(u64 size, u64 blk_size, enum string_size_units units,
char *buf, int len);
#define UNESCAPE_SPACE 0x01
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 8f8c441..bff19f8 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,60 @@ 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)
+ goto out;
+
+ if (blk_size >= divisor[units]) {
+ while (blk_size >= divisor[units]) {
+ remainder = do_div(blk_size, divisor[units]);
+ i++;
+ }
+ }
+ exp = divisor[units];
+ do_div(exp, 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];
+
if (size >= 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;
+ 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';
- }
+ 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);
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [patch 069/104] lib/string_helpers.c:string_get_size(): remove redundant prefixes
2015-02-14 0:05 ` James Bottomley
@ 2015-02-14 1:02 ` Andrew Morton
2015-02-14 4:03 ` James Bottomley
0 siblings, 1 reply; 7+ messages in thread
From: Andrew Morton @ 2015-02-14 1:02 UTC (permalink / raw)
To: James Bottomley; +Cc: torvalds, linux, linux-scsi
On Fri, 13 Feb 2015 16:05:54 -0800 James Bottomley <James.Bottomley@hansenpartnership.com> wrote:
> @@ -42,31 +44,60 @@ 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)
> + goto out;
whitespace wart.
> + if (blk_size >= divisor[units]) {
> + while (blk_size >= divisor[units]) {
> + remainder = do_div(blk_size, divisor[units]);
> + i++;
> + }
> + }
The `if' doesn't do anything.
> + exp = divisor[units];
> + do_div(exp, 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];
> +
> if (size >= divisor[units]) {
> while (size >= divisor[units]) {
> remainder = do_div(size, divisor[units]);
> i++;
> }
> + }
Here too.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch 069/104] lib/string_helpers.c:string_get_size(): remove redundant prefixes
2015-02-14 1:02 ` Andrew Morton
@ 2015-02-14 4:03 ` James Bottomley
0 siblings, 0 replies; 7+ messages in thread
From: James Bottomley @ 2015-02-14 4:03 UTC (permalink / raw)
To: Andrew Morton; +Cc: torvalds, linux, linux-scsi
On Fri, 2015-02-13 at 17:02 -0800, Andrew Morton wrote:
> On Fri, 13 Feb 2015 16:05:54 -0800 James Bottomley <James.Bottomley@hansenpartnership.com> wrote:
>
> > @@ -42,31 +44,60 @@ 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)
> > + goto out;
>
> whitespace wart.
Yes, I'll run it through checkpatch before submitting.
> > + if (blk_size >= divisor[units]) {
> > + while (blk_size >= divisor[units]) {
> > + remainder = do_div(blk_size, divisor[units]);
> > + i++;
> > + }
> > + }
>
> The `if' doesn't do anything.
Right ... I just copied from the original, but it's true we can unwrap
this.
> > + exp = divisor[units];
> > + do_div(exp, 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];
> > +
> > if (size >= divisor[units]) {
> > while (size >= divisor[units]) {
> > remainder = do_div(size, divisor[units]);
> > i++;
> > }
> > + }
>
> Here too.
Certainly,
James
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2015-02-14 4:03 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <54dd30d9.8sIvA5PVH18vSWTI%akpm@linux-foundation.org>
2015-02-12 23:25 ` [patch 069/104] lib/string_helpers.c:string_get_size(): remove redundant prefixes James Bottomley
2015-02-12 23:40 ` Andrew Morton
2015-02-12 23:45 ` James Bottomley
2015-02-12 23:55 ` Andrew Morton
2015-02-14 0:05 ` James Bottomley
2015-02-14 1:02 ` Andrew Morton
2015-02-14 4:03 ` James Bottomley
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox