]>
git.ipfire.org Git - thirdparty/mdadm.git/blob - Create.c
2 * mdctl - manage Linux "md" devices aka RAID arrays.
4 * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
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.
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.
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
22 * Email: <neilb@cse.unsw.edu.au>
24 * School of Computer Science and Engineering
25 * The University of New South Wales
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
)
40 * Create a new raid array.
42 * First check that necessary details are available
43 * (i.e. level, raid-disks)
45 * Then check each disk to see what might be on it
46 * and report anything interesting.
48 * If anything looks odd, and runstop not set,
51 * SET_ARRAY_INFO and ADD_NEW_DISK, and
52 * if runstop==run, or raiddisks diskswere used,
56 int maxdisc
= -1, mindisc
= -1;
61 mdu_array_info_t array
;
64 if (md_get_version(mdfd
) < 9000) {
65 fprintf(stderr
, Name
": Create requires md driver verison 0.90.0 or later\n");
70 Name
": a RAID level is needed to create an array.\n");
75 Name
": a number of --raid-disks must be given to create an array\n");
78 if (raiddisks
+sparedisks
> MD_SB_DISKS
) {
80 Name
": too many discs requested: %d+%d > %d\n",
81 raiddisks
, sparedisks
, MD_SB_DISKS
);
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
);
88 /* now set some defaults */
91 default: /* no layout */
95 layout
= map_name(r5layout
, "default");
98 Name
": layout defaults to %s\n", map_num(r5layout
, layout
));
105 fprintf(stderr
, Name
": chunk size defaults to 64K\n");
108 /* now look at the subdevs */
109 for (i
=0; i
<subdevs
; i
++) {
110 char *dname
= subdev
[i
];
112 int fd
= open(dname
, O_RDONLY
, 0);
114 fprintf(stderr
, Name
": Cannot open %s: %s\n",
115 dname
, strerror(errno
));
119 if (ioctl(fd
, BLKGETSIZE
, &dsize
)) {
120 fprintf(stderr
, Name
": Cannot get size of %s: %s\n",
121 dname
, strerror(errno
));
126 if (dsize
< MD_RESERVED_SECTORS
*2) {
127 fprintf(stderr
, Name
": %s is too small: %dK\n",
133 freesize
= MD_NEW_SIZE_SECTORS(dsize
);
136 if (size
&& freesize
< size
) {
137 fprintf(stderr
, Name
": %s is smaller that given size."
138 " %dK < %dK + superblock\n", dname
, freesize
, size
);
143 if (maxdisc
< 0 || (maxdisc
>=0 && freesize
> maxsize
)) {
147 if (mindisc
< 0 || (mindisc
>=0 && freesize
< minsize
)) {
151 warn
|= check_ext2(fd
, dname
);
152 warn
|= check_reiser(fd
, dname
);
153 warn
|= check_raid(fd
, dname
);
157 fprintf(stderr
, Name
": create aborted\n");
162 fprintf(stderr
, Name
": no size and no drives given - aborting create.\n");
167 fprintf(stderr
, Name
": size set to %dK\n", size
);
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
);
177 if (!ask("Continue creating array? ")) {
178 fprintf(stderr
, Name
": create aborted.\n");
183 fprintf(stderr
, Name
": creation continuing despite oddities due to --run\n");
187 /* Ok, lets try some ioctls */
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
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 */
203 array
.state
= 0; /* not clean, but no errors */
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
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
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,
217 * failed_disks is the number of disks marked failed
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.
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;
231 if (ioctl(mdfd
, SET_ARRAY_INFO
, &array
)) {
232 fprintf(stderr
, Name
": SET_ARRAY_INFO failed for %s: %s\n",
233 mddev
, strerror(errno
));
237 for (i
=0; i
<subdevs
; i
++) {
238 int fd
= open(subdev
[i
], O_RDONLY
, 0);
240 mdu_disk_info_t disk
;
242 fprintf(stderr
, Name
": failed to open %s after earlier success - aborting\n",
248 if ((level
==4 || level
==5) &&
249 disk
.number
>= raiddisks
-1)
251 disk
.raid_disk
= disk
.number
;
252 if (disk
.raid_disk
< raiddisks
)
253 disk
.state
= 6; /* active and in sync */
256 disk
.major
= MAJOR(stb
.st_rdev
);
257 disk
.minor
= MINOR(stb
.st_rdev
);
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
));
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
);
276 /* param is not actually used */
277 if (runstop
== 1 || subdevs
>= raiddisks
) {
279 if (ioctl(mdfd
, RUN_ARRAY
, ¶m
)) {
280 fprintf(stderr
, Name
": RUN_ARRAY failed: %s\n",
284 fprintf(stderr
, Name
": array %s started.\n", mddev
);
286 fprintf(stderr
, Name
": not starting array - not enough discs.\n");