From: NeilBrown Date: Fri, 20 Aug 2010 03:10:50 +0000 (+1000) Subject: Add gpt pseudo-metadata X-Git-Tag: mdadm-3.2~325 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=commitdiff_plain;h=0592faeb5e693d4317fb85d5ab013697a21c301d Add gpt pseudo-metadata This allows mdadm to work with gpt metadata to a limited extent. Signed-off-by: NeilBrown --- diff --git a/Makefile b/Makefile index 75a8a413..40f65af3 100644 --- a/Makefile +++ b/Makefile @@ -99,7 +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 \ + super-mbr.o super-gpt.o \ restripe.o sysfs.o sha1.o mapfile.o crc32.o sg_io.o msg.o \ platform-intel.o probe_roms.o @@ -107,7 +107,7 @@ 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 \ + super-mbr.c super-gpt.c \ restripe.c sysfs.c sha1.c mapfile.c crc32.c sg_io.c msg.c \ platform-intel.c probe_roms.c @@ -115,13 +115,13 @@ 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-mbr.o super-gpt.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-mbr.c super-gpt.c \ super-ddf.c sha1.c crc32.c msg.c bitmap.c \ platform-intel.c probe_roms.c @@ -130,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 super-mbr.c + platform-intel.c probe_roms.c sysfs.c super-mbr.c super-gpt.c ASSEMBLE_AUTO_SRCS := mdopen.c ASSEMBLE_FLAGS:= $(CFLAGS) -DMDASSEMBLE ifdef MDASSEMBLE_AUTO diff --git a/mdadm.h b/mdadm.h index f16cd7c0..08e45440 100644 --- a/mdadm.h +++ b/mdadm.h @@ -675,7 +675,7 @@ extern struct superswitch { extern struct superswitch super0, super1; extern struct superswitch super_imsm, super_ddf; -extern struct superswitch mbr; +extern struct superswitch mbr, gpt; struct metadata_update { int len; diff --git a/super-gpt.c b/super-gpt.c new file mode 100644 index 00000000..982b4e9b --- /dev/null +++ b/super-gpt.c @@ -0,0 +1,219 @@ +/* + * 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: + * + */ + +/* + * 'gpt' is a pseudo metadata type for devices which have a + * GPT 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_gpt(struct supertype *st) +{ + free(st->sb); + st->sb = NULL; +} + +#ifndef MDASSEMBLE +static void examine_gpt(struct supertype *st, char *homehost) +{ + struct GPT *gpt = st->sb + 512; + struct GPT_part_entry *gpe = st->sb + 1024; + unsigned int i; + + printf(" GPT Magic : %llx\n", (unsigned long long)__le64_to_cpu(gpt->magic)); + printf(" GPT Revision : %ld\n", (long)__le32_to_cpu(gpt->revision)); + for (i = 0; i < __le32_to_cpu(gpt->part_cnt); i++) { + printf(" Partition[%02d] : %12llu sectors at %12llu\n", + i, + (unsigned long long)__le64_to_cpu(gpe[i].starting_lba), + (unsigned long long)__le64_to_cpu(gpe[i].ending_lba)- + (unsigned long long)__le64_to_cpu(gpe[i].starting_lba) + +1 + ); + } +} +#endif /* MDASSEMBLE */ + +static int load_gpt(struct supertype *st, int fd, char *devname) +{ + struct MBR *super; + struct GPT *gpt_head; + int to_read; + + free_gpt(st); + + if (st->subarray[0]) + return 1; + + if (posix_memalign((void**)&super, 512, 32*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)) { + no_read: + if (devname) + fprintf(stderr, Name ": Cannot read partition table on %s\n", + devname); + free(super); + return 1; + } + + if (super->magic != MBR_SIGNATURE_MAGIC || + super->parts[0].part_type != MBR_GPT_PARTITION_TYPE) { + not_found: + if (devname) + fprintf(stderr, Name ": No partition table found on %s\n", + devname); + free(super); + return 1; + } + /* Seem to have GPT, load the header */ + gpt_head = (struct GPT*)(super+1); + if (read(fd, gpt_head, sizeof(*gpt_head)) != sizeof(*gpt_head)) + goto no_read; + if (gpt_head->magic != GPT_SIGNATURE_MAGIC) + goto not_found; + if (__le32_to_cpu(gpt_head->part_cnt) >= 128) + goto not_found; + + to_read = __le32_to_cpu(gpt_head->part_cnt) * sizeof(struct GPT_part_entry); + to_read = ((to_read+511)/512) * 512; + if (read(fd, gpt_head+1, to_read) != to_read) + goto no_read; + + st->sb = super; + + if (st->ss == NULL) { + st->ss = &gpt; + st->minor_version = 0; + st->max_devs = 1; + st->info = NULL; + } + return 0; +} + +static int store_gpt(struct supertype *st, int fd) +{ + /* FIXME should I save the boot loader */ + /* need to write two copies! */ + /* FIXME allow for blocks != 512 bytes + *etc + */ + struct MBR *super = st->sb; + struct GPT *gpt; + int to_write; + + gpt = (struct GPT*)(super+1); + + to_write = __le32_to_cpu(gpt->part_cnt) * sizeof(struct GPT_part_entry); + to_write = ((to_write+511)/512) * 512; + + lseek(fd, 0, 0); + if (write(fd, st->sb, to_write) != to_write) + return 4; + + fsync(fd); + ioctl(fd, BLKRRPART, 0); + return 0; +} + +static void getinfo_gpt(struct supertype *st, struct mdinfo *info) +{ + struct GPT *gpt = st->sb + 512; + struct GPT_part_entry *gpe = st->sb + 1024; + unsigned int i; + + memset(&info->array, 0, sizeof(info->array)); + memset(&info->disk, 0, sizeof(info->disk)); + strcpy(info->text_version, "gpt"); + strcpy(info->name, "gpt"); + info->component_size = 0; + + for (i = 0; i < __le32_to_cpu(gpt->part_cnt); i++) { + unsigned long long last = + (unsigned long long)__le64_to_cpu(gpe[i].ending_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, "gpt") != 0) + return NULL; + + st->ss = &gpt; + 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 ": gpt metadata cannot be used this way\n"); + return 0; +} +#endif + +struct superswitch gpt = { +#ifndef MDASSEMBLE + .examine_super = examine_gpt, +#endif + .validate_geometry = validate_geometry, + .match_metadata_desc = match_metadata_desc, + .load_super = load_gpt, + .store_super = store_gpt, + .getinfo_super = getinfo_gpt, + .free_super = free_gpt, + .name = "gpt", +}; diff --git a/util.c b/util.c index c93b0a7a..c2169d68 100644 --- a/util.c +++ b/util.c @@ -997,7 +997,7 @@ struct superswitch *superlist[] = { &super0, &super1, &super_ddf, &super_imsm, - &mbr, + &mbr, &gpt, NULL }; #if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO)