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 <dan.j.williams@intel.com>
This commit is contained in:
parent
db575f3b9e
commit
dab4a5134e
34
mdadm.h
34
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.....
|
||||
|
|
|
@ -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 ||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
26
sysfs.c
26
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))
|
||||
|
|
Loading…
Reference in New Issue