]>
git.ipfire.org Git - thirdparty/mdadm.git/blob - Grow.c
2 * mdadm - manage Linux "md" devices aka RAID arrays.
4 * Copyright (C) 2001-2004 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
32 #if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN)
33 #error no endian defined
38 int Grow_Add_device(char *devname
, int fd
, char *newdev
)
40 /* Add a device to an active array.
41 * Currently, just extend a linear array.
42 * This requires writing a new superblock on the
43 * new device, calling the kernel to add the device,
44 * and if that succeeds, update the superblock on
46 * This means that we need to *find* all other devices.
54 struct supertype
*st
= NULL
;
57 if (ioctl(fd
, GET_ARRAY_INFO
, &info
.array
) < 0) {
58 fprintf(stderr
, Name
": cannot get array info for %s\n", devname
);
62 st
= super_by_version(info
.array
.major_version
, info
.array
.minor_version
);
64 fprintf(stderr
, Name
": cannot handle arrays with superblock version %d\n", info
.array
.major_version
);
68 if (info
.array
.level
!= -1) {
69 fprintf(stderr
, Name
": can only add devices to linear arrays\n");
73 nfd
= open(newdev
, O_RDWR
|O_EXCL
);
75 fprintf(stderr
, Name
": cannot open %s\n", newdev
);
79 if ((stb
.st_mode
& S_IFMT
) != S_IFBLK
) {
80 fprintf(stderr
, Name
": %s is not a block device!\n", newdev
);
84 /* now check out all the devices and make sure we can read the superblock */
85 for (d
=0 ; d
< info
.array
.raid_disks
; d
++) {
90 if (ioctl(fd
, GET_DISK_INFO
, &disk
) < 0) {
91 fprintf(stderr
, Name
": cannot get device detail for device %d\n",
95 dv
= map_dev(disk
.major
, disk
.minor
);
97 fprintf(stderr
, Name
": cannot find device file for device %d\n",
101 fd2
= open(dv
, O_RDWR
);
103 fprintf(stderr
, Name
": cannot open device file %s\n", dv
);
106 if (super
) free(super
);
108 if (st
->ss
->load_super(st
, fd2
, &super
, NULL
)) {
109 fprintf(stderr
, Name
": cannot find super block on %s\n", dv
);
115 /* Ok, looks good. Lets update the superblock and write it out to
119 info
.disk
.number
= d
;
120 info
.disk
.major
= major(stb
.st_rdev
);
121 info
.disk
.minor
= minor(stb
.st_rdev
);
122 info
.disk
.raid_disk
= d
;
123 info
.disk
.state
= (1 << MD_DISK_SYNC
) | (1 << MD_DISK_ACTIVE
);
124 st
->ss
->update_super(&info
, super
, "grow", newdev
, 0);
126 if (st
->ss
->store_super(nfd
, super
)) {
127 fprintf(stderr
, Name
": Cannot store new superblock on %s\n", newdev
);
133 if (ioctl(fd
, ADD_NEW_DISK
, &info
.disk
) != 0) {
134 fprintf(stderr
, Name
": Cannot add new disk to this array\n");
137 /* Well, that seems to have worked.
138 * Now go through and update all superblocks
141 if (ioctl(fd
, GET_ARRAY_INFO
, &info
.array
) < 0) {
142 fprintf(stderr
, Name
": cannot get array info for %s\n", devname
);
147 for (d
=0 ; d
< info
.array
.raid_disks
; d
++) {
148 mdu_disk_info_t disk
;
152 if (ioctl(fd
, GET_DISK_INFO
, &disk
) < 0) {
153 fprintf(stderr
, Name
": cannot get device detail for device %d\n",
157 dv
= map_dev(disk
.major
, disk
.minor
);
159 fprintf(stderr
, Name
": cannot find device file for device %d\n",
163 fd2
= open(dv
, O_RDWR
);
165 fprintf(stderr
, Name
": cannot open device file %s\n", dv
);
168 if (st
->ss
->load_super(st
, fd2
, &super
, NULL
)) {
169 fprintf(stderr
, Name
": cannot find super block on %s\n", dv
);
173 info
.array
.raid_disks
= nd
+1;
174 info
.array
.nr_disks
= nd
+1;
175 info
.array
.active_disks
= nd
+1;
176 info
.array
.working_disks
= nd
+1;
177 info
.disk
.number
= nd
;
178 info
.disk
.major
= major(stb
.st_rdev
);
179 info
.disk
.minor
= minor(stb
.st_rdev
);
180 info
.disk
.raid_disk
= nd
;
181 info
.disk
.state
= (1 << MD_DISK_SYNC
) | (1 << MD_DISK_ACTIVE
);
182 st
->ss
->update_super(&info
, super
, "grow", dv
, 0);
184 if (st
->ss
->store_super(fd2
, super
)) {
185 fprintf(stderr
, Name
": Cannot store new superblock on %s\n", dv
);