From dab4a5134e8d946f3809163af6abb80a945c904c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 24 Feb 2009 18:45:56 -0700 Subject: [PATCH] sysfs: allow sysfs_read to detect and drop removed disks All operations that rely on loading from an existing container (like --add) will fail after a disk has been removed. Provide an option to skip missing / offline disks rather than abort. We attempt to do this in the load_super_{imsm,ddf}_all cases when mdmon is running i.e. we already have a consitent version of the metadata running in the system. Otherwise, we fail as normal and let the administrator fix up the container. Signed-off-by: Dan Williams --- mdadm.h | 34 ++++++++++++++++++---------------- super-ddf.c | 8 +++++++- super-intel.c | 9 +++++++-- sysfs.c | 26 +++++++++++++++++++++----- 4 files changed, 53 insertions(+), 24 deletions(-) diff --git a/mdadm.h b/mdadm.h index 5be3affe..f8f36859 100644 --- a/mdadm.h +++ b/mdadm.h @@ -334,22 +334,24 @@ extern int map_lock(struct map_ent **melp); extern void map_unlock(struct map_ent **melp); /* various details can be requested */ -#define GET_LEVEL 1 -#define GET_LAYOUT 2 -#define GET_COMPONENT 4 -#define GET_CHUNK 8 -#define GET_CACHE 16 -#define GET_MISMATCH 32 -#define GET_VERSION 64 -#define GET_DISKS 128 -#define GET_DEGRADED 256 -#define GET_SAFEMODE 512 - -#define GET_DEVS 1024 /* gets role, major, minor */ -#define GET_OFFSET 2048 -#define GET_SIZE 4096 -#define GET_STATE 8192 -#define GET_ERROR 16384 +enum sysfs_read_flags { + GET_LEVEL = (1 << 0), + GET_LAYOUT = (1 << 1), + GET_COMPONENT = (1 << 2), + GET_CHUNK = (1 << 3), + GET_CACHE = (1 << 4), + GET_MISMATCH = (1 << 5), + GET_VERSION = (1 << 6), + GET_DISKS = (1 << 7), + GET_DEGRADED = (1 << 8), + GET_SAFEMODE = (1 << 9), + GET_DEVS = (1 << 10), /* gets role, major, minor */ + GET_OFFSET = (1 << 11), + GET_SIZE = (1 << 12), + GET_STATE = (1 << 13), + GET_ERROR = (1 << 14), + SKIP_GONE_DEVS = (1 << 15), +}; /* If fd >= 0, get the array it is open on, * else use devnum. >=0 -> major9. <0..... diff --git a/super-ddf.c b/super-ddf.c index f621f4df..6c75998e 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -2734,8 +2734,14 @@ static int load_super_ddf_all(struct supertype *st, int fd, int seq; char nm[20]; int dfd; + int devnum = fd2devnum(fd); + enum sysfs_read_flags flags; - sra = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE); + flags = GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE; + if (mdmon_running(devnum)) + flags |= SKIP_GONE_DEVS; + + sra = sysfs_read(fd, 0, flags); if (!sra) return 1; if (sra->array.major_version != -1 || diff --git a/super-intel.c b/super-intel.c index f55d7076..dd69cb13 100644 --- a/super-intel.c +++ b/super-intel.c @@ -1976,9 +1976,14 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp, int rv; int devnum = fd2devnum(fd); int retry; + enum sysfs_read_flags flags; - /* check if this disk is a member of an active array */ - sra = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE); + flags = GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE; + if (mdmon_running(devnum)) + flags |= SKIP_GONE_DEVS; + + /* check if 'fd' an opened container */ + sra = sysfs_read(fd, 0, flags); if (!sra) return 1; diff --git a/sysfs.c b/sysfs.c index b9fd3da9..2dad7d3f 100644 --- a/sysfs.c +++ b/sysfs.c @@ -272,18 +272,34 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options) } } - dev->next = sra->devs; - sra->devs = dev; - strcpy(dev->sys_name, de->d_name); dev->disk.raid_disk = strtoul(buf, &ep, 10); if (*ep) dev->disk.raid_disk = -1; strcpy(dbase, "block/dev"); - if (load_sys(fname, buf)) - goto abort; + if (load_sys(fname, buf)) { + free(dev); + if (options & SKIP_GONE_DEVS) + continue; + else + goto abort; + } sscanf(buf, "%d:%d", &dev->disk.major, &dev->disk.minor); + /* special case check for block devices that can go 'offline' */ + if (options & SKIP_GONE_DEVS) { + strcpy(dbase, "block/device/state"); + if (load_sys(fname, buf) == 0 && + strncmp(buf, "offline", 7) == 0) { + free(dev); + continue; + } + } + + /* finally add this disk to the array */ + dev->next = sra->devs; + sra->devs = dev; + if (options & GET_OFFSET) { strcpy(dbase, "offset"); if (load_sys(fname, buf)) -- 2.39.2