Thread (4 messages) 4 messages, 3 authors, 2018-12-09

Re: [PATCH,1/2] genhd: avoid overflow of sectors in disk_stats

From: Huijin Park <hidden>
Date: 2018-12-09 14:45:16
Also in: linux-block, lkml

Hi Omar Sandoval,

On Sat, Dec 1, 2018 at 4:56 AM Omar Sandoval [off-list ref] wrote:
On Fri, Nov 30, 2018 at 04:32:40AM -0500, Huijin Park wrote:
quoted
From: "huijin.park" <redacted>

This patch changes the 'sectors' type to an u64.
In 32 bit system, the 'sectors' can accumulate up to about 2TiB.
If a 32 bit system makes i/o over 2TiB while running,
the 'sectors' will overflow.
As a result, the part_stat_read(sectors), the diskstats in proc and
the (lifetime|session)_write_kbytes in sysfs return invalid statistic.
What about parsers which expect it to be an unsigned long? E.g., iostat:
https://github.com/sysstat/sysstat/blob/v12.1.1/rd_stats.c#L736

At least with glibc, scanf seems to truncate sanely, but this appears to
be undefined.
The glibc APIs such as scanf and strtoul set return value and errno
to ULONG_MAX and ERANGE in overflow case.
I think ULONG_MAX and ERANGE are better than reset to zero because
of overflow. At least, application can notice overflow with errno.
Besides nowadays, a 32 bit is not enough size to show
an i/o accumulated size.
I met a problem like below. So I suggested this patch.

sh-3.2# mount | grep p19
/dev/mmcblk0p19 on /ext4_dir type ext4 (rw,relatime,data=ordered)
sh-3.2# cat /sys/fs/ext4/mmcblk0p19/session_write_kbytes
2147467268
sh-3.2# cat /sys/fs/ext4/mmcblk0p19/lifetime_write_kbytes
2147568561
sh-3.2# dd if=/dev/zero of=/ext4_dir/temp.bin bs=1M count=20 oflag=sync
20+0 records in
20+0 records out
20971520 bytes (21 MB) copied,
0.621939 s, 33.7 MB/s
sh-3.2# cat /sys/fs/ext4/mmcblk0p19/session_write_kbytes
4524
sh-3.2# cat /sys/fs/ext4/mmcblk0p19/lifetime_write_kbytes
105817
quoted
Signed-off-by: huijin.park <redacted>
---
 block/genhd.c         |    6 +++---
 include/linux/genhd.h |    2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/block/genhd.c b/block/genhd.c
index 0145bcb..7518dcd 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1343,10 +1343,10 @@ static int diskstats_show(struct seq_file *seqf, void *v)
              part_stat_unlock();
              part_in_flight(gp->queue, hd, inflight);
              seq_printf(seqf, "%4d %7d %s "
-                        "%lu %lu %lu %u "
-                        "%lu %lu %lu %u "
+                        "%lu %lu %llu %u "
+                        "%lu %lu %llu %u "
                         "%u %u %u "
-                        "%lu %lu %lu %u\n",
+                        "%lu %lu %llu %u\n",
                         MAJOR(part_devt(hd)), MINOR(part_devt(hd)),
                         disk_name(gp, hd->partno, buf),
                         part_stat_read(hd, ios[STAT_READ]),
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 0c5ee17..5bf86f9 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -84,7 +84,7 @@ struct partition {

 struct disk_stats {
      u64 nsecs[NR_STAT_GROUPS];
-     unsigned long sectors[NR_STAT_GROUPS];
+     u64 sectors[NR_STAT_GROUPS];
      unsigned long ios[NR_STAT_GROUPS];
      unsigned long merges[NR_STAT_GROUPS];
      unsigned long io_ticks;
--
1.7.9.5
Thanks,
Huijin
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help