Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/ledmon.conf.pod
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ Value also can be set by integer number - 0 means 'quiet' and 5 means 'all'.
B<LOG_PATH> - Sets a path to local log file. If this option is specified the
global log file F</var/log/ledmon.log> is not used.

B<BLINK_PERSISTENT_FAIL_ON_READD> - Controls whether the failure LED remains
on when a non-RAID drive is re-added after removal. If value is set to true,
the failure indication persists until the drive is manually addressed. If value
is set to false, non-RAID drives that reappear in the sysfs scan will
automatically recover from the failure state and the LED will be cleared. RAID
member drives always retain persistent failure regardless of this setting. The
default value is true.

B<RAID_MEMBERS_ONLY> - If flag is set to true ledmon will limit monitoring only
to drives that are RAID members. The default value is false.

Expand Down
8 changes: 8 additions & 0 deletions src/common/config_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ static int parse_next(FILE *fd, struct ledmon_conf *conf)
conf->raid_members_only = parse_bool(s);
if (conf->raid_members_only < 0)
return -1;
} else if (!strncmp(s, "BLINK_PERSISTENT_FAIL_ON_READD=", 31)) {
s += 31;
conf->blink_persistent_fail_on_readd = parse_bool(s);
if (conf->blink_persistent_fail_on_readd < 0)
return -1;
} else if (_parse_and_add_to_list(s, WHITELIST, WHITELIST_LEN, &conf->cntrls_allowlist)) {
/* Deprecated, provided for backwards compatibility */
return 0;
Expand Down Expand Up @@ -327,6 +332,9 @@ int ledmon_write_shared_conf(struct ledmon_conf *conf)
"RAID_MEMBERS_ONLY=%d\n", conf->raid_members_only);
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
"REBUILD_BLINK_ON_ALL=%d\n", conf->rebuild_blink_on_all);
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
"BLINK_PERSISTENT_FAIL_ON_READD=%d\n",
conf->blink_persistent_fail_on_readd);
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
"INTERVAL=%d\n", conf->scan_interval);
allowlist = conf_list_to_str(&conf->cntrls_allowlist);
Expand Down
1 change: 1 addition & 0 deletions src/common/config_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct ledmon_conf {
int blink_on_init;
int rebuild_blink_on_all;
int raid_members_only;
int blink_persistent_fail_on_readd;

/* allowlist and excludelist of controllers for blinking */
struct list cntrls_allowlist;
Expand Down
5 changes: 5 additions & 0 deletions src/ledmon/ledmon.c
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,10 @@ static void _add_block(struct block_device *block)
} else {
temp->ibpi = block->ibpi;
}
} else if (temp->ibpi == LED_IBPI_PATTERN_FAILED_DRIVE &&
!temp->raid_dev &&
!conf.blink_persistent_fail_on_readd) {
temp->ibpi = LED_IBPI_PATTERN_ADDED;
} else if (!(temp->ibpi == LED_IBPI_PATTERN_FAILED_DRIVE &&
block->ibpi == LED_IBPI_PATTERN_HOTSPARE) ||
(temp->ibpi == LED_IBPI_PATTERN_FAILED_DRIVE &&
Expand Down Expand Up @@ -884,6 +888,7 @@ static ledmon_status_code_t _init_ledmon_conf(void)
conf.blink_on_migration = 1;
conf.rebuild_blink_on_all = 0;
conf.raid_members_only = 0;
conf.blink_persistent_fail_on_readd = 1;
conf.scan_interval = LEDMON_DEF_SLEEP_INTERVAL;
return rc;
}
Expand Down
36 changes: 26 additions & 10 deletions src/ledmon/udev.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,40 @@ static struct udev_monitor *udev_monitor;

static int _compare(const struct block_device *bd, const char *syspath, struct led_ctx *ctx)
{
struct block_device *bd_new;
const char *udev_name;
const char *dev_name;
int ret;

if (!bd || !syspath)
return 0;

if (strcmp(bd->sysfs_path, syspath) == 0) {
if (strcmp(bd->sysfs_path, syspath) == 0)
return 1;
} else {
struct block_device *bd_new;
int ret;

bd_new = block_device_init(sysfs_get_cntrl_devices(ctx), syspath);
if (!bd_new)
return 0;

bd_new = block_device_init(sysfs_get_cntrl_devices(ctx), syspath);
if (bd_new) {
ret = block_compare(bd, bd_new);
block_device_fini(bd_new);

return ret;
if (ret)
return 1;
}

/*
* NVMe udev events may arrive with a virtual nvme-subsystem path
* that cannot be resolved to a PCI controller. Fall back to matching
* by device name so that add/remove events are not silently dropped.
*/
if (bd->devnode[0] == '\0')
return 0;

dev_name = strrchr(bd->devnode, '/');
dev_name = dev_name ? dev_name + 1 : bd->devnode;

udev_name = strrchr(syspath, '/');
udev_name = udev_name ? udev_name + 1 : syspath;

return strcmp(dev_name, udev_name) == 0;
}

static int create_udev_monitor(void)
Expand Down
7 changes: 7 additions & 0 deletions src/lib/pci_slot.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "config.h"
#include "led/libled.h"
Expand Down Expand Up @@ -71,6 +72,12 @@ struct slot_property *pci_slot_property_init(struct pci_slot *pci_slot)

result->bl_device = get_block_device_from_sysfs_path(pci_slot->ctx,
pci_slot->address, true);
if (result->bl_device) {
Comment thread
tasleson marked this conversation as resolved.
struct stat st;

if (stat(result->bl_device->devnode, &st) != 0)
result->bl_device = NULL;
}
result->slot_spec.pci = pci_slot;
snprintf(result->slot_id, PATH_MAX, "%s", pci_slot->sysfs_path);
result->c = &pci_slot_common;
Expand Down