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>
extern void map_unlock(struct map_ent **melp);
/* various details can be requested */
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.....
/* If fd >= 0, get the array it is open on,
* else use devnum. >=0 -> major9. <0.....
int seq;
char nm[20];
int dfd;
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 ||
if (!sra)
return 1;
if (sra->array.major_version != -1 ||
int rv;
int devnum = fd2devnum(fd);
int retry;
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);
- 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");
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);
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))
if (options & GET_OFFSET) {
strcpy(dbase, "offset");
if (load_sys(fname, buf))