* [RESEND PATCH v5 0/2] Introduce block device LED trigger
@ 2021-10-04 15:55 Ian Pilcher
2021-10-04 15:55 ` [RESEND PATCH v5 1/2] docs: Add block device (blkdev) LED trigger documentation Ian Pilcher
2021-10-04 15:55 ` [RESEND PATCH v5 2/2] leds: trigger: Add block device LED trigger Ian Pilcher
0 siblings, 2 replies; 7+ messages in thread
From: Ian Pilcher @ 2021-10-04 15:55 UTC (permalink / raw)
To: pavel; +Cc: linux-leds, linux-kernel, gregkh, kabel, hch
Changes from v4:
================
* Use xarrays, rather than lists, to model "links" between LEDs and block
devices. This allows many-to-many relationships without the need for a
separate link object.
* When resolving (getting) a block device by path, don't retry with
"/dev/" prepended to the path in the ENOENT case.
* Use an enum, rather than a boolean, to tell led_bdev_unlink() whether
the block device is being released or not.
* Use preprocessor constant, rather than magic number, for the mode passed
to blkdev_get_by_path() and blkdev_put().
* Split the data structure used by mode attribute show & store functions
into 2 separate arrays and move them into the functions that use them.
Changes from v3:
================
* Use blkdev_get_by_path() to "resolve" block devices
(struct block_device). With this change, there are now no changes
required to the block subsystem, so there are only 2 patches in this
series.
* link_device and unlink_device attributes now take paths to block device
special files (e.g. /dev/sda), rather than kernel names. Symbolic
links also work.
If the path written to the attribute doesn't exist (-ENOENT), we re-try
with /dev/ prepended, so "simple" names like sda will still work as long
as the corresponding special file exists in /dev.
* Fixed a bug that could cause "phantom" blinks because of old device
activity that was not recognized at the correct time.
* (Slightly) more detailed commit message for the patch that adds the
trigger code. As with v3, the real details are found in the comments
in the source file.
Changes from v2:
================
* Allow LEDs to be "linked" to partitions, as well as whole devices.
Internally, the trigger now works with block_device structs, rather
than gendisk structs.
(Investigating the lifecycle of block_device structs led me to
discover the device resource API, so ...)
* Use the device resource API to manage the trigger's per-block device
data structure (struct led_bdev_bdi). The trigger now uses a release
function to remove references to block devices that have been removed.
Because the release function is automatically called by the driver core,
there is no longer any need for the block layer to explictly call the
trigger's cleanup function.
* Since there is no need to provide a built-in "stub" cleanup function
when the trigger is built as a module, I have removed the always
built-in "core" portion of the trigger.
* Without a built-in component, the module does need access to the
block_class symbol. The second patch in this series exports the symbol
to the LEDTRIG_BLKDEV namespace and explains the reason for doing so.
* Changed the interval sysfs attribute from a device attribute to a class
attribute. It's single value that applies to all LEDs, so it didn't
make sense as a device atribute.
* As requested, I am posting the trigger code (ledtrig-blkdev.c) as a
single patch. This eliminates the commit messages that would otherwise
describe sections of the code, so I have added fairly extensive comments
to each function.
Changes from v1:
================
* Use correct address for LKML.
* Renamed the sysfs attributes used to manage and view the set of block
devices associated ("linked") with an LED.
- /sys/class/leds/<LED>/link_device to create associations
- /sys/class/leds/<LED>/unlink_device to remove associations
- /sys/class/leds/<LED>/linked_devices/ contains symlinks to all block
devices associated with the LED
- /sys/block/<DEVICE>/linked_leds (which only exists when the device is
associated with at least one LED) contains symlinks to all LEDs with
which the device is associated
link_device and unlink_device are write-only attributes, each of which
represents a single action, rather than any state. (The current state
is shown by the symbolic links in the <LED>/linked_devices/ and
<DEVICE>/linked_leds/ directories.)
* Simplified sysfs attribute store functions. link_device and
unlink_device no longer accept multiple devices at once, but this was
really just an artifact of the way that sysfs repeatedly calls the
store function when it doesn't "consume" all of its input, and it
seemed to be confusing and unpopular anyway.
* Use DEVICE_ATTR_* macros (rather than __ATTR) for the sysfs attributes.
* Removed all pr_info() "system administrator error" messages.
* Different minimum values for LED blink time (10 ms) and activity check
interval (25 ms).
v1 summary:
===========
This patch series adds a new "blkdev" LED trigger for disk (or other block
device) activity LEDs.
It has the following functionality.
* Supports all types of block devices, including virtual devices
(unlike the existing disk trigger which only works with ATA devices).
* LEDs can be configured to show read activity, write activity, or both.
* Supports multiple devices and multiple LEDs in arbitrary many-to-many
configurations. For example, it is possible to configure multiple
devices with device-specific read activity LEDs and a shared write
activity LED. (See Documentation/leds/ledtrig-blkdev.rst in the first
patch.)
* Doesn't add any overhead in the I/O path. Like the netdev LED trigger,
it periodically checks the configured devices for activity and blinks
its LEDs as appropriate.
* Blink duration (per LED) and interval between activity checks (global)
are configurable.
* Requires minimal changes to the block subsystem.
- Adds 1 pointer to struct gendisk,
- Adds (inline function) call in device_add_disk() to ensure that the
pointer is initialized to NULL (as protection against any drivers
that allocate a gendisk themselves and don't use kzalloc()), and
- Adds call in del_gendisk() to remove a device from the trigger when
that device is being removed.
These changes are all in patch #4, "block: Add block device LED trigger
integrations."
* The trigger can be mostly built as a module.
When the trigger is modular, a small portion is built in to provide a
"stub" function which can be called from del_gendisk(). The stub calls
into the modular code via a function pointer when needed. The trigger
also needs the ability to find gendisk's by name, which requires access
to the un-exported block_class and disk_type symbols.
Ian Pilcher (2):
docs: Add block device (blkdev) LED trigger documentation
leds: trigger: Add block device LED trigger
Documentation/ABI/testing/sysfs-block | 9 +
.../testing/sysfs-class-led-trigger-blkdev | 48 +
Documentation/leds/index.rst | 1 +
Documentation/leds/ledtrig-blkdev.rst | 148 +++
drivers/leds/trigger/Kconfig | 9 +
drivers/leds/trigger/Makefile | 1 +
drivers/leds/trigger/ledtrig-blkdev.c | 965 ++++++++++++++++++
7 files changed, 1181 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-class-led-trigger-blkdev
create mode 100644 Documentation/leds/ledtrig-blkdev.rst
create mode 100644 drivers/leds/trigger/ledtrig-blkdev.c
base-commit: 9e1ff307c779ce1f0f810c7ecce3d95bbae40896
--
2.31.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [RESEND PATCH v5 1/2] docs: Add block device (blkdev) LED trigger documentation
2021-10-04 15:55 [RESEND PATCH v5 0/2] Introduce block device LED trigger Ian Pilcher
@ 2021-10-04 15:55 ` Ian Pilcher
2021-10-04 15:55 ` [RESEND PATCH v5 2/2] leds: trigger: Add block device LED trigger Ian Pilcher
1 sibling, 0 replies; 7+ messages in thread
From: Ian Pilcher @ 2021-10-04 15:55 UTC (permalink / raw)
To: pavel; +Cc: linux-leds, linux-kernel, gregkh, kabel, hch
Add Documentation/ABI/testing/sysfs-class-led-trigger-blkdev to
document:
* /sys/class/leds/<led>/blink_time
* /sys/class/leds/<led>/mode
* /sys/class/leds/<led>/link_device
* /sys/class/leds/<led>/unlink_device
* /sys/class/leds/<led>/linked_devices
* /sys/class/ledtrig_blkdev/interval
Add /sys/block/<disk>/linked_leds to
Documentation/ABI/testing/sysfs-block.
Add overview in Documentation/leds/ledtrig-blkdev.rst.
Signed-off-by: Ian Pilcher <arequipeno@gmail.com>
---
Documentation/ABI/testing/sysfs-block | 9 ++
.../testing/sysfs-class-led-trigger-blkdev | 48 ++++++
Documentation/leds/index.rst | 1 +
Documentation/leds/ledtrig-blkdev.rst | 148 ++++++++++++++++++
4 files changed, 206 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-class-led-trigger-blkdev
create mode 100644 Documentation/leds/ledtrig-blkdev.rst
diff --git a/Documentation/ABI/testing/sysfs-block b/Documentation/ABI/testing/sysfs-block
index a0ed87386639..26931894084b 100644
--- a/Documentation/ABI/testing/sysfs-block
+++ b/Documentation/ABI/testing/sysfs-block
@@ -328,3 +328,12 @@ Description:
does not complete in this time then the block driver timeout
handler is invoked. That timeout handler can decide to retry
the request, to fail it or to start a device recovery strategy.
+
+What: /sys/block/<disk>/linked_leds
+Date: October 2021
+Contact: Ian Pilcher <arequipeno@gmail.com>
+Description:
+ Directory containing links to all LEDs that are associated
+ with this block device through the blkdev LED trigger. Only
+ present when at least one LED is associated. (See
+ Documentation/leds/ledtrig-blkdev.rst.)
diff --git a/Documentation/ABI/testing/sysfs-class-led-trigger-blkdev b/Documentation/ABI/testing/sysfs-class-led-trigger-blkdev
new file mode 100644
index 000000000000..292c581e2cda
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-led-trigger-blkdev
@@ -0,0 +1,48 @@
+What: /sys/class/leds/<led>/blink_time
+Date: October 2021
+Contact: Ian Pilcher <arequipeno@gmail.com>
+Description:
+ Time (in milliseconds) that the LED will be on during a single
+ "blink".
+
+What: /sys/class/leds/<led>/mode
+Date: October 2021
+Contact: Ian Pilcher <arequipeno@gmail.com>
+Description:
+ Type of events for which LED will blink - read, write,
+ or rw (both). Note that any activity that changes the state of
+ the device's non-volatile storage (including discards and cache
+ flushes) is considered to be a write.
+
+What: /sys/class/leds/<led>/link_device
+Date: October 2021
+Contact: Ian Pilcher <arequipeno@gmail.com>
+Description:
+ Associate a block device with this LED by writing the path to
+ the device special file (e.g. /dev/sda) to this attribute.
+ Symbolic links are followed.
+
+What: /sys/class/leds/<led>/unlink_device
+Date: October 2021
+Contact: Ian Pilcher <arequipeno@gmail.com>
+Description:
+ Remove the association between this LED and a block device by
+ writing the path to the device special file (e.g. /dev/sda) to
+ this attribute. Symbolic links are followed.
+
+What: /sys/class/leds/<led>/linked_devices
+Date: October 2021
+Contact: Ian Pilcher <arequipeno@gmail.com>
+Description:
+ Directory containing links to all block devices that are
+ associated with this LED. (Note that the names of the
+ symbolic links in this directory are *kernel* names, which
+ may not match the device special file paths written to
+ link_device and unlink_device.)
+
+What: /sys/class/ledtrig_blkdev/interval
+Date: October 2021
+Contact: Ian Pilcher <arequipeno@gmail.com>
+Description:
+ Frequency (in milliseconds) with which block devices associated
+ with the blkdev LED trigger will be checked for activity.
diff --git a/Documentation/leds/index.rst b/Documentation/leds/index.rst
index e5d63b940045..e3c24e468cbc 100644
--- a/Documentation/leds/index.rst
+++ b/Documentation/leds/index.rst
@@ -10,6 +10,7 @@ LEDs
leds-class
leds-class-flash
leds-class-multicolor
+ ledtrig-blkdev
ledtrig-oneshot
ledtrig-transient
ledtrig-usbport
diff --git a/Documentation/leds/ledtrig-blkdev.rst b/Documentation/leds/ledtrig-blkdev.rst
new file mode 100644
index 000000000000..5be141add33f
--- /dev/null
+++ b/Documentation/leds/ledtrig-blkdev.rst
@@ -0,0 +1,148 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=================================
+Block Device (blkdev) LED Trigger
+=================================
+
+Available when ``CONFIG_LEDS_TRIGGER_BLKDEV=y`` or
+``CONFIG_LEDS_TRIGGER_BLKDEV=m``.
+
+See also:
+
+* ``Documentation/ABI/testing/sysfs-class-led-trigger-blkdev``
+* ``Documentation/ABI/testing/sysfs-block`` (``/sys/block/<disk>/linked_leds``)
+
+Overview
+========
+
+.. note::
+ The examples below use ``<LED>`` to refer to the name of a
+ system-specific LED. If no suitable LED is available on a test
+ system (in a virtual machine, for example), it is possible to
+ use a userspace LED. (See ``Documentation/leds/uleds.rst``.)
+
+Verify that the ``blkdev`` LED trigger is available::
+
+ # grep blkdev /sys/class/leds/<LED>/trigger
+ ... rfkill-none blkdev
+
+(If the previous command produces no output, you may need to load the trigger
+module - ``modprobe ledtrig_blkdev``. If the module is not available, check
+the value of ``CONFIG_LEDS_TRIGGER_BLKDEV`` in your kernel configuration.)
+
+Associate the LED with the ``blkdev`` LED trigger::
+
+ # echo blkdev > /sys/class/leds/<LED>/trigger
+
+ # cat /sys/class/leds/<LED>/trigger
+ ... rfkill-none [blkdev]
+
+Note that several new device attributes are available in the
+``/sys/class/leds/<LED>`` directory.
+
+* ``link_device`` and ``unlink_device`` are used to manage the set of block
+ devices associated with this LED. The LED will blink in response to read or
+ write activity on its linked devices.
+
+* ``mode`` is used to control the type of device activity that will cause this
+ LED to blink - read activity, write activity, or both. (Note that any
+ activity that changes the state of a device's non-volatile storage is
+ considered to be a write. This includes discard and cache flush requests.)
+
+* ``blink_time`` is the duration (in milliseconds) of each blink of this LED.
+ (The minimum value is 10 milliseconds.)
+
+* The ``linked_devices`` directory will contain a symbolic link to every device
+ that is associated with this LED.
+
+Link a block device to the LED::
+
+ # echo /dev/sda > /sys/class/leds/<LED>/link_device
+
+ # ls /sys/class/leds/<LED>/linked_devices
+ sda
+
+(The value written to ``link_device`` must be the path of the device special
+file, such as ``/dev/sda``, that represents the block device - or the path of a
+symbolic link to such a device special file.)
+
+Read and write activity on the device should cause the LED to blink. The
+duration of each blink (in milliseconds) can be adjusted by setting
+``/sys/class/leds/<LED>/blink_time``. (But see **interval and blink_time**
+below.)
+
+Associate a second device with the LED::
+
+ # echo /dev/sdb > /sys/class/leds/<LED>/link_device
+
+ # ls /sys/class/leds/<LED>/linked_devices
+ sda sdb
+
+When a block device is linked to one or more LEDs, the LEDs are linked from
+the device's ``linked_leds`` directory::
+
+ # ls /sys/class/block/sd{a,b}/linked_leds
+ /sys/class/block/sda/linked_leds:
+ <LED>
+
+ /sys/class/block/sdb/linked_leds:
+ <LED>
+
+(The ``linked_leds`` directory only exists when the block device is linked to
+at least one LED.)
+
+``interval`` and ``blink_time``
+===============================
+
+* By default, linked block devices are checked for activity every 100
+ milliseconds. This frequency can be changed via the
+ ``/sys/class/ledtrig_blkdev/interval`` attribute. (The minimum value is 25
+ milliseconds.)
+
+* All associated devices are checked for activity every ``interval``
+ milliseconds, and a blink is triggered on appropriate LEDs. The duration
+ of an LED's blink is determined by its ``blink_time`` attribute. Thus
+ (assuming that activity of the relevant type has occurred on one of an LED's
+ linked devices), the LED will be on for ``blink_time`` milliseconds and off
+ for ``interval - blink_time`` milliseconds.
+
+* The LED subsystem ignores new blink requests for an LED that is already in
+ in the process of blinking, so setting a ``blink_time`` greater than or equal
+ to ``interval`` will cause some blinks to be missed.
+
+* Because of processing times, scheduling latencies, etc., avoiding missed
+ blinks actually requires a difference of at least a few milliseconds between
+ the ``blink_time`` and ``interval``. The required difference is likely to
+ vary from system to system. As a reference, a Thecus N5550 NAS requires a
+ difference of 7 milliseconds (``interval == 100``, ``blink_time == 93``).
+
+* The default values (``interval == 100``, ``blink_time == 75``) cause the LED
+ associated with a continuously active device to blink rapidly. For a more
+ "always on" effect, increase the ``blink_time`` (but not too much; see the
+ previous bullet).
+
+Other Notes
+===========
+
+* Many (possibly all) types of block devices work with this trigger, including:
+
+ * SCSI (including SATA and USB) hard disk drives and SSDs
+ * SCSI (including SATA and USB) optical drives
+ * NVMe SSDs
+ * SD cards
+ * loopback block devices (``/dev/loop*``)
+ * device mapper devices, such as LVM logical volumes
+ * MD RAID devices
+ * zRAM compressed RAM-disks
+ * partitions on block devics that support them
+
+* The names of the symbolic links in ``/sys/class/leds/<LED>/linked_devices``
+ are **kernel** names, which may not match the paths used for
+ ``link_device`` and ``unlink_device``. This is most likely when a symbolic
+ link is used to refer to the device (as is common with logical volumes), but
+ it can be true for any device, because nothing prevents the creation of
+ device special files with arbitrary names (e.g. ``sudo mknod /foo b 8 0``).
+
+* The ``blkdev`` LED trigger supports many-to-many device/LED associations.
+ A device can be associated with multiple LEDs, and an LED can be associated
+ with multiple devices.
--
2.31.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [RESEND PATCH v5 2/2] leds: trigger: Add block device LED trigger
2021-10-04 15:55 [RESEND PATCH v5 0/2] Introduce block device LED trigger Ian Pilcher
2021-10-04 15:55 ` [RESEND PATCH v5 1/2] docs: Add block device (blkdev) LED trigger documentation Ian Pilcher
@ 2021-10-04 15:55 ` Ian Pilcher
2021-10-05 21:27 ` Marek Behún
1 sibling, 1 reply; 7+ messages in thread
From: Ian Pilcher @ 2021-10-04 15:55 UTC (permalink / raw)
To: pavel; +Cc: linux-leds, linux-kernel, gregkh, kabel, hch
Add "blkdev" LED trigger to blink LEDs in response to block device
activity.
Add LEDS_TRIGGER_BLKDEV (tristate) config option to control building of
the trigger.
Signed-off-by: Ian Pilcher <arequipeno@gmail.com>
---
drivers/leds/trigger/Kconfig | 9 +
drivers/leds/trigger/Makefile | 1 +
drivers/leds/trigger/ledtrig-blkdev.c | 965 ++++++++++++++++++++++++++
3 files changed, 975 insertions(+)
create mode 100644 drivers/leds/trigger/ledtrig-blkdev.c
diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig
index 1f1d57288085..219d15c046d7 100644
--- a/drivers/leds/trigger/Kconfig
+++ b/drivers/leds/trigger/Kconfig
@@ -153,4 +153,13 @@ config LEDS_TRIGGER_TTY
When build as a module this driver will be called ledtrig-tty.
+config LEDS_TRIGGER_BLKDEV
+ tristate "LED Trigger for block devices"
+ depends on BLOCK
+ help
+ The blkdev LED trigger allows LEDs to be controlled by block device
+ activity (reads and writes).
+
+ See Documentation/leds/ledtrig-blkdev.rst.
+
endif # LEDS_TRIGGERS
d