mdadm-1.6.0
[thirdparty/mdadm.git] / Create.c
1 /*
2  * mdadm - manage Linux "md" devices aka RAID arrays.
3  *
4  * Copyright (C) 2001-2002 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 "mdadm.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, unsigned long size, int raiddisks, int sparedisks,
36            int subdevs, mddev_dev_t devlist,
37            int runstop, int verbose, int force)
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         unsigned long minsize=0, maxsize=0;
56         char *mindisc = NULL;
57         char *maxdisc = NULL;
58         int dnum;
59         mddev_dev_t dv;
60         int fail=0, warn=0;
61         struct stat stb;
62         int first_missing = MD_SB_DISKS*2;
63         int missing_disks = 0;
64         int insert_point = MD_SB_DISKS*2; /* where to insert a missing drive */
65         mddev_dev_t moved_disk = NULL; /* the disk that was moved out of the insert point */
66
67         mdu_array_info_t array;
68         
69
70         if (md_get_version(mdfd) < 9000) {
71                 fprintf(stderr, Name ": Create requires md driver version 0.90.0 or later\n");
72                 return 1;
73         }
74         if (level == UnSet) {
75                 fprintf(stderr,
76                         Name ": a RAID level is needed to create an array.\n");
77                 return 1;
78         }
79         if (raiddisks < 1) {
80                 fprintf(stderr,
81                         Name ": a number of --raid-devices must be given to create an array\n");
82                 return 1;
83         }
84         if (raiddisks < 4 && level == 6) {
85                 fprintf(stderr,
86                         Name ": at least 4 raid-devices needed for level 6\n");
87                 return 1;
88         }
89         if (raiddisks > 256 && level == 6) {
90                 fprintf(stderr,
91                         Name ": no more than 256 raid-devices supported for level 6\n");
92                 return 1;
93         }
94         if (raiddisks < 2 && level >= 4) {
95                 fprintf(stderr,
96                         Name ": at least 2 raid-devices needed for level 4 or 5\n");
97                 return 1;
98         }
99         if (raiddisks+sparedisks > MD_SB_DISKS) {
100                 fprintf(stderr,
101                         Name ": too many devices requested: %d+%d > %d\n",
102                         raiddisks, sparedisks, MD_SB_DISKS);
103                 return 1;
104         }
105         if (subdevs > raiddisks+sparedisks) {
106                 fprintf(stderr, Name ": You have listed more devices (%d) than are in the array(%d)!\n", subdevs, raiddisks+sparedisks);
107                 return 1;
108         }
109         if (subdevs < raiddisks+sparedisks) {
110                 fprintf(stderr, Name ": You haven't given enough devices (real or missing) to create this array\n");
111                 return 1;
112         }
113
114         /* now set some defaults */
115         if (layout == UnSet)
116                 switch(level) {
117                 default: /* no layout */
118                         layout = 0;
119                         break;
120                 case 5:
121                 case 6:
122                         layout = map_name(r5layout, "default");
123                         if (verbose)
124                                 fprintf(stderr,
125                                         Name ": layout defaults to %s\n", map_num(r5layout, layout));
126                         break;
127                 }
128
129         switch(level) {
130         case 4:
131         case 5:
132         case 6:
133         case 0:
134         case -1: /* linear */
135                 if (chunk == 0) {
136                         chunk = 64;
137                         if (verbose)
138                                 fprintf(stderr, Name ": chunk size defaults to 64K\n");
139                 }
140                 break;
141         default: /* raid1, multipath */
142                 if (chunk) {
143                         chunk = 0;
144                         if (verbose)
145                                 fprintf(stderr, Name ": chunk size ignored for this level\n");
146                 }
147                 break;
148         }
149
150         /* now look at the subdevs */
151         array.active_disks = 0;
152         array.working_disks = 0;
153         dnum = 0;
154         for (dv=devlist; dv; dv=dv->next, dnum++) {
155                 char *dname = dv->devname;
156                 unsigned long dsize, freesize;
157                 int fd;
158                 if (strcasecmp(dname, "missing")==0) {
159                         if (first_missing > dnum)
160                                 first_missing = dnum;
161                         missing_disks ++;
162                         continue;
163                 }
164                 array.working_disks++;
165                 if (dnum < raiddisks)
166                         array.active_disks++;
167                 fd = open(dname, O_RDONLY, 0);
168                 if (fd <0 ) {
169                         fprintf(stderr, Name ": Cannot open %s: %s\n",
170                                 dname, strerror(errno));
171                         fail=1;
172                         continue;
173                 }
174                 if (ioctl(fd, BLKGETSIZE, &dsize)) {
175                         fprintf(stderr, Name ": Cannot get size of %s: %s\n",
176                                 dname, strerror(errno));
177                         fail = 1;
178                         close(fd);
179                         continue;
180                 }
181                 if (dsize < MD_RESERVED_SECTORS*2) {
182                         fprintf(stderr, Name ": %s is too small: %luK\n",
183                                 dname, dsize/2);
184                         fail = 1;
185                         close(fd);
186                         continue;
187                 }
188                 freesize = MD_NEW_SIZE_SECTORS(dsize);
189                 freesize /= 2;
190
191                 if (size && freesize < size) {
192                         fprintf(stderr, Name ": %s is smaller that given size."
193                                 " %luK < %luK + superblock\n", dname, freesize, size);
194                         fail = 1;
195                         close(fd);
196                         continue;
197                 }
198                 if (maxdisc == NULL || (maxdisc && freesize > maxsize)) {
199                         maxdisc = dname;
200                         maxsize = freesize;
201                 }
202                 if (mindisc ==NULL || (mindisc && freesize < minsize)) {
203                         mindisc = dname;
204                         minsize = freesize;
205                 }
206                 warn |= check_ext2(fd, dname);
207                 warn |= check_reiser(fd, dname);
208                 warn |= check_raid(fd, dname);
209                 close(fd);
210         }
211         if (fail) {
212                 fprintf(stderr, Name ": create aborted\n");
213                 return 1;
214         }
215         if (size == 0) {
216                 if (mindisc == NULL) {
217                         fprintf(stderr, Name ": no size and no drives given - aborting create.\n");
218                         return 1;
219                 }
220                 size = minsize;
221                 if (verbose && level>0)
222                         fprintf(stderr, Name ": size set to %luK\n", size);
223         }
224         if (level >= 1 && ((maxsize-size)*100 > maxsize)) {
225                 fprintf(stderr, Name ": largest drive (%s) exceed size (%luK) by more than 1%%\n",
226                         maxdisc, size);
227                 warn = 1;
228         }
229
230         if (warn) {
231                 if (runstop!= 1) {
232                         if (!ask("Continue creating array? ")) {
233                                 fprintf(stderr, Name ": create aborted.\n");
234                                 return 1;
235                         }
236                 } else {
237                         if (verbose)
238                                 fprintf(stderr, Name ": creation continuing despite oddities due to --run\n");
239                 }
240         }
241
242         /* If this is  raid5, we want to configure the last active slot
243          * as missing, so that a reconstruct happens (faster than re-parity)
244          * FIX: Can we do this for raid6 as well?
245          */
246         if (force == 0 && first_missing >= raiddisks) {
247                 switch ( level ) {
248                 case 5:
249                         insert_point = raiddisks-1;
250                         sparedisks++;
251                         array.active_disks--;
252                         missing_disks++;
253                         break;
254                 default:
255                         break;
256                 }
257         }
258         
259         /* Ok, lets try some ioctls */
260
261         array.level = level;
262         array.size = size;
263         array.raid_disks = raiddisks;
264         /* The kernel should *know* what md_minor we are dealing
265          * with, but it chooses to trust me instead. Sigh
266          */
267         array.md_minor = 0;
268         if (fstat(mdfd, &stb)==0)
269                 array.md_minor = MINOR(stb.st_rdev);
270         array.not_persistent = 0;
271         /*** FIX: Need to do something about RAID-6 here ***/
272         if ( (level == 5 || level == 6) &&
273              (insert_point < raiddisks || first_missing < raiddisks) )
274                 array.state = 1; /* clean, but one+ drive will be missing */
275         else
276                 array.state = 0; /* not clean, but no errors */
277
278         /* There is lots of redundancy in these disk counts,
279          * raid_disks is the most meaningful value
280          *          it describes the geometry of the array
281          *          it is constant
282          * nr_disks is total number of used slots.
283          *          it should be raid_disks+spare_disks
284          * spare_disks is the number of extra disks present
285          *          see above
286          * active_disks is the number of working disks in
287          *          active slots. (With raid_disks)
288          * working_disks is the total number of working disks,
289          *          including spares
290          * failed_disks is the number of disks marked failed
291          *
292          * Ideally, the kernel would keep these (except raid_disks)
293          * up-to-date as we ADD_NEW_DISK, but it doesn't (yet).
294          * So for now, we assume that all raid and spare
295          * devices will be given.
296          */
297         array.spare_disks=sparedisks;
298         array.failed_disks=missing_disks;
299         array.nr_disks = array.working_disks + array.failed_disks;
300         array.layout = layout;
301         array.chunk_size = chunk*1024;
302
303         if (ioctl(mdfd, SET_ARRAY_INFO, &array)) {
304                 fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
305                         mddev, strerror(errno));
306                 return 1;
307         }
308         
309         for (dnum=0, dv = devlist ; dv ; dv=(dv->next)?(dv->next):moved_disk, dnum++) {
310                 int fd;
311                 struct stat stb;
312                 mdu_disk_info_t disk;
313
314                 disk.number = dnum;
315                 if (dnum == insert_point) {
316                         moved_disk = dv;
317                 }
318                 disk.raid_disk = disk.number;
319                 if (disk.raid_disk < raiddisks)
320                         disk.state = 6; /* active and in sync */
321                 else
322                         disk.state = 0;
323                 if (dnum == insert_point ||
324                     strcasecmp(dv->devname, "missing")==0) {
325                         disk.major = 0;
326                         disk.minor = 0;
327                         disk.state = 1; /* faulty */
328                 } else {
329                         fd = open(dv->devname, O_RDONLY, 0);
330                         if (fd < 0) {
331                                 fprintf(stderr, Name ": failed to open %s after earlier success - aborting\n",
332                                         dv->devname);
333                                 return 1;
334                         }
335                         fstat(fd, &stb);
336                         disk.major = MAJOR(stb.st_rdev);
337                         disk.minor = MINOR(stb.st_rdev);
338                         close(fd);
339                 }
340                 if (ioctl(mdfd, ADD_NEW_DISK, &disk)) {
341                         fprintf(stderr, Name ": ADD_NEW_DISK for %s failed: %s\n",
342                                 dv->devname, strerror(errno));
343                         return 1;
344                 }
345                 if (dv == moved_disk && dnum != insert_point) break;
346         }
347
348         /* param is not actually used */
349         if (runstop == 1 || subdevs >= raiddisks) {
350                 mdu_param_t param;
351                 if (ioctl(mdfd, RUN_ARRAY, &param)) {
352                         fprintf(stderr, Name ": RUN_ARRAY failed: %s\n",
353                                 strerror(errno));
354                         Manage_runstop(mddev, mdfd, -1);
355                         return 1;
356                 }
357                 fprintf(stderr, Name ": array %s started.\n", mddev);
358         } else {
359                 fprintf(stderr, Name ": not starting array - not enough devices.\n");
360         }
361         return 0;
362 }