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"); fprintf(stderr, "\n");
} }
sysfs_uevent(content, "change"); sysfs_uevent(content, "change");
wait_for(chosen_name);
close(mdfd); close(mdfd);
return 0; return 0;
} }

View File

@ -530,3 +530,44 @@ out:
close(fd); close(fd);
return rv; 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 \ Create.o Detail.o Examine.o Grow.o Monitor.o dlink.o Kill.o Query.o \
Incremental.o \ Incremental.o \
mdopen.o super0.o super1.o super-ddf.o super-intel.o bitmap.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 \ 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 \ Create.c Detail.c Examine.c Grow.c Monitor.c dlink.c Kill.c Query.c \
Incremental.c \ Incremental.c \
mdopen.c super0.c super1.c super-ddf.c super-intel.c bitmap.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 \ 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 \ 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 STATICSRC = pwgr.c
STATICOBJS = pwgr.o STATICOBJS = pwgr.o
ASSEMBLE_SRCS := mdassemble.c Assemble.c Manage.c config.c dlink.c util.c \ 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_AUTO_SRCS := mdopen.c sysfs.c
ASSEMBLE_FLAGS:= $(CFLAGS) -DMDASSEMBLE ASSEMBLE_FLAGS:= $(CFLAGS) -DMDASSEMBLE
ifdef MDASSEMBLE_AUTO ifdef MDASSEMBLE_AUTO

View File

