master - vgrename: add missing trace on error path
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=0a73a5012aece3...
Commit: 0a73a5012aece3d0f7fd03a270cfe5067c1fafc8
Parent: 96dc03b33782cf0e33f5fdf57cd8eb475e4bd7c9
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu Sep 3 10:38:16 2015 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Thu Sep 3 10:38:16 2015 -0500
vgrename: add missing trace on error path
---
tools/vgrename.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/tools/vgrename.c b/tools/vgrename.c
index 620345b..316228a 100644
--- a/tools/vgrename.c
+++ b/tools/vgrename.c
@@ -149,8 +149,10 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
if (!drop_cached_metadata(vg))
stack;
- if (!lockd_rename_vg_before(cmd, vg))
+ if (!lockd_rename_vg_before(cmd, vg)) {
+ stack;
goto error;
+ }
/* Change the volume group name */
vg_rename(cmd, vg, vg_name_new);
8 years, 7 months
master - lockd: vgrename fixes
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=96dc03b33782cf...
Commit: 96dc03b33782cf0e33f5fdf57cd8eb475e4bd7c9
Parent: d1d00fdeec04b1c856dfbe2d1ad8914e0968acfb
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu Sep 3 10:21:44 2015 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Thu Sep 3 10:21:44 2015 -0500
lockd: vgrename fixes
If busy locks in lvmlockd prevent vgrename, use the
correct error exit path, and print a user-friendly
error message.
---
lib/locking/lvmlockd.c | 6 ++++++
tools/vgrename.c | 2 +-
2 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c
index f3e2e2c..983ecc9 100644
--- a/lib/locking/lvmlockd.c
+++ b/lib/locking/lvmlockd.c
@@ -2423,6 +2423,12 @@ int lockd_rename_vg_before(struct cmd_context *cmd, struct volume_group *vg)
}
daemon_reply_destroy(reply);
+
+ /* Other hosts have not stopped the lockspace. */
+ if (result == -EBUSY) {
+ log_error("Lockspace for \"%s\" not stopped on other hosts", vg->name);
+ return 0;
+ }
if (!ret) {
log_error("lockd_rename_vg_before lvmlockd result %d", result);
diff --git a/tools/vgrename.c b/tools/vgrename.c
index 7e77b57..620345b 100644
--- a/tools/vgrename.c
+++ b/tools/vgrename.c
@@ -150,7 +150,7 @@ static int vg_rename_path(struct cmd_context *cmd, const char *old_vg_path,
stack;
if (!lockd_rename_vg_before(cmd, vg))
- return_0;
+ goto error;
/* Change the volume group name */
vg_rename(cmd, vg, vg_name_new);
8 years, 7 months
master - dev-cache: append (major:minor) to debug messages about adding device or its alias to cache
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=d1d00fdeec04b1...
Commit: d1d00fdeec04b1c856dfbe2d1ad8914e0968acfb
Parent: 00b610e5429582a4a62cdd2d475064dafab6fe87
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Sep 3 14:36:15 2015 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Sep 3 14:36:15 2015 +0200
dev-cache: append (major:minor) to debug messages about adding device or its alias to cache
device/dev-cache.c:350 /dev/sda: Added to device cache (8:0)
device/dev-cache.c:346 /dev/disk/by-id/lvm-pv-uuid-5nPovF-EWp4-vBwd-ylCJ-9Y0B-yzHQ-ek1li2: Aliased to /dev/sda in device cache (8:0)
...
---
lib/device/dev-cache.c | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/lib/device/dev-cache.c b/lib/device/dev-cache.c
index 043a722..4ed0130 100644
--- a/lib/device/dev-cache.c
+++ b/lib/device/dev-cache.c
@@ -341,11 +341,13 @@ static int _add_alias(struct device *dev, const char *path)
if (!dm_list_empty(&dev->aliases)) {
oldpath = dm_list_item(dev->aliases.n, struct dm_str_list)->str;
prefer_old = _compare_paths(path, oldpath);
- log_debug_devs("%s: Aliased to %s in device cache%s",
- path, oldpath, prefer_old ? "" : " (preferred name)");
+ log_debug_devs("%s: Aliased to %s in device cache%s (%d:%d)",
+ path, oldpath, prefer_old ? "" : " (preferred name)",
+ (int) MAJOR(dev->dev), (int) MINOR(dev->dev));
} else
- log_debug_devs("%s: Added to device cache", path);
+ log_debug_devs("%s: Added to device cache (%d:%d)", path,
+ (int) MAJOR(dev->dev), (int) MINOR(dev->dev));
if (prefer_old)
dm_list_add(&dev->aliases, &sl->list);
8 years, 7 months
master - filters: do not print [none:nil] as external device info's [source:handler] if "none" source is used
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=00b610e5429582...
Commit: 00b610e5429582a4a62cdd2d475064dafab6fe87
Parent: fc35b6988d65fe3f11a3f668cd8f01fe3294b562
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Sep 3 14:19:48 2015 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Sep 3 14:19:48 2015 +0200
filters: do not print [none:nil] as external device info's [source:handler] if "none" source is used
Print [source:handler] in filters' debug messages only if external
device info source other than "none" is used.
$ lvmconfig --type full devices/external_device_info_source
external_device_info_source="none
Before this patch (from the -vvvv log):
filters/filter-usable.c:47 /dev/mapper/test: Skipping: Too small to hold a PV [none:(nil)]
filters/filter-md.c:33 /dev/sdb: Skipping md component device [none:(nil)]
filters/filter-partitioned.c:25 /dev/vda: Skipping: Partition table signature found [none:(nil)]
With this patch applied:
filters/filter-usable.c:44 /dev/mapper/test: Skipping: Too small to hold a PV
filters/filter-md.c:35 /dev/sdb: Skipping md component device
filters/filter-partitioned.c:27 /dev/vda: Skipping: Partition table signature found
---
lib/filters/filter-fwraid.c | 9 +++++++--
lib/filters/filter-md.c | 9 +++++++--
lib/filters/filter-mpath.c | 9 +++++++--
lib/filters/filter-partitioned.c | 9 +++++++--
lib/filters/filter-usable.c | 11 ++++-------
5 files changed, 32 insertions(+), 15 deletions(-)
diff --git a/lib/filters/filter-fwraid.c b/lib/filters/filter-fwraid.c
index f16833e..0b3804f 100644
--- a/lib/filters/filter-fwraid.c
+++ b/lib/filters/filter-fwraid.c
@@ -61,6 +61,8 @@ static int _dev_is_fwraid(struct device *dev)
return 0;
}
+#define MSG_SKIPPING "%s: Skipping firmware RAID component device"
+
static int _ignore_fwraid(struct dev_filter *f __attribute__((unused)),
struct device *dev)
{
@@ -72,8 +74,11 @@ static int _ignore_fwraid(struct dev_filter *f __attribute__((unused)),
ret = _dev_is_fwraid(dev);
if (ret == 1) {
- log_debug_devs("%s: Skipping firmware RAID component device [%s:%p]",
- dev_name(dev), dev_ext_name(dev), dev->ext.handle);
+ if (dev->ext.src == DEV_EXT_NONE)
+ log_debug_devs(MSG_SKIPPING, dev_name(dev));
+ else
+ log_debug_devs(MSG_SKIPPING " [%s:%p]", dev_name(dev),
+ dev_ext_name(dev), dev->ext.handle);
return 0;
}
diff --git a/lib/filters/filter-md.c b/lib/filters/filter-md.c
index ad9f540..f4e3613 100644
--- a/lib/filters/filter-md.c
+++ b/lib/filters/filter-md.c
@@ -18,6 +18,8 @@
#ifdef __linux__
+#define MSG_SKIPPING "%s: Skipping md component device"
+
static int _ignore_md(struct dev_filter *f __attribute__((unused)),
struct device *dev)
{
@@ -29,8 +31,11 @@ static int _ignore_md(struct dev_filter *f __attribute__((unused)),
ret = dev_is_md(dev, NULL);
if (ret == 1) {
- log_debug_devs("%s: Skipping md component device [%s:%p]",
- dev_name(dev), dev_ext_name(dev), dev->ext.handle);
+ if (dev->ext.src == DEV_EXT_NONE)
+ log_debug_devs(MSG_SKIPPING, dev_name(dev));
+ else
+ log_debug_devs(MSG_SKIPPING " [%s:%p]", dev_name(dev),
+ dev_ext_name(dev), dev->ext.handle);
return 0;
}
diff --git a/lib/filters/filter-mpath.c b/lib/filters/filter-mpath.c
index 0016a51..692e83f 100644
--- a/lib/filters/filter-mpath.c
+++ b/lib/filters/filter-mpath.c
@@ -244,11 +244,16 @@ static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
return 0;
}
+#define MSG_SKIPPING "%s: Skipping mpath component device"
+
static int _ignore_mpath(struct dev_filter *f, struct device *dev)
{
if (_dev_is_mpath(f, dev) == 1) {
- log_debug_devs("%s: Skipping mpath component device [%s:%p]",
- dev_name(dev), dev_ext_name(dev), dev->ext.handle);
+ if (dev->ext.src == DEV_EXT_NONE)
+ log_debug_devs(MSG_SKIPPING, dev_name(dev));
+ else
+ log_debug_devs(MSG_SKIPPING " [%s:%p]", dev_name(dev),
+ dev_ext_name(dev), dev->ext.handle);
return 0;
}
diff --git a/lib/filters/filter-partitioned.c b/lib/filters/filter-partitioned.c
index 9ca8f6f..be0ea99 100644
--- a/lib/filters/filter-partitioned.c
+++ b/lib/filters/filter-partitioned.c
@@ -16,13 +16,18 @@
#include "lib.h"
#include "filter.h"
+#define MSG_SKIPPING "%s: Skipping: Partition table signature found"
+
static int _passes_partitioned_filter(struct dev_filter *f, struct device *dev)
{
struct dev_types *dt = (struct dev_types *) f->private;
if (dev_is_partitioned(dt, dev)) {
- log_debug_devs("%s: Skipping: Partition table signature found [%s:%p]",
- dev_name(dev), dev_ext_name(dev), dev->ext.handle);
+ if (dev->ext.src == DEV_EXT_NONE)
+ log_debug_devs(MSG_SKIPPING, dev_name(dev));
+ else
+ log_debug_devs(MSG_SKIPPING " [%s:%p]", dev_name(dev),
+ dev_ext_name(dev), dev->ext.handle);
return 0;
}
diff --git a/lib/filters/filter-usable.c b/lib/filters/filter-usable.c
index a4cfc69..e39cb54 100644
--- a/lib/filters/filter-usable.c
+++ b/lib/filters/filter-usable.c
@@ -29,22 +29,19 @@ static int _native_check_pv_min_size(struct device *dev)
/* Check it's accessible */
if (!dev_open_readonly_quiet(dev)) {
- log_debug_devs("%s: Skipping: open failed [%s:%p]",
- dev_name(dev), dev_ext_name(dev), dev->ext.handle);
+ log_debug_devs("%s: Skipping: open failed", dev_name(dev));
return 0;
}
/* Check it's not too small */
if (!dev_get_size(dev, &size)) {
- log_debug_devs("%s: Skipping: dev_get_size failed [%s:%p]",
- dev_name(dev), dev_ext_name(dev), dev->ext.handle);
+ log_debug_devs("%s: Skipping: dev_get_size failed", dev_name(dev));
goto out;
}
if (size < pv_min_size()) {
- log_debug_devs("%s: Skipping: %s [%s:%p]", dev_name(dev),
- _too_small_to_hold_pv_msg,
- dev_ext_name(dev), dev->ext.handle);
+ log_debug_devs("%s: Skipping: %s", dev_name(dev),
+ _too_small_to_hold_pv_msg);
goto out;
}
8 years, 7 months
master - libdm: pkgconfig: fix devmapper.pc to not reference nonexistent rt.pc file
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=fc35b6988d65fe...
Commit: fc35b6988d65fe3f11a3f668cd8f01fe3294b562
Parent: b86bd3b074e2f2e7574487b35a6559893bb5a44a
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu Sep 3 09:28:42 2015 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Thu Sep 3 09:28:42 2015 +0200
libdm: pkgconfig: fix devmapper.pc to not reference nonexistent rt.pc file
librt doesn't have a pkgconfig file so use Libs.private: -lrt instead
to declare the dependency directly.
The same applies for -lm which is also used and which hasn't been
defined in the devmapper.pc file yet.
---
WHATS_NEW_DM | 1 +
configure | 4 ++--
configure.in | 4 ++--
libdm/libdevmapper.pc.in | 3 ++-
4 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 6852e61..8d74222 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.107 -
===================================
+ Fix devmapper.pc pkgconfig file to not reference non-existent rt.pc file.
Reinstate dm_task_get_info@Base to libdevmapper exports. (1.02.106)
Version 1.02.106 - 26th August 2015
diff --git a/configure b/configure
index ff914d8..f4820c4 100755
--- a/configure
+++ b/configure
@@ -659,7 +659,7 @@ SELINUX_PC
SELINUX_LIBS
REPLICATORS
READLINE_LIBS
-RT_PC
+RT_LIB
RAID
PYTHON_LIBDIRS
PYTHON_INCDIRS
@@ -12847,7 +12847,7 @@ fi
$as_echo "#define HAVE_REALTIME 1" >>confdefs.h
LIBS="-lrt $LIBS"
- RT_PC="librt"
+ RT_LIB="-lrt"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Disabling realtime clock" >&5
$as_echo "$as_me: WARNING: Disabling realtime clock" >&2;}
diff --git a/configure.in b/configure.in
index dfd105a..3d83af5 100644
--- a/configure.in
+++ b/configure.in
@@ -1581,7 +1581,7 @@ if test "$REALTIME" = yes; then
if test "$HAVE_REALTIME" = yes; then
AC_DEFINE([HAVE_REALTIME], 1, [Define to 1 to include support for realtime clock.])
LIBS="-lrt $LIBS"
- RT_PC="librt"
+ RT_LIB="-lrt"
else
AC_MSG_WARN(Disabling realtime clock)
fi
@@ -1995,7 +1995,7 @@ AC_SUBST(PYTHON_LIBDIRS)
AC_SUBST(QUORUM_CFLAGS)
AC_SUBST(QUORUM_LIBS)
AC_SUBST(RAID)
-AC_SUBST(RT_PC)
+AC_SUBST(RT_LIB)
AC_SUBST(READLINE_LIBS)
AC_SUBST(REPLICATORS)
AC_SUBST(SACKPT_CFLAGS)
diff --git a/libdm/libdevmapper.pc.in b/libdm/libdevmapper.pc.in
index 63c0720..f29f920 100644
--- a/libdm/libdevmapper.pc.in
+++ b/libdm/libdevmapper.pc.in
@@ -8,4 +8,5 @@ Description: device-mapper library
Version: @DM_LIB_PATCHLEVEL@
Cflags: -I${includedir}
Libs: -L${libdir} -ldevmapper
-Requires.private: @SELINUX_PC@ @UDEV_PC@ @RT_PC@
+Requires.private: @SELINUX_PC@ @UDEV_PC@
+Libs.private: -lm @RT_LIB@
8 years, 7 months
master - man: fix typo in dmstats.8.in
by Bryn Reeves
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=b86bd3b074e2f2...
Commit: b86bd3b074e2f2e7574487b35a6559893bb5a44a
Parent: 341460178871140500cf14c89022e013ced943d5
Author: Bryn M. Reeves <bmr(a)redhat.com>
AuthorDate: Wed Sep 2 23:01:46 2015 +0100
Committer: Bryn M. Reeves <bmr(a)redhat.com>
CommitterDate: Wed Sep 2 23:01:46 2015 +0100
man: fix typo in dmstats.8.in
---
man/dmstats.8.in | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/man/dmstats.8.in b/man/dmstats.8.in
index 3ffd534..daa489d 100644
--- a/man/dmstats.8.in
+++ b/man/dmstats.8.in
@@ -1,4 +1,4 @@
-eTH DMSTATS 8 "Jul 25 2015" "Linux" "MAINTENANCE COMMANDS"
+.TH DMSTATS 8 "Jul 25 2015" "Linux" "MAINTENANCE COMMANDS"
.SH NAME
dmstats \(em device-mapper statistics management
.SH SYNOPSIS
8 years, 7 months
master - man: document --regionid in dmstats.8.in
by Bryn Reeves
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=34146017887114...
Commit: 341460178871140500cf14c89022e013ced943d5
Parent: d31c4e0bc12fb673d4b30ba8846eec8e27ae6276
Author: Bryn M. Reeves <bmr(a)redhat.com>
AuthorDate: Wed Sep 2 20:35:43 2015 +0100
Committer: Bryn M. Reeves <bmr(a)redhat.com>
CommitterDate: Wed Sep 2 21:03:03 2015 +0100
man: document --regionid in dmstats.8.in
---
man/dmstats.8.in | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/man/dmstats.8.in b/man/dmstats.8.in
index 69ba2a3..3ffd534 100644
--- a/man/dmstats.8.in
+++ b/man/dmstats.8.in
@@ -1,4 +1,4 @@
-.TH DMSTATS 8 "Jul 25 2015" "Linux" "MAINTENANCE COMMANDS"
+eTH DMSTATS 8 "Jul 25 2015" "Linux" "MAINTENANCE COMMANDS"
.SH NAME
dmstats \(em device-mapper statistics management
.SH SYNOPSIS
@@ -223,6 +223,9 @@ string is stored with the region. Subsequent operations may supply a
program ID in order to select only regions with a matching value. The
default program ID for dmstats-managed regions is "dmstats".
.TP
+.BR \-\-regionid \fIid
+Specify the region to operate on.
+.TP
.BR \-\-relative
If displaying the histogram report show relative (percentage) values
instead of absolute counts.
8 years, 7 months
master - man: update dmstats.8.in examples
by Bryn Reeves
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=d31c4e0bc12fb6...
Commit: d31c4e0bc12fb673d4b30ba8846eec8e27ae6276
Parent: 031cd2bb0dc436619b1e186512a024ea095c2324
Author: Bryn M. Reeves <bmr(a)redhat.com>
AuthorDate: Wed Sep 2 12:19:13 2015 +0100
Committer: Bryn M. Reeves <bmr(a)redhat.com>
CommitterDate: Wed Sep 2 21:03:03 2015 +0100
man: update dmstats.8.in examples
Make sure that correct 'dmstats create' messages are shown for all
examples and fix LV examples to use correct dmsetup output name
format (vg/lv -> vg-lv).
---
man/dmstats.8.in | 22 +++++++++++-----------
1 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/man/dmstats.8.in b/man/dmstats.8.in
index eb8f400..69ba2a3 100644
--- a/man/dmstats.8.in
+++ b/man/dmstats.8.in
@@ -779,17 +779,17 @@ Create a whole-device region with 8 areas on every device
.br
# dmstats create --areas 8
.br
-vg00/lvol1: Created new region with 8 area(s) as region ID 0
+vg00-lvol1: Created new region with 8 area(s) as region ID 0
.br
-vg00/lvol2: Created new region with 8 area(s) as region ID 0
+vg00-lvol2: Created new region with 8 area(s) as region ID 0
.br
-vg00/lvol3: Created new region with 8 area(s) as region ID 0
+vg00-lvol3: Created new region with 8 area(s) as region ID 0
.br
-vg01/lvol0: Created new region with 8 area(s) as region ID 2
+vg01-lvol0: Created new region with 8 area(s) as region ID 2
.br
-vg01/lvol1: Created new region with 8 area(s) as region ID 0
+vg01-lvol1: Created new region with 8 area(s) as region ID 0
.br
-vg00/lvol2: Created new region with 8 area(s) as region ID 1
+vg00-lvol2: Created new region with 8 area(s) as region ID 1
.br
.br
@@ -806,7 +806,7 @@ using dmsetup
.br
# dmsetup stats create --areasize 10G vg00/lvol1
.br
-vg00/lvol1: Created new region with 5 area(s) as region ID 1
+vg00-lvol1: Created new region with 5 area(s) as region ID 1
.br
.br
@@ -814,7 +814,7 @@ Create a 1GiB region with 16 areas at the start of vg00/lvol1
.br
# dmstats create --start 0 --len 1G --areas=16 vg00/lvol1
.br
-vg00/lvol1: Created new region with 16 area(s) as region ID 0
+vg00-lvol1: Created new region with 16 area(s) as region ID 0
.br
.br
@@ -854,11 +854,11 @@ Create one region for reach target contained in device vg00/lvol1
.br
# dmstats create --segments vg00/lvol1
.br
-Created new region with 1 area(s) as region ID 0
+vg00-lvol1: Created new region with 1 area(s) as region ID 0
.br
-Created new region with 1 area(s) as region ID 1
+vg00-lvol1: Created new region with 1 area(s) as region ID 1
.br
-Created new region with 1 area(s) as region ID 2
+vg00-lvol1: Created new region with 1 area(s) as region ID 2
.br
.br
8 years, 7 months
master - dmstats: improve stats column names
by Bryn Reeves
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=031cd2bb0dc436...
Commit: 031cd2bb0dc436619b1e186512a024ea095c2324
Parent: 3c0fc6f0dad6489c7530d3b844e6db3c9ac620cf
Author: Bryn M. Reeves <bmr(a)redhat.com>
AuthorDate: Sat Aug 22 19:35:43 2015 +0100
Committer: Bryn M. Reeves <bmr(a)redhat.com>
CommitterDate: Wed Sep 2 21:03:03 2015 +0100
dmstats: improve stats column names
Improve the names and labels of stats reports columns, ensure that
the minimum field widths allow unambiguos labels to be shown and
update the man page descriptions of these fields.
---
man/dmstats.8.in | 120 ++++++++++++++++++++++++++++-------------------------
tools/dmsetup.c | 77 ++++++++++++++++++----------------
2 files changed, 104 insertions(+), 93 deletions(-)
diff --git a/man/dmstats.8.in b/man/dmstats.8.in
index be7fb11..eb8f400 100644
--- a/man/dmstats.8.in
+++ b/man/dmstats.8.in
@@ -487,58 +487,58 @@ conventional Linux iostat program and are derived from the basic counter
values provided by the kernel for each area.
.br
.HP
-.B rrqm
+.B reads_merged_per_sec
.br
-Read requests merged per second.
+Reads merged per second.
.HP
-.B wrqm
+.B writes_merged_per_sec
.br
-Write requests merged per second.
+Writes merged per second.
.HP
-.B rs
+.B reads_per_sec
.br
-Read requests per second.
+Reads completed per second.
.HP
-.B ws
+.B writes_per_sec
.br
-Write requests per second.
+Writes completed per second.
.HP
-.B rsec
+.B read_size_per_sec
.br
-Sectors read per second.
+Size of data read per second.
.HP
-.B wsec
+.B write_size_per_sec
.br
-Sectors written per second.
+Size of data written per second.
.HP
-.B arqsz
+.B avg_request_size
.br
-The average size of requests submitted to the area.
+Average request size.
.HP
-.B qusz
+.B queue_size
.br
-The average queue length.
+Average queue size.
.HP
.B await
.br
-The average wait time for read and write requests.
+The average wait time for read and write operations.
.HP
.B r_await
.br
-The average wait time for read requests.
+The average wait time for read operations.
.HP
.B w_await
.br
-The average wait time for write requests.
+The average wait time for write operations.
.HP
-.B tput
+.B throughput
.br
-The device throughput in requests per second.
+The device throughput in operations per second.
.HP
-.B svctm
+.B service_time
.br
-The average service time (in milliseconds) for I/O requests that
-were issued to the device.
+The average service time (in milliseconds) for operations issued
+to the device.
.HP
.B util
.br
@@ -561,11 +561,13 @@ when a statistics region is created.
.B region_start
.br
.br
-The region start sector in units of 512 byte sectors.
+The region start location. Display units are selected by the
+\fB--units\fP option.
.HP
.B region_len
.br
-The length of the region in units of 512 byte sectors.
+The length of the region. Display units are selected by the
+\fB--units\fP option.
.HP
.B area_id
.br
@@ -574,18 +576,18 @@ statistics library and uniquely identify each area within a region. Each
ID corresponds to a distinct set of performance counters for that area
of the statistics region. Area identifiers are always monotonically
increasing within a region so that higher ID values correspond to
-greater sector addresses within the region and no gaps in the sequence
-of identifiers exist. Sorting a report by device, region start, and area
-ID (the default) will then produce rows in order of ascending region and
-area address.
+greater sector addresses within the area and no gaps in the sequence of
+identifiers exist.
.HP
.B area_start
.br
-The area start sector in units of 512 byte sectors.
+The area start location. Display units are selected by the
+\fB--units\fP option.
.HP
.B area_len
.br
-The length of the area in units of 512 byte sectors.
+The length of the area. Display units are selected by the
+\fB--units\fP option.
.HP
.B area_count
.br
@@ -603,7 +605,7 @@ The auxiliary data value associated with this region.
.B interval_ns
.br
The estimated interval over which the current counter values have
-accumulated. The vaulue is reported as an interger expressed in units
+accumulated. The value is reported as an interger expressed in units
of nanoseconds.
.br
.HP
@@ -623,57 +625,61 @@ area. The first eleven of these match the counters provided in
counters for read and write time.
.P
.HP
-.B reads
+.B read_count
.br
-The number of reads successfully completed this interval.
+Count of reads completed this interval.
.HP
-.B read_merges
+.B reads_merged_count
.br
-The number of read requests merged this interval. This field is
-incremented every time a pair of requests are merged to create a single
-request to be issued to the device.
+Count of reads merged this interval.
.HP
-.B read_sectors
+.B read_sector_count
.br
-The number of 512 byte sectors read this interval.
+Count of 512 byte sectors read this interval.
.HP
-.B read_nsecs
+.B read_time
.br
-The number of nanoseconds spent reading during this interval.
+Accumulated duration of all read requests (ns).
.HP
-.B writes
+.B write_count
.br
-The number of writes successfully completed this interval.
+Count of writes completed this interval.
.HP
-.B write_merges
+.B writes_merged_count
.br
-The number of write requests merged this interval. This field is
-incremented every time a pair of requests are merged to create a single
-request to be issued to the device.
+Count of writes merged this interval.
.HP
-.B write_sectors
+.B write_sector_count
.br
-The number of 512 byte sectors written this interval.
+Count of 512 byte sectors written this interval.
.HP
.B write_nsecs
.br
-The number of nanoseconds spent writing during this interval.
+Accumulated duration of all write requests (ns).
.HP
-.B in_progress
+.B in_progress_count
.br
-The number of reads and writes currently in progress.
+Count of requests currently in progress.
.HP
-.B io_nsecs
+.B io_ticks
.br
-The number of nanoseconds spent reading and writing.
+Nanoseconds spent servicing requests.
.HP
-.B weighted_io_nsecs
+.B queue_ticks
.br
This field is incremented at each I/O start, I/O completion, I/O merge,
or read of these stats by the number of I/Os in progress multiplied by
the number of milliseconds spent doing I/O since the last update of this
field. This can provide an easy measure of both I/O completion time and
the backlog that may be accumulating.
+.HP
+.B read_ticks
+.br
+Nanoseconds spent servicing reads.
+.HP
+.B write_ticks
+.br
+Nanoseconds spent servicing writes.
.br
.SS Histogram fields
Histograms measure the frequency distribution of user specified I/O
diff --git a/tools/dmsetup.c b/tools/dmsetup.c
index bffeb7f..9c9711d 100644
--- a/tools/dmsetup.c
+++ b/tools/dmsetup.c
@@ -4136,34 +4136,34 @@ FIELD_O(NAME, dm_split_name, STR, "LV", lv_name, 4, dm_lv_name, "lv_name", "LVM
FIELD_O(NAME, dm_split_name, STR, "LVLayer", lv_layer, 7, dm_lv_layer_name, "lv_layer", "LVM device layer.")
/* basic stats counters */
-FIELD_F(STATS, NUM, "Reads", 5, dm_stats_reads, "reads", "Number of reads completed.")
-FIELD_F(STATS, NUM, "RdMrges", 5, dm_stats_reads_merged, "reads_merged", "Number of reads merged.")
-FIELD_F(STATS, NUM, "RdSectors", 5, dm_stats_read_sectors, "read_sectors", "Number of sectors read.")
-FIELD_F(STATS, NUM, "RdNsec", 5, dm_stats_read_nsecs, "read_nsecs", "Time spent reading.")
-FIELD_F(STATS, NUM, "Writes", 5, dm_stats_writes, "writes", "Number of writes completed.")
-FIELD_F(STATS, NUM, "WrMerges", 5, dm_stats_writes_merged, "writes_merged", "Number of writes merged.")
-FIELD_F(STATS, NUM, "WrSectors", 5, dm_stats_write_sectors, "write_sectors", "Number of sectors written.")
-FIELD_F(STATS, NUM, "WrNsec", 5, dm_stats_write_nsecs, "write_nsecs", "Time spent writing.")
-FIELD_F(STATS, NUM, "InProgress", 5, dm_stats_io_in_progress, "in_progress", "Number of I/Os currently in progress.")
-FIELD_F(STATS, NUM, "IoNsec", 5, dm_stats_io_nsecs, "io_nsecs", "Time spent doing I/O.")
-FIELD_F(STATS, NUM, "WtIoNsec", 5, dm_stats_weighted_io_nsecs, "weighted_io_nsecs", "Weighted time spent doing I/O.")
-FIELD_F(STATS, NUM, "TotalRdNsec", 5, dm_stats_total_read_nsecs, "total_rd_nsecs", "Total time spent reading.")
-FIELD_F(STATS, NUM, "TotalWrNsec", 5, dm_stats_total_write_nsecs, "total_wr_nsecs", "Total time spent writing.")
+FIELD_F(STATS, NUM, "#Reads", 6, dm_stats_reads, "read_count", "Count of reads completed.")
+FIELD_F(STATS, NUM, "#RdMrgs", 7, dm_stats_reads_merged, "reads_merged_count", "Count of read requests merged.")
+FIELD_F(STATS, NUM, "#RdSectors", 10, dm_stats_read_sectors, "read_sector_count", "Count of sectors read.")
+FIELD_F(STATS, NUM, "AccRdTime", 11, dm_stats_read_nsecs, "read_time", "Accumulated duration of all read requests (ns).")
+FIELD_F(STATS, NUM, "#Writes", 7, dm_stats_writes, "write_count", "Count of writes completed.")
+FIELD_F(STATS, NUM, "#WrMrgs", 7, dm_stats_writes_merged, "writes_merged_count", "Count of write requests merged.")
+FIELD_F(STATS, NUM, "#WrSectors", 10, dm_stats_write_sectors, "write_sector_count", "Count of sectors written.")
+FIELD_F(STATS, NUM, "AccWrTime", 11, dm_stats_write_nsecs, "write_time", "Accumulated duration of all writes (ns).")
+FIELD_F(STATS, NUM, "#InProg", 7, dm_stats_io_in_progress, "in_progress_count", "Count of requests currently in progress.")
+FIELD_F(STATS, NUM, "IoTicks", 7, dm_stats_io_nsecs, "io_ticks", "Nanoseconds spent servicing requests.")
+FIELD_F(STATS, NUM, "QueueTicks", 10, dm_stats_weighted_io_nsecs, "queue_ticks", "Total nanoseconds spent in queue.")
+FIELD_F(STATS, NUM, "RdTicks", 7, dm_stats_total_read_nsecs, "read_ticks", "Nanoseconds spent servicing reads.")
+FIELD_F(STATS, NUM, "WrTicks", 7, dm_stats_total_write_nsecs, "write_ticks", "Nanoseconds spent servicing writes.")
/* Stats derived metrics */
-FIELD_F(STATS, NUM, "RRqM/s", 5, dm_stats_rrqm, "rrqm", "Read requests merged per second.")
-FIELD_F(STATS, NUM, "WRqM/s", 5, dm_stats_wrqm, "wrqm", "Write requests merged per second.")
-FIELD_F(STATS, NUM, "R/s", 5, dm_stats_rs, "rs", "Reads per second.")
-FIELD_F(STATS, NUM, "W/s", 5, dm_stats_ws, "ws", "Writes per second.")
-FIELD_F(STATS, NUM, "RSz/s", 5, dm_stats_read_secs, "rsize_sec", "Size of data read per second.")
-FIELD_F(STATS, NUM, "WSz/s", 5, dm_stats_write_secs, "wsize_sec", "Size of data written per second.")
-FIELD_F(STATS, NUM, "AvRqSz", 5, dm_stats_arqsz, "arqsz", "Average request size.")
-FIELD_F(STATS, NUM, "QSize", 5, dm_stats_qusz, "qusz", "Average queue size.")
+FIELD_F(STATS, NUM, "RMrg/s", 6, dm_stats_rrqm, "reads_merged_per_sec", "Read requests merged per second.")
+FIELD_F(STATS, NUM, "WMrg/s", 6, dm_stats_wrqm, "writes_merged_per_sec", "Write requests merged per second.")
+FIELD_F(STATS, NUM, "R/s", 3, dm_stats_rs, "reads_per_sec", "Reads per second.")
+FIELD_F(STATS, NUM, "W/s", 3, dm_stats_ws, "writes_per_sec", "Writes per second.")
+FIELD_F(STATS, NUM, "RSz/s", 5, dm_stats_read_secs, "read_size_per_sec", "Size of data read per second.")
+FIELD_F(STATS, NUM, "WSz/s", 5, dm_stats_write_secs, "write_size_per_sec", "Size of data written per second.")
+FIELD_F(STATS, NUM, "AvgRqSz", 7, dm_stats_arqsz, "avg_request_size", "Average request size.")
+FIELD_F(STATS, NUM, "QSize", 5, dm_stats_qusz, "queue_size", "Average queue size.")
FIELD_F(STATS, NUM, "AWait", 5, dm_stats_await, "await", "Averate wait time.")
-FIELD_F(STATS, NUM, "RdAWait", 5, dm_stats_r_await, "r_await", "Averate read wait time.")
-FIELD_F(STATS, NUM, "WrAWait", 5, dm_stats_w_await, "w_await", "Averate write wait time.")
-FIELD_F(STATS, NUM, "TPut", 5, dm_stats_tput, "tput", "Throughput.")
-FIELD_F(STATS, NUM, "SvcTm", 5, dm_stats_svctm, "svctm", "Service time.")
+FIELD_F(STATS, NUM, "RdAWait", 7, dm_stats_r_await, "read_await", "Averate read wait time.")
+FIELD_F(STATS, NUM, "WrAWait", 7, dm_stats_w_await, "write_await", "Averate write wait time.")
+FIELD_F(STATS, NUM, "Throughput", 10, dm_stats_tput, "throughput", "Throughput.")
+FIELD_F(STATS, NUM, "SvcTm", 5, dm_stats_svctm, "service_time", "Service time.")
FIELD_F(STATS, NUM, "Util%", 5, dm_stats_util, "util", "Utilization.")
/* Histogram fields */
@@ -4175,18 +4175,18 @@ FIELD_F(STATS, STR, "Histogram%", 10, dm_stats_hist_percent_bounds, "hist_percen
FIELD_F(STATS, STR, "Histogram%", 10, dm_stats_hist_percent_ranges, "hist_percent_ranges", "Relative latency histogram with bin ranges.")
/* Stats interval duration estimates */
-FIELD_F(STATS, NUM, "IntervalNSec", 10, dm_stats_sample_interval_ns, "interval_ns", "Sampling interval in nanoseconds.")
+FIELD_F(STATS, NUM, "IntervalNs", 10, dm_stats_sample_interval_ns, "interval_ns", "Sampling interval in nanoseconds.")
FIELD_F(STATS, NUM, "Interval", 8, dm_stats_sample_interval, "interval", "Sampling interval.")
/* Stats report meta-fields */
FIELD_F(STATS_META, NUM, "RgID", 4, dm_stats_region_id, "region_id", "Region ID.")
-FIELD_F(STATS_META, SIZ, "RStart", 5, dm_stats_region_start, "region_start", "Region start.")
-FIELD_F(STATS_META, SIZ, "RSize", 5, dm_stats_region_len, "region_len", "Region length.")
+FIELD_F(STATS_META, SIZ, "RgStart", 5, dm_stats_region_start, "region_start", "Region start.")
+FIELD_F(STATS_META, SIZ, "RgSize", 5, dm_stats_region_len, "region_len", "Region length.")
FIELD_F(STATS_META, NUM, "ArID", 4, dm_stats_area_id, "area_id", "Area ID.")
-FIELD_F(STATS_META, SIZ, "AStart", 5, dm_stats_area_start, "area_start", "Area offset from start of device.")
-FIELD_F(STATS_META, SIZ, "ASize", 5, dm_stats_area_len, "area_len", "Area length.")
-FIELD_F(STATS_META, SIZ, "AOff", 5, dm_stats_area_offset, "area_offset", "Area offset from start of region.")
-FIELD_F(STATS_META, NUM, "#Areas", 3, dm_stats_area_count, "area_count", "Area count.")
+FIELD_F(STATS_META, SIZ, "ArStart", 7, dm_stats_area_start, "area_start", "Area offset from start of device.")
+FIELD_F(STATS_META, SIZ, "ArSize", 6, dm_stats_area_len, "area_len", "Area length.")
+FIELD_F(STATS_META, SIZ, "ArOff", 5, dm_stats_area_offset, "area_offset", "Area offset from start of region.")
+FIELD_F(STATS_META, NUM, "#Areas", 6, dm_stats_area_count, "area_count", "Area count.")
FIELD_F(STATS_META, STR, "ProgID", 6, dm_stats_program_id, "program_id", "Program ID.")
FIELD_F(STATS_META, STR, "AuxDat", 6, dm_stats_aux_data, "aux_data", "Auxiliary data.")
FIELD_F(STATS_META, STR, "Precise", 7, dm_stats_precise, "precise", "Set if nanosecond precision counters are enabled.")
@@ -4208,12 +4208,17 @@ static const char *default_report_options = "name,major,minor,attr,open,segments
static const char *splitname_report_options = "vg_name,lv_name,lv_layer";
/* Stats counters & derived metrics. */
-#define RD_COUNTERS "reads,reads_merged,read_sectors,read_nsecs,total_rd_nsecs"
-#define WR_COUNTERS "writes,writes_merged,write_sectors,write_nsecs,total_wr_nsecs"
-#define IO_COUNTERS "in_progress,io_nsecs,weighted_io_nsecs"
-#define METRICS "rrqm,wrqm,rs,ws,rsize_sec,wsize_sec,arqsz,qusz,util,await,r_await,w_await"
+#define RD_COUNTERS "read_count,reads_merged_count,read_sector_count,read_time,read_ticks"
+#define WR_COUNTERS "write_count,writes_merged_count,write_sector_count,write_time,write_ticks"
+#define IO_COUNTERS "in_progress_count,io_ticks,queue_ticks"
#define COUNTERS RD_COUNTERS "," WR_COUNTERS "," IO_COUNTERS
+#define METRICS "reads_merged_per_sec,writes_merged_per_sec," \
+ "reads_per_sec,writes_per_sec," \
+ "read_size_per_sec,write_size_per_sec," \
+ "avg_request_size,queue_size,util," \
+ "await,read_await,write_await"
+
/* Device, region and area metadata. */
#define STATS_DEV_INFO "name,region_id"
#define STATS_AREA_INFO "area_id,area_start,area_len"
8 years, 7 months
master - dmstats: add histogram support
by Bryn Reeves
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=3c0fc6f0dad648...
Commit: 3c0fc6f0dad6489c7530d3b844e6db3c9ac620cf
Parent: a0cf3d47f1747d64a0d54027903ddea1c858793c
Author: Bryn M. Reeves <bmr(a)redhat.com>
AuthorDate: Tue Aug 18 12:40:03 2015 +0100
Committer: Bryn M. Reeves <bmr(a)redhat.com>
CommitterDate: Wed Sep 2 21:02:12 2015 +0100
dmstats: add histogram support
Add support to dmstats to create and report histograms.
Add a --histogram switch to 'create' that accepts a string
description of bin boundaries and DR_STATS and DR_STATS_META fields
to report bin configuration and absolute and relative histogram
values:
hist_bins
hist_bounds
hist_ranges
hist_count
hist_count_bounds
hist_count_ranges
hist_percent
hist_percent_bounds
hist_percent_ranges
A new 'histogram' subcommand displays a report that emphasizes
histogram data as either counters or percentage values.
---
WHATS_NEW_DM | 2 +
man/dmstats.8.in | 154 ++++++++++++++++++++++++++++++++++++++++
tools/dmsetup.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 356 insertions(+), 8 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index b361b3e..6852e61 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -4,6 +4,8 @@ Version 1.02.107 -
Version 1.02.106 - 26th August 2015
===================================
+ Add basic report fields for displaying latency histogram data.
+ Add dmstats --histogram to specify histogram boundaries for a region.
Add public methods to libdm-stats to access numerical histogram data.
Add the ability to parse histogram data into numeric form to libdm-stats.
Add 'precise' column to statistics reports.
diff --git a/man/dmstats.8.in b/man/dmstats.8.in
index ad5f952..be7fb11 100644
--- a/man/dmstats.8.in
+++ b/man/dmstats.8.in
@@ -32,6 +32,8 @@ dmstats \(em device-mapper statistics management
.IR nr_areas ]
.RB |[ \-\-areasize
.IR area_size ]]
+.RB [ \-\-histogram
+.IR boundaries ]
.RB [ \-\-precise ]
.RB [[ \-\-start
.IR start_sector ]
@@ -56,6 +58,28 @@ dmstats \(em device-mapper statistics management
.B dmstats help
.RB [ \-c | \-C | \-\-columns ]
.br
+.B dmstats histogram
+.RI [ device_name ]
+.RB [ \-\-interval
+.IR seconds ]
+.RB [ \-\-count
+.IR count ]
+.RB [ \-\-units
+.IR units ]
+.RB [ \-\-allprograms ]
+.RB [ \-\-programid
+.IR id ]
+.RB [ \-\-relative ]
+.RB [ \-\-regionid
+.IR id ]
+.RB [ \-O | \-\-sort
+.IR sort_fields ]
+.RB [ \-S | \-\-select
+.IR Selection ]
+.RB [ \-\-units
+.IR units ]
+.RB [ \-\-nosuffix ]
+.br
.B dmstats list
.RI [ device_name ]
.RB [ \-\-allprograms
@@ -154,6 +178,13 @@ When printing statistics counters, also atomically reset them to zero.
Specify the iteration count for repeating reports. If the count
argument is zero reports will continue to repeat until interrupted.
.TP
+.B \-\-histogram \fIboundaries
+Specify the boundaries of a latency histogram to be tracked for the
+region as a comma separated list of latency values. Latency values are
+given in nanoseconds. An optional unit suffix of ns, us, ms, or s may be
+given after each value to specify units of nanoseconds, microseconds,
+miliseconds or seconds respectively.
+.TP
.B \-\-interval \fIseconds
Specify the interval in seconds between successive iterations for
repeating reports. If \-\-interval is specified but \-\-count is not,
@@ -192,6 +223,10 @@ string is stored with the region. Subsequent operations may supply a
program ID in order to select only regions with a matching value. The
default program ID for dmstats-managed regions is "dmstats".
.TP
+.BR \-\-relative
+If displaying the histogram report show relative (percentage) values
+instead of absolute counts.
+.TP
.BR \-S | \-\-select \ \fIselection
Display only rows that match selection criteria. All rows with the
additional "selected" column (-o selected) showing 1 if the row matches
@@ -245,6 +280,8 @@ regions (with the exception of in-flight IO counters).
.IR nr_areas ]
.RB [ \-\-areasize
.IR area_size ]
+.RB [ \-\-histogram
+.IR boundaries ]
.RB [ \-\-precise ]
.RB [[ \-\-start
.IR start_sector ]
@@ -268,6 +305,20 @@ device-mapper device's table.
If the \fB\-\-precise\fP option is used the command will attempt to
create a region using nanosecond precision counters.
+If \fB\-\-histogram\fP is given a latency histogram will be tracked for
+the new region. The boundaries of the histogram bins are given as a
+comma separated list of latency values. There is an implicit lower bound
+of zero on the first bin and an implicit upper bound of infinity (or the
+configured interval duration) on the final bin.
+
+Latencies are given in nanoseconds. An optional unit suffix of ns, us,
+ms, or s may be given after each value to specify units of nanoseconds,
+microseconds, miliseconds or seconds respectively, so for example, 10ms
+is equivalent to 10000000. Latency values with a precision of less than
+one milisecond can only be used when precise timestamps are enabled: if
+\fB\-\-precise\fP is not given and values less than one milisecond are
+used it will be enabled automatically.
+
An optional \fBprogram_id\fP or \fBaux_data\fP string may be associated
with the region. A \fBprogram_id\fP may then be used to select regions
for subsequent list, print, and report operations. The \fBaux_data\fP
@@ -309,6 +360,38 @@ Outputs a summary of the commands available, optionally including
the list of report fields.
.br
.TP
+.B histogram
+.RB [ \-\-allprograms ]
+.RB [ \-\-interval
+.IR seconds ]
+.RB [ \-\-count
+.IR count ]
+.RB [ \-\-units
+.IR unit ]
+.RB [ \-\-relative ]
+.RB [ \-\-regionid
+.IR id ]
+.RB [ \-\-programid
+.IR id ]
+.RB [ \-O | \-\-sort
+.IR sort_fields ]
+.RB [ \-S | \-\-select
+.IR Selection ]
+.RB [ \-\-units
+.IR units ]
+.br
+Start a report for the specified region or for all present regions that
+emphasizes latency histograms in the default field options. If the count
+argument is specified, the report will repeat at a fixed interval set by
+the \fB\-\-interval\fP option. The default interval is one second.
+
+If the \fB\-\-allprograms\fP switch is given, all regions will be
+listed, regardless of region program ID values.
+
+If \fB\-\-relative\fP is given the default histogram field displays the
+relative histogram instead of absolute counts.
+.br
+.TP
.B list
.RI [ device_name ]
.RB [ \-\-allprograms ]
@@ -592,6 +675,77 @@ the number of milliseconds spent doing I/O since the last update of this
field. This can provide an easy measure of both I/O completion time and
the backlog that may be accumulating.
.br
+.SS Histogram fields
+Histograms measure the frequency distribution of user specified I/O
+latency intervals. Histogram bin boundaries are specified when a region
+is created.
+
+A brief representation of the histogram values and latency intervals can
+be included in the report using these fields.
+.P
+.HP
+.B hist_count
+.br
+A list of the histogram counts for the current statistics area in order
+of ascending latency value. Each value represents the number of I/Os
+with latency times falling into that bin's time range during the sample
+period.
+.HP
+.B hist_count_bounds
+.br
+A list of the histogram counts for the current statistics area in order
+of ascending latency value including bin boundaries: each count is
+prefixed by the lower bound of the corresponding histogram bin.
+.HP
+.B hist_count_ranges
+.br
+A list of the histogram counts for the current statistics area in order
+of ascending latency value including bin boundaries: each count is
+prefixed by both the lower and upper bounds of the corresponding
+histogram bin.
+.HP
+.B hist_percent
+.br
+A list of the relative histogram values for the current statistics area
+in order of ascending latency value, expressed as a percentage. Each
+value represents the proportion of I/Os with latency times falling into
+that bin's time range during the sample period.
+.HP
+.B hist_percent_bounds
+.br
+A list of the relative histogram values for the current statistics area
+in order of ascending latency value, expressed as a percentage and
+including bin boundaries. Each value represents the proportion of I/Os
+with latency times falling into that bin's time range during the sample
+period and is prefixed with the corresponding bin's lower bound.
+.HP
+.B hist_percent_ranges
+.br
+A list of the relative histogram values for the current statistics area
+in order of ascending latency value, expressed as a percentage and
+including bin boundaries. Each value represents the proportion of I/Os
+with latency times falling into that bin's time range during the sample
+period and is prefixed with the corresponding bin's lower and upper
+bounds.
+.HP
+.B hist_bounds
+.br
+A list of the histogram boundary values for the current statistics area
+in order of ascending latency value. The values are expressed in whole
+units of seconds, miliseconds, microseconds or nanoseconds with a suffix
+indicating the unit.
+.HP
+.B hist_ranges
+.br
+A list of the histogram bin ranges for the current statistics area in
+order of ascending latency value. The values are expressed as
+"LOWER-UPPER" in whole units of seconds, miliseconds, microseconds or
+nanoseconds with a suffix indicating the unit.
+.HP
+.B hist_bins
+.br
+The number of latency histogram bins configured for the area.
+.br
.br
.P
.SH EXAMPLES
diff --git a/tools/dmsetup.c b/tools/dmsetup.c
index 976d9e3..bffeb7f 100644
--- a/tools/dmsetup.c
+++ b/tools/dmsetup.c
@@ -172,6 +172,7 @@ enum {
FORCE_ARG,
GID_ARG,
HELP_ARG,
+ HISTOGRAM_ARG,
INACTIVE_ARG,
INTERVAL_ARG,
LENGTH_ARG,
@@ -195,6 +196,7 @@ enum {
RAW_ARG,
READAHEAD_ARG,
REGION_ID_ARG,
+ RELATIVE_ARG,
RETRY_ARG,
ROWS_ARG,
SEPARATOR_ARG,
@@ -3436,6 +3438,153 @@ static int _dm_stats_precise_disp(struct dm_report *rh,
return dm_report_field_int(rh, field, (const int *) &precise);
}
+static const char *_get_histogram_string(const struct dm_stats *dms, int rel,
+ int vals, int bounds)
+{
+ const struct dm_histogram *dmh;
+ int flags = 0;
+
+ if (!(dmh = dm_stats_get_histogram(dms, DM_STATS_REGION_CURRENT,
+ DM_STATS_AREA_CURRENT)))
+ return ""; /* No histogram. */
+
+ flags |= (vals) ? DM_HISTOGRAM_VALUES
+ : 0;
+
+ flags |= bounds;
+
+ flags |= (rel) ? DM_HISTOGRAM_PERCENT
+ : 0;
+
+ flags |= DM_HISTOGRAM_SUFFIX;
+
+ /* FIXME: make unit conversion optional. */
+ return dm_histogram_to_string(dmh, -1, 0, flags);
+}
+
+static int _stats_hist_count_disp(struct dm_report *rh,
+ struct dm_report_field *field, const void *data,
+ int bounds)
+{
+ const struct dm_stats *dms = (const struct dm_stats *) data;
+ const char *histogram;
+
+ histogram = _get_histogram_string(dms, 0, 1, bounds); /* counts */
+
+ if (!histogram)
+ return_0;
+
+ return dm_report_field_string(rh, field, (const char * const *) &histogram);
+}
+
+static int _dm_stats_hist_count_disp(struct dm_report *rh,
+ struct dm_pool *mem __attribute__((unused)),
+ struct dm_report_field *field, const void *data,
+ void *private __attribute__((unused)))
+{
+ return _stats_hist_count_disp(rh, field, data, 0);
+}
+
+static int _dm_stats_hist_count_bounds_disp(struct dm_report *rh,
+ struct dm_pool *mem __attribute__((unused)),
+ struct dm_report_field *field, const void *data,
+ void *private __attribute__((unused)))
+{
+ return _stats_hist_count_disp(rh, field, data, DM_HISTOGRAM_BOUNDS_LOWER);
+}
+
+static int _dm_stats_hist_count_ranges_disp(struct dm_report *rh,
+ struct dm_pool *mem __attribute__((unused)),
+ struct dm_report_field *field, const void *data,
+ void *private __attribute__((unused)))
+{
+ return _stats_hist_count_disp(rh, field, data, DM_HISTOGRAM_BOUNDS_RANGE);
+}
+
+static int _stats_hist_percent_disp(struct dm_report *rh,
+ struct dm_report_field *field, const void *data,
+ int bounds)
+{
+
+ /* FIXME: configurable to-string options. */
+ const struct dm_stats *dms = (const struct dm_stats *) data;
+ const char *histogram;
+
+ histogram = _get_histogram_string(dms, 1, 1, bounds); /* relative values */
+
+ if (!histogram)
+ return_0;
+
+ return dm_report_field_string(rh, field, (const char * const *) &histogram);
+}
+
+static int _dm_stats_hist_percent_disp(struct dm_report *rh,
+ struct dm_pool *mem __attribute__((unused)),
+ struct dm_report_field *field, const void *data,
+ void *private __attribute__((unused)))
+{
+ return _stats_hist_percent_disp(rh, field, data, 0);
+}
+
+static int _dm_stats_hist_percent_bounds_disp(struct dm_report *rh,
+ struct dm_pool *mem __attribute__((unused)),
+ struct dm_report_field *field, const void *data,
+ void *private __attribute__((unused)))
+{
+ return _stats_hist_percent_disp(rh, field, data, DM_HISTOGRAM_BOUNDS_LOWER);
+}
+
+static int _dm_stats_hist_percent_ranges_disp(struct dm_report *rh,
+ struct dm_pool *mem __attribute__((unused)),
+ struct dm_report_field *field, const void *data,
+ void *private __attribute__((unused)))
+{
+ return _stats_hist_percent_disp(rh, field, data, DM_HISTOGRAM_BOUNDS_RANGE);
+}
+
+static int _stats_hist_bounds_disp(struct dm_report *rh,
+ struct dm_report_field *field, const void *data,
+ int bounds)
+{
+ /* FIXME: configurable to-string options. */
+ const struct dm_stats *dms = (const struct dm_stats *) data;
+ const char *histogram;
+
+ histogram = _get_histogram_string(dms, 0, 0, bounds);
+
+ if (!histogram)
+ return_0;
+
+ return dm_report_field_string(rh, field, (const char * const *) &histogram);
+}
+
+static int _dm_stats_hist_bounds_disp(struct dm_report *rh,
+ struct dm_pool *mem __attribute__((unused)),
+ struct dm_report_field *field, const void *data,
+ void *private __attribute__((unused)))
+{
+ return _stats_hist_bounds_disp(rh, field, data, DM_HISTOGRAM_BOUNDS_LOWER);
+}
+
+static int _dm_stats_hist_ranges_disp(struct dm_report *rh,
+ struct dm_pool *mem __attribute__((unused)),
+ struct dm_report_field *field, const void *data,
+ void *private __attribute__((unused)))
+{
+ return _stats_hist_bounds_disp(rh, field, data, DM_HISTOGRAM_BOUNDS_RANGE);
+}
+
+static int _dm_stats_hist_bins_disp(struct dm_report *rh,
+ struct dm_pool *mem __attribute__((unused)),
+ struct dm_report_field *field, const void *data,
+ void *private __attribute__((unused)))
+{
+ const struct dm_stats *dms = (const struct dm_stats *) data;
+ int bins;
+ bins = dm_stats_get_region_nr_histogram_bins(dms, DM_STATS_REGION_CURRENT);
+ return dm_report_field_int(rh, field, (const int *) &bins);
+}
+
static int _dm_stats_rrqm_disp(struct dm_report *rh,
struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field, const void *data,
@@ -4017,6 +4166,14 @@ FIELD_F(STATS, NUM, "TPut", 5, dm_stats_tput, "tput", "Throughput.")
FIELD_F(STATS, NUM, "SvcTm", 5, dm_stats_svctm, "svctm", "Service time.")
FIELD_F(STATS, NUM, "Util%", 5, dm_stats_util, "util", "Utilization.")
+/* Histogram fields */
+FIELD_F(STATS, STR, "Histogram Counts", 16, dm_stats_hist_count, "hist_count", "Latency histogram counts.")
+FIELD_F(STATS, STR, "Histogram Counts", 16, dm_stats_hist_count_bounds, "hist_count_bounds", "Latency histogram counts with bin boundaries.")
+FIELD_F(STATS, STR, "Histogram Counts", 16, dm_stats_hist_count_ranges, "hist_count_ranges", "Latency histogram counts with bin ranges.")
+FIELD_F(STATS, STR, "Histogram%", 10, dm_stats_hist_percent, "hist_percent", "Relative latency histogram.")
+FIELD_F(STATS, STR, "Histogram%", 10, dm_stats_hist_percent_bounds, "hist_percent_bounds", "Relative latency histogram with bin boundaries.")
+FIELD_F(STATS, STR, "Histogram%", 10, dm_stats_hist_percent_ranges, "hist_percent_ranges", "Relative latency histogram with bin ranges.")
+
/* Stats interval duration estimates */
FIELD_F(STATS, NUM, "IntervalNSec", 10, dm_stats_sample_interval_ns, "interval_ns", "Sampling interval in nanoseconds.")
FIELD_F(STATS, NUM, "Interval", 8, dm_stats_sample_interval, "interval", "Sampling interval.")
@@ -4032,7 +4189,10 @@ FIELD_F(STATS_META, SIZ, "AOff", 5, dm_stats_area_offset, "area_offset", "Area o
FIELD_F(STATS_META, NUM, "#Areas", 3, dm_stats_area_count, "area_count", "Area count.")
FIELD_F(STATS_META, STR, "ProgID", 6, dm_stats_program_id, "program_id", "Program ID.")
FIELD_F(STATS_META, STR, "AuxDat", 6, dm_stats_aux_data, "aux_data", "Auxiliary data.")
-FIELD_F(STATS_META, STR, "Precise", 5, dm_stats_precise, "precise", "Set if the nanosecond precision timers are enabled.")
+FIELD_F(STATS_META, STR, "Precise", 7, dm_stats_precise, "precise", "Set if nanosecond precision counters are enabled.")
+FIELD_F(STATS_META, STR, "#Bins", 9, dm_stats_hist_bins, "hist_bins", "The number of histogram bins configured.")
+FIELD_F(STATS_META, STR, "Histogram Bounds", 16, dm_stats_hist_bounds, "hist_bounds", "Latency histogram bin boundaries.")
+FIELD_F(STATS_META, STR, "Histogram Ranges", 16, dm_stats_hist_ranges, "hist_ranges", "Latency histogram bin ranges.")
{0, 0, 0, 0, "", "", NULL, NULL},
/* *INDENT-ON* */
};
@@ -4056,14 +4216,20 @@ static const char *splitname_report_options = "vg_name,lv_name,lv_layer";
/* Device, region and area metadata. */
#define STATS_DEV_INFO "name,region_id"
-#define STATS_AREA_INFO STATS_DEV_INFO ",region_start,region_len,area_count,area_id,area_start,area_len"
+#define STATS_AREA_INFO "area_id,area_start,area_len"
+#define STATS_AREA_INFO_FULL STATS_DEV_INFO ",region_start,region_len,area_count,area_id,area_start,area_len"
#define STATS_REGION_INFO STATS_DEV_INFO ",region_start,region_len,area_count,area_len"
+/* Minimal set of fields for histogram report. */
+#define STATS_HIST STATS_REGION_INFO ",util,await"
+
/* Default stats report options. */
-static const char *_stats_default_report_options = STATS_DEV_INFO ",area_id,area_start,area_len," METRICS;
-static const char *_stats_raw_report_options = STATS_DEV_INFO ",area_id,area_start,area_len," COUNTERS;
+static const char *_stats_default_report_options = STATS_DEV_INFO "," STATS_AREA_INFO "," METRICS;
+static const char *_stats_raw_report_options = STATS_DEV_INFO "," STATS_AREA_INFO "," COUNTERS;
static const char *_stats_list_options = STATS_REGION_INFO ",program_id";
-static const char *_stats_area_list_options = STATS_AREA_INFO ",program_id";
+static const char *_stats_area_list_options = STATS_AREA_INFO_FULL ",program_id";
+static const char *_stats_hist_options = STATS_HIST ",hist_count_bounds";
+static const char *_stats_hist_relative_options = STATS_HIST ",hist_percent_bounds";
static int _report_init(const struct command *cmd, const char *subcommand)
{
@@ -4089,6 +4255,10 @@ static int _report_init(const struct command *cmd, const char *subcommand)
options = (char *) ((_switches[VERBOSE_ARG])
? _stats_area_list_options
: _stats_list_options);
+ else if (!strcmp(subcommand, "histogram"))
+ options = (char *) ((_switches[RELATIVE_ARG])
+ ? _stats_hist_relative_options
+ : _stats_hist_options);
else {
options = (char *) ((!_switches[RAW_ARG])
? _stats_default_report_options
@@ -4481,12 +4651,16 @@ static int _do_stats_create_regions(struct dm_stats *dms,
const char *aux_data)
{
uint64_t this_start = 0, this_len = len, region_id = UINT64_C(0);
+ const char *devname = NULL, *histogram = _string_args[HISTOGRAM_ARG];
+ int r = 0, precise = _switches[PRECISE_ARG];
+ struct dm_histogram *bounds = NULL; /* histogram bounds */
char *target_type, *params; /* unused */
struct dm_task *dmt;
struct dm_info info;
void *next = NULL;
- const char *devname = NULL;
- int r = 0, precise = _switches[PRECISE_ARG];
+
+ if (histogram && !(bounds = dm_histogram_bounds_from_string(histogram)))
+ return 0;
if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) {
dm_stats_destroy(dms);
@@ -4533,7 +4707,7 @@ static int _do_stats_create_regions(struct dm_stats *dms,
this_len = (segments) ? segment_len : this_len;
if (!dm_stats_create_region(dms, ®ion_id,
this_start, this_len, step,
- precise, NULL,
+ precise, bounds,
program_id, aux_data)) {
log_error("%s: Could not create statistics region.",
devname);
@@ -4550,6 +4724,7 @@ static int _do_stats_create_regions(struct dm_stats *dms,
out:
dm_task_destroy(dmt);
dm_stats_destroy(dms);
+ dm_histogram_bounds_destroy(bounds);
return r;
}
@@ -4652,6 +4827,14 @@ static int _stats_create(CMD_ARGS)
}
}
+ if (_switches[HISTOGRAM_ARG]) {
+ if (!dm_stats_driver_supports_histogram()) {
+ log_error("Using --histogram requires driver version "
+ "4.32.0 or later.");
+ goto out;
+ }
+ }
+
if (!strlen(program_id))
/* force creation of a region with no id */
dm_stats_set_program_id(dms, 1, NULL);
@@ -4886,6 +5069,7 @@ static struct command _stats_subcommands[] = {
{"clear", "--regionid <id> [<device>]", 0, -1, 1, 0, _stats_clear},
{"create", CREATE_OPTS "\n\t\t" ID_OPTS "[<device>]", 0, -1, 1, 0, _stats_create},
{"delete", "--regionid <id> <device>", 1, -1, 1, 0, _stats_delete},
+ {"histogram", REPORT_OPTS "[<device>]", 0, -1, 1, 0, _stats_report},
{"list", "[--programid <id>] [<device>]", 0, -1, 1, 0, _stats_report},
{"print", PRINT_OPTS "[<device>]", 0, -1, 1, 0, _stats_print},
{"report", REPORT_OPTS "[<device>]", 0, -1, 1, 0, _stats_report},
@@ -5500,6 +5684,7 @@ static int _process_switches(int *argcp, char ***argvp, const char *dev_dir)
{"force", 0, &ind, FORCE_ARG},
{"gid", 1, &ind, GID_ARG},
{"help", 0, &ind, HELP_ARG},
+ {"histogram", 1, &ind, HISTOGRAM_ARG},
{"inactive", 0, &ind, INACTIVE_ARG},
{"interval", 1, &ind, INTERVAL_ARG},
{"length", 1, &ind, LENGTH_ARG},
@@ -5523,6 +5708,7 @@ static int _process_switches(int *argcp, char ***argvp, const char *dev_dir)
{"raw", 0, &ind, RAW_ARG},
{"readahead", 1, &ind, READAHEAD_ARG},
{"regionid", 1, &ind, REGION_ID_ARG},
+ {"relative", 0, &ind, RELATIVE_ARG},
{"retry", 0, &ind, RETRY_ARG},
{"rows", 0, &ind, ROWS_ARG},
{"segments", 0, &ind, SEGMENTS_ARG},
@@ -5638,6 +5824,10 @@ static int _process_switches(int *argcp, char ***argvp, const char *dev_dir)
return 0;
if (c == 'h' || ind == HELP_ARG)
_switches[HELP_ARG]++;
+ if (ind == HISTOGRAM_ARG) {
+ _switches[HISTOGRAM_ARG]++;
+ _string_args[HISTOGRAM_ARG] = optarg;
+ }
if (ind == CLEAR_ARG)
_switches[CLEAR_ARG]++;
if (c == 'c' || c == 'C' || ind == COLS_ARG)
@@ -5678,6 +5868,8 @@ static int _process_switches(int *argcp, char ***argvp, const char *dev_dir)
_switches[REGION_ID_ARG]++;
_int_args[REGION_ID_ARG] = atoi(optarg);
}
+ if (ind == RELATIVE_ARG)
+ _switches[RELATIVE_ARG]++;
if (ind == SEPARATOR_ARG) {
_switches[SEPARATOR_ARG]++;
_string_args[SEPARATOR_ARG] = optarg;
8 years, 7 months