summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2008-05-15 16:48:21 +1000
committerNeil Brown <neilb@suse.de>2008-05-15 16:48:21 +1000
commit2f6079dc96180335fdb56d0b89e462e903abbb50 (patch)
treec643ba942b6a7a2ccb100e3707eed3d139b5253d
parent598f0d58ac3544e25f90f2d34337e15764f4d877 (diff)
downloadmdadm-2f6079dc96180335fdb56d0b89e462e903abbb50.tar.gz
mdadm-2f6079dc96180335fdb56d0b89e462e903abbb50.tar.xz
mdadm-2f6079dc96180335fdb56d0b89e462e903abbb50.zip
Create a container member
From: Neil Brown <neilb@suse.de>
-rw-r--r--Create.c10
-rw-r--r--mdadm.h4
-rw-r--r--super-ddf.c5
-rw-r--r--sysfs.c3
-rw-r--r--util.c23
5 files changed, 42 insertions, 3 deletions
diff --git a/Create.c b/Create.c
index 0bc4738..c1d607f 100644
--- a/Create.c
+++ b/Create.c
@@ -537,7 +537,15 @@ int Create(struct supertype *st, char *mddev, int mdfd,
if (st->ss->external) {
char ver[100];
- strcat(strcpy(ver, "external:"), st->ss->text_version);
+ if (st->ss->external == 1)
+ /* container */
+ strcat(strcpy(ver, "external:"), st->ss->text_version);
+ else {
+ /* member */
+ sprintf(ver, "external:/%s/%d",
+ devnum2devname(st->container_dev),
+ st->container_member);
+ }
if ((vers % 100) < 2 ||
sra == NULL ||
sysfs_set_str(sra, NULL, "metadata_version",
diff --git a/mdadm.h b/mdadm.h
index 4c0e9e1..dae73cc 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -397,6 +397,8 @@ struct supertype {
struct superswitch *ss;
int minor_version;
int max_devs;
+ int container_dev; /* devnum of container */
+ int container_member; /* numerical position in container */
void *sb;
void *info;
};
@@ -563,6 +565,8 @@ extern int open_mddev_devnum(char *devname, int devnum, char *name,
char *chosen_name, int parts);
extern int open_container(int fd);
+extern char *devnum2devname(int num);
+extern int fd2devnum(int fd);
#define LEVEL_MULTIPATH (-4)
#define LEVEL_LINEAR (-1)
diff --git a/super-ddf.c b/super-ddf.c
index b494647..69ca320 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -416,7 +416,7 @@ struct ddf_super {
#define offsetof(t,f) ((size_t)&(((t*)0)->f))
#endif
-struct superswitch super_ddf_container, super_ddf_bvd;
+extern struct superswitch super_ddf_container, super_ddf_bvd;
static int calc_crc(void *buf, int len)
{
@@ -1657,6 +1657,7 @@ static int init_super_ddf_bvd(struct supertype *st,
return 0;
}
ve = &ddf->virt->entries[venum];
+ st->container_member = venum;
/* A Virtual Disk GUID contains the T10 Vendor ID, controller type,
* timestamp, random number
@@ -2023,6 +2024,8 @@ int validate_geometry_ddf(struct supertype *st,
st->ss = &super_ddf_bvd;
if (load_super_ddf_all(st, cfd, (void **)&ddf, NULL, 1) == 0) {
st->sb = ddf;
+ st->container_dev = fd2devnum(cfd);
+ st->container_member = 27; // FIXME
close(cfd);
return st->ss->validate_geometry(st, level, layout,
raiddisks, chunk, size,
diff --git a/sysfs.c b/sysfs.c
index 6fa76fd..8b5a6ff 100644
--- a/sysfs.c
+++ b/sysfs.c
@@ -34,7 +34,7 @@ int load_sys(char *path, char *buf)
return -1;
n = read(fd, buf, 1024);
close(fd);
- if (n <=0 || n >= 1024)
+ if (n <0 || n >= 1024)
return -1;
buf[n] = 0;
if (buf[n-1] == '\n')
@@ -316,6 +316,7 @@ int sysfs_set_array(struct mdinfo *sra,
{
int rv = 0;
sra->array = info->array;
+
if (info->array.level < 0)
return 0; /* FIXME */
rv |= sysfs_set_str(sra, NULL, "level",
diff --git a/util.c b/util.c
index 7b43ee2..8ea3069 100644
--- a/util.c
+++ b/util.c
@@ -978,6 +978,29 @@ int open_container(int fd)
return -1;
}
+char *devnum2devname(int num)
+{
+ char name[100];
+ if (num > 0)
+ sprintf(name, "md%d", num);
+ else
+ sprintf(name, "md_d%d", -1-num);
+ return strdup(name);
+}
+
+int fd2devnum(int fd)
+{
+ struct stat stb;
+ if (fstat(fd, &stb) == 0 &&
+ (S_IFMT&stb.st_mode)==S_IFBLK) {
+ if (major(stb.st_rdev) == MD_MAJOR)
+ return minor(stb.st_rdev);
+ else
+ return -1- (minor(stb.st_rdev)>>6);
+ }
+ return -1;
+}
+
#ifdef __TINYC__
/* tinyc doesn't optimize this check in ioctl.h out ... */
unsigned int __invalid_size_argument_for_IOC = 0;