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:
Dan Williams 2009-02-24 18:45:56 -07:00
parent db575f3b9e
commit dab4a5134e
4 changed files with 53 additions and 24 deletions

34
mdadm.h
View File

@ -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.....

View File

@ -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 ||

View File

@ -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
View File

@ -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))