Tuned rules don't get applied to new devices

Solution Unverified - Updated

Environment

Red Hat Enterprise Linux 8
Red Hat Enterprise Linux 7

Issue

  • Tuned is not setting all values, specifically 'readahead'

Resolution

A solution for this issue has been released via the following errata which have the fix for this issue:

If you still see the problem after the package has been upgraded, contact Red Hat Support.

Root Cause

The issue was that when udev sends the 'remove' event it does not send any device attributes with it so _device_is_supported check must be omitted in the code for the remove event to be received properly by tuned.

Diagnostic Steps

Before attaching a new device, enable 'tuned' in debug mode with the following command:

	# tuned -D -l /tmp/tuned_tests.log

Reproduce this issue is easy.

Initial status:

	# lsblk -t
	NAME          ALIGNMENT MIN-IO OPT-IO PHY-SEC LOG-SEC ROTA SCHED       RQ-SIZE   RA WSAME
	sda                   0    512      0     512     512    1 deadline        128 8192    2G
	sdb                   0    512      0     512     512    1 deadline        128 8192    2G
	sr0                   0    512      0     512     512    1 deadline        128  128    0B
	vda                   0    512      0     512     512    1 mq-deadline     256 8192    0B
	├─vda1                0    512      0     512     512    1 mq-deadline     256 8192    0B
	└─vda2                0    512      0     512     512    1 mq-deadline     256 8192    0B
	  ├─rhel-root         0    512      0     512     512    1                 128 8192    0B
	  └─rhel-swap         0    512      0     512     512    1                 128 8192    0B
	vdb                   0    512      0     512     512    1 mq-deadline     256 8192    0B
	vdc                   0    512      0     512     512    1 mq-deadline     256 8192    0B
	vdd                   0    512      0     512     512    1 mq-deadline     256 8192    0B
	└─vdd1                0    512      0     512     512    1 mq-deadline     256 8192    0B
	  └─rhel-root         0    512      0     512     512    1                 128 8192    0B

After removing the four test devices (sda, sdb, vdb, vdc):

	# lsblk -t
	NAME          ALIGNMENT MIN-IO OPT-IO PHY-SEC LOG-SEC ROTA SCHED       RQ-SIZE   RA WSAME
	sr0                   0    512      0     512     512    1 deadline        128  128    0B
	vda                   0    512      0     512     512    1 mq-deadline     256 8192    0B
	├─vda1                0    512      0     512     512    1 mq-deadline     256 8192    0B
	└─vda2                0    512      0     512     512    1 mq-deadline     256 8192    0B
	  ├─rhel-root         0    512      0     512     512    1                 128 8192    0B
	  └─rhel-swap         0    512      0     512     512    1                 128 8192    0B
	vdd                   0    512      0     512     512    1 mq-deadline     256 8192    0B
	└─vdd1                0    512      0     512     512    1 mq-deadline     256 8192    0B
	  └─rhel-root         0    512      0     512     512    1                 128 8192    0B

