From: NeilBrown Date: Thu, 19 Aug 2010 06:48:34 +0000 (+1000) Subject: Add mbr pseudo metadata handler. X-Git-Tag: mdadm-3.2~326 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=commitdiff_plain;h=0f22b998fb9cf8478810b89cd50fa5b4fbf11d38;hp=64436f0628a14f4e979b93bea57aba4b4c6143e8 Add mbr pseudo metadata handler. To support incorpating a new bare device into a collection of arrays - one partition each - mdadm needs a modest understanding of partition tables. The main needs to be able to recognise a partition table on one device and copy it onto another. This will be done using pseudo metadata types 'mbr' and 'gpt'. Signed-off-by: NeilBrown --- diff --git a/Assemble.c b/Assemble.c index 42f71fd4..23d0b826 100644 --- a/Assemble.c +++ b/Assemble.c @@ -262,8 +262,14 @@ int Assemble(struct supertype *st, char *mddev, tmpdev->used = 2; } else if (tst->ss->load_super(tst,dfd, NULL)) { if (report_missmatch) - fprintf( stderr, Name ": no RAID superblock on %s\n", - devname); + fprintf(stderr, Name ": no RAID superblock on %s\n", + devname); + } else if (tst->ss->compare_super == NULL) { + if (report_missmatch) + fprintf(stderr, Name ": Cannot assemble %s metadata on %s\n", + tst->ss->name, devname); + tst->ss->free_super(tst); + tmpdev->used = 2; } else if (auto_assem && st == NULL && !conf_test_metadata(tst->ss->name, tst->ss->match_home(tst, homehost) == 1)) { diff --git a/Examine.c b/Examine.c index 7fbd4ae2..01838c8b 100644 --- a/Examine.c +++ b/Examine.c @@ -100,7 +100,11 @@ int Examine(mddev_dev_t devlist, int brief, int export, int scan, devlist->devname, 0, 0, NULL); /* Ok, its good enough to try, though the checksum could be wrong */ - if (brief) { + if (brief && st->ss->brief_examine_super == NULL) { + if (!scan) + fprintf(stderr, Name ": No brief listing for %s on %s\n", + st->ss->name, devlist->devname); + } else if (brief) { struct array *ap; char *d; for (ap=arrays; ap; ap=ap->next) { diff --git a/Incremental.c b/Incremental.c index fe6aad28..bcbd78d0 100644 --- a/Incremental.c +++ b/Incremental.c @@ -142,11 +142,13 @@ int Incremental(char *devname, int verbose, int runstop, rv = try_spare(devname, &dfd, policy, st, verbose); goto out; } - if (st->ss->load_super(st, dfd, NULL)) { + if (st->ss->compare_super == NULL || + st->ss->load_super(st, dfd, NULL)) { if (verbose >= 0) fprintf(stderr, Name ": no RAID superblock on %s.\n", devname); rv = try_spare(devname, &dfd, policy, st, verbose); + free(st); goto out; } close (dfd); dfd = -1; diff --git a/Kill.c b/Kill.c index 3d1810f0..f5c30e97 100644 --- a/Kill.c +++ b/Kill.c @@ -53,7 +53,7 @@ int Kill(char *dev, struct supertype *st, int force, int quiet, int noexcl) } if (st == NULL) st = guess_super(fd); - if (st == NULL) { + if (st == NULL || st->ss->init_super == NULL) { if (!quiet) fprintf(stderr, Name ": Unrecognised md component device - %s\n", dev); close(fd); diff --git a/Makefile b/Makefile index af9804c5..75a8a413 100644 --- a/Makefile +++ b/Makefile @@ -99,6 +99,7 @@ OBJS = mdadm.o config.o policy.o mdstat.o ReadMe.o util.o Manage.o Assemble.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 \ + super-mbr.o \ restripe.o sysfs.o sha1.o mapfile.o crc32.o sg_io.o msg.o \ platform-intel.o probe_roms.o @@ -106,16 +107,21 @@ SRCS = mdadm.c config.c policy.c mdstat.c ReadMe.c util.c Manage.c Assemble.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 \ + super-mbr.c \ restripe.c sysfs.c sha1.c mapfile.c crc32.c sg_io.c msg.c \ platform-intel.c probe_roms.c +INCL = mdadm.h part.h bitmap.h + MON_OBJS = mdmon.o monitor.o managemon.o util.o mdstat.o sysfs.o config.o policy.o \ Kill.o sg_io.o dlink.o ReadMe.o super0.o super1.o super-intel.o \ + super-mbr.o \ super-ddf.o sha1.o crc32.o msg.o bitmap.o \ platform-intel.o probe_roms.o MON_SRCS = mdmon.c monitor.c managemon.c util.c mdstat.c sysfs.c config.c policy.c \ Kill.c sg_io.c dlink.c ReadMe.c super0.c super1.c super-intel.c \ + super-mbr.c \ super-ddf.c sha1.c crc32.c msg.c bitmap.c \ platform-intel.c probe_roms.c @@ -124,7 +130,7 @@ STATICOBJS = pwgr.o ASSEMBLE_SRCS := mdassemble.c Assemble.c Manage.c config.c policy.c dlink.c util.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 sysfs.c + platform-intel.c probe_roms.c sysfs.c super-mbr.c ASSEMBLE_AUTO_SRCS := mdopen.c ASSEMBLE_FLAGS:= $(CFLAGS) -DMDASSEMBLE ifdef MDASSEMBLE_AUTO @@ -149,20 +155,20 @@ mdadm : $(OBJS) mdadm.static : $(OBJS) $(STATICOBJS) $(CC) $(LDFLAGS) -static -o mdadm.static $(OBJS) $(STATICOBJS) -mdadm.tcc : $(SRCS) mdadm.h +mdadm.tcc : $(SRCS) $(INCL) $(TCC) -o mdadm.tcc $(SRCS) -mdadm.klibc : $(SRCS) mdadm.h +mdadm.klibc : $(SRCS) $(INCL) rm -f $(OBJS) $(CC) -nostdinc -iwithprefix include -I$(KLIBC)/klibc/include -I$(KLIBC)/linux/include -I$(KLIBC)/klibc/arch/i386/include -I$(KLIBC)/klibc/include/bits32 $(CFLAGS) $(SRCS) -mdadm.Os : $(SRCS) mdadm.h +mdadm.Os : $(SRCS) $(INCL) $(CC) -o mdadm.Os $(CFLAGS) $(LDFLAGS) -DHAVE_STDINT_H -Os $(SRCS) -mdadm.O2 : $(SRCS) mdadm.h mdmon.O2 +mdadm.O2 : $(SRCS) $(INCL) mdmon.O2 $(CC) -o mdadm.O2 $(CFLAGS) $(LDFLAGS) -DHAVE_STDINT_H -O2 -D_FORTIFY_SOURCE=2 $(SRCS) -mdmon.O2 : $(MON_SRCS) mdadm.h mdmon.h +mdmon.O2 : $(MON_SRCS) $(INCL) mdmon.h $(CC) -o mdmon.O2 $(CFLAGS) $(LDFLAGS) $(MON_LDFLAGS) -DHAVE_STDINT_H -O2 -D_FORTIFY_SOURCE=2 $(MON_SRCS) # use '-z now' to guarantee no dynamic linker interactions with the monitor thread @@ -173,25 +179,25 @@ msg.o: msg.c msg.h test_stripe : restripe.c mdadm.h $(CC) $(CXFLAGS) $(LDFLAGS) -o test_stripe -DMAIN restripe.c -mdassemble : $(ASSEMBLE_SRCS) mdadm.h +mdassemble : $(ASSEMBLE_SRCS) $(INCL) rm -f $(OBJS) $(DIET_GCC) $(ASSEMBLE_FLAGS) -o mdassemble $(ASSEMBLE_SRCS) $(STATICSRC) -mdassemble.static : $(ASSEMBLE_SRCS) mdadm.h +mdassemble.static : $(ASSEMBLE_SRCS) $(INCL) rm -f $(OBJS) $(CC) $(LDFLAGS) $(ASSEMBLE_FLAGS) -static -DHAVE_STDINT_H -o mdassemble.static $(ASSEMBLE_SRCS) $(STATICSRC) -mdassemble.auto : $(ASSEMBLE_SRCS) mdadm.h $(ASSEMBLE_AUTO_SRCS) +mdassemble.auto : $(ASSEMBLE_SRCS) $(INCL) $(ASSEMBLE_AUTO_SRCS) rm -f mdassemble.static $(MAKE) MDASSEMBLE_AUTO=1 mdassemble.static mv mdassemble.static mdassemble.auto -mdassemble.uclibc : $(ASSEMBLE_SRCS) mdadm.h +mdassemble.uclibc : $(ASSEMBLE_SRCS) $(INCL) rm -f $(OJS) $(UCLIBC_GCC) $(ASSEMBLE_FLAGS) -DUCLIBC -DHAVE_STDINT_H -static -o mdassemble.uclibc $(ASSEMBLE_SRCS) $(STATICSRC) # This doesn't work -mdassemble.klibc : $(ASSEMBLE_SRCS) mdadm.h +mdassemble.klibc : $(ASSEMBLE_SRCS) $(INCL) rm -f $(OBJS) $(KLIBC_GCC) $(ASSEMBLE_FLAGS) -o mdassemble $(ASSEMBLE_SRCS) @@ -213,8 +219,8 @@ mdadm.conf.man : mdadm.conf.5 mdassemble.man : mdassemble.8 nroff -man mdassemble.8 > mdassemble.man -$(OBJS) : mdadm.h mdmon.h bitmap.h -$(MON_OBJS) : mdadm.h mdmon.h bitmap.h +$(OBJS) : $(INCL) mdmon.h +$(MON_OBJS) : $(INCL) mdmon.h sha1.o : sha1.c sha1.h md5.h $(CC) $(CFLAGS) -DHAVE_STDINT_H -o sha1.o -c sha1.c diff --git a/mdadm.h b/mdadm.h index 1fe25745..f16cd7c0 100644 --- a/mdadm.h +++ b/mdadm.h @@ -671,9 +671,11 @@ 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[]; +} *superlist[]; -extern struct superswitch super_imsm; +extern struct superswitch super0, super1; +extern struct superswitch super_imsm, super_ddf; +extern struct superswitch mbr; struct metadata_update { int len; diff --git a/part.h b/part.h new file mode 100644 index 00000000..0afea33b --- /dev/null +++ b/part.h @@ -0,0 +1,82 @@ +/* + * mdadm - manage Linux "md" devices aka RAID arrays. + * + * Copyright (C) 2010 Neil Brown + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Neil Brown + * Email: + * + */ + +/* Structure definitions ext for MBR and GPT partition tables + */ + + +#define MBR_SIGNATURE_MAGIC __cpu_to_le16(0xAA55) +#define MBR_PARTITIONS 4 + +struct MBR_part_record { + __u8 bootable; + __u8 first_head; + __u8 first_sector; + __u8 first_cyl; + __u8 part_type; + __u8 last_head; + __u8 last_sector; + __u8 last_cyl; + __u32 first_sect_lba; + __u32 blocks_num; +}; + +struct MBR { + __u8 pad[446]; + struct MBR_part_record parts[MBR_PARTITIONS]; + __u16 magic; +} __attribute__((packed)); + + + +#define GPT_SIGNATURE_MAGIC __cpu_to_le64(0x5452415020494645ULL) +#define MBR_GPT_PARTITION_TYPE 0xEE + +struct GPT_part_entry { + unsigned char type_guid[16]; + unsigned char partition_guid[16]; + __u64 starting_lba; + __u64 ending_lba; + unsigned char attr_bits[8]; + unsigned char name[72]; +} __attribute__((packed)); + +struct GPT { + __u64 magic; + __u32 revision; + __u32 header_size; + __u32 crc; + __u32 pad1; + __u64 current_lba; + __u64 backup_lba; + __u64 first_lba; + __u64 last_lba; + __u8 guid[16]; + __u64 part_start; + __u32 part_cnt; + __u32 part_size; + __u32 part_crc; + __u8 pad2[420]; +} __attribute__((packed)); diff --git a/super-mbr.c b/super-mbr.c new file mode 100644 index 00000000..811ad1dc --- /dev/null +++ b/super-mbr.c @@ -0,0 +1,213 @@ +/* + * mdadm - manage Linux "md" devices aka RAID arrays. + * + * Copyright (C) 2010 Neil Brown + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Neil Brown + * Email: + * + */ + +/* + * 'mbr' is a pseudo metadata type for devices which have a + * partition table in the Master Boot Record (mbr) also known + * as a dos partition table. + * + * Obviously arrays cannot be created or assembled for this type. + * It is used to allow a new bare device to have an partition table + * added so the member partitions can then be included in other + * arrays as relevant. + * + * The meaning operations are: + * examine_super, but not brief_examine_super or export_examine + * load_super + * store_super + */ + +#include "mdadm.h" +#include "part.h" + +static void free_mbr(struct supertype *st) +{ + free(st->sb); + st->sb = NULL; +} + +#ifndef MDASSEMBLE + +static void examine_mbr(struct supertype *st, char *homehost) +{ + struct MBR *sb = st->sb; + int i; + + printf(" MBR Magic : %04x\n", sb->magic); + for (i = 0; i < MBR_PARTITIONS; i++) + if (sb->parts[i].blocks_num) + printf("Partition[%d] : %12lu sectors at %12lu (type %02x)\n", + i, + (unsigned long)__le32_to_cpu(sb->parts[i].blocks_num), + (unsigned long)__le32_to_cpu(sb->parts[i].first_sect_lba), + sb->parts[i].part_type); + +} + +#endif /*MDASSEMBLE */ + +static int load_super_mbr(struct supertype *st, int fd, char *devname) +{ + /* try to read an mbr + * Return + * 0 on success + * 1 cannot get record + * 2 record is meaningless + */ + struct MBR *super; + + free_mbr(st); + + if (st->subarray[0]) + return 1; + + if (posix_memalign((void**)&super, 512, 512) != 0) { + fprintf(stderr, Name ": %s could not allocate superblock\n", + __func__); + return 1; + } + + ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */ + + lseek(fd, 0, 0); + if (read(fd, super, sizeof(*super)) != sizeof(*super)) { + if (devname) + fprintf(stderr, Name ": Cannot read partition table on %s\n", + devname); + free(super); + return 1; + } + + if (super->magic != MBR_SIGNATURE_MAGIC) { + if (devname) + fprintf(stderr, Name ": No partition table found on %s\n", + devname); + free(super); + return 1; + } + + st->sb = super; + + if (st->ss == NULL) { + st->ss = &mbr; + st->minor_version = 0; + st->max_devs = 1; + st->info = NULL; + } + return 0; +} + +static int store_mbr(struct supertype *st, int fd) +{ + struct MBR *old, *super; + + if (posix_memalign((void**)&old, 512, 512) != 0) { + fprintf(stderr, Name ": %s could not allocate superblock\n", + __func__); + return 1; + } + + ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */ + + lseek(fd, 0, 0); + if (read(fd, old, sizeof(*old)) != sizeof(*old)) { + free(old); + return 1; + } + + super = st->sb; + memcpy(super->pad, old->pad, sizeof(super->pad)); + free(old); + lseek(fd, 0, 0); + if (write(fd, super, sizeof(*super)) != sizeof(*super)) + return 4; + fsync(fd); + ioctl(fd, BLKRRPART, 0); + return 0; +} + +static void getinfo_mbr(struct supertype *st, struct mdinfo *info) +{ + struct MBR *sb = st->sb; + int i; + + memset(&info->array, 0, sizeof(info->array)); + memset(&info->disk, 0, sizeof(info->disk)); + strcpy(info->text_version, "mbr"); + strcpy(info->name, "mbr"); + info->component_size = 0; + + for (i = 0; i < MBR_PARTITIONS ; i++) + if (sb->parts[i].blocks_num) { + unsigned long last = + (unsigned long)__le32_to_cpu(sb->parts[i].blocks_num) + + (unsigned long)__le32_to_cpu(sb->parts[i].first_sect_lba); + if (last > info->component_size) + info->component_size = last; + } + +} + +static struct supertype *match_metadata_desc(char *arg) +{ + struct supertype *st = malloc(sizeof(*st)); + + if (!st) + return st; + if (strcmp(arg, "mbr") != 0) + return NULL; + + st->ss = &mbr; + st->info = NULL; + st->minor_version = 0; + st->max_devs = 1; + st->sb = NULL; + return st; +} + +#ifndef MDASSEMBLE +static int validate_geometry(struct supertype *st, int level, + int layout, int raiddisks, + int chunk, unsigned long long size, + char *subdev, unsigned long long *freesize, + int verbose) +{ + fprintf(stderr, Name ": mbr metadata cannot be used this way\n"); + return 0; +} +#endif + +struct superswitch mbr = { +#ifndef MDASSEMBLE + .examine_super = examine_mbr, +#endif + .validate_geometry = validate_geometry, + .match_metadata_desc = match_metadata_desc, + .load_super = load_super_mbr, + .store_super = store_mbr, + .getinfo_super = getinfo_mbr, + .free_super = free_mbr, + .name = "mbr", +}; diff --git a/util.c b/util.c index c9bdd6eb..c93b0a7a 100644 --- a/util.c +++ b/util.c @@ -65,55 +65,7 @@ struct blkpg_partition { char volname[BLKPG_VOLNAMELTH]; /* volume label */ }; -/* partition table structures so we can check metadata position - * against the end of the last partition. - * Only handle MBR ant GPT partition tables. - */ -struct MBR_part_record { - __u8 bootable; - __u8 first_head; - __u8 first_sector; - __u8 first_cyl; - __u8 part_type; - __u8 last_head; - __u8 last_sector; - __u8 last_cyl; - __u32 first_sect_lba; - __u32 blocks_num; -}; - -struct MBR { - __u8 pad[446]; - struct MBR_part_record parts[4]; - __u16 magic; -} __attribute__((packed)); - -struct GPT_part_entry { - unsigned char type_guid[16]; - unsigned char partition_guid[16]; - __u64 starting_lba; - __u64 ending_lba; - unsigned char attr_bits[8]; - unsigned char name[72]; -} __attribute__((packed)); - -struct GPT { - __u64 magic; - __u32 revision; - __u32 header_size; - __u32 crc; - __u32 pad1; - __u64 current_lba; - __u64 backup_lba; - __u64 first_lba; - __u64 last_lba; - __u8 guid[16]; - __u64 part_start; - __u32 part_cnt; - __u32 part_size; - __u32 part_crc; - __u8 pad2[420]; -} __attribute__((packed)); +#include "part.h" /* Force a compilation error if condition is true */ #define BUILD_BUG_ON(condition) ((void)BUILD_BUG_ON_ZERO(condition)) @@ -124,14 +76,6 @@ struct GPT { aren't permitted). */ #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) - -/* MBR/GPT magic numbers */ -#define MBR_SIGNATURE_MAGIC __cpu_to_le16(0xAA55) -#define GPT_SIGNATURE_MAGIC __cpu_to_le64(0x5452415020494645ULL) - -#define MBR_PARTITIONS 4 -#define MBR_GPT_PARTITION_TYPE 0xEE - /* * Parse a 128 bit uuid in 4 integers * format is 32 hexx nibbles with options :. separator @@ -1049,7 +993,12 @@ void wait_for(char *dev, int fd) dprintf("%s: timeout waiting for %s\n", __func__, dev); } -struct superswitch *superlist[] = { &super0, &super1, &super_ddf, &super_imsm, NULL }; +struct superswitch *superlist[] = +{ + &super0, &super1, + &super_ddf, &super_imsm, + &mbr, + NULL }; #if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO)