Merge branch 'devel' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/mdadm into devel-3.0
This commit is contained in:
commit
45b662b611
|
@ -1070,6 +1070,7 @@ int Assemble(struct supertype *st, char *mddev,
|
|||
fprintf(stderr, "\n");
|
||||
}
|
||||
sysfs_uevent(content, "change");
|
||||
wait_for(chosen_name);
|
||||
close(mdfd);
|
||||
return 0;
|
||||
}
|
||||
|
|
41
Detail.c
41
Detail.c
|
@ -530,3 +530,44 @@ out:
|
|||
close(fd);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int Detail_Platform(struct superswitch *ss, int scan, int verbose)
|
||||
{
|
||||
/* display platform capabilities for the given metadata format
|
||||
* 'scan' in this context means iterate over all metadata types
|
||||
*/
|
||||
int i;
|
||||
int err = 1;
|
||||
|
||||
if (ss && ss->detail_platform)
|
||||
err = ss->detail_platform(verbose);
|
||||
else if (ss) {
|
||||
if (verbose)
|
||||
fprintf(stderr, Name ": %s metadata is platform independent\n",
|
||||
ss->name ? : "[no name]");
|
||||
} else if (!scan) {
|
||||
if (verbose)
|
||||
fprintf(stderr, Name ": specify a metadata type or --scan\n");
|
||||
}
|
||||
|
||||
if (!scan)
|
||||
return err;
|
||||
|
||||
for (i = 0; superlist[i]; i++) {
|
||||
struct superswitch *meta = superlist[i];
|
||||
|
||||
if (meta == ss)
|
||||
continue;
|
||||
if (verbose)
|
||||
fprintf(stderr, Name ": checking metadata %s\n",
|
||||
meta->name ? : "[no name]");
|
||||
if (!meta->detail_platform) {
|
||||
if (verbose)
|
||||
fprintf(stderr, Name ": %s metadata is platform independent\n",
|
||||
meta->name ? : "[no name]");
|
||||
} else
|
||||
err |= meta->detail_platform(verbose);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
13
Makefile
13
Makefile
|
@ -76,23 +76,28 @@ OBJS = mdadm.o config.o mdstat.o ReadMe.o util.o Manage.o Assemble.o Build.o \
|
|||
Create.o Detail.o Examine.o Grow.o Monitor.o dlink.o Kill.o Query.o \
|
||||
Incremental.o \
|
||||
mdopen.o super0.o super1.o super-ddf.o super-intel.o bitmap.o \
|
||||
restripe.o sysfs.o sha1.o mapfile.o crc32.o sg_io.o msg.o
|
||||
restripe.o sysfs.o sha1.o mapfile.o crc32.o sg_io.o msg.o \
|
||||
platform-intel.o probe_roms.o
|
||||
|
||||
SRCS = mdadm.c config.c mdstat.c ReadMe.c util.c Manage.c Assemble.c Build.c \
|
||||
Create.c Detail.c Examine.c Grow.c Monitor.c dlink.c Kill.c Query.c \
|
||||
Incremental.c \
|
||||
mdopen.c super0.c super1.c super-ddf.c super-intel.c bitmap.c \
|
||||
restripe.c sysfs.c sha1.c mapfile.c crc32.c sg_io.c msg.c
|
||||
restripe.c sysfs.c sha1.c mapfile.c crc32.c sg_io.c msg.c \
|
||||
platform-intel.c probe_roms.c
|
||||
|
||||
MON_OBJS = mdmon.o monitor.o managemon.o util.o mdstat.o sysfs.o config.o \
|
||||
Kill.o sg_io.o dlink.o ReadMe.o super0.o super1.o super-intel.o \
|
||||
super-ddf.o sha1.o crc32.o msg.o Monitor.o bitmap.o
|
||||
super-ddf.o sha1.o crc32.o msg.o Monitor.o bitmap.o \
|
||||
platform-intel.o probe_roms.o
|
||||
|
||||
|
||||
STATICSRC = pwgr.c
|
||||
STATICOBJS = pwgr.o
|
||||
|
||||
ASSEMBLE_SRCS := mdassemble.c Assemble.c Manage.c config.c dlink.c util.c \
|
||||
super0.c super1.c super-ddf.c super-intel.c sha1.c crc32.c sg_io.c mdstat.c
|
||||
super0.c super1.c super-ddf.c super-intel.c sha1.c crc32.c sg_io.c mdstat.c \
|
||||
platform-intel.c probe_roms.c
|
||||
ASSEMBLE_AUTO_SRCS := mdopen.c sysfs.c
|
||||
ASSEMBLE_FLAGS:= $(CFLAGS) -DMDASSEMBLE
|
||||
ifdef MDASSEMBLE_AUTO
|
||||
|
|
|
@ -616,7 +616,7 @@ int Wait(char *dev)
|
|||
break;
|
||||
|
||||
if (!e || e->percent < 0) {
|
||||
if (e &&
|
||||
if (e && e->metadata_version &&
|
||||
strncmp(e->metadata_version, "external:", 9) == 0) {
|
||||
if (is_subarray(&e->metadata_version[9]))
|
||||
ping_monitor(&e->metadata_version[9]);
|
||||
|
|
2
ReadMe.c
2
ReadMe.c
|
@ -107,6 +107,7 @@ struct option long_options[] = {
|
|||
{"query", 0, 0, 'Q'},
|
||||
{"examine-bitmap", 0, 0, 'X'},
|
||||
{"auto-detect", 0, 0, AutoDetect},
|
||||
{"detail-platform", 0, 0, DetailPlatform},
|
||||
|
||||
/* synonyms */
|
||||
{"monitor", 0, 0, 'F'},
|
||||
|
@ -466,6 +467,7 @@ char Help_misc[] =
|
|||
" --query -Q : Display general information about how a\n"
|
||||
" device relates to the md driver\n"
|
||||
" --detail -D : Display details of an array\n"
|
||||
" --detail-platform : Display hardware/firmware details\n"
|
||||
" --examine -E : Examine superblock on an array component\n"
|
||||
" --examine-bitmap -X: Display contents of a bitmap file\n"
|
||||
" --zero-superblock : erase the MD superblock from a device.\n"
|
||||
|
|
35
mdadm.8
35
mdadm.8
|
@ -51,7 +51,7 @@ each device is a path to one common physical storage device.
|
|||
is also not true RAID, and it only involves one device. It
|
||||
provides a layer over a true device that can be used to inject faults.
|
||||
|
||||
B CONTAINER
|
||||
.B CONTAINER
|
||||
is different again. A
|
||||
.B CONTAINER
|
||||
is a collection of devices that are
|
||||
|
@ -364,9 +364,13 @@ creating a DDF array a
|
|||
.B CONTAINER
|
||||
will be created, and normal arrays can be created in that container.
|
||||
.IP imsm
|
||||
Use the Intel Matrix Storage Manager metadata format. This creates a
|
||||
Use the Intel(R) Matrix Storage Manager metadata format. This creates a
|
||||
.B CONTAINER
|
||||
which is managed in a similar manner to DDF.
|
||||
which is managed in a similar manner to DDF, and is supported by an
|
||||
option-rom on some platforms:
|
||||
.IP
|
||||
.B http://www.intel.com/design/chipsets/matrixstorage_sb.htm
|
||||
.PP
|
||||
.RE
|
||||
|
||||
.TP
|
||||
|
@ -1008,6 +1012,11 @@ Information about what is discovered is presented.
|
|||
.BR \-D ", " \-\-detail
|
||||
Print detail of one or more md devices.
|
||||
|
||||
.TP
|
||||
.BR \-\-detail\-platform
|
||||
Print detail of the platform's raid capabilities (firmware / hardware
|
||||
topology) for a given metadata format.
|
||||
|
||||
.TP
|
||||
.BR \-Y ", " \-\-export
|
||||
When used with
|
||||
|
@ -1561,6 +1570,26 @@ The array has multiple failed devices such that it is unusable.
|
|||
There was an error while trying to get information about the device.
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B \-\-detail\-platform
|
||||
Print detail of the platform's raid capabilities (firmware / hardware
|
||||
topology). If the metadata is specified with
|
||||
.B \-e
|
||||
or
|
||||
.B \-\-metadata=
|
||||
then the return status will be:
|
||||
.RS
|
||||
.TP
|
||||
0
|
||||
metadata successfully enumerated its platform components on this system
|
||||
.TP
|
||||
1
|
||||
metadata is platform independent
|
||||
.TP
|
||||
2
|
||||
metadata failed to find its platform components on this system
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B \-\-examine
|
||||
The device should be a component of an md array.
|
||||
|
|
4
mdadm.c
4
mdadm.c
|
@ -217,6 +217,7 @@ int main(int argc, char *argv[])
|
|||
case 'w':
|
||||
case 'W':
|
||||
case Waitclean:
|
||||
case DetailPlatform:
|
||||
case 'K': if (!mode) newmode = MISC; break;
|
||||
}
|
||||
if (mode && newmode == mode) {
|
||||
|
@ -769,6 +770,7 @@ int main(int argc, char *argv[])
|
|||
case O(MISC,'w'):
|
||||
case O(MISC,'W'):
|
||||
case O(MISC, Waitclean):
|
||||
case O(MISC, DetailPlatform):
|
||||
if (devmode && devmode != opt &&
|
||||
(devmode == 'E' || (opt == 'E' && devmode != 'Q'))) {
|
||||
fprintf(stderr, Name ": --examine/-E cannot be given with -%c\n",
|
||||
|
@ -1211,6 +1213,8 @@ int main(int argc, char *argv[])
|
|||
rv = Examine(devlist, scan?(verbose>1?0:verbose+1):brief,
|
||||
export, scan,
|
||||
SparcAdjust, ss, homehost);
|
||||
} else if (devmode == DetailPlatform) {
|
||||
rv = Detail_Platform(ss ? ss->ss : NULL, ss ? scan : 1, verbose);
|
||||
} else {
|
||||
if (devlist == NULL) {
|
||||
if ((devmode=='D' || devmode == Waitclean) && scan) {
|
||||
|
|
6
mdadm.h
6
mdadm.h
|
@ -225,6 +225,7 @@ enum special_options {
|
|||
Symlinks,
|
||||
AutoDetect,
|
||||
Waitclean,
|
||||
DetailPlatform,
|
||||
};
|
||||
|
||||
/* structures read from config file */
|
||||
|
@ -441,6 +442,9 @@ extern struct superswitch {
|
|||
void (*brief_detail_super)(struct supertype *st);
|
||||
void (*export_detail_super)(struct supertype *st);
|
||||
|
||||
/* Optional: platform hardware / firmware details */
|
||||
int (*detail_platform)(int verbose);
|
||||
|
||||
/* Used:
|
||||
* to get uuid to storing in bitmap metadata
|
||||
* and 'reshape' backup-data metadata
|
||||
|
@ -585,6 +589,7 @@ extern struct superswitch {
|
|||
|
||||
int swapuuid; /* true if uuid is bigending rather than hostendian */
|
||||
int external;
|
||||
const char *name; /* canonical metadata name */
|
||||
} super0, super1, super_ddf, *superlist[];
|
||||
|
||||
extern struct superswitch super_imsm;
|
||||
|
@ -723,6 +728,7 @@ extern int Create(struct supertype *st, char *mddev,
|
|||
char *bitmap_file, int bitmap_chunk, int write_behind, int delay, int autof);
|
||||
|
||||
extern int Detail(char *dev, int brief, int export, int test, char *homehost);
|
||||
extern int Detail_Platform(struct superswitch *ss, int scan, int verbose);
|
||||
extern int Query(char *dev);
|
||||
extern int Examine(mddev_dev_t devlist, int brief, int export, int scan,
|
||||
int SparcAdjust, struct supertype *forcest, char *homehost);
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* Intel(R) Matrix Storage Manager hardware and firmware support routines
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#include "mdadm.h"
|
||||
#include "platform-intel.h"
|
||||
#include "probe_roms.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
void free_sys_dev(struct sys_dev **list)
|
||||
{
|
||||
while (*list) {
|
||||
struct sys_dev *next = (*list)->next;
|
||||
|
||||
if ((*list)->path)
|
||||
free((*list)->path);
|
||||
free(*list);
|
||||
*list = next;
|
||||
}
|
||||
}
|
||||
|
||||
struct sys_dev *find_driver_devices(const char *bus, const char *driver)
|
||||
{
|
||||
/* search sysfs for devices driven by 'driver' */
|
||||
char path[256];
|
||||
char link[256];
|
||||
char *c;
|
||||
DIR *driver_dir;
|
||||
struct dirent *de;
|
||||
struct sys_dev *head = NULL;
|
||||
struct sys_dev *list = NULL;
|
||||
|
||||
sprintf(path, "/sys/bus/%s/drivers/%s", bus, driver);
|
||||
driver_dir = opendir(path);
|
||||
if (!driver_dir)
|
||||
return NULL;
|
||||
for (de = readdir(driver_dir); de; de = readdir(driver_dir)) {
|
||||
/* is 'de' a device? check that the 'subsystem' link exists and
|
||||
* that its target matches 'bus'
|
||||
*/
|
||||
sprintf(path, "/sys/bus/%s/drivers/%s/%s/subsystem",
|
||||
bus, driver, de->d_name);
|
||||
if (readlink(path, link, sizeof(link)) < 0)
|
||||
continue;
|
||||
c = strrchr(link, '/');
|
||||
if (!c)
|
||||
continue;
|
||||
if (strncmp(bus, c+1, strlen(bus)) != 0)
|
||||
continue;
|
||||
|
||||
/* start / add list entry */
|
||||
if (!head) {
|
||||
head = malloc(sizeof(*head));
|
||||
list = head;
|
||||
} else {
|
||||
list->next = malloc(sizeof(*head));
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
if (!list) {
|
||||
free_sys_dev(&head);
|
||||
break;
|
||||
}
|
||||
|
||||
/* generate canonical path name for the device */
|
||||
sprintf(path, "/sys/bus/%s/drivers/%s/%s",
|
||||
bus, driver, de->d_name);
|
||||
list->path = canonicalize_file_name(path);
|
||||
list->next = NULL;
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
__u16 devpath_to_vendor(const char *dev_path)
|
||||
{
|
||||
char path[strlen(dev_path) + strlen("/vendor") + 1];
|
||||
char vendor[7];
|
||||
int fd;
|
||||
__u16 id = 0xffff;
|
||||
int n;
|
||||
|
||||
sprintf(path, "%s/vendor", dev_path);
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return 0xffff;
|
||||
|
||||
n = read(fd, vendor, sizeof(vendor));
|
||||
if (n == sizeof(vendor)) {
|
||||
vendor[n - 1] = '\0';
|
||||
id = strtoul(vendor, NULL, 16);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static int platform_has_intel_ahci(void)
|
||||
{
|
||||
struct sys_dev *devices = find_driver_devices("pci", "ahci");
|
||||
struct sys_dev *dev;
|
||||
int ret = 0;
|
||||
|
||||
for (dev = devices; dev; dev = dev->next)
|
||||
if (devpath_to_vendor(dev->path) == 0x8086) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
free_sys_dev(&devices);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static struct imsm_orom imsm_orom;
|
||||
static int scan(const void *start, const void *end)
|
||||
{
|
||||
int offset;
|
||||
const struct imsm_orom *imsm_mem;
|
||||
int len = (end - start);
|
||||
|
||||
for (offset = 0; offset < len; offset += 4) {
|
||||
imsm_mem = start + offset;
|
||||
if (memcmp(imsm_mem->signature, "$VER", 4) == 0) {
|
||||
imsm_orom = *imsm_mem;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct imsm_orom *find_imsm_orom(void)
|
||||
{
|
||||
static int populated = 0;
|
||||
|
||||
/* it's static data so we only need to read it once */
|
||||
if (populated)
|
||||
return &imsm_orom;
|
||||
|
||||
if (!platform_has_intel_ahci())
|
||||
return NULL;
|
||||
|
||||
/* scan option-rom memory looking for an imsm signature */
|
||||
if (probe_roms_init() != 0)
|
||||
return NULL;
|
||||
probe_roms();
|
||||
populated = scan_adapter_roms(scan);
|
||||
probe_roms_exit();
|
||||
|
||||
if (populated)
|
||||
return &imsm_orom;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *devt_to_devpath(dev_t dev)
|
||||
{
|
||||
char device[40];
|
||||
|
||||
sprintf(device, "/sys/dev/block/%d:%d/device", major(dev), minor(dev));
|
||||
return canonicalize_file_name(device);
|
||||
}
|
||||
|
||||
static char *diskfd_to_devpath(int fd)
|
||||
{
|
||||
/* return the device path for a disk, return NULL on error or fd
|
||||
* refers to a partition
|
||||
*/
|
||||
struct stat st;
|
||||
|
||||
if (fstat(fd, &st) != 0)
|
||||
return NULL;
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
return NULL;
|
||||
|
||||
return devt_to_devpath(st.st_rdev);
|
||||
}
|
||||
|
||||
int path_attached_to_hba(const char *disk_path, const char *hba_path)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!disk_path || !hba_path)
|
||||
return 0;
|
||||
|
||||
if (strncmp(disk_path, hba_path, strlen(hba_path)) == 0)
|
||||
rc = 1;
|
||||
else
|
||||
rc = 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int devt_attached_to_hba(dev_t dev, const char *hba_path)
|
||||
{
|
||||
char *disk_path = devt_to_devpath(dev);
|
||||
int rc = path_attached_to_hba(disk_path, hba_path);
|
||||
|
||||
if (disk_path)
|
||||
free(disk_path);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int disk_attached_to_hba(int fd, const char *hba_path)
|
||||
{
|
||||
char *disk_path = diskfd_to_devpath(fd);
|
||||
int rc = path_attached_to_hba(disk_path, hba_path);
|
||||
|
||||
if (disk_path)
|
||||
free(disk_path);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Intel(R) Matrix Storage Manager hardware and firmware support routines
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#include <asm/types.h>
|
||||
#include <strings.h>
|
||||
|
||||
/* The IMSM OROM Version Table definition */
|
||||
struct imsm_orom {
|
||||
__u8 signature[4];
|
||||
__u8 table_ver_major; /* Currently 2 (can change with future revs) */
|
||||
__u8 table_ver_minor; /* Currently 2 (can change with future revs) */
|
||||
__u16 major_ver; /* Example: 8 as in 8.6.0.1020 */
|
||||
__u16 minor_ver; /* Example: 6 as in 8.6.0.1020 */
|
||||
__u16 hotfix_ver; /* Example: 0 as in 8.6.0.1020 */
|
||||
__u16 build; /* Example: 1020 as in 8.6.0.1020 */
|
||||
__u8 len; /* number of bytes in this entire table */
|
||||
__u8 checksum; /* checksum of all the bytes in this table */
|
||||
__u16 rlc; /* RAID Level Capability */
|
||||
/* we assume the cpu is x86 as the orom should not be found
|
||||
* anywhere else
|
||||
*/
|
||||
#define IMSM_OROM_RLC_RAID0 (1 << 0)
|
||||
#define IMSM_OROM_RLC_RAID1 (1 << 1)
|
||||
#define IMSM_OROM_RLC_RAID10 (1 << 2)
|
||||
#define IMSM_OROM_RLC_RAID1E (1 << 3)
|
||||
#define IMSM_OROM_RLC_RAID5 (1 << 4)
|
||||
#define IMSM_OROM_RLC_RAID_CNG (1 << 5)
|
||||
__u16 sss; /* Strip Size Supported */
|
||||
#define IMSM_OROM_SSS_2kB (1 << 0)
|
||||
#define IMSM_OROM_SSS_4kB (1 << 1)
|
||||
#define IMSM_OROM_SSS_8kB (1 << 2)
|
||||
#define IMSM_OROM_SSS_16kB (1 << 3)
|
||||
#define IMSM_OROM_SSS_32kB (1 << 4)
|
||||
#define IMSM_OROM_SSS_64kB (1 << 5)
|
||||
#define IMSM_OROM_SSS_128kB (1 << 6)
|
||||
#define IMSM_OROM_SSS_256kB (1 << 7)
|
||||
#define IMSM_OROM_SSS_512kB (1 << 8)
|
||||
#define IMSM_OROM_SSS_1MB (1 << 9)
|
||||
#define IMSM_OROM_SSS_2MB (1 << 10)
|
||||
#define IMSM_OROM_SSS_4MB (1 << 11)
|
||||
#define IMSM_OROM_SSS_8MB (1 << 12)
|
||||
#define IMSM_OROM_SSS_16MB (1 << 13)
|
||||
#define IMSM_OROM_SSS_32MB (1 << 14)
|
||||
#define IMSM_OROM_SSS_64MB (1 << 15)
|
||||
__u16 dpa; /* Disks Per Array supported */
|
||||
__u16 tds; /* Total Disks Supported */
|
||||
__u8 vpa; /* # Volumes Per Array supported */
|
||||
__u8 vphba; /* # Volumes Per Host Bus Adapter supported */
|
||||
/* Attributes supported. This should map to the
|
||||
* attributes in the MPB. Also, lower 16 bits
|
||||
* should match/duplicate RLC bits above.
|
||||
*/
|
||||
__u32 attr;
|
||||
#define IMSM_OROM_ATTR_RAID0 IMSM_OROM_RLC_RAID0
|
||||
#define IMSM_OROM_ATTR_RAID1 IMSM_OROM_RLC_RAID1
|
||||
#define IMSM_OROM_ATTR_RAID10 IMSM_OROM_RLC_RAID10
|
||||
#define IMSM_OROM_ATTR_RAID1E IMSM_OROM_RLC_RAID1E
|
||||
#define IMSM_OROM_ATTR_RAID5 IMSM_OROM_RLC_RAID5
|
||||
#define IMSM_OROM_ATTR_RAID_CNG IMSM_OROM_RLC_RAID_CNG
|
||||
#define IMSM_OROM_ATTR_2TB (1 << 29)
|
||||
#define IMSM_OROM_ATTR_PM (1 << 30)
|
||||
#define IMSM_OROM_ATTR_ChecksumVerify (1 << 31)
|
||||
__u32 reserved1;
|
||||
__u32 reserved2;
|
||||
} __attribute__((packed));
|
||||
|
||||
static inline int imsm_orom_has_raid0(const struct imsm_orom *orom)
|
||||
{
|
||||
return !!(orom->rlc & IMSM_OROM_RLC_RAID0);
|
||||
}
|
||||
static inline int imsm_orom_has_raid1(const struct imsm_orom *orom)
|
||||
{
|
||||
return !!(orom->rlc & IMSM_OROM_RLC_RAID1);
|
||||
}
|
||||
static inline int imsm_orom_has_raid1e(const struct imsm_orom *orom)
|
||||
{
|
||||
return !!(orom->rlc & IMSM_OROM_RLC_RAID1E);
|
||||
}
|
||||
static inline int imsm_orom_has_raid10(const struct imsm_orom *orom)
|
||||
{
|
||||
return !!(orom->rlc & IMSM_OROM_RLC_RAID10);
|
||||
}
|
||||
static inline int imsm_orom_has_raid5(const struct imsm_orom *orom)
|
||||
{
|
||||
return !!(orom->rlc & IMSM_OROM_RLC_RAID5);
|
||||
}
|
||||
|
||||
/**
|
||||
* imsm_orom_has_chunk - check if the orom supports the given chunk size
|
||||
* @orom: orom pointer from find_imsm_orom
|
||||
* @chunk: chunk size in kibibytes
|
||||
*/
|
||||
static inline int imsm_orom_has_chunk(const struct imsm_orom *orom, int chunk)
|
||||
{
|
||||
int fs = ffs(chunk);
|
||||
|
||||
if (!fs)
|
||||
return 0;
|
||||
fs--; /* bit num to bit index */
|
||||
return !!(orom->sss & (1 << (fs - 1)));
|
||||
}
|
||||
|
||||
struct sys_dev {
|
||||
char *path;
|
||||
struct sys_dev *next;
|
||||
};
|
||||
|
||||
struct sys_dev *find_driver_devices(const char *bus, const char *driver);
|
||||
__u16 devpath_to_vendor(const char *dev_path);
|
||||
void free_sys_dev(struct sys_dev **list);
|
||||
const struct imsm_orom *find_imsm_orom(void);
|
||||
int disk_attached_to_hba(int fd, const char *hba_path);
|
||||
char *devt_to_devpath(dev_t dev);
|
||||
int path_attached_to_hba(const char *disk_path, const char *hba_path);
|
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* probe_roms - scan for Adapter ROMS
|
||||
*
|
||||
* (based on linux-2.6:arch/x86/kernel/probe_roms_32.c)
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "probe_roms.h"
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
static void *rom_mem = MAP_FAILED;
|
||||
static int rom_fd = -1;
|
||||
const static int rom_len = 0xf0000 - 0xc0000; /* option-rom memory region */
|
||||
static int _sigbus;
|
||||
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
static void sigbus(int sig)
|
||||
{
|
||||
_sigbus = 1;
|
||||
}
|
||||
|
||||
static int probe_address8(const __u8 *ptr, __u8 *val)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
*val = *ptr;
|
||||
if (_sigbus)
|
||||
rc = -1;
|
||||
_sigbus = 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int probe_address16(const __u16 *ptr, __u16 *val)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
*val = *ptr;
|
||||
if (_sigbus)
|
||||
rc = -1;
|
||||
_sigbus = 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void probe_roms_exit(void)
|
||||
{
|
||||
signal(SIGBUS, SIG_DFL);
|
||||
if (rom_fd >= 0) {
|
||||
close(rom_fd);
|
||||
rom_fd = -1;
|
||||
}
|
||||
if (rom_mem != MAP_FAILED) {
|
||||
munmap(rom_mem, rom_len);
|
||||
rom_mem = MAP_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int probe_roms_init(void)
|
||||
{
|
||||
int fd;
|
||||
int rc = 0;
|
||||
|
||||
if (signal(SIGBUS, sigbus) == SIG_ERR)
|
||||
rc = -1;
|
||||
if (rc == 0) {
|
||||
fd = open("/dev/mem", O_RDONLY);
|
||||
if (fd < 0)
|
||||
rc = -1;
|
||||
}
|
||||
if (rc == 0) {
|
||||
rom_mem = mmap(NULL, rom_len, PROT_READ, MAP_PRIVATE, fd, 0xc0000);
|
||||
if (rom_mem == MAP_FAILED)
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
if (rc == 0)
|
||||
rom_fd = fd;
|
||||
else
|
||||
probe_roms_exit();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* isa_bus_to_virt - convert physical address to mmap'd region
|
||||
* @addr - address to convert
|
||||
*
|
||||
* Only valid between a successful call to probe_roms_init and the
|
||||
* corresponding probe_roms_exit
|
||||
*/
|
||||
static void *isa_bus_to_virt(unsigned long addr)
|
||||
{
|
||||
return rom_mem + (addr - 0xc0000);
|
||||
}
|
||||
|
||||
struct resource {
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static struct resource system_rom_resource = {
|
||||
.name = "System ROM",
|
||||
.start = 0xf0000,
|
||||
.end = 0xfffff,
|
||||
};
|
||||
|
||||
static struct resource extension_rom_resource = {
|
||||
.name = "Extension ROM",
|
||||
.start = 0xe0000,
|
||||
.end = 0xeffff,
|
||||
};
|
||||
|
||||
static struct resource adapter_rom_resources[] = { {
|
||||
.name = "Adapter ROM",
|
||||
.start = 0xc8000,
|
||||
.end = 0,
|
||||
}, {
|
||||
.name = "Adapter ROM",
|
||||
.start = 0,
|
||||
.end = 0,
|
||||
}, {
|
||||
.name = "Adapter ROM",
|
||||
.start = 0,
|
||||
.end = 0,
|
||||
}, {
|
||||
.name = "Adapter ROM",
|
||||
.start = 0,
|
||||
.end = 0,
|
||||
}, {
|
||||
.name = "Adapter ROM",
|
||||
.start = 0,
|
||||
.end = 0,
|
||||
}, {
|
||||
.name = "Adapter ROM",
|
||||
.start = 0,
|
||||
.end = 0,
|
||||
} };
|
||||
|
||||
static struct resource video_rom_resource = {
|
||||
.name = "Video ROM",
|
||||
.start = 0xc0000,
|
||||
.end = 0xc7fff,
|
||||
};
|
||||
|
||||
#define ROMSIGNATURE 0xaa55
|
||||
|
||||
static int romsignature(const unsigned char *rom)
|
||||
{
|
||||
const unsigned short * const ptr = (const unsigned short *)rom;
|
||||
unsigned short sig = 0;
|
||||
|
||||
return probe_address16(ptr, &sig) == 0 && sig == ROMSIGNATURE;
|
||||
}
|
||||
|
||||
static int romchecksum(const unsigned char *rom, unsigned long length)
|
||||
{
|
||||
unsigned char sum, c;
|
||||
|
||||
for (sum = 0; length && probe_address8(rom++, &c) == 0; length--)
|
||||
sum += c;
|
||||
return !length && !sum;
|
||||
}
|
||||
|
||||
int scan_adapter_roms(scan_fn fn)
|
||||
{
|
||||
/* let scan_fn examing each of the adapter roms found by probe_roms */
|
||||
int i;
|
||||
int found;
|
||||
|
||||
if (rom_fd < 0)
|
||||
return 0;
|
||||
|
||||
found = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(adapter_rom_resources); i++) {
|
||||
struct resource *res = &adapter_rom_resources[i];
|
||||
|
||||
if (res->start) {
|
||||
found = fn(isa_bus_to_virt(res->start),
|
||||
isa_bus_to_virt(res->end));
|
||||
if (found)
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void probe_roms(void)
|
||||
{
|
||||
const void *rom;
|
||||
unsigned long start, length, upper;
|
||||
unsigned char c;
|
||||
int i;
|
||||
|
||||
if (rom_fd < 0)
|
||||
return;
|
||||
|
||||
/* video rom */
|
||||
upper = adapter_rom_resources[0].start;
|
||||
for (start = video_rom_resource.start; start < upper; start += 2048) {
|
||||
rom = isa_bus_to_virt(start);
|
||||
if (!romsignature(rom))
|
||||
continue;
|
||||
|
||||
video_rom_resource.start = start;
|
||||
|
||||
if (probe_address8(rom + 2, &c) != 0)
|
||||
continue;
|
||||
|
||||
/* 0 < length <= 0x7f * 512, historically */
|
||||
length = c * 512;
|
||||
|
||||
/* if checksum okay, trust length byte */
|
||||
if (length && romchecksum(rom, length))
|
||||
video_rom_resource.end = start + length - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
|
||||
if (start < upper)
|
||||
start = upper;
|
||||
|
||||
/* system rom */
|
||||
upper = system_rom_resource.start;
|
||||
|
||||
/* check for extension rom (ignore length byte!) */
|
||||
rom = isa_bus_to_virt(extension_rom_resource.start);
|
||||
if (romsignature(rom)) {
|
||||
length = extension_rom_resource.end - extension_rom_resource.start + 1;
|
||||
if (romchecksum(rom, length))
|
||||
upper = extension_rom_resource.start;
|
||||
}
|
||||
|
||||
/* check for adapter roms on 2k boundaries */
|
||||
for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) {
|
||||
rom = isa_bus_to_virt(start);
|
||||
if (!romsignature(rom))
|
||||
continue;
|
||||
|
||||
if (probe_address8(rom + 2, &c) != 0)
|
||||
continue;
|
||||
|
||||
/* 0 < length <= 0x7f * 512, historically */
|
||||
length = c * 512;
|
||||
|
||||
/* but accept any length that fits if checksum okay */
|
||||
if (!length || start + length > upper || !romchecksum(rom, length))
|
||||
continue;
|
||||
|
||||
adapter_rom_resources[i].start = start;
|
||||
adapter_rom_resources[i].end = start + length - 1;
|
||||
|
||||
start = adapter_rom_resources[i++].end & ~2047UL;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* probe_roms - scan for Adapter ROMS
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
void probe_roms_exit(void);
|
||||
int probe_roms_init(void);
|
||||
typedef int (*scan_fn)(const void *start, const void *end);
|
||||
int scan_adapter_roms(scan_fn fn);
|
||||
void probe_roms(void);
|
|
@ -3569,4 +3569,5 @@ struct superswitch super_ddf = {
|
|||
.prepare_update = ddf_prepare_update,
|
||||
.activate_spare = ddf_activate_spare,
|
||||
#endif
|
||||
.name = "ddf",
|
||||
};
|
||||
|
|
825
super-intel.c
825
super-intel.c
File diff suppressed because it is too large
Load Diff
1
super0.c
1
super0.c
|
@ -1110,4 +1110,5 @@ struct superswitch super0 = {
|
|||
.locate_bitmap = locate_bitmap0,
|
||||
.write_bitmap = write_bitmap0,
|
||||
.free_super = free_super0,
|
||||
.name = "0.90",
|
||||
};
|
||||
|
|
1
super1.c
1
super1.c
|
@ -1574,4 +1574,5 @@ struct superswitch super1 = {
|
|||
#else
|
||||
.swapuuid = 1,
|
||||
#endif
|
||||
.name = "1.0",
|
||||
};
|
||||
|
|
21
test
21
test
|
@ -40,7 +40,8 @@ mdsize11=19992
|
|||
mdsize12=19988
|
||||
|
||||
cleanup() {
|
||||
$mdadm -Ss
|
||||
udevadm settle
|
||||
$mdadm -Ssq
|
||||
for d in 0 1 2 3 4 5 6 7
|
||||
do
|
||||
losetup -d /dev/loop$d ; # rm -f $targetdir/mdtest$d
|
||||
|
@ -63,6 +64,7 @@ do
|
|||
eval dev$d=/dev/loop$d
|
||||
eval file$d=$targetdir/mdtest$d
|
||||
eval devlist=\"\$devlist \$dev$d\"
|
||||
#" <-- add this quote to un-confuse vim syntax highlighting
|
||||
done
|
||||
path0=$dev6
|
||||
path1=$dev7
|
||||
|
@ -171,7 +173,20 @@ rotest() {
|
|||
fsck -fn $dev >&2
|
||||
}
|
||||
|
||||
setup_environment() {
|
||||
if [ -f $1 ]; then
|
||||
. $environment
|
||||
setup_env
|
||||
fi
|
||||
}
|
||||
|
||||
reset_environment() {
|
||||
if [ -f $1 ]; then
|
||||
reset_env
|
||||
unset setup_env
|
||||
unset reset_env
|
||||
fi
|
||||
}
|
||||
|
||||
for script in tests/$prefix tests/$prefix*[^~]
|
||||
do
|
||||
|
@ -182,14 +197,18 @@ do
|
|||
mdadm -Ssq
|
||||
mdadm --zero $devlist 2> /dev/null
|
||||
mdadm --zero $devlist 2> /dev/null
|
||||
environment="tests/env-`basename $script`"
|
||||
setup_environment $environment
|
||||
# source script in a subshell, so it has access to our
|
||||
# namespace, but cannot change it.
|
||||
if ( set -ex ; . $script ) 2> $targetdir/log
|
||||
then echo "$script succeeded"
|
||||
else cat $targetdir/log ; cat $targetdir/stderr
|
||||
echo "$script failed"
|
||||
reset_environment $environment
|
||||
exit 1
|
||||
fi
|
||||
reset_environment $environment
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# create raid arrays with varying degress of overlap
|
||||
mdadm -CR $container -e imsm -n 6 $dev0 $dev1 $dev2 $dev3 $dev4 $dev5
|
||||
imsm_check container 6
|
||||
|
||||
size=1910
|
||||
level=1
|
||||
num_disks=2
|
||||
mdadm -CR $member0 $dev0 $dev1 -n $num_disks -l $level -z $size
|
||||
mdadm -CR $member1 $dev1 $dev2 -n $num_disks -l $level -z $size
|
||||
mdadm -CR $member2 $dev2 $dev3 -n $num_disks -l $level -z $size
|
||||
mdadm -CR $member3 $dev3 $dev4 -n $num_disks -l $level -z $size
|
||||
mdadm -CR $member4 $dev4 $dev5 -n $num_disks -l $level -z $size
|
||||
|
||||
offset=0
|
||||
imsm_check member $member0 $num_disks $level $size $offset
|
||||
offset=$((offset+size+2048))
|
||||
imsm_check member $member1 $num_disks $level $size $offset
|
||||
offset=$((offset+size+2048))
|
||||
imsm_check member $member2 $num_disks $level $size $offset
|
||||
offset=$((offset+size+2048))
|
||||
imsm_check member $member3 $num_disks $level $size $offset
|
||||
# at this point there should be more freespace at the start of the disk
|
||||
# than the end
|
||||
offset=0
|
||||
imsm_check member $member4 $num_disks $level $size $offset
|
|
@ -0,0 +1 @@
|
|||
env-imsm
|
|
@ -0,0 +1,68 @@
|
|||
imsm_check() {
|
||||
case $1 in
|
||||
container )
|
||||
grep -s "$(((418 * $2)/2)) blocks super external:imsm" /proc/mdstat > /dev/null || {
|
||||
echo >&2 "ERROR correctly formed container not found"; cat /proc/mdstat; exit 1;}
|
||||
;;
|
||||
member )
|
||||
member=$2
|
||||
num_disks=$3
|
||||
level=$4
|
||||
size=$5
|
||||
offset=$6
|
||||
err=0
|
||||
|
||||
eval `stat -L -c "let major=0x%t; let minor=0x%T;" $member`
|
||||
sysfs=/sys/dev/block/${major}:${minor}
|
||||
if [ ! -f ${sysfs}/md/array_state ]; then
|
||||
echo "member array $member not found" >&2
|
||||
cat /proc/mdstat >&2
|
||||
exit 1
|
||||
fi
|
||||
for i in `seq 0 $((num_disks-1))`
|
||||
do
|
||||
_offset=`cat ${sysfs}/md/rd${i}/offset`
|
||||
if [ $offset -ne $((_offset/2)) ]; then
|
||||
echo "offset mismatch expected $offset got $_offset" >&2
|
||||
err=$((err+1))
|
||||
fi
|
||||
_size=`cat ${sysfs}/md/rd${i}/size`
|
||||
if [ $size -ne $_size ]; then
|
||||
echo "offset mismatch expected $size got $_size" >&2
|
||||
err=$((err+1))
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $err -gt 0 ]; then
|
||||
echo "$member failed check" >&2
|
||||
cat /proc/mdstat >&2
|
||||
mdadm -E /dev/loop0 >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
* ) echo >&2 ERROR unknown check $1 ; exit 1;
|
||||
esac
|
||||
}
|
||||
|
||||
setup_env() {
|
||||
export IMSM_DEVNAME_AS_SERIAL=1
|
||||
export IMSM_NO_PLATFORM=1
|
||||
container=/dev/md/container
|
||||
member0=/dev/md/vol0
|
||||
member1=/dev/md/vol1
|
||||
member2=/dev/md/vol2
|
||||
member3=/dev/md/vol3
|
||||
member4=/dev/md/vol4
|
||||
}
|
||||
|
||||
reset_env() {
|
||||
unset IMSM_DEVNAME_AS_SERIAL
|
||||
unset IMSM_NO_PLATFORM
|
||||
unset imsm_check
|
||||
unset container
|
||||
unset member0
|
||||
unset member1
|
||||
unset member2
|
||||
unset member3
|
||||
unset member4
|
||||
}
|
Loading…
Reference in New Issue