mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 02:49:02 -04:00
Detect degraded state for Bcachefs and Linux MD RAID arrays
This commit is contained in:
parent
2852b09d47
commit
89b1f47c33
1 changed files with 72 additions and 19 deletions
|
|
@ -840,18 +840,26 @@ static int devdereference_bcachefs(uint64_t device, const char* dir, tommy_list*
|
|||
}
|
||||
|
||||
/*
|
||||
* mountinfo format
|
||||
* 0 - mount ID
|
||||
* 1 - parent ID
|
||||
* 2 - major:minor
|
||||
* 3 - root
|
||||
* 4 - mount point
|
||||
* 5 - options
|
||||
* 6 - "-" (separator)
|
||||
* 7 - fs
|
||||
* 8 - mount source - /dev/device
|
||||
* Example of /proc/self/mountinfo entry for bcachefs:
|
||||
*
|
||||
* 36 35 0:34 / /mnt/bcachefs rw,noatime shared:1 - bcachefs /dev/sda:/dev/sdb rw,degraded,metadata_replicas=2
|
||||
*
|
||||
* Before " - " (id_map):
|
||||
* id_map[0] = mount ID (36)
|
||||
* id_map[1] = parent ID (35)
|
||||
* id_map[2] = major:minor (0:34)
|
||||
* id_map[3] = root (/)
|
||||
* id_map[4] = mount point (/mnt/bcachefs)
|
||||
* id_map[5] = mount options (rw,noatime)
|
||||
*
|
||||
* After " - " (fs_map):
|
||||
* fs_map[0] = filesystem type (bcachefs)
|
||||
* fs_map[1] = mount source (/dev/sda:/dev/sdb, member devices separated by ':')
|
||||
* fs_map[2] = super options (rw,degraded,metadata_replicas=2)
|
||||
*/
|
||||
size_t best_len = 0;
|
||||
int degraded = 0;
|
||||
|
||||
while (1) {
|
||||
char buf[PATH_MAX * 2 + 64];
|
||||
char* id_map[8];
|
||||
|
|
@ -901,6 +909,14 @@ static int devdereference_bcachefs(uint64_t device, const char* dir, tommy_list*
|
|||
best_len = mp_len;
|
||||
unescape_mount(fs_map[1]);
|
||||
pathcpy(device_list, sizeof(device_list), fs_map[1]);
|
||||
|
||||
/* check if mounted degraded */
|
||||
if ((fs_mac >= 3 && strstr(fs_map[2], "degraded") != 0)
|
||||
|| (id_mac >= 6 && strstr(id_map[5], "degraded") != 0)) {
|
||||
degraded = 1;
|
||||
} else {
|
||||
degraded = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -920,6 +936,10 @@ static int devdereference_bcachefs(uint64_t device, const char* dir, tommy_list*
|
|||
struct stat st;
|
||||
if (stat(dev_map[i], &st) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
if (errno == ENOENT) {
|
||||
degraded = 1;
|
||||
continue;
|
||||
}
|
||||
log_error(errno, "Failed stat %s. %s.", dev_map[i], strerror(errno));
|
||||
goto bail;
|
||||
/* LCOV_EXCL_STOP */
|
||||
|
|
@ -943,7 +963,7 @@ static int devdereference_bcachefs(uint64_t device, const char* dir, tommy_list*
|
|||
if (tommy_list_empty(devlist))
|
||||
goto bail;
|
||||
|
||||
return 0;
|
||||
return degraded ? 1 : 0;
|
||||
|
||||
bail:
|
||||
tommy_list_foreach(devlist, free);
|
||||
|
|
@ -3131,16 +3151,46 @@ static dev_t devread(const char* path)
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check if an MD RAID array is running in degraded mode by inspecting the
|
||||
* sysfs degraded attribute. Returns 1 if degraded, 0 if healthy or not an MD array.
|
||||
*/
|
||||
#if HAVE_LINUX_DEVICE
|
||||
static int devtree_md_degraded(const char* path)
|
||||
{
|
||||
char buf[32];
|
||||
ssize_t len = sysread(path, buf, sizeof(buf) - 1);
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
|
||||
buf[len] = 0;
|
||||
int val = strtoi(buf, 0, 10);
|
||||
if (val > 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Read a device tree filling the specified list of disk_t entries.
|
||||
*/
|
||||
#if HAVE_LINUX_DEVICE
|
||||
static int devtree(devinfo_t* parent, dev_t device, tommy_list* list)
|
||||
static int devtree(devinfo_t* parent, dev_t device, tommy_list* list, int* degraded)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
DIR* d;
|
||||
int slaves = 0;
|
||||
|
||||
/* check if this device or parent partition is a degraded MD array */
|
||||
pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/md/degraded", major(device), minor(device));
|
||||
if (devtree_md_degraded(path))
|
||||
*degraded = 1;
|
||||
|
||||
pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/../md/degraded", major(device), minor(device));
|
||||
if (devtree_md_degraded(path))
|
||||
*degraded = 1;
|
||||
|
||||
pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves", major(device), minor(device));
|
||||
|
||||
/* check if there is a slaves list */
|
||||
|
|
@ -3163,7 +3213,7 @@ static int devtree(devinfo_t* parent, dev_t device, tommy_list* list)
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
if (devtree(parent, subdev, list) != 0) {
|
||||
if (devtree(parent, subdev, list, degraded) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
closedir(d);
|
||||
return -1;
|
||||
|
|
@ -4095,11 +4145,8 @@ int devquery(tommy_list* high, tommy_list* low)
|
|||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
if (ret > 0) {
|
||||
log_fatal(ENXIO, "DANGER! Disk '%s' is degraded due to missing device(s).\n", devinfo->name);
|
||||
log_tag("degraded:%s\n", esc_tag(devinfo->name));
|
||||
degraded = 1;
|
||||
}
|
||||
|
||||
int disk_degraded = ret > 0;
|
||||
|
||||
devinfo->file[0] = 0;
|
||||
for (tommy_node* j = tommy_list_head(&devlist); j != 0; j = j->next) {
|
||||
|
|
@ -4130,7 +4177,7 @@ int devquery(tommy_list* high, tommy_list* low)
|
|||
pathcat(devinfo->file, sizeof(devinfo->file), file);
|
||||
|
||||
/* expand the tree of devices */
|
||||
if (devtree(devinfo, dev->device, low) != 0) {
|
||||
if (devtree(devinfo, dev->device, low, &disk_degraded) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EEXTERNAL, "Failed to expand device '%u:%u'.\n", major(dev->device), minor(dev->device));
|
||||
return -1;
|
||||
|
|
@ -4138,6 +4185,12 @@ int devquery(tommy_list* high, tommy_list* low)
|
|||
}
|
||||
}
|
||||
|
||||
if (disk_degraded) {
|
||||
log_fatal(ENXIO, "DANGER! Disk '%s' is degraded due to missing device(s).\n", devinfo->name);
|
||||
log_tag("degraded:%s\n", esc_tag(devinfo->name));
|
||||
degraded = 1;
|
||||
}
|
||||
|
||||
tommy_list_foreach(&devlist, free);
|
||||
}
|
||||
#else
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue