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);
|
extern void map_unlock(struct map_ent **melp);
|
||||||
|
|
||||||
/* various details can be requested */
|
/* various details can be requested */
|
||||||
#define GET_LEVEL 1
|
enum sysfs_read_flags {
|
||||||
#define GET_LAYOUT 2
|
GET_LEVEL = (1 << 0),
|
||||||
#define GET_COMPONENT 4
|
GET_LAYOUT = (1 << 1),
|
||||||
#define GET_CHUNK 8
|
GET_COMPONENT = (1 << 2),
|
||||||
#define GET_CACHE 16
|
GET_CHUNK = (1 << 3),
|
||||||
#define GET_MISMATCH 32
|
GET_CACHE = (1 << 4),
|
||||||
#define GET_VERSION 64
|
GET_MISMATCH = (1 << 5),
|
||||||
#define GET_DISKS 128
|
GET_VERSION = (1 << 6),
|
||||||
#define GET_DEGRADED 256
|
GET_DISKS = (1 << 7),
|
||||||
#define GET_SAFEMODE 512
|
GET_DEGRADED = (1 << 8),
|
||||||
|
GET_SAFEMODE = (1 << 9),
|
||||||
#define GET_DEVS 1024 /* gets role, major, minor */
|
GET_DEVS = (1 << 10), /* gets role, major, minor */
|
||||||
#define GET_OFFSET 2048
|
GET_OFFSET = (1 << 11),
|
||||||
#define GET_SIZE 4096
|
GET_SIZE = (1 << 12),
|
||||||
#define GET_STATE 8192
|
GET_STATE = (1 << 13),
|
||||||
#define GET_ERROR 16384
|
GET_ERROR = (1 << 14),
|
||||||
|
SKIP_GONE_DEVS = (1 << 15),
|
||||||
|
};
|
||||||
|
|
||||||
/* If fd >= 0, get the array it is open on,
|
/* If fd >= 0, get the array it is open on,
|
||||||
* else use devnum. >=0 -> major9. <0.....
|
* else use devnum. >=0 -> major9. <0.....
|
||||||
|
|
|
@ -2734,8 +2734,14 @@ static int load_super_ddf_all(struct supertype *st, int fd,
|
||||||
int seq;
|
int seq;
|
||||||
char nm[20];
|
char nm[20];
|
||||||
int dfd;
|
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)
|
if (!sra)
|
||||||
return 1;
|
return 1;
|
||||||
if (sra->array.major_version != -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 rv;
|
||||||
int devnum = fd2devnum(fd);
|
int devnum = fd2devnum(fd);
|
||||||
int retry;
|
int retry;
|
||||||
|
enum sysfs_read_flags flags;
|
||||||
|
|
||||||
/* check if this disk is a member of an active array */
|
flags = GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE;
|
||||||
sra = sysfs_read(fd, 0, 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)
|
if (!sra)
|
||||||
return 1;
|
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);
|
strcpy(dev->sys_name, de->d_name);
|
||||||
dev->disk.raid_disk = strtoul(buf, &ep, 10);
|
dev->disk.raid_disk = strtoul(buf, &ep, 10);
|
||||||
if (*ep) dev->disk.raid_disk = -1;
|
if (*ep) dev->disk.raid_disk = -1;
|
||||||
|
|
||||||
strcpy(dbase, "block/dev");
|
strcpy(dbase, "block/dev");
|
||||||
if (load_sys(fname, buf))
|
if (load_sys(fname, buf)) {
|
||||||
goto abort;
|
free(dev);
|
||||||
|
if (options & SKIP_GONE_DEVS)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
sscanf(buf, "%d:%d", &dev->disk.major, &dev->disk.minor);
|
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) {
|
if (options & GET_OFFSET) {
|
||||||
strcpy(dbase, "offset");
|
strcpy(dbase, "offset");
|
||||||
if (load_sys(fname, buf))
|
if (load_sys(fname, buf))
|
||||||
|
|
Loading…
Reference in New Issue