Change write_init_super to be called only once.
[thirdparty/mdadm.git] / Manage.c
1 /*
2  * mdadm - manage Linux "md" devices aka RAID arrays.
3  *
4  * Copyright (C) 2001-2006 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: <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 #define REGISTER_DEV            _IO (MD_MAJOR, 1)
35 #define START_MD                _IO (MD_MAJOR, 2)
36 #define STOP_MD                 _IO (MD_MAJOR, 3)
37
38 int Manage_ro(char *devname, int fd, int readonly)
39 {
40         /* switch to readonly or rw
41          *
42          * requires >= 0.90.0
43          * first check that array is runing
44          * use RESTART_ARRAY_RW or STOP_ARRAY_RO
45          *
46          */
47         mdu_array_info_t array;
48
49         if (md_get_version(fd) < 9000) {
50                 fprintf(stderr, Name ": need md driver version 0.90.0 or later\n");
51                 return 1;
52         }
53         if (ioctl(fd, GET_ARRAY_INFO, &array)) {
54                 fprintf(stderr, Name ": %s does not appear to be active.\n",
55                         devname);
56                 return 1;
57         }
58
59         if (readonly>0) {
60                 if (ioctl(fd, STOP_ARRAY_RO, NULL)) {
61                         fprintf(stderr, Name ": failed to set readonly for %s: %s\n",
62                                 devname, strerror(errno));
63                         return 1;
64                 }
65         } else if (readonly < 0) {
66                 if (ioctl(fd, RESTART_ARRAY_RW, NULL)) {
67                         fprintf(stderr, Name ": failed to set writable for %s: %s\n",
68                                 devname, strerror(errno));
69                         return 1;
70                 }
71         }
72         return 0;
73 }
74
75 #ifndef MDASSEMBLE
76
77 int Manage_runstop(char *devname, int fd, int runstop, int quiet)
78 {
79         /* Run or stop the array. array must already be configured
80          * required >= 0.90.0
81          */
82         mdu_param_t param; /* unused */
83
84         if (runstop == -1 && md_get_version(fd) < 9000) {
85                 if (ioctl(fd, STOP_MD, 0)) {
86                         if (!quiet) fprintf(stderr, Name ": stopping device %s failed: %s\n",
87                                             devname, strerror(errno));
88                         return 1;
89                 }
90         }
91
92         if (md_get_version(fd) < 9000) {
93                 fprintf(stderr, Name ": need md driver version 0.90.0 or later\n");
94                 return 1;
95         }
96         /*
97         if (ioctl(fd, GET_ARRAY_INFO, &array)) {
98                 fprintf(stderr, Name ": %s does not appear to be active.\n",
99                         devname);
100                 return 1;
101         }
102         */
103         if (runstop>0) {
104                 if (ioctl(fd, RUN_ARRAY, &param)) {
105                         fprintf(stderr, Name ": failed to run array %s: %s\n",
106                                 devname, strerror(errno));
107                         return 1;
108                 }
109                 if (quiet <= 0)
110                         fprintf(stderr, Name ": started %s\n", devname);
111         } else if (runstop < 0){
112                 struct map_ent *map = NULL;
113                 struct stat stb;
114                 if (ioctl(fd, STOP_ARRAY, NULL)) {
115                         if (quiet==0)
116                                 fprintf(stderr, Name ": fail to stop array %s: %s\n",
117                                         devname, strerror(errno));
118                         return 1;
119                 }
120                 if (quiet <= 0)
121                         fprintf(stderr, Name ": stopped %s\n", devname);
122                 if (fstat(fd, &stb) == 0) {
123                         int devnum;
124                         if (major(stb.st_rdev) == MD_MAJOR)
125                                 devnum = minor(stb.st_rdev);
126                         else
127                                 devnum = -1-(minor(stb.st_rdev)>>6);
128                         map_delete(&map, devnum);
129                         map_write(map);
130                         map_free(map);
131                 }
132         }
133         return 0;
134 }
135
136 int Manage_resize(char *devname, int fd, long long size, int raid_disks)
137 {
138         mdu_array_info_t info;
139         if (ioctl(fd, GET_ARRAY_INFO, &info) != 0) {
140                 fprintf(stderr, Name ": Cannot get array information for %s: %s\n",
141                         devname, strerror(errno));
142                 return 1;
143         }
144         if (size >= 0)
145                 info.size = size;
146         if (raid_disks > 0)
147                 info.raid_disks = raid_disks;
148         if (ioctl(fd, SET_ARRAY_INFO, &info) != 0) {
149                 fprintf(stderr, Name ": Cannot set device size/shape for %s: %s\n",
150                         devname, strerror(errno));
151                 return 1;
152         }
153         return 0;
154 }
155
156 int Manage_reconfig(char *devname, int fd, int layout)
157 {
158         mdu_array_info_t info;
159         if (ioctl(fd, GET_ARRAY_INFO, &info) != 0) {
160                 fprintf(stderr, Name ": Cannot get array information for %s: %s\n",
161                         devname, strerror(errno));
162                 return 1;
163         }
164         info.layout = layout;
165         printf("layout set to %d\n", info.layout);
166         if (ioctl(fd, SET_ARRAY_INFO, &info) != 0) {
167                 fprintf(stderr, Name ": Cannot set layout for %s: %s\n",
168                         devname, strerror(errno));
169                 return 1;
170         }
171         return 0;
172 }
173
174 int Manage_subdevs(char *devname, int fd,
175                    mddev_dev_t devlist, int verbose)
176 {
177         /* do something to each dev.
178          * devmode can be
179          *  'a' - add the device
180          *         try HOT_ADD_DISK
181          *         If that fails EINVAL, try ADD_NEW_DISK
182          *  'r' - remove the device HOT_REMOVE_DISK
183          *        device can be 'faulty' or 'detached' in which case all
184          *        matching devices are removed.
185          *  'f' - set the device faulty SET_DISK_FAULTY
186          *        device can be 'detached' in which case any device that
187          *        is inaccessible will be marked faulty.
188          */
189         mdu_array_info_t array;
190         mdu_disk_info_t disc;
191         unsigned long long array_size;
192         mddev_dev_t dv, next = NULL;
193         struct stat stb;
194         int j, jnext = 0;
195         int tfd;
196         struct supertype *st, *tst;
197         int duuid[4];
198         int ouuid[4];
199
200         if (ioctl(fd, GET_ARRAY_INFO, &array)) {
201                 fprintf(stderr, Name ": cannot get array info for %s\n",
202                         devname);
203                 return 1;
204         }
205
206         /* array.size is only 32 bit and may be truncated.
207          * So read from sysfs if possible, and record number of sectors
208          */
209
210         array_size = get_component_size(fd);
211         if (array_size <= 0)
212                 array_size = array.size * 2;
213
214         tst = super_by_fd(fd);
215         if (!tst) {
216                 fprintf(stderr, Name ": unsupport array - version %d.%d\n",
217                         array.major_version, array.minor_version);
218                 return 1;
219         }
220
221         for (dv = devlist, j=0 ; dv; dv = next, j = jnext) {
222                 unsigned long long ldsize;
223                 char dvname[20];
224                 char *dnprintable = dv->devname;
225
226                 next = dv->next;
227                 jnext = 0;
228
229                 if (strcmp(dv->devname, "failed")==0 ||
230                     strcmp(dv->devname, "faulty")==0) {
231                         if (dv->disposition != 'r') {
232                                 fprintf(stderr, Name ": %s only meaningful "
233                                         "with -r, not -%c\n",
234                                         dv->devname, dv->disposition);
235                                 return 1;
236                         }
237                         for (; j < array.raid_disks + array.nr_disks ; j++) {
238                                 disc.number = j;
239                                 if (ioctl(fd, GET_DISK_INFO, &disc))
240                                         continue;
241                                 if (disc.major == 0 && disc.minor == 0)
242                                         continue;
243                                 if ((disc.state & 1) == 0) /* faulty */
244                                         continue;
245                                 stb.st_rdev = makedev(disc.major, disc.minor);
246                                 next = dv;
247                                 jnext = j+1;
248                                 sprintf(dvname,"%d:%d", disc.major, disc.minor);
249                                 dnprintable = dvname;
250                                 break;
251                         }
252                         if (jnext == 0)
253                                 continue;
254                 } else if (strcmp(dv->devname, "detached") == 0) {
255                         if (dv->disposition != 'r' && dv->disposition != 'f') {
256                                 fprintf(stderr, Name ": %s only meaningful "
257                                         "with -r of -f, not -%c\n",
258                                         dv->devname, dv->disposition);
259                                 return 1;
260                         }
261                         for (; j < array.raid_disks + array.nr_disks; j++) {
262                                 int sfd;
263                                 disc.number = j;
264                                 if (ioctl(fd, GET_DISK_INFO, &disc))
265                                         continue;
266                                 if (disc.major == 0 && disc.minor == 0)
267                                         continue;
268                                 sprintf(dvname,"%d:%d", disc.major, disc.minor);
269                                 sfd = dev_open(dvname, O_RDONLY);
270                                 if (sfd >= 0) {
271                                         close(sfd);
272                                         continue;
273                                 }
274                                 if (dv->disposition == 'f' &&
275                                     (disc.state & 1) == 1) /* already faulty */
276                                         continue;
277                                 if (errno != ENXIO)
278                                         continue;
279                                 stb.st_rdev = makedev(disc.major, disc.minor);
280                                 next = dv;
281                                 jnext = j+1;
282                                 dnprintable = dvname;
283                                 break;
284                         }
285                         if (jnext == 0)
286                                 continue;
287                 } else {
288                         j = 0;
289
290                         if (stat(dv->devname, &stb)) {
291                                 fprintf(stderr, Name ": cannot find %s: %s\n",
292                                         dv->devname, strerror(errno));
293                                 return 1;
294                         }
295                         if ((stb.st_mode & S_IFMT) != S_IFBLK) {
296                                 fprintf(stderr, Name ": %s is not a "
297                                         "block device.\n",
298                                         dv->devname);
299                                 return 1;
300                         }
301                 }
302                 switch(dv->disposition){
303                 default:
304                         fprintf(stderr, Name ": internal error - devmode[%s]=%d\n",
305                                 dv->devname, dv->disposition);
306                         return 1;
307                 case 'a':
308                         /* add the device */
309
310                         /* Make sure it isn't in use (in 2.6 or later) */
311                         tfd = open(dv->devname, O_RDONLY|O_EXCL);
312                         if (tfd < 0) {
313                                 fprintf(stderr, Name ": Cannot open %s: %s\n",
314                                         dv->devname, strerror(errno));
315                                 return 1;
316                         }
317                         remove_partitions(tfd);
318
319                         st = dup_super(tst);
320
321                         if (array.not_persistent==0)
322                                 st->ss->load_super(st, tfd, NULL);
323
324                         if (!get_dev_size(tfd, dv->devname, &ldsize)) {
325                                 close(tfd);
326                                 return 1;
327                         }
328                         close(tfd);
329
330                         if (array.major_version == 0 &&
331                             md_get_version(fd)%100 < 2) {
332                                 if (ioctl(fd, HOT_ADD_DISK,
333                                           (unsigned long)stb.st_rdev)==0) {
334                                         if (verbose >= 0)
335                                                 fprintf(stderr, Name ": hot added %s\n",
336                                                         dv->devname);
337                                         continue;
338                                 }
339
340                                 fprintf(stderr, Name ": hot add failed for %s: %s\n",
341                                         dv->devname, strerror(errno));
342                                 return 1;
343                         }
344
345                         if (array.not_persistent == 0) {
346
347                                 /* Make sure device is large enough */
348                                 if (tst->ss->avail_size(tst, ldsize/512) <
349                                     array_size) {
350                                         fprintf(stderr, Name ": %s not large enough to join array\n",
351                                                 dv->devname);
352                                         return 1;
353                                 }
354
355                                 /* need to find a sample superblock to copy, and
356                                  * a spare slot to use
357                                  */
358                                 for (j = 0; j < tst->max_devs; j++) {
359                                         char *dev;
360                                         int dfd;
361                                         disc.number = j;
362                                         if (ioctl(fd, GET_DISK_INFO, &disc))
363                                                 continue;
364                                         if (disc.major==0 && disc.minor==0)
365                                                 continue;
366                                         if ((disc.state & 4)==0) continue; /* sync */
367                                         /* Looks like a good device to try */
368                                         dev = map_dev(disc.major, disc.minor, 1);
369                                         if (!dev) continue;
370                                         dfd = dev_open(dev, O_RDONLY);
371                                         if (dfd < 0) continue;
372                                         if (tst->ss->load_super(tst, dfd,
373                                                                 NULL)) {
374                                                 close(dfd);
375                                                 continue;
376                                         }
377                                         close(dfd);
378                                         break;
379                                 }
380                                 if (!tst->sb) {
381                                         fprintf(stderr, Name ": cannot find valid superblock in this array - HELP\n");
382                                         return 1;
383                                 }
384                                 /* Possibly this device was recently part of the array
385                                  * and was temporarily removed, and is now being re-added.
386                                  * If so, we can simply re-add it.
387                                  */
388                                 tst->ss->uuid_from_super(tst, duuid);
389
390                                 /* re-add doesn't work for version-1 superblocks
391                                  * before 2.6.18 :-(
392                                  */
393                                 if (array.major_version == 1 &&
394                                     get_linux_version() <= 2006018)
395                                         ;
396                                 else if (st->sb) {
397                                         st->ss->uuid_from_super(st, ouuid);
398                                         if (memcmp(duuid, ouuid, sizeof(ouuid))==0) {
399                                                 /* looks close enough for now.  Kernel
400                                                  * will worry about whether a bitmap
401                                                  * based reconstruction is possible.
402                                                  */
403                                                 struct mdinfo mdi;
404                                                 st->ss->getinfo_super(st, &mdi);
405                                                 disc.major = major(stb.st_rdev);
406                                                 disc.minor = minor(stb.st_rdev);
407                                                 disc.number = mdi.disk.number;
408                                                 disc.raid_disk = mdi.disk.raid_disk;
409                                                 disc.state = mdi.disk.state;
410                                                 if (dv->writemostly)
411                                                         disc.state |= 1 << MD_DISK_WRITEMOSTLY;
412                                                 if (ioctl(fd, ADD_NEW_DISK, &disc) == 0) {
413                                                         if (verbose >= 0)
414                                                                 fprintf(stderr, Name ": re-added %s\n", dv->devname);
415                                                         continue;
416                                                 }
417                                                 /* fall back on normal-add */
418                                         }
419                                 }
420                         } else {
421                                 /* non-persistent. Must ensure that new drive
422                                  * is at least array.size big.
423                                  */
424                                 if (ldsize/512 < array_size) {
425                                         fprintf(stderr, Name ": %s not large enough to join array\n",
426                                                 dv->devname);
427                                         return 1;
428                                 }
429                         }
430                         /* in 2.6.17 and earlier, version-1 superblocks won't
431                          * use the number we write, but will choose a free number.
432                          * we must choose the same free number, which requires
433                          * starting at 'raid_disks' and counting up
434                          */
435                         for (j = array.raid_disks; j< tst->max_devs; j++) {
436                                 disc.number = j;
437                                 if (ioctl(fd, GET_DISK_INFO, &disc))
438                                         break;
439                                 if (disc.major==0 && disc.minor==0)
440                                         break;
441                                 if (disc.state & 8) /* removed */
442                                         break;
443                         }
444                         disc.major = major(stb.st_rdev);
445                         disc.minor = minor(stb.st_rdev);
446                         disc.number =j;
447                         disc.state = 0;
448                         if (array.not_persistent==0) {
449                                 int dfd;
450                                 if (dv->writemostly)
451                                         disc.state |= 1 << MD_DISK_WRITEMOSTLY;
452                                 dfd = open(dv->devname, O_RDWR | O_EXCL);
453                                 tst->ss->add_to_super(tst, &disc, dfd,
454                                                       dv->devname);
455                                 /* write_init_super will close 'dfd' */
456                                 if (tst->ss->write_init_super(tst))
457                                         return 1;
458                         } else if (dv->re_add) {
459                                 /*  this had better be raid1.
460                                  * As we are "--re-add"ing we must find a spare slot
461                                  * to fill.
462                                  */
463                                 char *used = malloc(array.raid_disks);
464                                 memset(used, 0, array.raid_disks);
465                                 for (j=0; j< tst->max_devs; j++) {
466                                         mdu_disk_info_t disc2;
467                                         disc2.number = j;
468                                         if (ioctl(fd, GET_DISK_INFO, &disc2))
469                                                 continue;
470                                         if (disc2.major==0 && disc2.minor==0)
471                                                 continue;
472                                         if (disc2.state & 8) /* removed */
473                                                 continue;
474                                         if (disc2.raid_disk < 0)
475                                                 continue;
476                                         if (disc2.raid_disk > array.raid_disks)
477                                                 continue;
478                                         used[disc2.raid_disk] = 1;
479                                 }
480                                 for (j=0 ; j<array.raid_disks; j++)
481                                         if (!used[j]) {
482                                                 disc.raid_disk = j;
483                                                 disc.state |= (1<<MD_DISK_SYNC);
484                                                 break;
485                                         }
486                         }
487                         if (dv->writemostly)
488                                 disc.state |= (1 << MD_DISK_WRITEMOSTLY);
489                         if (ioctl(fd,ADD_NEW_DISK, &disc)) {
490                                 fprintf(stderr, Name ": add new device failed for %s as %d: %s\n",
491                                         dv->devname, j, strerror(errno));
492                                 return 1;
493                         }
494                         if (verbose >= 0)
495                                 fprintf(stderr, Name ": added %s\n", dv->devname);
496                         break;
497
498                 case 'r':
499                         /* hot remove */
500                         /* FIXME check that it is a current member */
501                         if (ioctl(fd, HOT_REMOVE_DISK, (unsigned long)stb.st_rdev)) {
502                                 fprintf(stderr, Name ": hot remove failed "
503                                         "for %s: %s\n", dnprintable,
504                                         strerror(errno));
505                                 return 1;
506                         }
507                         if (verbose >= 0)
508                                 fprintf(stderr, Name ": hot removed %s\n",
509                                         dnprintable);
510                         break;
511
512                 case 'f': /* set faulty */
513                         /* FIXME check current member */
514                         if (ioctl(fd, SET_DISK_FAULTY, (unsigned long) stb.st_rdev)) {
515                                 fprintf(stderr, Name ": set device faulty failed for %s:  %s\n",
516                                         dnprintable, strerror(errno));
517                                 return 1;
518                         }
519                         if (verbose >= 0)
520                                 fprintf(stderr, Name ": set %s faulty in %s\n",
521                                         dnprintable, devname);
522                         break;
523                 }
524         }
525         return 0;
526
527 }
528
529 int autodetect(void)
530 {
531         /* Open any md device, and issue the RAID_AUTORUN ioctl */
532         int rv = 1;
533         int fd = dev_open("9:0", O_RDONLY);
534         if (fd >= 0) {
535                 if (ioctl(fd, RAID_AUTORUN, 0) == 0)
536                         rv = 0;
537                 close(fd);
538         }
539         return rv;
540 }
541 #endif