We add five devices (sda, sdb, vdb, vdc, vde), but only the fifth one, vde, gets the expected `readahead=8192 and other values from tuned profile applied:

	# lsblk -t
	NAME          ALIGNMENT MIN-IO OPT-IO PHY-SEC LOG-SEC ROTA SCHED       RQ-SIZE   RA WSAME
	sda                   0    512      0     512     512    1 deadline        128  128    2G
	sdb                   0    512      0     512     512    1 deadline        128  128    2G
	sr0                   0    512      0     512     512    1 deadline        128  128    0B
	vda                   0    512      0     512     512    1 mq-deadline     256 8192    0B
	├─vda1                0    512      0     512     512    1 mq-deadline     256 8192    0B
	└─vda2                0    512      0     512     512    1 mq-deadline     256 8192    0B
	  ├─rhel-root         0    512      0     512     512    1                 128 8192    0B
	  └─rhel-swap         0    512      0     512     512    1                 128 8192    0B
	vdb                   0    512      0     512     512    1 mq-deadline     256  128    0B
	vdc                   0    512      0     512     512    1 mq-deadline     256  128    0B
	vdd                   0    512      0     512     512    1 mq-deadline     256 8192    0B
	└─vdd1                0    512      0     512     512    1 mq-deadline     256 8192    0B
	  └─rhel-root         0    512      0     512     512    1                 128 8192    0B
	vde                   0    512      0     512     512    1 mq-deadline     256 8192    0B ← This is the new one.

The content of 'tuned.log' in debug mode:

	[...]
	2018-06-11 08:07:23,270 INFO     tuned.plugins.hotplug: device 'vdb' added
	2018-06-11 08:07:25,764 DEBUG    tuned.daemon.daemon: updating monitors
	2018-06-11 08:07:25,765 DEBUG    tuned.units.manager: updating monitor <tuned.monitors.monitor_disk.DiskMonitor object at 0x7f35c34211d0>
	2018-06-11 08:07:25,765 DEBUG    tuned.daemon.daemon: performing tunings
	2018-06-11 08:07:35,778 DEBUG    tuned.daemon.daemon: updating monitors
	2018-06-11 08:07:35,778 DEBUG    tuned.units.manager: updating monitor <tuned.monitors.monitor_disk.DiskMonitor object at 0x7f35c34211d0>
	2018-06-11 08:07:35,779 DEBUG    tuned.daemon.daemon: performing tunings
	2018-06-11 08:07:36,803 INFO     tuned.plugins.hotplug: device 'sda' added
	2018-06-11 08:07:45,792 DEBUG    tuned.daemon.daemon: updating monitors
	2018-06-11 08:07:45,793 DEBUG    tuned.units.manager: updating monitor <tuned.monitors.monitor_disk.DiskMonitor object at 0x7f35c34211d0>
	2018-06-11 08:07:45,793 DEBUG    tuned.daemon.daemon: performing tunings
	2018-06-11 08:07:46,772 INFO     tuned.plugins.hotplug: device 'vdc' added
	2018-06-11 08:07:55,368 INFO     tuned.plugins.hotplug: device 'sdb' added
	2018-06-11 08:07:55,806 DEBUG    tuned.daemon.daemon: updating monitors
	2018-06-11 08:07:55,807 DEBUG    tuned.units.manager: updating monitor <tuned.monitors.monitor_disk.DiskMonitor object at 0x7f35c34211d0>
	2018-06-11 08:07:55,807 DEBUG    tuned.daemon.daemon: performing tunings
	2018-06-11 08:08:05,820 DEBUG    tuned.daemon.daemon: updating monitors
	2018-06-11 08:08:05,820 DEBUG    tuned.units.manager: updating monitor <tuned.monitors.monitor_disk.DiskMonitor object at 0x7f35c34211d0>
	2018-06-11 08:08:05,821 DEBUG    tuned.daemon.daemon: performing tunings
	2018-06-11 08:08:05,971 INFO     tuned.plugins.hotplug: device 'vde' added
	2018-06-11 08:08:05,972 INFO     tuned.plugins.hotplug: instance disk: adding new device vde
	2018-06-11 08:08:05,972 DEBUG    tuned.utils.commands: Read data from file: '<closed file u'/sys/block/vde/queue/read_ahead_kb', mode 'r' at 0x7f35c411bae0>' > '128
	'
	2018-06-11 08:08:05,972 DEBUG    tuned.utils.commands: Writing to file: '/sys/block/vde/queue/read_ahead_kb' < '8192'
	2018-06-11 08:08:05,973 DEBUG    tuned.utils.commands: Executing ['hdparm', '-B', u'/dev/vde'].
	2018-06-11 08:08:15,834 DEBUG    tuned.daemon.daemon: updating monitors
	2018-06-11 08:08:15,834 DEBUG    tuned.units.manager: updating monitor <tuned.monitors.monitor_disk.DiskMonitor object at 0x7f35c34211d0>
	2018-06-11 08:08:15,835 DEBUG    tuned.daemon.daemon: performing tunings
	[...]

The line that appears with a new device:

	2018-06-11 08:08:05,972 INFO     tuned.plugins.hotplug: instance disk: adding new device vde

The sequence is:

(1) "tuned.plugins.hotplug: device 'vde' added" ---> (2) "tuned.plugins.hotplug: instance disk: adding new device vde"

And as mentioned just above the line marked as (2) does not appear when the values are not applied. The code is in tuned/plugins/hotplug.py:

		def _hardware_events_callback(self, event, device):
				if event == "add":
						log.info("device '%s' added" % device.sys_name) ← ← ← ← (1)
						self._add_device(device)
				elif event == "remove":
						log.info("device '%s' removed" % device.sys_name)
						self._remove_device(device)

		def _add_device(self, device):
				device_name = device.sys_name
				if device_name in (self._assigned_devices | self._free_devices): ← ← This is where we decide to apply the rules or not
						return

				for instance_name, instance in self._instances.items():
						if len(self._get_matching_devices(instance, [device_name])) == 1:
								log.info("instance %s: adding new device %s" % (instance_name, device_name)) ← ← (2)
								self._assigned_devices.add(device_name)
								instance.devices.add(device_name)
								self._call_device_script(instance, instance.script_pre, "apply", [device_name])
								self._added_device_apply_tuning(instance, device_name)
								self._call_device_script(instance, instance.script_post, "apply", [device_name])
								break

So the existing devices are already in either _assigned_devices or in _free_devices:

	if device_name in (self._assigned_devices | self._free_devices)

This is where we should be removing the device from the list:

			def _remove_device(self, device):
					device_name = device.sys_name
					if device_name not in (self._assigned_devices | self._free_devices):
							return
	
					for instance in self._instances.values():
							if device_name in instance.devices:
									self._call_device_script(instance, instance.script_post, "unapply", [device_name])
									self._removed_device_unapply_tuning(instance, device_name)
									self._call_device_script(instance, instance.script_pre, "unapply", [device_name])
									instance.devices.remove(device_name)
									instance.active = len(instance.devices) > 0
									self._assigned_devices.remove(device_name)
									break
					else:
							self._free_devices.remove(device_name)

And this removal happens when we receive a udev event for 'remove':

			def _hardware_events_callback(self, event, device):
					if event == "add":
							log.info("device '%s' added" % device.sys_name)
							self._add_device(device)
					elif event == "remove":
							log.info("device '%s' removed" % device.sys_name)
							self._remove_device(device)

Testing 'remove' and 'add' uevent:

	# echo "remove" > /sys/block/sda/uevent 
	 

2018-06-11 09:27:43,448 INFO     tuned.plugins.hotplug: device 'sda' removed
2018-06-11 09:27:43,448 DEBUG    tuned.utils.commands: Writing to file: '/sys/block/sda/queue/read_ahead_kb' < '128'

	# echo "add" > /sys/block/sda/uevent 

2018-06-11 09:29:00,927 DEBUG    tuned.utils.commands: Writing to file: '/sys/block/sda/queue/read_ahead_kb' < '8192'
2018-06-11 09:29:00,931 DEBUG    tuned.utils.commands: Executing ['hdparm', '-B', u'/dev/sda'].

On removal we have this in the output of the command 'udevadm monitor':

	KERNEL[5622.611054] remove   /devices/pci0000:00/0000:00:0c.0/virtio7/host2/target2:0:0/2:0:0:0/bsg/2:0:0:0 (bsg)
	KERNEL[5622.611460] remove   /devices/pci0000:00/0000:00:0c.0/virtio7/host2/target2:0:0/2:0:0:0/scsi_generic/sg1 (scsi_generic)
	KERNEL[5622.611471] remove   /devices/pci0000:00/0000:00:0c.0/virtio7/host2/target2:0:0/2:0:0:0/scsi_device/2:0:0:0 (scsi_device)
	KERNEL[5622.611478] remove   /devices/pci0000:00/0000:00:0c.0/virtio7/host2/target2:0:0/2:0:0:0/scsi_disk/2:0:0:0 (scsi_disk)
	KERNEL[5622.611538] remove   /devices/virtual/bdi/8:0 (bdi)
	KERNEL[5622.611580] remove   /devices/pci0000:00/0000:00:0c.0/virtio7/host2/target2:0:0/2:0:0:0/block/sda (block)
	KERNEL[5622.614160] remove   /devices/pci0000:00/0000:00:0c.0/virtio7/host2/target2:0:0/2:0:0:0 (scsi)
	UDEV  [5622.614790] remove   /devices/virtual/bdi/8:0 (bdi)
	KERNEL[5622.617180] remove   /devices/pci0000:00/0000:00:0c.0/virtio7/host2/target2:0:0 (scsi)
	UDEV  [5622.617805] remove   /devices/pci0000:00/0000:00:0c.0/virtio7/host2/target2:0:0/2:0:0:0/scsi_disk/2:0:0:0 (scsi_disk)
	UDEV  [5622.618328] remove   /devices/pci0000:00/0000:00:0c.0/virtio7/host2/target2:0:0/2:0:0:0/scsi_device/2:0:0:0 (scsi_device)
	UDEV  [5622.618751] remove   /devices/pci0000:00/0000:00:0c.0/virtio7/host2/target2:0:0/2:0:0:0/block/sda (block)
	UDEV  [5622.620970] remove   /devices/pci0000:00/0000:00:0c.0/virtio7/host2/target2:0:0/2:0:0:0/bsg/2:0:0:0 (bsg)
	UDEV  [5622.764687] remove   /devices/pci0000:00/0000:00:0c.0/virtio7/host2/target2:0:0/2:0:0:0/scsi_generic/sg1 (scsi_generic)
	UDEV  [5622.765310] remove   /devices/pci0000:00/0000:00:0c.0/virtio7/host2/target2:0:0/2:0:0:0 (scsi)
	UDEV  [5622.765554] remove   /devices/pci0000:00/0000:00:0c.0/virtio7/host2/target2:0:0 (scsi)
SBR
Components
Tags

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.