]>
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
);
195 int Grow_addbitmap(char *devname
, int fd
, char *file
, int chunk
, int delay
)
198 * First check that array doesn't have a bitmap
199 * Then create the bitmap
202 * For internal bitmaps, we need to check the version,
203 * find all the active devices, and write the bitmap block
206 mdu_bitmap_file_t bmf
;
207 mdu_array_info_t array
;
208 struct supertype
*st
;
210 if (ioctl(fd
, GET_BITMAP_FILE
, &bmf
) != 0) {
212 fprintf(stderr
, Name
": Memory allocation failure.\n");
214 fprintf(stderr
, Name
": bitmaps not supported by this kernel.\n");
217 if (bmf
.pathname
[0]) {
218 fprintf(stderr
, Name
": %s already has a bitmap (%s)\n",
219 devname
, bmf
.pathname
);
222 if (ioctl(fd
, GET_ARRAY_INFO
, &array
) != 0) {
223 fprintf(stderr
, Name
": cannot get array status for %s\n", devname
);
226 if (array
.state
& (1<<MD_SB_BITMAP_PRESENT
)) {
227 fprintf(stderr
, Name
": Internal bitmap already present on %s\n",
231 st
= super_by_version(array
.major_version
, array
.minor_version
);
233 fprintf(stderr
, Name
": Cannot understand version %d.%d\n",
234 array
.major_version
, array
.minor_version
);
237 if (strcmp(file
, "internal") == 0) {
239 for (d
=0; d
< st
->max_devs
; d
++) {
240 mdu_disk_info_t disk
;
243 if (ioctl(fd
, GET_DISK_INFO
, &disk
) < 0)
245 if (disk
.major
== 0 &&
248 if ((disk
.state
& (1<<MD_DISK_SYNC
))==0)
250 dv
= map_dev(disk
.major
, disk
.minor
);
253 int fd2
= open(dv
, O_RDWR
);
256 if (st
->ss
->load_super(st
, fd2
, &super
, NULL
)==0) {
257 st
->ss
->add_internal_bitmap(super
,
260 st
->ss
->write_bitmap(st
, fd2
, super
);
265 array
.state
|= (1<<MD_SB_BITMAP_PRESENT
);
266 if (ioctl(fd
, SET_ARRAY_INFO
, &array
)!= 0) {
267 fprintf(stderr
, Name
": failed to set internal bitmap.\n");