@ -616,7 +616,7 @@ int Wait(char *dev)
break; break;
if (!e || e->percent < 0) { if (!e || e->percent < 0) {
if (e && if (e && e->metadata_version &&
strncmp(e->metadata_version, "external:", 9) == 0) { strncmp(e->metadata_version, "external:", 9) == 0) {
if (is_subarray(&e->metadata_version[9])) if (is_subarray(&e->metadata_version[9]))
ping_monitor(&e->metadata_version[9]); ping_monitor(&e->metadata_version[9]);

View File

@ -107,6 +107,7 @@ struct option long_options[] = {
{"query", 0, 0, 'Q'}, {"query", 0, 0, 'Q'},
{"examine-bitmap", 0, 0, 'X'}, {"examine-bitmap", 0, 0, 'X'},
{"auto-detect", 0, 0, AutoDetect}, {"auto-detect", 0, 0, AutoDetect},
{"detail-platform", 0, 0, DetailPlatform},
/* synonyms */ /* synonyms */
{"monitor", 0, 0, 'F'}, {"monitor", 0, 0, 'F'},
@ -466,6 +467,7 @@ char Help_misc[] =
" --query -Q : Display general information about how a\n" " --query -Q : Display general information about how a\n"
" device relates to the md driver\n" " device relates to the md driver\n"
" --detail -D : Display details of an array\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 -E : Examine superblock on an array component\n"
" --examine-bitmap -X: Display contents of a bitmap file\n" " --examine-bitmap -X: Display contents of a bitmap file\n"
" --zero-superblock : erase the MD superblock from a device.\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 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. provides a layer over a true device that can be used to inject faults.
B CONTAINER .B CONTAINER
is different again. A is different again. A
.B CONTAINER .B CONTAINER
is a collection of devices that are is a collection of devices that are
@ -364,9 +364,13 @@ creating a DDF array a
.B CONTAINER .B CONTAINER
will be created, and normal arrays can be created in that container. will be created, and normal arrays can be created in that container.
.IP imsm .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 .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 .RE
.TP .TP
@ -1008,6 +1012,11 @@ Information about what is discovered is presented.
.BR \-D ", " \-\-detail .BR \-D ", " \-\-detail
Print detail of one or more md devices. 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 .TP
.BR \-Y ", " \-\-export .BR \-Y ", " \-\-export
When used with 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. There was an error while trying to get information about the device.
.RE .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 .TP
.B \-\-examine .B \-\-examine
The device should be a component of an md array. 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 'W': case 'W':
case Waitclean: case Waitclean:
case DetailPlatform:
case 'K': if (!mode) newmode = MISC; break; case 'K': if (!mode) newmode = MISC; break;
} }
if (mode && newmode == mode) { 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,'W'): case O(MISC,'W'):
case O(MISC, Waitclean): case O(MISC, Waitclean):
case O(MISC, DetailPlatform):
if (devmode && devmode != opt && if (devmode && devmode != opt &&
(devmode == 'E' || (opt == 'E' && devmode != 'Q'))) { (devmode == 'E' || (opt == 'E' && devmode != 'Q'))) {
fprintf(stderr, Name ": --examine/-E cannot be given with -%c\n", 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, rv = Examine(devlist, scan?(verbose>1?0:verbose+1):brief,
export, scan, export, scan,
SparcAdjust, ss, homehost); SparcAdjust, ss, homehost);
} else if (devmode == DetailPlatform) {
rv = Detail_Platform(ss ? ss->ss : NULL, ss ? scan : 1, verbose);
} else { } else {
if (devlist == NULL) { if (devlist == NULL) {
if ((devmode=='D' || devmode == Waitclean) && scan) { if ((devmode=='D' || devmode == Waitclean) && scan) {

View File

@ -225,6 +225,7 @@ enum special_options {
Symlinks, Symlinks,
AutoDetect, AutoDetect,
Waitclean, Waitclean,
DetailPlatform,
}; };
/* structures read from config file */ /* structures read from config file */
@ -441,6 +442,9 @@ extern struct superswitch {
void (*brief_detail_super)(struct supertype *st); void (*brief_detail_super)(struct supertype *st);
void (*export_detail_super)(struct supertype *st); void (*export_detail_super)(struct supertype *st);
/* Optional: platform hardware / firmware details */
int (*detail_platform)(int verbose);
/* Used: /* Used:
* to get uuid to storing in bitmap metadata * to get uuid to storing in bitmap metadata
* and 'reshape' backup-data metadata * and 'reshape' backup-data metadata
@ -585,6 +589,7 @@ extern struct superswitch {
int swapuuid; /* true if uuid is bigending rather than hostendian */ int swapuuid; /* true if uuid is bigending rather than hostendian */
int external; int external;
const char *name; /* canonical metadata name */
} super0, super1, super_ddf, *superlist[]; } super0, super1, super_ddf, *superlist[];
extern struct superswitch super_imsm; 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); 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(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 Query(char *dev);
extern int Examine(mddev_dev_t devlist, int brief, int export, int scan, extern int Examine(mddev_dev_t devlist, int brief, int export, int scan,
int SparcAdjust, struct supertype *forcest, char *homehost); 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, .prepare_update = ddf_prepare_update,
.activate_spare = ddf_activate_spare, .activate_spare = ddf_activate_spare,
#endif #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, .locate_bitmap = locate_bitmap0,
.write_bitmap = write_bitmap0, .write_bitmap = write_bitmap0,
.free_super = free_super0, .free_super = free_super0,
.name = "0.90",
}; };

View File

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

21
test
View File

@ -40,7 +40,8 @@ mdsize11=19992
mdsize12=19988 mdsize12=19988
cleanup() { cleanup() {
$mdadm -Ss udevadm settle
$mdadm -Ssq
for d in 0 1 2 3 4 5 6 7 for d in 0 1 2 3 4 5 6 7
do do
losetup -d /dev/loop$d ; # rm -f $targetdir/mdtest$d losetup -d /dev/loop$d ; # rm -f $targetdir/mdtest$d
@ -63,6 +64,7 @@ do
eval dev$d=/dev/loop$d eval dev$d=/dev/loop$d
eval file$d=$targetdir/mdtest$d eval file$d=$targetdir/mdtest$d
eval devlist=\"\$devlist \$dev$d\" eval devlist=\"\$devlist \$dev$d\"
#" <-- add this quote to un-confuse vim syntax highlighting
done done
path0=$dev6 path0=$dev6
path1=$dev7 path1=$dev7
@ -171,7 +173,20 @@ rotest() {
fsck -fn $dev >&2 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*[^~] for script in tests/$prefix tests/$prefix*[^~]
do do
@ -182,14 +197,18 @@ do
mdadm -Ssq mdadm -Ssq
mdadm --zero $devlist 2> /dev/null mdadm --zero $devlist 2> /dev/null
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 # source script in a subshell, so it has access to our
# namespace, but cannot change it. # namespace, but cannot change it.
if ( set -ex ; . $script ) 2> $targetdir/log if ( set -ex ; . $script ) 2> $targetdir/log
then echo "$script succeeded" then echo "$script succeeded"
else cat $targetdir/log ; cat $targetdir/stderr else cat $targetdir/log ; cat $targetdir/stderr
echo "$script failed" echo "$script failed"
reset_environment $environment
exit 1 exit 1
fi fi
reset_environment $environment
fi fi
done done
exit 0 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
}