Merge branch 'devel' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/mdadm into devel-3.0

This commit is contained in:
NeilBrown 2008-12-18 16:58:25 +11:00
commit 45b662b611
20 changed files with 1624 additions and 122 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

239
platform-intel.c Normal file
View File

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

129
platform-intel.h Normal file
View File

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

279
probe_roms.c Normal file
View File

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

24
probe_roms.h Normal file
View File

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

View File

@ -3569,4 +3569,5 @@ struct superswitch super_ddf = {
.prepare_update = ddf_prepare_update,
.activate_spare = ddf_activate_spare,
#endif
.name = "ddf",
};

File diff suppressed because it is too large Load Diff

View File

@ -1110,4 +1110,5 @@ struct superswitch super0 = {
.locate_bitmap = locate_bitmap0,
.write_bitmap = write_bitmap0,
.free_super = free_super0,
.name = "0.90",
};

View File

@ -1574,4 +1574,5 @@ struct superswitch super1 = {
#else
.swapuuid = 1,
#endif
.name = "1.0",
};

21
test
View File

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

25
tests/08imsm-overlap Normal file
View File

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

1
tests/env-08imsm-overlap Symbolic link
View File

@ -0,0 +1 @@
env-imsm

68
tests/env-imsm Normal file
View File

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