Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid counting disk io twice for NVMe SSD block device #1244

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions psutil/_pslinux.py
Original file line number Diff line number Diff line change
Expand Up @@ -1017,23 +1017,24 @@ def disk_io_counters():
system as a dict of raw tuples.
"""
# determine partitions we want to look for
partition_suffix = re.compile(r'^p*\d+$')

def get_partitions():
partitions = []
with open_text("%s/partitions" % get_procfs_path()) as f:
lines = f.readlines()[2:]
for line in reversed(lines):
_, _, _, name = line.split()
if name[-1].isdigit():
# we're dealing with a partition (e.g. 'sda1'); 'sda' will
# also be around but we want to omit it
partitions.append(name)
else:
if not partitions or not partitions[-1].startswith(name):
# we're dealing with a disk entity for which no
# partitions have been defined (e.g. 'sda' but
# 'sda1' was not around), see:
# https://github.com/giampaolo/psutil/issues/338
if partitions and partitions[-1].startswith(name):
suffix = partitions[-1][len(name):]
if not partition_suffix.match(suffix):
# If a disk entity (e.g. 'sda' or 'nvme0n1') has
# partition(e.g. 'sda1' or 'nvme0n1p1'),
# we will deal with the partition and ignore the
# disk entiy.
partitions.append(name)
else:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this incorrectly assumes the last disk it a partition.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kportertx
get_partitions returns both partitions and disk without any partitions. If the last disk is not a partition, it will be a disk without partition.

partitions.append(name)
return partitions

retdict = {}
Expand Down
33 changes: 33 additions & 0 deletions psutil/tests/test_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,39 @@ def open_mock(name, *args, **kwargs):
self.assertEqual(ret.write_time, 0)
self.assertEqual(ret.busy_time, 0)

def test_disk_io_counters_with_nvme(self):
def open_mock(name, *args, **kwargs):
if name == '/proc/partitions':
return io.StringIO(textwrap.dedent(u"""\
major minor #blocks name

259 0 250059096 nvme0n1
259 1 266240 nvme0n1p1
259 2 16384 nvme0n1p2
"""))
elif name == '/proc/diskstats':
return io.StringIO(textwrap.dedent(u"""\
259 0 nvme0n1 3 6 9 12 15 18 21 24 27 30 33
259 1 nvme0n1p1 1 2 3 4 5 6 7 8 9 10 11
259 2 nvme0n1p2 2 4 6 8 10 12 14 16 18 20 22
"""))
else:
return orig_open(name, *args, **kwargs)

orig_open = open
patch_point = 'builtins.open' if PY3 else '__builtin__.open'
with mock.patch(patch_point, side_effect=open_mock) as m:
ret = psutil.disk_io_counters(nowrap=False)
assert m.called
self.assertEqual(ret.read_count, 3)
self.assertEqual(ret.read_merged_count, 6)
self.assertEqual(ret.read_bytes, 9 * SECTOR_SIZE)
self.assertEqual(ret.read_time, 12)
self.assertEqual(ret.write_count, 15)
self.assertEqual(ret.write_merged_count, 18)
self.assertEqual(ret.write_bytes, 21 * SECTOR_SIZE)
self.assertEqual(ret.write_time, 24)
self.assertEqual(ret.busy_time, 30)

# =====================================================================
# --- misc
Expand Down