2001-06-08 04:36:23 +02:00
|
|
|
/*
|
2002-03-08 01:03:52 +01:00
|
|
|
* mdadm - manage Linux "md" devices aka RAID arrays.
|
2001-06-08 04:36:23 +02:00
|
|
|
*
|
2013-09-03 06:16:22 +02:00
|
|
|
* Copyright (C) 2001-2013 Neil Brown <neilb@suse.de>
|
2001-06-08 04:36:23 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
* Author: Neil Brown
|
2009-06-02 06:35:45 +02:00
|
|
|
* Email: <neilb@suse.de>
|
2001-06-08 04:36:23 +02:00
|
|
|
*/
|
|
|
|
|
2002-03-08 01:03:52 +01:00
|
|
|
#include "mdadm.h"
|
2001-06-08 04:36:23 +02:00
|
|
|
#include "md_p.h"
|
|
|
|
#include "md_u.h"
|
2017-04-20 04:40:06 +02:00
|
|
|
#include <ctype.h>
|
2008-09-18 07:05:20 +02:00
|
|
|
#include <dirent.h>
|
2001-06-08 04:36:23 +02:00
|
|
|
|
2013-06-20 22:21:05 +02:00
|
|
|
static int cmpstringp(const void *p1, const void *p2)
|
|
|
|
{
|
|
|
|
return strcmp(* (char * const *) p1, * (char * const *) p2);
|
|
|
|
}
|
|
|
|
|
2013-06-27 21:39:27 +02:00
|
|
|
static int add_device(const char *dev, char ***p_devices,
|
|
|
|
int *p_max_devices, int n_devices)
|
|
|
|
{
|
|
|
|
if (n_devices + 1 >= *p_max_devices) {
|
|
|
|
*p_max_devices += 16;
|
|
|
|
*p_devices = xrealloc(*p_devices, *p_max_devices *
|
|
|
|
sizeof(**p_devices));
|
|
|
|
if (!*p_devices) {
|
|
|
|
*p_max_devices = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
(*p_devices)[n_devices] = xstrdup(dev);
|
|
|
|
return n_devices + 1;
|
|
|
|
}
|
|
|
|
|
2012-07-09 09:20:16 +02:00
|
|
|
int Detail(char *dev, struct context *c)
|
2001-06-08 04:36:23 +02:00
|
|
|
{
|
|
|
|
/*
|
2017-03-29 21:23:50 +02:00
|
|
|
* Print out details for an md array
|
2001-06-08 04:36:23 +02:00
|
|
|
*/
|
2008-07-25 00:35:11 +02:00
|
|
|
int fd = open(dev, O_RDONLY);
|
2001-06-08 04:36:23 +02:00
|
|
|
mdu_array_info_t array;
|
mdadm: add --no-devices to avoid component devices detail information
When people assemble a md raid device with a large number of
component deivces (e.g. 1500 DASD disks), the raid device detail
information generated by 'mdadm --detail --export $devnode' is very
large. It is because the detail information contains information of
all the component disks (even the missing/failed ones).
In such condition, when udev-md-raid-arrays.rules is triggered and
internally calls "mdadm --detail --no-devices --export $devnode",
user may observe systemd error message ""invalid message length". It
is because the following on-stack raw message buffer in systemd code
is not big enough,
systemd/src/libudev/libudev-monitor.c
_public_ struct udev_device *udev_monito ...
struct ucred *cred;
union {
struct udev_monitor_netlink_header nlh;
char raw[8192];
} buf;
Even change size of raw[] from 8KB to larger size, it may still be not
enough for detail message of a md raid device with much larger number of
component devices.
To fix this problem, an extra option '--no-devices' is added (the
original idea is proposed by Neil Brown). When printing detailed
information of a md raid device, if '--no-devices' is specified, then
all component devices information will not be printed, then the output
message size can be restricted to a small number, even with the systemd
only has 8KB on-disk raw buffer, the md raid array udev rules can work
correctly without failure message.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: NeilBrown <neilb@suse.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2019-07-31 07:29:29 +02:00
|
|
|
mdu_disk_info_t *disks = NULL;
|
2005-08-15 08:54:20 +02:00
|
|
|
int next;
|
2001-06-08 04:36:23 +02:00
|
|
|
int d;
|
|
|
|
time_t atime;
|
2012-07-09 09:20:05 +02:00
|
|
|
char *str;
|
2013-06-20 22:21:05 +02:00
|
|
|
char **devices = NULL;
|
|
|
|
int max_devices = 0, n_devices = 0;
|
2003-10-29 00:20:01 +01:00
|
|
|
int spares = 0;
|
2004-06-04 14:03:19 +02:00
|
|
|
struct stat stb;
|
2004-08-11 04:16:01 +02:00
|
|
|
int failed = 0;
|
2021-07-27 10:25:18 +02:00
|
|
|
struct supertype *st = NULL;
|
2010-11-22 09:35:25 +01:00
|
|
|
char *subarray = NULL;
|
2006-03-29 01:02:45 +02:00
|
|
|
int max_disks = MD_SB_DISKS; /* just a default */
|
2010-11-22 10:24:35 +01:00
|
|
|
struct mdinfo *info = NULL;
|
2021-07-27 10:25:18 +02:00
|
|
|
struct mdinfo *sra = NULL;
|
2013-05-13 08:57:10 +02:00
|
|
|
struct mdinfo *subdev;
|
2008-09-18 07:05:20 +02:00
|
|
|
char *member = NULL;
|
|
|
|
char *container = NULL;
|
2001-06-08 04:36:23 +02:00
|
|
|
|
2012-07-09 09:20:16 +02:00
|
|
|
int rv = c->test ? 4 : 1;
|
2007-05-21 06:25:50 +02:00
|
|
|
int avail_disks = 0;
|
2011-11-01 16:09:25 +01:00
|
|
|
char *avail = NULL;
|
2013-05-13 08:57:10 +02:00
|
|
|
int external;
|
|
|
|
int inactive;
|
2017-08-18 12:00:23 +02:00
|
|
|
int is_container = 0;
|
mdadm: Introduce new array state 'broken' for raid0/linear
Currently if a md raid0/linear array gets one or more members removed while
being mounted, kernel keeps showing state 'clean' in the 'array_state'
sysfs attribute. Despite udev signaling the member device is gone, 'mdadm'
cannot issue the STOP_ARRAY ioctl successfully, given the array is mounted.
Nothing else hints that something is wrong (except that the removed devices
don't show properly in the output of mdadm 'detail' command). There is no
other property to be checked, and if user is not performing reads/writes
to the array, even kernel log is quiet and doesn't give a clue about the
missing member.
This patch is the mdadm counterpart of kernel new array state 'broken'.
The 'broken' state mimics the state 'clean' in every aspect, being useful
only to distinguish if an array has some member missing. All necessary
paths in mdadm were changed to deal with 'broken' state, and in case the
tool runs in a kernel that is not updated, it'll work normally, i.e., it
doesn't require the 'broken' state in order to work.
Also, this patch changes the way the array state is showed in the 'detail'
command (for raid0/linear only) - now it takes the 'array_state' sysfs
attribute into account instead of only rely in the MD_SB_CLEAN flag.
Cc: Jes Sorensen <jes.sorensen@gmail.com>
Cc: NeilBrown <neilb@suse.de>
Cc: Song Liu <songliubraving@fb.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@canonical.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2019-09-03 21:49:01 +02:00
|
|
|
char *arrayst;
|
2001-07-26 09:00:09 +02:00
|
|
|
|
2001-06-08 04:36:23 +02:00
|
|
|
if (fd < 0) {
|
2012-07-09 09:14:16 +02:00
|
|
|
pr_err("cannot open %s: %s\n",
|
2001-06-08 04:36:23 +02:00
|
|
|
dev, strerror(errno));
|
2003-10-29 00:20:01 +01:00
|
|
|
return rv;
|
2001-06-08 04:36:23 +02:00
|
|
|
}
|
2017-08-10 11:43:48 +02:00
|
|
|
sra = sysfs_read(fd, NULL, GET_VERSION | GET_DEVS |
|
|
|
|
GET_ARRAY_STATE | GET_STATE);
|
2017-04-05 21:26:53 +02:00
|
|
|
if (!sra) {
|
2017-04-25 20:34:31 +02:00
|
|
|
if (md_get_array_info(fd, &array)) {
|
|
|
|
pr_err("%s does not appear to be an md device\n", dev);
|
2021-07-27 10:25:18 +02:00
|
|
|
goto out;
|
2017-04-25 20:34:31 +02:00
|
|
|
}
|
2001-06-08 04:36:23 +02:00
|
|
|
}
|
2017-04-05 21:26:53 +02:00
|
|
|
external = (sra != NULL && sra->array.major_version == -1 &&
|
|
|
|
sra->array.minor_version == -2);
|
2017-08-10 11:43:48 +02:00
|
|
|
inactive = (sra != NULL && !md_array_is_active(sra));
|
2013-05-13 08:57:10 +02:00
|
|
|
st = super_by_fd(fd, &subarray);
|
2017-05-24 11:34:22 +02:00
|
|
|
if (md_get_array_info(fd, &array)) {
|
|
|
|
if (errno == ENODEV) {
|
|
|
|
if (sra->array.major_version == -1 &&
|
|
|
|
sra->array.minor_version == -1 &&
|
|
|
|
sra->devs == NULL) {
|
|
|
|
pr_err("Array associated with md device %s does not exist.\n",
|
|
|
|
dev);
|
2021-07-27 10:25:18 +02:00
|
|
|
goto out;
|
2017-05-24 11:34:22 +02:00
|
|
|
}
|
|
|
|
array = sra->array;
|
|
|
|
} else {
|
|
|
|
pr_err("cannot get array detail for %s: %s\n",
|
|
|
|
dev, strerror(errno));
|
2021-07-27 10:25:18 +02:00
|
|
|
goto out;
|
2017-03-27 05:36:56 +02:00
|
|
|
}
|
2001-06-08 04:36:23 +02:00
|
|
|
}
|
2005-05-04 01:44:32 +02:00
|
|
|
|
2017-08-18 12:00:23 +02:00
|
|
|
if (array.raid_disks == 0 && external)
|
|
|
|
is_container = 1;
|
2004-06-04 14:03:19 +02:00
|
|
|
if (fstat(fd, &stb) != 0 && !S_ISBLK(stb.st_mode))
|
|
|
|
stb.st_rdev = 0;
|
2003-10-29 00:20:01 +01:00
|
|
|
rv = 0;
|
2004-08-11 04:16:01 +02:00
|
|
|
|
2008-09-18 07:05:20 +02:00
|
|
|
if (st)
|
|
|
|
max_disks = st->max_devs;
|
|
|
|
|
2010-11-23 05:31:18 +01:00
|
|
|
if (subarray) {
|
2008-09-18 07:05:20 +02:00
|
|
|
/* This is a subarray of some container.
|
|
|
|
* We want the name of the container, and the member
|
|
|
|
*/
|
2016-05-18 20:23:13 +02:00
|
|
|
dev_t devid = devnm2devid(st->container_devnm);
|
2013-03-01 23:28:33 +01:00
|
|
|
int cfd, err;
|
2010-11-23 05:31:18 +01:00
|
|
|
|
|
|
|
member = subarray;
|
2012-11-01 06:14:01 +01:00
|
|
|
container = map_dev_preferred(major(devid), minor(devid),
|
|
|
|
1, c->prefer);
|
2013-03-01 23:28:33 +01:00
|
|
|
cfd = open_dev(st->container_devnm);
|
|
|
|
if (cfd >= 0) {
|
|
|
|
err = st->ss->load_container(st, cfd, NULL);
|
|
|
|
close(cfd);
|
|
|
|
if (err == 0)
|
|
|
|
info = st->ss->container_content(st, subarray);
|
|
|
|
}
|
2008-09-18 07:05:20 +02:00
|
|
|
}
|
2005-06-08 01:03:46 +02:00
|
|
|
|
2013-05-13 08:57:10 +02:00
|
|
|
/* try to load a superblock. Try sra->devs first, then try ioctl */
|
2017-04-12 23:05:55 +02:00
|
|
|
if (st && !info)
|
|
|
|
for (d = 0, subdev = sra ? sra->devs : NULL;
|
|
|
|
d < max_disks || subdev;
|
|
|
|
subdev ? (void)(subdev = subdev->next) : (void)(d++)){
|
2004-08-11 04:16:01 +02:00
|
|
|
mdu_disk_info_t disk;
|
|
|
|
char *dv;
|
2010-08-05 04:10:57 +02:00
|
|
|
int fd2;
|
|
|
|
int err;
|
2017-04-12 23:05:55 +02:00
|
|
|
|
2013-05-13 08:57:10 +02:00
|
|
|
if (subdev)
|
|
|
|
disk = subdev->disk;
|
|
|
|
else {
|
|
|
|
disk.number = d;
|
2017-03-29 21:23:50 +02:00
|
|
|
if (md_get_disk_info(fd, &disk) < 0)
|
2013-05-13 08:57:10 +02:00
|
|
|
continue;
|
|
|
|
if (d >= array.raid_disks &&
|
2017-04-25 18:21:39 +02:00
|
|
|
disk.major == 0 && disk.minor == 0)
|
2013-05-13 08:57:10 +02:00
|
|
|
continue;
|
|
|
|
}
|
2010-08-05 04:10:57 +02:00
|
|
|
|
|
|
|
if (array.raid_disks > 0 &&
|
|
|
|
(disk.state & (1 << MD_DISK_ACTIVE)) == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
dv = map_dev(disk.major, disk.minor, 1);
|
|
|
|
if (!dv)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
fd2 = dev_open(dv, O_RDONLY);
|
|
|
|
if (fd2 < 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (st->sb)
|
|
|
|
st->ss->free_super(st);
|
|
|
|
|
|
|
|
err = st->ss->load_super(st, fd2, NULL);
|
|
|
|
close(fd2);
|
|
|
|
if (err)
|
|
|
|
continue;
|
2010-11-22 10:24:35 +01:00
|
|
|
if (info)
|
|
|
|
free(info);
|
|
|
|
if (subarray)
|
|
|
|
info = st->ss->container_content(st, subarray);
|
|
|
|
else {
|
2012-07-09 09:14:16 +02:00
|
|
|
info = xmalloc(sizeof(*info));
|
2010-11-22 10:24:35 +01:00
|
|
|
st->ss->getinfo_super(st, info, NULL);
|
|
|
|
}
|
|
|
|
if (!info)
|
|
|
|
continue;
|
2010-08-05 04:10:57 +02:00
|
|
|
|
|
|
|
if (array.raid_disks != 0 && /* container */
|
2010-11-22 10:24:35 +01:00
|
|
|
(info->array.ctime != array.ctime ||
|
|
|
|
info->array.level != array.level)) {
|
2010-08-05 04:10:57 +02:00
|
|
|
st->ss->free_super(st);
|
|
|
|
continue;
|
2004-08-11 04:16:01 +02:00
|
|
|
}
|
2010-08-05 04:10:57 +02:00
|
|
|
/* some formats (imsm) have free-floating-spares
|
2010-12-26 11:59:31 +01:00
|
|
|
* with a uuid of uuid_zero, they don't
|
2010-08-05 04:10:57 +02:00
|
|
|
* have very good info about the rest of the
|
|
|
|
* container, so keep searching when
|
|
|
|
* encountering such a device. Otherwise, stop
|
|
|
|
* after the first successful call to
|
|
|
|
* ->load_super.
|
|
|
|
*/
|
2010-12-26 11:59:31 +01:00
|
|
|
if (memcmp(uuid_zero,
|
2010-11-22 10:24:35 +01:00
|
|
|
info->uuid,
|
2010-12-26 11:59:31 +01:00
|
|
|
sizeof(uuid_zero)) == 0) {
|
2010-08-05 04:10:57 +02:00
|
|
|
st->ss->free_super(st);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
2004-08-11 04:16:01 +02:00
|
|
|
}
|
|
|
|
|
2001-06-08 04:36:23 +02:00
|
|
|
/* Ok, we have some info to print... */
|
2020-11-22 16:12:29 +01:00
|
|
|
if (inactive && info)
|
2020-09-14 04:52:18 +02:00
|
|
|
str = map_num(pers, info->array.level);
|
|
|
|
else
|
|
|
|
str = map_num(pers, array.level);
|
2007-05-08 09:17:33 +02:00
|
|
|
|
2012-07-09 09:20:16 +02:00
|
|
|
if (c->export) {
|
2008-09-18 07:05:20 +02:00
|
|
|
if (array.raid_disks) {
|
2012-07-09 09:20:05 +02:00
|
|
|
if (str)
|
|
|
|
printf("MD_LEVEL=%s\n", str);
|
2008-09-18 07:05:20 +02:00
|
|
|
printf("MD_DEVICES=%d\n", array.raid_disks);
|
|
|
|
} else {
|
2017-08-18 12:00:23 +02:00
|
|
|
if (is_container)
|
2013-05-13 08:57:10 +02:00
|
|
|
printf("MD_LEVEL=container\n");
|
2008-09-18 07:05:20 +02:00
|
|
|
printf("MD_DEVICES=%d\n", array.nr_disks);
|
|
|
|
}
|
|
|
|
if (container) {
|
|
|
|
printf("MD_CONTAINER=%s\n", container);
|
|
|
|
printf("MD_MEMBER=%s\n", member);
|
|
|
|
} else {
|
|
|
|
if (sra && sra->array.major_version < 0)
|
|
|
|
printf("MD_METADATA=%s\n", sra->text_version);
|
|
|
|
else
|
2010-01-11 21:38:12 +01:00
|
|
|
printf("MD_METADATA=%d.%d\n",
|
2017-04-25 18:21:39 +02:00
|
|
|
array.major_version,
|
|
|
|
array.minor_version);
|
2008-09-18 07:05:20 +02:00
|
|
|
}
|
2012-08-13 00:00:21 +02:00
|
|
|
|
2010-11-22 10:24:35 +01:00
|
|
|
if (st && st->sb && info) {
|
2008-09-18 08:12:28 +02:00
|
|
|
char nbuf[64];
|
2008-11-04 10:50:39 +01:00
|
|
|
struct map_ent *mp, *map = NULL;
|
2010-08-05 04:10:57 +02:00
|
|
|
|
2010-11-22 10:24:35 +01:00
|
|
|
fname_from_uuid(st, info, nbuf, ':');
|
2017-04-25 18:21:39 +02:00
|
|
|
printf("MD_UUID=%s\n", nbuf + 5);
|
2010-11-22 10:24:35 +01:00
|
|
|
mp = map_by_uuid(&map, info->uuid);
|
2008-11-04 10:50:39 +01:00
|
|
|
if (mp && mp->path &&
|
2012-10-04 08:34:20 +02:00
|
|
|
strncmp(mp->path, "/dev/md/", 8) == 0) {
|
|
|
|
printf("MD_DEVNAME=");
|
2017-04-25 18:21:39 +02:00
|
|
|
print_escape(mp->path + 8);
|
2012-10-04 08:34:20 +02:00
|
|
|
putchar('\n');
|
|
|
|
}
|
2007-12-14 10:15:21 +01:00
|
|
|
|
2008-09-18 08:12:28 +02:00
|
|
|
if (st->ss->export_detail_super)
|
|
|
|
st->ss->export_detail_super(st);
|
2018-06-11 11:03:44 +02:00
|
|
|
map_free(map);
|
2008-11-04 10:50:39 +01:00
|
|
|
} else {
|
|
|
|
struct map_ent *mp, *map = NULL;
|
2009-10-14 02:41:57 +02:00
|
|
|
char nbuf[64];
|
2012-11-01 06:14:01 +01:00
|
|
|
mp = map_by_devnm(&map, fd2devnm(fd));
|
2009-10-14 02:41:57 +02:00
|
|
|
if (mp) {
|
|
|
|
__fname_from_uuid(mp->uuid, 0, nbuf, ':');
|
|
|
|
printf("MD_UUID=%s\n", nbuf+5);
|
|
|
|
}
|
2008-11-04 10:50:39 +01:00
|
|
|
if (mp && mp->path &&
|
2012-10-04 08:34:20 +02:00
|
|
|
strncmp(mp->path, "/dev/md/", 8) == 0) {
|
|
|
|
printf("MD_DEVNAME=");
|
|
|
|
print_escape(mp->path+8);
|
|
|
|
putchar('\n');
|
|
|
|
}
|
2018-06-11 11:03:44 +02:00
|
|
|
map_free(map);
|
2008-09-18 08:12:28 +02:00
|
|
|
}
|
mdadm: add --no-devices to avoid component devices detail information
When people assemble a md raid device with a large number of
component deivces (e.g. 1500 DASD disks), the raid device detail
information generated by 'mdadm --detail --export $devnode' is very
large. It is because the detail information contains information of
all the component disks (even the missing/failed ones).
In such condition, when udev-md-raid-arrays.rules is triggered and
internally calls "mdadm --detail --no-devices --export $devnode",
user may observe systemd error message ""invalid message length". It
is because the following on-stack raw message buffer in systemd code
is not big enough,
systemd/src/libudev/libudev-monitor.c
_public_ struct udev_device *udev_monito ...
struct ucred *cred;
union {
struct udev_monitor_netlink_header nlh;
char raw[8192];
} buf;
Even change size of raw[] from 8KB to larger size, it may still be not
enough for detail message of a md raid device with much larger number of
component devices.
To fix this problem, an extra option '--no-devices' is added (the
original idea is proposed by Neil Brown). When printing detailed
information of a md raid device, if '--no-devices' is specified, then
all component devices information will not be printed, then the output
message size can be restricted to a small number, even with the systemd
only has 8KB on-disk raw buffer, the md raid array udev rules can work
correctly without failure message.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: NeilBrown <neilb@suse.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2019-07-31 07:29:29 +02:00
|
|
|
if (!c->no_devices && sra) {
|
2013-06-19 02:35:23 +02:00
|
|
|
struct mdinfo *mdi;
|
|
|
|
for (mdi = sra->devs; mdi; mdi = mdi->next) {
|
2017-04-25 18:21:39 +02:00
|
|
|
char *path;
|
2019-02-12 05:53:18 +01:00
|
|
|
char *sysdev = xstrdup(mdi->sys_name);
|
2017-04-20 04:40:06 +02:00
|
|
|
char *cp;
|
2017-04-25 18:21:39 +02:00
|
|
|
|
|
|
|
path = map_dev(mdi->disk.major,
|
|
|
|
mdi->disk.minor, 0);
|
2017-04-20 04:40:06 +02:00
|
|
|
for (cp = sysdev; *cp; cp++)
|
|
|
|
if (!isalnum(*cp))
|
|
|
|
*cp = '_';
|
2013-06-19 02:35:23 +02:00
|
|
|
|
|
|
|
if (mdi->disk.raid_disk >= 0)
|
|
|
|
printf("MD_DEVICE_%s_ROLE=%d\n",
|
2017-04-20 04:40:06 +02:00
|
|
|
sysdev,
|
2013-06-19 02:35:23 +02:00
|
|
|
mdi->disk.raid_disk);
|
|
|
|
else
|
|
|
|
printf("MD_DEVICE_%s_ROLE=spare\n",
|
2017-04-20 04:40:06 +02:00
|
|
|
sysdev);
|
2013-06-19 02:35:23 +02:00
|
|
|
if (path)
|
|
|
|
printf("MD_DEVICE_%s_DEV=%s\n",
|
2017-04-20 04:40:06 +02:00
|
|
|
sysdev, path);
|
2013-06-19 02:35:23 +02:00
|
|
|
}
|
|
|
|
}
|
2007-05-08 09:17:33 +02:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2014-11-03 23:35:20 +01:00
|
|
|
disks = xmalloc(max_disks * 2 * sizeof(mdu_disk_info_t));
|
|
|
|
for (d = 0; d < max_disks * 2; d++) {
|
2017-04-25 18:21:39 +02:00
|
|
|
disks[d].state = (1 << MD_DISK_REMOVED);
|
2010-01-29 05:45:36 +01:00
|
|
|
disks[d].major = disks[d].minor = 0;
|
2015-12-18 03:51:54 +01:00
|
|
|
disks[d].number = -1;
|
2017-04-25 18:21:39 +02:00
|
|
|
disks[d].raid_disk = d / 2;
|
2010-01-29 05:45:36 +01:00
|
|
|
}
|
|
|
|
|
2017-04-25 18:21:39 +02:00
|
|
|
next = array.raid_disks * 2;
|
2013-05-13 08:57:10 +02:00
|
|
|
if (inactive) {
|
|
|
|
struct mdinfo *mdi;
|
2017-08-10 11:43:48 +02:00
|
|
|
for (mdi = sra->devs; mdi; mdi = mdi->next) {
|
|
|
|
disks[next++] = mdi->disk;
|
|
|
|
disks[next - 1].number = -1;
|
|
|
|
}
|
2013-05-13 08:57:10 +02:00
|
|
|
} else for (d = 0; d < max_disks; d++) {
|
2010-01-29 05:45:36 +01:00
|
|
|
mdu_disk_info_t disk;
|
|
|
|
disk.number = d;
|
2017-03-29 21:23:50 +02:00
|
|
|
if (md_get_disk_info(fd, &disk) < 0) {
|
2010-01-29 05:45:36 +01:00
|
|
|
if (d < array.raid_disks)
|
2012-07-09 09:14:16 +02:00
|
|
|
pr_err("cannot get device detail for device %d: %s\n",
|
2010-01-29 05:45:36 +01:00
|
|
|
d, strerror(errno));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (disk.major == 0 && disk.minor == 0)
|
|
|
|
continue;
|
2017-04-25 18:21:39 +02:00
|
|
|
if (disk.raid_disk >= 0 && disk.raid_disk < array.raid_disks &&
|
|
|
|
disks[disk.raid_disk * 2].state == (1 << MD_DISK_REMOVED) &&
|
|
|
|
((disk.state & (1 << MD_DISK_JOURNAL)) == 0))
|
|
|
|
disks[disk.raid_disk * 2] = disk;
|
|
|
|
else if (disk.raid_disk >= 0 &&
|
|
|
|
disk.raid_disk < array.raid_disks &&
|
|
|
|
disks[disk.raid_disk * 2 + 1].state ==
|
|
|
|
(1 << MD_DISK_REMOVED) &&
|
|
|
|
!(disk.state & (1 << MD_DISK_JOURNAL)))
|
|
|
|
disks[disk.raid_disk * 2 + 1] = disk;
|
|
|
|
else if (next < max_disks * 2)
|
2010-01-29 05:45:36 +01:00
|
|
|
disks[next++] = disk;
|
|
|
|
}
|
|
|
|
|
2012-07-09 09:14:16 +02:00
|
|
|
avail = xcalloc(array.raid_disks, 1);
|
2010-01-29 05:45:36 +01:00
|
|
|
|
2017-04-25 18:21:39 +02:00
|
|
|
for (d = 0; d < array.raid_disks; d++) {
|
2021-02-09 10:39:51 +01:00
|
|
|
char *dv, *dv_rep;
|
|
|
|
dv = map_dev_preferred(disks[d*2].major,
|
|
|
|
disks[d*2].minor, 0, c->prefer);
|
|
|
|
dv_rep = map_dev_preferred(disks[d*2+1].major,
|
|
|
|
disks[d*2+1].minor, 0, c->prefer);
|
|
|
|
|
|
|
|
if ((dv && (disks[d*2].state & (1<<MD_DISK_SYNC))) ||
|
|
|
|
(dv_rep && (disks[d*2+1].state & (1<<MD_DISK_SYNC)))) {
|
2010-01-29 05:45:36 +01:00
|
|
|
avail_disks ++;
|
|
|
|
avail[d] = 1;
|
2015-12-10 15:19:46 +01:00
|
|
|
} else
|
|
|
|
rv |= !! c->test;
|
2010-01-29 05:45:36 +01:00
|
|
|
}
|
|
|
|
|
2012-07-09 09:20:16 +02:00
|
|
|
if (c->brief) {
|
2008-06-26 01:33:37 +02:00
|
|
|
mdu_bitmap_file_t bmf;
|
2017-08-18 12:00:23 +02:00
|
|
|
if (inactive && !is_container)
|
|
|
|
printf("INACTIVE-ARRAY %s", dev);
|
|
|
|
else
|
|
|
|
printf("ARRAY %s", dev);
|
2013-05-13 06:57:41 +02:00
|
|
|
if (c->verbose > 0) {
|
2009-05-11 07:18:20 +02:00
|
|
|
if (array.raid_disks)
|
2009-10-01 04:38:31 +02:00
|
|
|
printf(" level=%s num-devices=%d",
|
2017-04-25 18:21:39 +02:00
|
|
|
str ? str : "-unknown-",
|
|
|
|
array.raid_disks);
|
2017-08-18 12:00:23 +02:00
|
|
|
else if (is_container)
|
2009-10-01 04:38:31 +02:00
|
|
|
printf(" level=container num-devices=%d",
|
2009-05-11 07:18:20 +02:00
|
|
|
array.nr_disks);
|
2013-05-13 08:57:10 +02:00
|
|
|
else
|
|
|
|
printf(" num-devices=%d", array.nr_disks);
|
2009-05-11 07:18:20 +02:00
|
|
|
}
|
2008-09-18 07:05:20 +02:00
|
|
|
if (container) {
|
|
|
|
printf(" container=%s", container);
|
|
|
|
printf(" member=%s", member);
|
|
|
|
} else {
|
|
|
|
if (sra && sra->array.major_version < 0)
|
|
|
|
printf(" metadata=%s", sra->text_version);
|
|
|
|
else
|
2017-04-25 18:21:39 +02:00
|
|
|
printf(" metadata=%d.%d", array.major_version,
|
|
|
|
array.minor_version);
|
2008-09-18 07:05:20 +02:00
|
|
|
}
|
2008-06-26 01:33:37 +02:00
|
|
|
|
|
|
|
/* Only try GET_BITMAP_FILE for 0.90.01 and later */
|
2017-04-05 21:26:53 +02:00
|
|
|
if (ioctl(fd, GET_BITMAP_FILE, &bmf) == 0 && bmf.pathname[0]) {
|
2008-06-26 01:33:37 +02:00
|
|
|
printf(" bitmap=%s", bmf.pathname);
|
|
|
|
}
|
2007-12-14 10:15:21 +01:00
|
|
|
} else {
|
2006-01-31 00:23:45 +01:00
|
|
|
mdu_bitmap_file_t bmf;
|
2002-04-04 03:58:32 +02:00
|
|
|
unsigned long long larray_size;
|
2006-01-31 01:39:50 +01:00
|
|
|
struct mdstat_ent *ms = mdstat_read(0, 0);
|
2004-06-04 14:03:19 +02:00
|
|
|
struct mdstat_ent *e;
|
2012-11-01 06:14:01 +01:00
|
|
|
char *devnm;
|
2004-06-04 14:03:19 +02:00
|
|
|
|
2012-11-01 06:14:01 +01:00
|
|
|
devnm = stat2devnm(&stb);
|
2017-04-25 18:21:39 +02:00
|
|
|
for (e = ms; e; e = e->next)
|
2012-11-01 06:14:01 +01:00
|
|
|
if (strcmp(e->devnm, devnm) == 0)
|
2004-06-04 14:03:19 +02:00
|
|
|
break;
|
2006-12-14 07:32:57 +01:00
|
|
|
if (!get_dev_size(fd, NULL, &larray_size))
|
|
|
|
larray_size = 0;
|
2002-03-15 06:21:36 +01:00
|
|
|
|
2002-03-07 00:17:40 +01:00
|
|
|
printf("%s:\n", dev);
|
2007-12-14 10:15:21 +01:00
|
|
|
|
2008-09-18 07:05:20 +02:00
|
|
|
if (container)
|
2017-04-25 18:21:39 +02:00
|
|
|
printf(" Container : %s, member %s\n",
|
|
|
|
container, member);
|
2008-09-18 07:05:20 +02:00
|
|
|
else {
|
2017-04-25 18:21:39 +02:00
|
|
|
if (sra && sra->array.major_version < 0)
|
|
|
|
printf(" Version : %s\n",
|
|
|
|
sra->text_version);
|
|
|
|
else
|
|
|
|
printf(" Version : %d.%d\n",
|
|
|
|
array.major_version,
|
|
|
|
array.minor_version);
|
2008-09-18 07:05:20 +02:00
|
|
|
}
|
2007-12-14 10:15:21 +01:00
|
|
|
|
2002-03-07 00:17:40 +01:00
|
|
|
atime = array.ctime;
|
2008-09-18 07:05:20 +02:00
|
|
|
if (atime)
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Creation Time : %.24s\n", ctime(&atime));
|
2017-08-18 12:00:23 +02:00
|
|
|
if (is_container)
|
2012-07-09 09:20:05 +02:00
|
|
|
str = "container";
|
2013-05-13 08:57:10 +02:00
|
|
|
if (str)
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Raid Level : %s\n", str);
|
2002-03-15 06:21:36 +01:00
|
|
|
if (larray_size)
|
2017-04-25 18:21:39 +02:00
|
|
|
printf(" Array Size : %llu%s\n",
|
|
|
|
(larray_size >> 10),
|
2012-08-13 00:00:21 +02:00
|
|
|
human_size(larray_size));
|
2006-01-30 01:13:26 +01:00
|
|
|
if (array.level >= 1) {
|
2013-02-05 05:32:49 +01:00
|
|
|
if (sra)
|
|
|
|
array.major_version = sra->array.major_version;
|
2006-01-30 01:13:26 +01:00
|
|
|
if (array.major_version != 0 &&
|
2006-01-31 00:42:53 +01:00
|
|
|
(larray_size >= 0xFFFFFFFFULL|| array.size == 0)) {
|
2017-04-25 18:21:39 +02:00
|
|
|
unsigned long long dsize;
|
|
|
|
|
|
|
|
dsize = get_component_size(fd);
|
2006-01-31 00:42:53 +01:00
|
|
|
if (dsize > 0)
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Used Dev Size : %llu%s\n",
|
2009-02-02 00:03:20 +01:00
|
|
|
dsize/2,
|
|
|
|
human_size((long long)dsize<<9));
|
2006-01-31 00:42:53 +01:00
|
|
|
else
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Used Dev Size : unknown\n");
|
2006-01-31 00:42:53 +01:00
|
|
|
} else
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Used Dev Size : %lu%s\n",
|
2016-01-28 01:57:54 +01:00
|
|
|
(unsigned long)array.size,
|
2017-04-25 18:21:39 +02:00
|
|
|
human_size((unsigned long long)
|
|
|
|
array.size << 10));
|
2006-01-30 01:13:26 +01:00
|
|
|
}
|
2008-09-18 07:05:20 +02:00
|
|
|
if (array.raid_disks)
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Raid Devices : %d\n", array.raid_disks);
|
|
|
|
printf(" Total Devices : %d\n", array.nr_disks);
|
2012-08-13 00:00:21 +02:00
|
|
|
if (!container &&
|
2008-09-18 07:05:20 +02:00
|
|
|
((sra == NULL && array.major_version == 0) ||
|
|
|
|
(sra && sra->array.major_version == 0)))
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Preferred Minor : %d\n", array.md_minor);
|
2007-12-14 10:15:21 +01:00
|
|
|
if (sra == NULL || sra->array.major_version >= 0)
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Persistence : Superblock is %spersistent\n",
|
2017-04-25 18:21:39 +02:00
|
|
|
array.not_persistent ? "not " : "");
|
2002-03-07 00:17:40 +01:00
|
|
|
printf("\n");
|
2006-03-28 08:39:29 +02:00
|
|
|
/* Only try GET_BITMAP_FILE for 0.90.01 and later */
|
2017-04-05 21:26:53 +02:00
|
|
|
if (ioctl(fd, GET_BITMAP_FILE, &bmf) == 0 && bmf.pathname[0]) {
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Intent Bitmap : %s\n", bmf.pathname);
|
2006-01-31 00:23:45 +01:00
|
|
|
printf("\n");
|
2020-03-16 03:16:49 +01:00
|
|
|
} else if (array.state & (1<<MD_SB_CLUSTERED))
|
|
|
|
printf(" Intent Bitmap : Internal(Clustered)\n\n");
|
|
|
|
else if (array.state & (1<<MD_SB_BITMAP_PRESENT))
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Intent Bitmap : Internal\n\n");
|
2002-03-07 00:17:40 +01:00
|
|
|
atime = array.utime;
|
2008-09-18 07:05:20 +02:00
|
|
|
if (atime)
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Update Time : %.24s\n", ctime(&atime));
|
2010-01-29 05:45:36 +01:00
|
|
|
if (array.raid_disks) {
|
2012-08-13 00:00:21 +02:00
|
|
|
static char *sync_action[] = {
|
|
|
|
", recovering", ", resyncing",
|
|
|
|
", reshaping", ", checking" };
|
2010-01-29 05:45:36 +01:00
|
|
|
char *st;
|
|
|
|
if (avail_disks == array.raid_disks)
|
|
|
|
st = "";
|
|
|
|
else if (!enough(array.level, array.raid_disks,
|
2012-02-07 04:04:47 +01:00
|
|
|
array.layout, 1, avail))
|
2010-01-29 05:45:36 +01:00
|
|
|
st = ", FAILED";
|
|
|
|
else
|
|
|
|
st = ", degraded";
|
|
|
|
|
mdadm: Introduce new array state 'broken' for raid0/linear
Currently if a md raid0/linear array gets one or more members removed while
being mounted, kernel keeps showing state 'clean' in the 'array_state'
sysfs attribute. Despite udev signaling the member device is gone, 'mdadm'
cannot issue the STOP_ARRAY ioctl successfully, given the array is mounted.
Nothing else hints that something is wrong (except that the removed devices
don't show properly in the output of mdadm 'detail' command). There is no
other property to be checked, and if user is not performing reads/writes
to the array, even kernel log is quiet and doesn't give a clue about the
missing member.
This patch is the mdadm counterpart of kernel new array state 'broken'.
The 'broken' state mimics the state 'clean' in every aspect, being useful
only to distinguish if an array has some member missing. All necessary
paths in mdadm were changed to deal with 'broken' state, and in case the
tool runs in a kernel that is not updated, it'll work normally, i.e., it
doesn't require the 'broken' state in order to work.
Also, this patch changes the way the array state is showed in the 'detail'
command (for raid0/linear only) - now it takes the 'array_state' sysfs
attribute into account instead of only rely in the MD_SB_CLEAN flag.
Cc: Jes Sorensen <jes.sorensen@gmail.com>
Cc: NeilBrown <neilb@suse.de>
Cc: Song Liu <songliubraving@fb.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@canonical.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2019-09-03 21:49:01 +02:00
|
|
|
if (array.state & (1 << MD_SB_CLEAN)) {
|
|
|
|
if ((array.level == 0) ||
|
|
|
|
(array.level == LEVEL_LINEAR))
|
|
|
|
arrayst = map_num(sysfs_array_states,
|
|
|
|
sra->array_state);
|
|
|
|
else
|
|
|
|
arrayst = "clean";
|
2020-10-24 11:43:12 +02:00
|
|
|
} else {
|
mdadm: Introduce new array state 'broken' for raid0/linear
Currently if a md raid0/linear array gets one or more members removed while
being mounted, kernel keeps showing state 'clean' in the 'array_state'
sysfs attribute. Despite udev signaling the member device is gone, 'mdadm'
cannot issue the STOP_ARRAY ioctl successfully, given the array is mounted.
Nothing else hints that something is wrong (except that the removed devices
don't show properly in the output of mdadm 'detail' command). There is no
other property to be checked, and if user is not performing reads/writes
to the array, even kernel log is quiet and doesn't give a clue about the
missing member.
This patch is the mdadm counterpart of kernel new array state 'broken'.
The 'broken' state mimics the state 'clean' in every aspect, being useful
only to distinguish if an array has some member missing. All necessary
paths in mdadm were changed to deal with 'broken' state, and in case the
tool runs in a kernel that is not updated, it'll work normally, i.e., it
doesn't require the 'broken' state in order to work.
Also, this patch changes the way the array state is showed in the 'detail'
command (for raid0/linear only) - now it takes the 'array_state' sysfs
attribute into account instead of only rely in the MD_SB_CLEAN flag.
Cc: Jes Sorensen <jes.sorensen@gmail.com>
Cc: NeilBrown <neilb@suse.de>
Cc: Song Liu <songliubraving@fb.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@canonical.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2019-09-03 21:49:01 +02:00
|
|
|
arrayst = "active";
|
2020-10-24 11:43:12 +02:00
|
|
|
if (array.state & (1<<MD_SB_CLUSTERED)) {
|
|
|
|
for (d = 0; d < max_disks * 2; d++) {
|
|
|
|
char *dv;
|
|
|
|
mdu_disk_info_t disk = disks[d];
|
|
|
|
|
|
|
|
/* only check first valid disk in cluster env */
|
|
|
|
if ((disk.state & (MD_DISK_SYNC | MD_DISK_ACTIVE))
|
|
|
|
&& (disk.major | disk.minor)) {
|
|
|
|
dv = map_dev_preferred(disk.major, disk.minor, 0,
|
|
|
|
c->prefer);
|
|
|
|
if (!dv)
|
|
|
|
continue;
|
|
|
|
arrayst = IsBitmapDirty(dv) ? "active" : "clean";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
mdadm: Introduce new array state 'broken' for raid0/linear
Currently if a md raid0/linear array gets one or more members removed while
being mounted, kernel keeps showing state 'clean' in the 'array_state'
sysfs attribute. Despite udev signaling the member device is gone, 'mdadm'
cannot issue the STOP_ARRAY ioctl successfully, given the array is mounted.
Nothing else hints that something is wrong (except that the removed devices
don't show properly in the output of mdadm 'detail' command). There is no
other property to be checked, and if user is not performing reads/writes
to the array, even kernel log is quiet and doesn't give a clue about the
missing member.
This patch is the mdadm counterpart of kernel new array state 'broken'.
The 'broken' state mimics the state 'clean' in every aspect, being useful
only to distinguish if an array has some member missing. All necessary
paths in mdadm were changed to deal with 'broken' state, and in case the
tool runs in a kernel that is not updated, it'll work normally, i.e., it
doesn't require the 'broken' state in order to work.
Also, this patch changes the way the array state is showed in the 'detail'
command (for raid0/linear only) - now it takes the 'array_state' sysfs
attribute into account instead of only rely in the MD_SB_CLEAN flag.
Cc: Jes Sorensen <jes.sorensen@gmail.com>
Cc: NeilBrown <neilb@suse.de>
Cc: Song Liu <songliubraving@fb.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@canonical.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2019-09-03 21:49:01 +02:00
|
|
|
|
2020-04-14 10:19:41 +02:00
|
|
|
printf(" State : %s%s%s%s%s%s%s \n",
|
mdadm: Introduce new array state 'broken' for raid0/linear
Currently if a md raid0/linear array gets one or more members removed while
being mounted, kernel keeps showing state 'clean' in the 'array_state'
sysfs attribute. Despite udev signaling the member device is gone, 'mdadm'
cannot issue the STOP_ARRAY ioctl successfully, given the array is mounted.
Nothing else hints that something is wrong (except that the removed devices
don't show properly in the output of mdadm 'detail' command). There is no
other property to be checked, and if user is not performing reads/writes
to the array, even kernel log is quiet and doesn't give a clue about the
missing member.
This patch is the mdadm counterpart of kernel new array state 'broken'.
The 'broken' state mimics the state 'clean' in every aspect, being useful
only to distinguish if an array has some member missing. All necessary
paths in mdadm were changed to deal with 'broken' state, and in case the
tool runs in a kernel that is not updated, it'll work normally, i.e., it
doesn't require the 'broken' state in order to work.
Also, this patch changes the way the array state is showed in the 'detail'
command (for raid0/linear only) - now it takes the 'array_state' sysfs
attribute into account instead of only rely in the MD_SB_CLEAN flag.
Cc: Jes Sorensen <jes.sorensen@gmail.com>
Cc: NeilBrown <neilb@suse.de>
Cc: Song Liu <songliubraving@fb.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@canonical.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2019-09-03 21:49:01 +02:00
|
|
|
arrayst, st,
|
2017-04-25 18:21:39 +02:00
|
|
|
(!e || (e->percent < 0 &&
|
|
|
|
e->percent != RESYNC_PENDING &&
|
2020-04-14 10:19:41 +02:00
|
|
|
e->percent != RESYNC_DELAYED &&
|
|
|
|
e->percent != RESYNC_REMOTE)) ?
|
2017-04-25 18:21:39 +02:00
|
|
|
"" : sync_action[e->resync],
|
2011-06-23 04:06:47 +02:00
|
|
|
larray_size ? "": ", Not Started",
|
2017-04-25 18:21:39 +02:00
|
|
|
(e && e->percent == RESYNC_DELAYED) ?
|
|
|
|
" (DELAYED)": "",
|
|
|
|
(e && e->percent == RESYNC_PENDING) ?
|
2020-04-14 10:19:41 +02:00
|
|
|
" (PENDING)": "",
|
|
|
|
(e && e->percent == RESYNC_REMOTE) ?
|
|
|
|
" (REMOTE)": "");
|
2017-08-18 12:00:23 +02:00
|
|
|
} else if (inactive && !is_container) {
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" State : inactive\n");
|
2010-01-29 05:45:36 +01:00
|
|
|
}
|
2008-09-18 07:05:20 +02:00
|
|
|
if (array.raid_disks)
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Active Devices : %d\n", array.active_disks);
|
2013-05-13 08:57:10 +02:00
|
|
|
if (array.working_disks > 0)
|
2017-04-25 18:21:39 +02:00
|
|
|
printf(" Working Devices : %d\n",
|
|
|
|
array.working_disks);
|
2008-09-18 07:05:20 +02:00
|
|
|
if (array.raid_disks) {
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Failed Devices : %d\n", array.failed_disks);
|
2021-06-18 15:53:31 +02:00
|
|
|
if (!external)
|
|
|
|
printf(" Spare Devices : %d\n", array.spare_disks);
|
2008-09-18 07:05:20 +02:00
|
|
|
}
|
2002-03-07 00:17:40 +01:00
|
|
|
printf("\n");
|
|
|
|
if (array.level == 5) {
|
2012-07-09 09:20:05 +02:00
|
|
|
str = map_num(r5layout, array.layout);
|
2017-04-25 18:21:39 +02:00
|
|
|
printf(" Layout : %s\n",
|
|
|
|
str ? str : "-unknown-");
|
2002-03-07 00:17:40 +01:00
|
|
|
}
|
2019-11-04 04:27:49 +01:00
|
|
|
if (array.level == 0 && array.layout) {
|
|
|
|
str = map_num(r0layout, array.layout);
|
|
|
|
printf(" Layout : %s\n",
|
|
|
|
str ? str : "-unknown-");
|
|
|
|
}
|
2009-07-14 07:12:29 +02:00
|
|
|
if (array.level == 6) {
|
2012-07-09 09:20:05 +02:00
|
|
|
str = map_num(r6layout, array.layout);
|
2017-04-25 18:21:39 +02:00
|
|
|
printf(" Layout : %s\n",
|
|
|
|
str ? str : "-unknown-");
|
2009-07-14 07:12:29 +02:00
|
|
|
}
|
2004-08-11 04:16:01 +02:00
|
|
|
if (array.level == 10) {
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Layout :");
|
2008-10-13 07:15:18 +02:00
|
|
|
print_r10_layout(array.layout);
|
|
|
|
printf("\n");
|
2004-08-11 04:16:01 +02:00
|
|
|
}
|
2002-03-07 00:17:40 +01:00
|
|
|
switch (array.level) {
|
|
|
|
case 0:
|
|
|
|
case 4:
|
|
|
|
case 5:
|
2004-08-11 04:16:01 +02:00
|
|
|
case 10:
|
|
|
|
case 6:
|
2007-12-14 10:15:21 +01:00
|
|
|
if (array.chunk_size)
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Chunk Size : %dK\n\n",
|
2007-12-14 10:15:21 +01:00
|
|
|
array.chunk_size/1024);
|
2002-03-07 00:17:40 +01:00
|
|
|
break;
|
|
|
|
case -1:
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Rounding : %dK\n\n",
|
|
|
|
array.chunk_size/1024);
|
2002-03-07 00:17:40 +01:00
|
|
|
break;
|
2017-04-25 18:21:39 +02:00
|
|
|
default:
|
|
|
|
break;
|
2002-03-07 00:17:40 +01:00
|
|
|
}
|
2007-12-14 10:13:43 +01:00
|
|
|
|
2017-03-29 11:54:16 +02:00
|
|
|
if (array.raid_disks) {
|
2017-04-25 18:21:39 +02:00
|
|
|
struct mdinfo *mdi;
|
|
|
|
|
|
|
|
mdi = sysfs_read(fd, NULL, GET_CONSISTENCY_POLICY);
|
2017-03-29 11:54:16 +02:00
|
|
|
if (mdi) {
|
|
|
|
char *policy = map_num(consistency_policies,
|
|
|
|
mdi->consistency_policy);
|
|
|
|
sysfs_free(mdi);
|
|
|
|
if (policy)
|
|
|
|
printf("Consistency Policy : %s\n\n",
|
|
|
|
policy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-11 04:16:01 +02:00
|
|
|
if (e && e->percent >= 0) {
|
2012-08-13 00:00:21 +02:00
|
|
|
static char *sync_action[] = {
|
2017-04-25 18:21:39 +02:00
|
|
|
"Rebuild", "Resync", "Reshape", "Check"};
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" %7s Status : %d%% complete\n",
|
|
|
|
sync_action[e->resync], e->percent);
|
2004-08-11 04:16:01 +02:00
|
|
|
}
|
2004-06-04 14:03:19 +02:00
|
|
|
|
2012-09-20 03:06:25 +02:00
|
|
|
if ((st && st->sb) && (info && info->reshape_active)) {
|
2006-03-29 00:44:05 +02:00
|
|
|
#if 0
|
|
|
|
This is pretty boring
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Reshape pos'n : %llu%s\n",
|
2017-04-25 18:21:39 +02:00
|
|
|
(unsigned long long) info->reshape_progress << 9,
|
|
|
|
human_size((unsigned long long)
|
|
|
|
info->reshape_progress << 9));
|
2006-03-29 00:44:05 +02:00
|
|
|
#endif
|
2011-06-23 03:48:03 +02:00
|
|
|
if (info->delta_disks != 0)
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Delta Devices : %d, (%d->%d)\n",
|
2012-08-13 00:00:21 +02:00
|
|
|
info->delta_disks,
|
|
|
|
array.raid_disks - info->delta_disks,
|
|
|
|
array.raid_disks);
|
2010-11-22 10:24:35 +01:00
|
|
|
if (info->new_level != array.level) {
|
2012-07-09 09:20:05 +02:00
|
|
|
str = map_num(pers, info->new_level);
|
2017-04-25 18:21:39 +02:00
|
|
|
printf(" New Level : %s\n",
|
|
|
|
str ? str : "-unknown-");
|
2006-03-29 00:44:05 +02:00
|
|
|
}
|
2010-11-22 10:24:35 +01:00
|
|
|
if (info->new_level != array.level ||
|
|
|
|
info->new_layout != array.layout) {
|
|
|
|
if (info->new_level == 5) {
|
2017-04-25 18:21:39 +02:00
|
|
|
str = map_num(r5layout,
|
|
|
|
info->new_layout);
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" New Layout : %s\n",
|
2017-04-25 18:21:39 +02:00
|
|
|
str ? str : "-unknown-");
|
2006-03-29 00:44:05 +02:00
|
|
|
}
|
2010-11-22 10:24:35 +01:00
|
|
|
if (info->new_level == 6) {
|
2017-04-25 18:21:39 +02:00
|
|
|
str = map_num(r6layout,
|
|
|
|
info->new_layout);
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" New Layout : %s\n",
|
2017-04-25 18:21:39 +02:00
|
|
|
str ? str : "-unknown-");
|
2009-10-29 00:02:24 +01:00
|
|
|
}
|
2010-11-22 10:24:35 +01:00
|
|
|
if (info->new_level == 10) {
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" New Layout : near=%d, %s=%d\n",
|
2017-04-25 18:21:39 +02:00
|
|
|
info->new_layout & 255,
|
|
|
|
(info->new_layout & 0x10000) ?
|
|
|
|
"offset" : "far",
|
|
|
|
(info->new_layout >> 8) & 255);
|
2006-03-29 00:44:05 +02:00
|
|
|
}
|
|
|
|
}
|
2010-11-22 10:24:35 +01:00
|
|
|
if (info->new_chunk != array.chunk_size)
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" New Chunksize : %dK\n",
|
|
|
|
info->new_chunk/1024);
|
2006-03-29 00:44:05 +02:00
|
|
|
printf("\n");
|
|
|
|
} else if (e && e->percent >= 0)
|
|
|
|
printf("\n");
|
2018-04-10 03:25:39 +02:00
|
|
|
free_mdstat(ms);
|
|
|
|
|
2007-12-14 10:14:33 +01:00
|
|
|
if (st && st->sb)
|
2019-11-29 15:21:08 +01:00
|
|
|
st->ss->detail_super(st, c->homehost, subarray);
|
2004-08-11 04:16:01 +02:00
|
|
|
|
2017-04-25 18:21:39 +02:00
|
|
|
if (array.raid_disks == 0 && sra &&
|
|
|
|
sra->array.major_version == -1 &&
|
|
|
|
sra->array.minor_version == -2 &&
|
|
|
|
sra->text_version[0] != '/') {
|
2008-09-18 07:05:20 +02:00
|
|
|
/* This looks like a container. Find any active arrays
|
|
|
|
* That claim to be a member.
|
|
|
|
*/
|
|
|
|
DIR *dir = opendir("/sys/block");
|
|
|
|
struct dirent *de;
|
|
|
|
|
2017-03-29 11:54:16 +02:00
|
|
|
printf(" Member Arrays :");
|
2008-09-18 07:05:20 +02:00
|
|
|
|
|
|
|
while (dir && (de = readdir(dir)) != NULL) {
|
2017-03-17 12:55:43 +01:00
|
|
|
char path[287];
|
2008-09-18 07:05:20 +02:00
|
|
|
char vbuf[1024];
|
|
|
|
int nlen = strlen(sra->sys_name);
|
2016-05-18 20:23:13 +02:00
|
|
|
dev_t devid;
|
2008-09-18 07:05:20 +02:00
|
|
|
if (de->d_name[0] == '.')
|
|
|
|
continue;
|
2017-04-25 18:21:39 +02:00
|
|
|
sprintf(path,
|
|
|
|
"/sys/block/%s/md/metadata_version",
|
2008-09-18 07:05:20 +02:00
|
|
|
de->d_name);
|
2016-03-04 22:00:21 +01:00
|
|
|
if (load_sys(path, vbuf, sizeof(vbuf)) < 0)
|
2008-09-18 07:05:20 +02:00
|
|
|
continue;
|
2017-04-25 18:21:39 +02:00
|
|
|
if (strncmp(vbuf, "external:", 9) ||
|
|
|
|
!is_subarray(vbuf + 9) ||
|
|
|
|
strncmp(vbuf + 10, sra->sys_name, nlen) ||
|
|
|
|
vbuf[10 + nlen] != '/')
|
2008-09-18 07:05:20 +02:00
|
|
|
continue;
|
2012-11-01 06:14:01 +01:00
|
|
|
devid = devnm2devid(de->d_name);
|
2017-04-25 18:21:39 +02:00
|
|
|
printf(" %s",
|
|
|
|
map_dev_preferred(major(devid),
|
|
|
|
minor(devid), 1,
|
|
|
|
c->prefer));
|
2008-09-18 07:05:20 +02:00
|
|
|
}
|
|
|
|
if (dir)
|
|
|
|
closedir(dir);
|
|
|
|
printf("\n\n");
|
|
|
|
}
|
|
|
|
|
mdadm: add --no-devices to avoid component devices detail information
When people assemble a md raid device with a large number of
component deivces (e.g. 1500 DASD disks), the raid device detail
information generated by 'mdadm --detail --export $devnode' is very
large. It is because the detail information contains information of
all the component disks (even the missing/failed ones).
In such condition, when udev-md-raid-arrays.rules is triggered and
internally calls "mdadm --detail --no-devices --export $devnode",
user may observe systemd error message ""invalid message length". It
is because the following on-stack raw message buffer in systemd code
is not big enough,
systemd/src/libudev/libudev-monitor.c
_public_ struct udev_device *udev_monito ...
struct ucred *cred;
union {
struct udev_monitor_netlink_header nlh;
char raw[8192];
} buf;
Even change size of raw[] from 8KB to larger size, it may still be not
enough for detail message of a md raid device with much larger number of
component devices.
To fix this problem, an extra option '--no-devices' is added (the
original idea is proposed by Neil Brown). When printing detailed
information of a md raid device, if '--no-devices' is specified, then
all component devices information will not be printed, then the output
message size can be restricted to a small number, even with the systemd
only has 8KB on-disk raw buffer, the md raid array udev rules can work
correctly without failure message.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: NeilBrown <neilb@suse.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2019-07-31 07:29:29 +02:00
|
|
|
if (!c->no_devices) {
|
|
|
|
if (array.raid_disks)
|
|
|
|
printf(" Number Major Minor RaidDevice State\n");
|
|
|
|
else
|
|
|
|
printf(" Number Major Minor RaidDevice\n");
|
|
|
|
}
|
2002-03-07 00:17:40 +01:00
|
|
|
}
|
mdadm: add --no-devices to avoid component devices detail information
When people assemble a md raid device with a large number of
component deivces (e.g. 1500 DASD disks), the raid device detail
information generated by 'mdadm --detail --export $devnode' is very
large. It is because the detail information contains information of
all the component disks (even the missing/failed ones).
In such condition, when udev-md-raid-arrays.rules is triggered and
internally calls "mdadm --detail --no-devices --export $devnode",
user may observe systemd error message ""invalid message length". It
is because the following on-stack raw message buffer in systemd code
is not big enough,
systemd/src/libudev/libudev-monitor.c
_public_ struct udev_device *udev_monito ...
struct ucred *cred;
union {
struct udev_monitor_netlink_header nlh;
char raw[8192];
} buf;
Even change size of raw[] from 8KB to larger size, it may still be not
enough for detail message of a md raid device with much larger number of
component devices.
To fix this problem, an extra option '--no-devices' is added (the
original idea is proposed by Neil Brown). When printing detailed
information of a md raid device, if '--no-devices' is specified, then
all component devices information will not be printed, then the output
message size can be restricted to a small number, even with the systemd
only has 8KB on-disk raw buffer, the md raid array udev rules can work
correctly without failure message.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: NeilBrown <neilb@suse.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2019-07-31 07:29:29 +02:00
|
|
|
|
|
|
|
/* if --no_devices specified, not print component devices info */
|
|
|
|
if (c->no_devices)
|
|
|
|
goto skip_devices_state;
|
2005-08-15 08:54:20 +02:00
|
|
|
|
2017-04-25 18:21:39 +02:00
|
|
|
for (d = 0; d < max_disks * 2; d++) {
|
2005-08-15 08:54:20 +02:00
|
|
|
char *dv;
|
|
|
|
mdu_disk_info_t disk = disks[d];
|
|
|
|
|
2017-04-25 18:21:39 +02:00
|
|
|
if (d >= array.raid_disks * 2 &&
|
|
|
|
disk.major == 0 && disk.minor == 0)
|
2012-10-23 08:16:16 +02:00
|
|
|
continue;
|
2017-04-25 18:21:39 +02:00
|
|
|
if ((d & 1) && disk.major == 0 && disk.minor == 0)
|
2002-04-04 03:58:32 +02:00
|
|
|
continue;
|
2012-07-09 09:20:16 +02:00
|
|
|
if (!c->brief) {
|
2017-04-25 18:21:39 +02:00
|
|
|
if (d == array.raid_disks*2)
|
|
|
|
printf("\n");
|
2015-12-23 02:15:32 +01:00
|
|
|
if (disk.number < 0 && disk.raid_disk < 0)
|
2013-05-13 08:57:10 +02:00
|
|
|
printf(" - %5d %5d - ",
|
|
|
|
disk.major, disk.minor);
|
2017-04-25 18:21:39 +02:00
|
|
|
else if (disk.raid_disk < 0 ||
|
|
|
|
disk.state & (1 << MD_DISK_JOURNAL))
|
2007-12-14 10:13:43 +01:00
|
|
|
printf(" %5d %5d %5d - ",
|
2004-08-11 04:16:01 +02:00
|
|
|
disk.number, disk.major, disk.minor);
|
2015-12-18 03:51:54 +01:00
|
|
|
else if (disk.number < 0)
|
|
|
|
printf(" - %5d %5d %5d ",
|
|
|
|
disk.major, disk.minor, disk.raid_disk);
|
2004-08-11 04:16:01 +02:00
|
|
|
else
|
2007-12-14 10:13:43 +01:00
|
|
|
printf(" %5d %5d %5d %5d ",
|
2017-04-25 18:21:39 +02:00
|
|
|
disk.number, disk.major, disk.minor,
|
|
|
|
disk.raid_disk);
|
2008-09-18 07:05:20 +02:00
|
|
|
}
|
2012-07-09 09:20:16 +02:00
|
|
|
if (!c->brief && array.raid_disks) {
|
2017-04-25 18:21:39 +02:00
|
|
|
if (disk.state & (1 << MD_DISK_FAULTY)) {
|
2007-12-14 10:13:43 +01:00
|
|
|
printf(" faulty");
|
2004-08-11 04:16:01 +02:00
|
|
|
if (disk.raid_disk < array.raid_disks &&
|
|
|
|
disk.raid_disk >= 0)
|
|
|
|
failed++;
|
|
|
|
}
|
2017-04-25 18:21:39 +02:00
|
|
|
if (disk.state & (1 << MD_DISK_ACTIVE))
|
|
|
|
printf(" active");
|
|
|
|
if (disk.state & (1 << MD_DISK_SYNC)) {
|
2012-05-30 05:08:39 +02:00
|
|
|
printf(" sync");
|
2017-04-25 18:21:39 +02:00
|
|
|
if (array.level == 10 &&
|
|
|
|
(array.layout & ~0x1FFFF) == 0) {
|
2012-05-30 05:08:39 +02:00
|
|
|
int nc = array.layout & 0xff;
|
|
|
|
int fc = (array.layout >> 8) & 0xff;
|
|
|
|
int copies = nc*fc;
|
2017-04-25 18:21:39 +02:00
|
|
|
if (fc == 1 &&
|
|
|
|
array.raid_disks % copies == 0 &&
|
|
|
|
copies <= 26) {
|
|
|
|
/* We can divide the devices
|
|
|
|
into 'sets' */
|
|
|
|
int set;
|
|
|
|
set = disk.raid_disk % copies;
|
2012-05-30 05:08:39 +02:00
|
|
|
printf(" set-%c", set + 'A');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-04-25 18:21:39 +02:00
|
|
|
if (disk.state & (1 << MD_DISK_REMOVED))
|
|
|
|
printf(" removed");
|
|
|
|
if (disk.state & (1 << MD_DISK_WRITEMOSTLY))
|
|
|
|
printf(" writemostly");
|
|
|
|
if (disk.state & (1 << MD_DISK_FAILFAST))
|
|
|
|
printf(" failfast");
|
|
|
|
if (disk.state & (1 << MD_DISK_JOURNAL))
|
|
|
|
printf(" journal");
|
2005-08-15 08:54:20 +02:00
|
|
|
if ((disk.state &
|
2017-05-16 20:04:22 +02:00
|
|
|
((1 << MD_DISK_ACTIVE) | (1 << MD_DISK_SYNC) |
|
|
|
|
(1 << MD_DISK_REMOVED) | (1 << MD_DISK_FAULTY) |
|
|
|
|
(1 << MD_DISK_JOURNAL))) == 0) {
|
2005-08-15 08:54:20 +02:00
|
|
|
printf(" spare");
|
2017-04-12 20:48:10 +02:00
|
|
|
if (disk.raid_disk < array.raid_disks &&
|
|
|
|
disk.raid_disk >= 0)
|
|
|
|
printf(" rebuilding");
|
2004-08-11 04:16:01 +02:00
|
|
|
}
|
2003-10-29 00:20:01 +01:00
|
|
|
}
|
2017-04-25 18:21:39 +02:00
|
|
|
if (disk.state == 0)
|
|
|
|
spares++;
|
|
|
|
dv = map_dev_preferred(disk.major, disk.minor, 0, c->prefer);
|
2012-08-13 00:00:21 +02:00
|
|
|
if (dv != NULL) {
|
2013-06-27 21:39:27 +02:00
|
|
|
if (c->brief)
|
|
|
|
n_devices = add_device(dv, &devices,
|
2017-04-25 18:21:39 +02:00
|
|
|
&max_devices, n_devices);
|
2013-06-27 21:39:27 +02:00
|
|
|
else
|
2003-03-03 00:11:38 +01:00
|
|
|
printf(" %s", dv);
|
2021-02-09 10:39:51 +01:00
|
|
|
} else if (disk.major | disk.minor)
|
|
|
|
printf(" missing");
|
2017-04-25 18:21:39 +02:00
|
|
|
if (!c->brief)
|
|
|
|
printf("\n");
|
2001-06-08 04:36:23 +02:00
|
|
|
}
|
mdadm: add --no-devices to avoid component devices detail information
When people assemble a md raid device with a large number of
component deivces (e.g. 1500 DASD disks), the raid device detail
information generated by 'mdadm --detail --export $devnode' is very
large. It is because the detail information contains information of
all the component disks (even the missing/failed ones).
In such condition, when udev-md-raid-arrays.rules is triggered and
internally calls "mdadm --detail --no-devices --export $devnode",
user may observe systemd error message ""invalid message length". It
is because the following on-stack raw message buffer in systemd code
is not big enough,
systemd/src/libudev/libudev-monitor.c
_public_ struct udev_device *udev_monito ...
struct ucred *cred;
union {
struct udev_monitor_netlink_header nlh;
char raw[8192];
} buf;
Even change size of raw[] from 8KB to larger size, it may still be not
enough for detail message of a md raid device with much larger number of
component devices.
To fix this problem, an extra option '--no-devices' is added (the
original idea is proposed by Neil Brown). When printing detailed
information of a md raid device, if '--no-devices' is specified, then
all component devices information will not be printed, then the output
message size can be restricted to a small number, even with the systemd
only has 8KB on-disk raw buffer, the md raid array udev rules can work
correctly without failure message.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: NeilBrown <neilb@suse.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2019-07-31 07:29:29 +02:00
|
|
|
|
|
|
|
skip_devices_state:
|
2017-04-25 18:21:39 +02:00
|
|
|
if (spares && c->brief && array.raid_disks)
|
|
|
|
printf(" spares=%d", spares);
|
2012-07-09 09:20:16 +02:00
|
|
|
if (c->brief && st && st->sb)
|
2019-11-29 15:21:08 +01:00
|
|
|
st->ss->brief_detail_super(st, subarray);
|
2012-09-20 03:06:25 +02:00
|
|
|
if (st)
|
|
|
|
st->ss->free_super(st);
|
2005-05-04 01:44:18 +02:00
|
|
|
|
2013-06-20 22:21:05 +02:00
|
|
|
if (c->brief && c->verbose > 0 && devices) {
|
|
|
|
qsort(devices, n_devices, sizeof(*devices), cmpstringp);
|
|
|
|
printf("\n devices=%s", devices[0]);
|
|
|
|
for (d = 1; d < n_devices; d++)
|
|
|
|
printf(",%s", devices[d]);
|
|
|
|
}
|
2012-07-09 09:20:16 +02:00
|
|
|
if (c->brief)
|
|
|
|
printf("\n");
|
|
|
|
if (c->test &&
|
2017-04-25 18:21:39 +02:00
|
|
|
!enough(array.level, array.raid_disks, array.layout, 1, avail))
|
2007-05-21 06:25:50 +02:00
|
|
|
rv = 2;
|
|
|
|
|
2007-05-22 01:46:29 +02:00
|
|
|
out:
|
mdadm: add --no-devices to avoid component devices detail information
When people assemble a md raid device with a large number of
component deivces (e.g. 1500 DASD disks), the raid device detail
information generated by 'mdadm --detail --export $devnode' is very
large. It is because the detail information contains information of
all the component disks (even the missing/failed ones).
In such condition, when udev-md-raid-arrays.rules is triggered and
internally calls "mdadm --detail --no-devices --export $devnode",
user may observe systemd error message ""invalid message length". It
is because the following on-stack raw message buffer in systemd code
is not big enough,
systemd/src/libudev/libudev-monitor.c
_public_ struct udev_device *udev_monito ...
struct ucred *cred;
union {
struct udev_monitor_netlink_header nlh;
char raw[8192];
} buf;
Even change size of raw[] from 8KB to larger size, it may still be not
enough for detail message of a md raid device with much larger number of
component devices.
To fix this problem, an extra option '--no-devices' is added (the
original idea is proposed by Neil Brown). When printing detailed
information of a md raid device, if '--no-devices' is specified, then
all component devices information will not be printed, then the output
message size can be restricted to a small number, even with the systemd
only has 8KB on-disk raw buffer, the md raid array udev rules can work
correctly without failure message.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: NeilBrown <neilb@suse.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2019-07-31 07:29:29 +02:00
|
|
|
free(info);
|
|
|
|
free(disks);
|
2004-08-11 04:16:01 +02:00
|
|
|
close(fd);
|
2010-11-22 09:35:25 +01:00
|
|
|
free(subarray);
|
2011-11-01 16:09:25 +01:00
|
|
|
free(avail);
|
2021-07-27 10:25:18 +02:00
|
|
|
if (devices)
|
|
|
|
for (d = 0; d < n_devices; d++)
|
|
|
|
free(devices[d]);
|
2013-06-20 22:21:05 +02:00
|
|
|
free(devices);
|
2011-11-01 04:51:14 +01:00
|
|
|
sysfs_free(sra);
|
2021-07-27 10:25:18 +02:00
|
|
|
free(st);
|
2003-10-29 00:20:01 +01:00
|
|
|
return rv;
|
2001-06-08 04:36:23 +02:00
|
|
|
}
|
2008-12-09 00:59:18 +01:00
|
|
|
|
2012-10-04 08:34:11 +02:00
|
|
|
int Detail_Platform(struct superswitch *ss, int scan, int verbose, int export, char *controller_path)
|
2008-12-09 00:59:18 +01:00
|
|
|
{
|
|
|
|
/* display platform capabilities for the given metadata format
|
|
|
|
* 'scan' in this context means iterate over all metadata types
|
|
|
|
*/
|
|
|
|
int i;
|
|
|
|
int err = 1;
|
|
|
|
|
2012-10-02 08:28:30 +02:00
|
|
|
if (ss && export && ss->export_detail_platform)
|
2012-10-04 08:34:11 +02:00
|
|
|
err = ss->export_detail_platform(verbose, controller_path);
|
2012-10-02 08:28:30 +02:00
|
|
|
else if (ss && ss->detail_platform)
|
2012-10-04 08:34:11 +02:00
|
|
|
err = ss->detail_platform(verbose, 0, controller_path);
|
2008-12-09 00:59:18 +01:00
|
|
|
else if (ss) {
|
2012-07-09 09:18:09 +02:00
|
|
|
if (verbose > 0)
|
2012-07-09 09:14:16 +02:00
|
|
|
pr_err("%s metadata is platform independent\n",
|
2008-12-09 00:59:18 +01:00
|
|
|
ss->name ? : "[no name]");
|
|
|
|
} else if (!scan) {
|
2012-07-09 09:18:09 +02:00
|
|
|
if (verbose > 0)
|
2012-07-09 09:14:16 +02:00
|
|
|
pr_err("specify a metadata type or --scan\n");
|
2008-12-09 00:59:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!scan)
|
|
|
|
return err;
|
|
|
|
|
2012-10-02 08:37:48 +02:00
|
|
|
err = 0;
|
2008-12-09 00:59:18 +01:00
|
|
|
for (i = 0; superlist[i]; i++) {
|
|
|
|
struct superswitch *meta = superlist[i];
|
|
|
|
|
|
|
|
if (meta == ss)
|
|
|
|
continue;
|
2012-07-09 09:18:09 +02:00
|
|
|
if (verbose > 0)
|
2012-07-09 09:14:16 +02:00
|
|
|
pr_err("checking metadata %s\n",
|
2008-12-09 00:59:18 +01:00
|
|
|
meta->name ? : "[no name]");
|
|
|
|
if (!meta->detail_platform) {
|
2012-07-09 09:18:09 +02:00
|
|
|
if (verbose > 0)
|
2012-07-09 09:14:16 +02:00
|
|
|
pr_err("%s metadata is platform independent\n",
|
2008-12-09 00:59:18 +01:00
|
|
|
meta->name ? : "[no name]");
|
2012-10-02 08:28:30 +02:00
|
|
|
} else if (export && meta->export_detail_platform) {
|
2012-10-04 08:34:11 +02:00
|
|
|
err |= meta->export_detail_platform(verbose, controller_path);
|
2008-12-09 00:59:18 +01:00
|
|
|
} else
|
2012-10-04 08:34:11 +02:00
|
|
|
err |= meta->detail_platform(verbose, 0, controller_path);
|
2008-12-09 00:59:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|