]> git.neil.brown.name Git - mdadm.git/blob - super-gpt.c
Introduce stat2kname() and fd2kname()
[mdadm.git] / super-gpt.c
1 /*
2  * mdadm - manage Linux "md" devices aka RAID arrays.
3  *
4  * Copyright (C) 2010 Neil Brown <neilb@suse.de>
5  *
6  *
7  *    This program is free software; you can redistribute it and/or modify
8  *    it under the terms of the GNU General Public License as published by
9  *    the Free Software Foundation; either version 2 of the License, or
10  *    (at your option) any later version.
11  *
12  *    This program is distributed in the hope that it will be useful,
13  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *    GNU General Public License for more details.
16  *
17  *    You should have received a copy of the GNU General Public License
18  *    along with this program; if not, write to the Free Software
19  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  *    Author: Neil Brown
22  *    Email: <neil@brown.name>
23  *
24  */
25
26 /*
27  * 'gpt' is a pseudo metadata type for devices which have a
28  * GPT partition table.
29  *
30  * Obviously arrays cannot be created or assembled for this type.
31  * It is used to allow a new bare device to have an partition table
32  * added so the member partitions can then be included in other
33  * arrays as relevant.
34  *
35  * The meaning operations are:
36  * examine_super, but not brief_examine_super or export_examine
37  * load_super
38  * store_super
39  */
40
41 #include "mdadm.h"
42 #include "part.h"
43
44 static void free_gpt(struct supertype *st)
45 {
46         free(st->sb);
47         st->sb = NULL;
48 }
49
50 #ifndef MDASSEMBLE
51 static void examine_gpt(struct supertype *st, char *homehost)
52 {
53         struct GPT *gpt = st->sb + 512;
54         struct GPT_part_entry *gpe = st->sb + 1024;
55         unsigned int i;
56
57         printf("    GPT Magic : %llx\n", (unsigned long long)__le64_to_cpu(gpt->magic));
58         printf(" GPT Revision : %ld\n", (long)__le32_to_cpu(gpt->revision));
59         for (i = 0; i < __le32_to_cpu(gpt->part_cnt); i++) {
60                 printf("  Partition[%02d] : %12llu sectors at %12llu\n",
61                        i,
62                        (unsigned long long)__le64_to_cpu(gpe[i].starting_lba),
63                        (unsigned long long)__le64_to_cpu(gpe[i].ending_lba)-
64                        (unsigned long long)__le64_to_cpu(gpe[i].starting_lba)
65                        +1
66                         );
67         }
68 }
69 #endif /* MDASSEMBLE */
70
71 static int load_gpt(struct supertype *st, int fd, char *devname)
72 {
73         struct MBR *super;
74         struct GPT *gpt_head;
75         int to_read;
76
77         free_gpt(st);
78
79         if (posix_memalign((void**)&super, 4096, 32*512) != 0) {
80                 pr_err("could not allocate superblock\n");
81                 return 1;
82         }
83
84         lseek(fd, 0, 0);
85         if (read(fd, super, sizeof(*super)) != sizeof(*super)) {
86         no_read:
87                 if (devname)
88                         pr_err("Cannot read partition table on %s\n",
89                                 devname);
90                 free(super);
91                 return 1;
92         }
93
94         if (super->magic != MBR_SIGNATURE_MAGIC ||
95             super->parts[0].part_type != MBR_GPT_PARTITION_TYPE) {
96         not_found:
97                 if (devname)
98                         pr_err("No partition table found on %s\n",
99                                 devname);
100                 free(super);
101                 return 1;
102         }
103         /* Seem to have GPT, load the header */
104         gpt_head = (struct GPT*)(super+1);
105         if (read(fd, gpt_head, sizeof(*gpt_head)) != sizeof(*gpt_head))
106                 goto no_read;
107         if (gpt_head->magic != GPT_SIGNATURE_MAGIC)
108                 goto not_found;
109         if (__le32_to_cpu(gpt_head->part_cnt) >= 128)
110                 goto not_found;
111
112         to_read = __le32_to_cpu(gpt_head->part_cnt) * sizeof(struct GPT_part_entry);
113         to_read =  ((to_read+511)/512) * 512;
114         if (read(fd, gpt_head+1, to_read) != to_read)
115                 goto no_read;
116
117         st->sb = super;
118
119         if (st->ss == NULL) {
120                 st->ss = &gpt;
121                 st->minor_version = 0;
122                 st->max_devs = 1;
123                 st->info = NULL;
124         }
125         return 0;
126 }
127
128 static int store_gpt(struct supertype *st, int fd)
129 {
130         /* FIXME should I save the boot loader */
131         /* need to write two copies! */
132         /* FIXME allow for blocks != 512 bytes
133          *etc
134          */
135         struct MBR *super = st->sb;
136         struct GPT *gpt;
137         int to_write;
138
139         gpt = (struct GPT*)(super+1);
140
141         to_write = __le32_to_cpu(gpt->part_cnt) * sizeof(struct GPT_part_entry);
142         to_write =  ((to_write+511)/512) * 512;
143
144         lseek(fd, 0, 0);
145         if (write(fd, st->sb, to_write) != to_write)
146                 return 4;
147
148         fsync(fd);
149         ioctl(fd, BLKRRPART, 0);
150         return 0;
151 }
152
153 static void getinfo_gpt(struct supertype *st, struct mdinfo *info, char *map)
154 {
155         struct GPT *gpt = st->sb + 512;
156         struct GPT_part_entry *gpe = st->sb + 1024;
157         unsigned int i;
158
159         memset(&info->array, 0, sizeof(info->array));
160         memset(&info->disk, 0, sizeof(info->disk));
161         strcpy(info->text_version, "gpt");
162         strcpy(info->name, "gpt");
163         info->component_size = 0;
164
165         for (i = 0; i < __le32_to_cpu(gpt->part_cnt); i++) {
166                 unsigned long long last =
167                         (unsigned long long)__le64_to_cpu(gpe[i].ending_lba);
168                 if (last > info->component_size)
169                         info->component_size = last;
170         }
171 }
172
173 static struct supertype *match_metadata_desc(char *arg)
174 {
175         struct supertype *st = xmalloc(sizeof(*st));
176
177         if (!st)
178                 return st;
179         if (strcmp(arg, "gpt") != 0) {
180                 free(st);
181                 return NULL;
182         }
183
184         st->ss = &gpt;
185         st->info = NULL;
186         st->minor_version = 0;
187         st->max_devs = 1;
188         st->sb = NULL;
189         return st;
190 }
191
192 #ifndef MDASSEMBLE
193 static int validate_geometry(struct supertype *st, int level,
194                              int layout, int raiddisks,
195                              int *chunk, unsigned long long size,
196                              unsigned long long data_offset,
197                              char *subdev, unsigned long long *freesize,
198                              int verbose)
199 {
200         pr_err("gpt metadata cannot be used this way\n");
201         return 0;
202 }
203 #endif
204
205 struct superswitch gpt = {
206 #ifndef MDASSEMBLE
207         .examine_super = examine_gpt,
208         .validate_geometry = validate_geometry,
209 #endif
210         .match_metadata_desc = match_metadata_desc,
211         .load_super = load_gpt,
212         .store_super = store_gpt,
213         .getinfo_super = getinfo_gpt,
214         .free_super = free_gpt,
215         .name = "gpt",
216 };