mdctl-v0.4.1
[thirdparty/mdadm.git] / Create.c
1 /*
2  * mdctl - manage Linux "md" devices aka RAID arrays.
3  *
4  * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
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: <neilb@cse.unsw.edu.au>
23  *    Paper: Neil Brown
24  *           School of Computer Science and Engineering
25  *           The University of New South Wales
26  *           Sydney, 2052
27  *           Australia
28  */
29
30 #include "mdctl.h"
31 #include        "md_u.h"
32 #include        "md_p.h"
33
34 int Create(char *mddev, int mdfd,
35            int chunk, int level, int layout, int size, int raiddisks, int sparedisks,
36            int subdevs, char *subdev[],
37            int runstop, int verbose)
38 {
39         /*
40          * Create a new raid array.
41          *
42          * First check that necessary details are available
43          * (i.e. level, raid-disks)
44          *
45          * Then check each disk to see what might be on it
46          * and report anything interesting.
47          *
48          * If anything looks odd, and runstop not set,
49          * abort.
50          *
51          * SET_ARRAY_INFO and ADD_NEW_DISK, and
52          * if runstop==run, or raiddisks diskswere used,
53          * RUN_ARRAY
54          */
55         int minsize, maxsize;
56         int maxdisc= -1, mindisc = -1;
57         int i;
58         int fail=0, warn=0;
59         struct stat stb;
60
61         mdu_array_info_t array;
62         
63
64         if (md_get_version(mdfd) < 9000) {
65             fprintf(stderr, Name ": Create requires md driver verison 0.90.0 or later\n");
66             return 1;
67         }
68         if (level == -10) {
69                 fprintf(stderr,
70                         Name ": a RAID level is needed to create an array.\n");
71                 return 1;
72         }
73         if (raiddisks < 1) {
74                 fprintf(stderr,
75                         Name ": a number of --raid-disks must be given to create an array\n");
76                 return 1;
77         }
78         if (raiddisks+sparedisks > MD_SB_DISKS) {
79                 fprintf(stderr,
80                         Name ": too many discs requested: %d+%d > %d\n",
81                         raiddisks, sparedisks, MD_SB_DISKS);
82                 return 1;
83         }
84         if (subdevs > raiddisks+sparedisks) {
85             fprintf(stderr, Name ": You have listed more disks (%d) than are in the array(%d)!\n", subdevs, raiddisks+sparedisks);
86             return 1;
87         }
88         /* now set some defaults */
89         if (layout == -1)
90                 switch(level) {
91                 default: /* no layout */
92                         layout = 0;
93                         break;
94                 case 5:
95                         layout = map_name(r5layout, "default");
96                         if (verbose)
97                                 fprintf(stderr,
98                                         Name ": layout defaults to %s\n", map_num(r5layout, layout));
99                         break;
100                 }
101
102         if (chunk == 0) {
103                 chunk = 64;
104                 if (verbose)
105                         fprintf(stderr, Name ": chunk size defaults to 64K\n");
106         }
107
108         /* now look at the subdevs */
109         for (i=0; i<subdevs; i++) {
110                 char *dname = subdev[i];
111                 int dsize, freesize;
112                 int fd = open(dname, O_RDONLY, 0);
113                 if (fd <0 ) {
114                         fprintf(stderr, Name ": Cannot open %s: %s\n",
115                                 dname, strerror(errno));
116                         fail=1;
117                         continue;
118                 }
119                 if (ioctl(fd, BLKGETSIZE, &dsize)) {
120                         fprintf(stderr, Name ": Cannot get size of %s: %s\n",
121                                 dname, strerror(errno));
122                         fail = 1;
123                         close(fd);
124                         continue;
125                 }
126                 if (dsize < MD_RESERVED_SECTORS*2) {
127                     fprintf(stderr, Name ": %s is too small: %dK\n",
128                             dname, dsize/2);
129                     fail = 1;
130                     close(fd);
131                     continue;
132                 }
133                 freesize = MD_NEW_SIZE_SECTORS(dsize);
134                 freesize /= 2;
135
136                 if (size && freesize < size) {
137                     fprintf(stderr, Name ": %s is smaller that given size."
138                             " %dK < %dK + superblock\n", dname, freesize, size);
139                     fail = 1;
140                     close(fd);
141                     continue;
142                 }
143                 if (maxdisc< 0 || (maxdisc>=0 && freesize > maxsize)) {
144                     maxdisc = i;
145                     maxsize = freesize;
146                 }
147                 if (mindisc < 0 || (mindisc >=0 && freesize < minsize)) {
148                     mindisc = i;
149                     minsize = freesize;
150                 }
151                 warn |= check_ext2(fd, dname);
152                 warn |= check_reiser(fd, dname);
153                 warn |= check_raid(fd, dname);
154                 close(fd);
155         }
156         if (fail) {
157             fprintf(stderr, Name ": create aborted\n");
158             return 1;
159         }
160         if (size == 0) {
161             if (mindisc == -1) {
162                 fprintf(stderr, Name ": no size and no drives given - aborting create.\n");
163                 return 1;
164             }
165             size = minsize;
166             if (verbose)
167                 fprintf(stderr, Name ": size set to %dK\n", size);
168         }
169         if ((maxsize-size)*100 > maxsize) {
170             fprintf(stderr, Name ": largest drive (%s) exceed size (%dK) by more than 1%\n",
171                     subdev[maxdisc], size);
172             warn = 1;
173         }
174
175         if (warn) {
176             if (runstop!= 1) {
177                 if (!ask("Continue creating array? ")) {
178                     fprintf(stderr, Name ": create aborted.\n");
179                     return 1;
180                 }
181             } else {
182                 if (verbose)
183                     fprintf(stderr, Name ": creation continuing despite oddities due to --run\n");
184             }
185         }
186
187         /* Ok, lets try some ioctls */
188
189         array.level = level;
190         array.size = size;
191         array.nr_disks = raiddisks+sparedisks+(level==4||level==5);
192         array.raid_disks = raiddisks;
193         /* The kernel should *know* what md_minor we are dealing
194          * with, but it chooses to trust me instead. Sigh
195          */
196         array.md_minor = 0;
197         if (fstat(mdfd, &stb)==0)
198                 array.md_minor = MINOR(stb.st_rdev);
199         array.not_persistent = 0;
200         if (level == 4 || level == 5)
201             array.state = 1; /* clean, but one drive will be missing */
202         else
203             array.state = 0; /* not clean, but no errors */
204
205         /* There is lots of redundancy in these disk counts,
206          * raid_disks is the most meaningful value
207          *          it describes the geometry of the array
208          *          it is constant
209          * nr_disks is total number of used slots.
210          *          it should be raid_disks+spare_disks
211          * spare_disks is the number of extra disks present
212          *          see above
213          * active_disks is the number of working disks in
214          *          active slots. (With raid_disks)
215          * working_disks is the total number of working disks,
216          *          including spares
217          * failed_disks is the number of disks marked failed
218          *
219          * Ideally, the kernel would keep these (except raid_disks)
220          * up-to-date as we ADD_NEW_DISK, but it doesn't (yet).
221          * So for now, we assume that all raid and spare
222          * devices will be given.
223          */
224         array.active_disks=raiddisks-(level==4||level==5);
225         array.working_disks=raiddisks+sparedisks;
226         array.spare_disks=sparedisks + (level==4||level==5);
227         array.failed_disks=0;
228         array.layout = layout;
229         array.chunk_size = chunk*1024;
230
231         if (ioctl(mdfd, SET_ARRAY_INFO, &array)) {
232             fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
233                     mddev, strerror(errno));
234             return 1;
235         }
236         
237         for (i=0; i<subdevs; i++) {
238             int fd = open(subdev[i], O_RDONLY, 0);
239             struct stat stb;
240             mdu_disk_info_t disk;
241             if (fd < 0) {
242                 fprintf(stderr, Name ": failed to open %s after earlier success - aborting\n",
243                         subdev[i]);
244                 return 1;
245             }
246             fstat(fd, &stb);
247             disk.number = i;
248             if ((level==4 || level==5) &&
249                 disk.number >= raiddisks-1)
250                 disk.number++;
251             disk.raid_disk = disk.number;
252             if (disk.raid_disk < raiddisks)
253                 disk.state = 6; /* active and in sync */
254             else
255                 disk.state = 0;
256             disk.major = MAJOR(stb.st_rdev);
257             disk.minor = MINOR(stb.st_rdev);
258             close(fd);
259             if (ioctl(mdfd, ADD_NEW_DISK, &disk)) {
260                 fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\n",
261                         subdev[i], strerror(errno));
262                 return 1;
263             }
264         }
265
266         /* hack */
267         if (level==4 || level==5) {
268                 mdu_disk_info_t disk;
269                 disk.number = raiddisks-1;
270                 disk.raid_disk = disk.number;
271                 disk.state = 1; /* faulty */
272                 disk.major = disk.minor = 0;
273                 ioctl(mdfd,ADD_NEW_DISK, &disk);
274         }
275
276         /* param is not actually used */
277         if (runstop == 1 || subdevs >= raiddisks) {
278                 mdu_param_t param;
279                 if (ioctl(mdfd, RUN_ARRAY, &param)) {
280                         fprintf(stderr, Name ": RUN_ARRAY failed: %s\n",
281                                 strerror(errno));
282                         return 1;
283                 }
284                 fprintf(stderr, Name ": array %s started.\n", mddev);
285         } else {
286                 fprintf(stderr, Name ": not starting array - not enough discs.\n");
287         }
288         return 0;
289 }