|
|
e8cf60 |
diff --git a/tuned/plugins/plugin_disk.py b/tuned/plugins/plugin_disk.py
|
|
|
e8cf60 |
index 41ae452..408d9d1 100644
|
|
|
e8cf60 |
--- a/tuned/plugins/plugin_disk.py
|
|
|
e8cf60 |
+++ b/tuned/plugins/plugin_disk.py
|
|
|
e8cf60 |
@@ -27,22 +27,42 @@ class DiskPlugin(hotplug.Plugin):
|
|
|
e8cf60 |
def _init_devices(self):
|
|
|
e8cf60 |
super(DiskPlugin, self)._init_devices()
|
|
|
e8cf60 |
self._devices_supported = True
|
|
|
e8cf60 |
+ self._use_hdparm = True
|
|
|
e8cf60 |
self._free_devices = set()
|
|
|
e8cf60 |
+ self._hdparm_apm_devices = set()
|
|
|
e8cf60 |
for device in self._hardware_inventory.get_devices("block"):
|
|
|
e8cf60 |
if self._device_is_supported(device):
|
|
|
e8cf60 |
self._free_devices.add(device.sys_name)
|
|
|
e8cf60 |
+ if self._use_hdparm and self._is_hdparm_apm_supported(device.sys_name):
|
|
|
e8cf60 |
+ self._hdparm_apm_devices.add(device.sys_name)
|
|
|
e8cf60 |
|
|
|
e8cf60 |
self._assigned_devices = set()
|
|
|
e8cf60 |
|
|
|
e8cf60 |
def _get_device_objects(self, devices):
|
|
|
e8cf60 |
return [self._hardware_inventory.get_device("block", x) for x in devices]
|
|
|
e8cf60 |
|
|
|
e8cf60 |
+ def _is_hdparm_apm_supported(self, device):
|
|
|
e8cf60 |
+ (rc, out, err_msg) = self._cmd.execute(["hdparm", "-C", "/dev/%s" % device], \
|
|
|
e8cf60 |
+ no_errors = [errno.ENOENT], return_err=True)
|
|
|
e8cf60 |
+ if rc == -errno.ENOENT:
|
|
|
e8cf60 |
+ log.warn("hdparm command not found, ignoring for other devices")
|
|
|
e8cf60 |
+ self._use_hdparm = False
|
|
|
e8cf60 |
+ return False
|
|
|
e8cf60 |
+ elif rc:
|
|
|
e8cf60 |
+ log.info("Device '%s' not supported by hdparm" % device)
|
|
|
e8cf60 |
+ log.debug("(rc: %s, msg: '%s')" % (rc, err_msg))
|
|
|
e8cf60 |
+ return False
|
|
|
e8cf60 |
+ elif "unknown" in out:
|
|
|
e8cf60 |
+ log.info("Driver for device '%s' does not support apm command" % device)
|
|
|
e8cf60 |
+ return False
|
|
|
e8cf60 |
+ return True
|
|
|
e8cf60 |
+
|
|
|
e8cf60 |
@classmethod
|
|
|
e8cf60 |
def _device_is_supported(cls, device):
|
|
|
e8cf60 |
return device.device_type == "disk" and \
|
|
|
e8cf60 |
device.attributes.get("removable", None) == b"0" and \
|
|
|
e8cf60 |
(device.parent is None or \
|
|
|
e8cf60 |
- device.parent.subsystem in ["scsi", "virtio", "xen"])
|
|
|
e8cf60 |
+ device.parent.subsystem in ["scsi", "virtio", "xen", "nvme"])
|
|
|
e8cf60 |
|
|
|
e8cf60 |
def _hardware_events_init(self):
|
|
|
e8cf60 |
self._hardware_inventory.subscribe(self, "block", self._hardware_events_callback)
|
|
|
e8cf60 |
@@ -142,6 +162,8 @@ class DiskPlugin(hotplug.Plugin):
|
|
|
e8cf60 |
return not "standby" in out and not "sleeping" in out
|
|
|
e8cf60 |
|
|
|
e8cf60 |
def _instance_update_dynamic(self, instance, device):
|
|
|
e8cf60 |
+ if not device in self._hdparm_apm_devices:
|
|
|
e8cf60 |
+ return
|
|
|
e8cf60 |
load = instance._load_monitor.get_device_load(device)
|
|
|
e8cf60 |
if load is None:
|
|
|
e8cf60 |
return
|
|
|
e8cf60 |
@@ -202,7 +224,7 @@ class DiskPlugin(hotplug.Plugin):
|
|
|
e8cf60 |
diff = [new_old[0] - new_old[1] for new_old in zip(new_load, old_load)]
|
|
|
e8cf60 |
instance._stats[device]["diff"] = diff
|
|
|
e8cf60 |
|
|
|
e8cf60 |
- # adapt maximum expected load if the difference is higer
|
|
|
e8cf60 |
+ # adapt maximum expected load if the difference is higher
|
|
|
e8cf60 |
old_max_load = instance._stats[device]["max"]
|
|
|
e8cf60 |
max_load = [max(pair) for pair in zip(old_max_load, diff)]
|
|
|
e8cf60 |
instance._stats[device]["max"] = max_load
|
|
|
e8cf60 |
@@ -219,6 +241,15 @@ class DiskPlugin(hotplug.Plugin):
|
|
|
e8cf60 |
else:
|
|
|
e8cf60 |
instance._idle[device][operation] = 0
|
|
|
e8cf60 |
|
|
|
e8cf60 |
+ def _instance_apply_dynamic(self, instance, device):
|
|
|
e8cf60 |
+ # At the moment we support dynamic tuning just for devices compatible with hdparm apm commands
|
|
|
e8cf60 |
+ # If in future will be added new functionality not connected to this command,
|
|
|
e8cf60 |
+ # it is needed to change it here
|
|
|
e8cf60 |
+ if device not in self._hdparm_apm_devices:
|
|
|
e8cf60 |
+ log.info("There is no dynamic tuning available for device '%s' at time" % device)
|
|
|
e8cf60 |
+ else:
|
|
|
e8cf60 |
+ super(DiskPlugin, self)._instance_apply_dynamic(*args, **kwargs)
|
|
|
e8cf60 |
+
|
|
|
e8cf60 |
def _instance_unapply_dynamic(self, instance, device):
|
|
|
e8cf60 |
pass
|
|
|
e8cf60 |
|
|
|
e8cf60 |
@@ -248,6 +279,12 @@ class DiskPlugin(hotplug.Plugin):
|
|
|
e8cf60 |
|
|
|
e8cf60 |
@command_set("apm", per_device=True)
|
|
|
e8cf60 |
def _set_apm(self, value, device, sim):
|
|
|
e8cf60 |
+ if device not in self._hdparm_apm_devices:
|
|
|
e8cf60 |
+ if not sim:
|
|
|
e8cf60 |
+ log.info("apm option is not supported for device '%s'" % device)
|
|
|
e8cf60 |
+ return None
|
|
|
e8cf60 |
+ else:
|
|
|
e8cf60 |
+ return str(value)
|
|
|
e8cf60 |
if self._apm_errcnt < consts.ERROR_THRESHOLD:
|
|
|
e8cf60 |
if not sim:
|
|
|
e8cf60 |
(rc, out) = self._cmd.execute(["hdparm", "-B", str(value), "/dev/" + device], no_errors = [errno.ENOENT])
|
|
|
e8cf60 |
@@ -258,6 +295,10 @@ class DiskPlugin(hotplug.Plugin):
|
|
|
e8cf60 |
|
|
|
e8cf60 |
@command_get("apm")
|
|
|
e8cf60 |
def _get_apm(self, device, ignore_missing=False):
|
|
|
e8cf60 |
+ if device not in self._hdparm_apm_devices:
|
|
|
e8cf60 |
+ if not ignore_missing:
|
|
|
e8cf60 |
+ log.info("apm option is not supported for device '%s'" % device)
|
|
|
e8cf60 |
+ return None
|
|
|
e8cf60 |
value = None
|
|
|
e8cf60 |
err = False
|
|
|
e8cf60 |
(rc, out) = self._cmd.execute(["hdparm", "-B", "/dev/" + device], no_errors = [errno.ENOENT])
|
|
|
e8cf60 |
@@ -278,6 +319,12 @@ class DiskPlugin(hotplug.Plugin):
|
|
|
e8cf60 |
|
|
|
e8cf60 |
@command_set("spindown", per_device=True)
|
|
|
e8cf60 |
def _set_spindown(self, value, device, sim):
|
|
|
e8cf60 |
+ if device not in self._hdparm_apm_devices:
|
|
|
e8cf60 |
+ if not sim:
|
|
|
e8cf60 |
+ log.info("spindown option is not supported for device '%s'" % device)
|
|
|
e8cf60 |
+ return None
|
|
|
e8cf60 |
+ else:
|
|
|
e8cf60 |
+ return str(value)
|
|
|
e8cf60 |
if self._spindown_errcnt < consts.ERROR_THRESHOLD:
|
|
|
e8cf60 |
if not sim:
|
|
|
e8cf60 |
(rc, out) = self._cmd.execute(["hdparm", "-S", str(value), "/dev/" + device], no_errors = [errno.ENOENT])
|
|
|
e8cf60 |
@@ -288,6 +335,10 @@ class DiskPlugin(hotplug.Plugin):
|
|
|
e8cf60 |
|
|
|
e8cf60 |
@command_get("spindown")
|
|
|
e8cf60 |
def _get_spindown(self, device, ignore_missing=False):
|
|
|
e8cf60 |
+ if device not in self._hdparm_apm_devices:
|
|
|
e8cf60 |
+ if not ignore_missing:
|
|
|
e8cf60 |
+ log.info("spindown option is not supported for device '%s'" % device)
|
|
|
e8cf60 |
+ return None
|
|
|
e8cf60 |
# There's no way how to get current/old spindown value, hardcoding vendor specific 253
|
|
|
e8cf60 |
return 253
|
|
|
e8cf60 |
|
|
|
e8cf60 |
@@ -355,6 +406,6 @@ class DiskPlugin(hotplug.Plugin):
|
|
|
e8cf60 |
value = self._cmd.read_file(sys_file, no_error=ignore_missing).strip()
|
|
|
e8cf60 |
if len(value) == 0:
|
|
|
e8cf60 |
if not ignore_missing:
|
|
|
e8cf60 |
- log.info("disk_scheduler_quantum option is not supported by this HW")
|
|
|
e8cf60 |
+ log.info("disk_scheduler_quantum option is not supported for device '%s'" % device)
|
|
|
e8cf60 |
return None
|
|
|
e8cf60 |
return int(value)
|