Change MAJOR() etc to major() etc
[thirdparty/mdadm.git] / Grow.c
1 /*
2  * mdadm - manage Linux "md" devices aka RAID arrays.
3  *
4  * Copyright (C) 2001-2004 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 #include        "mdadm.h"
30 #include        "dlink.h"
31
32 #if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN)
33 #error no endian defined
34 #endif
35 #include        "md_u.h"
36 #include        "md_p.h"
37
38 int Grow_Add_device(char *devname, int fd, char *newdev)
39 {
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
45          * all other devices.
46          * This means that we need to *find* all other devices.
47          */
48         mdu_array_info_t array;
49         mdu_disk_info_t disk;
50         mdp_super_t super;
51         struct stat stb;
52         int nfd, fd2;
53         int d, nd;
54         
55
56         if (ioctl(fd, GET_ARRAY_INFO, &array) < 0) {
57                 fprintf(stderr, Name ": cannot get array info for %s\n", devname);
58                 return 1;
59         }
60
61         if (array.level != -1) {
62                 fprintf(stderr, Name ": can only add devices to linear arrays\n");
63                 return 1;
64         }
65
66         nfd = open(newdev, O_RDWR|O_EXCL);
67         if (nfd < 0) {
68                 fprintf(stderr, Name ": cannot open %s\n", newdev);
69                 return 1;
70         }
71         fstat(nfd, &stb);
72         if ((stb.st_mode & S_IFMT) != S_IFBLK) {
73                 fprintf(stderr, Name ": %s is not a block device!\n", newdev);
74                 close(nfd);
75                 return 1;
76         }
77         /* now check out all the devices and make sure we can read the superblock */
78         for (d=0 ; d < array.raid_disks ; d++) {
79                 mdu_disk_info_t disk;
80                 char *dv;
81
82                 disk.number = d;
83                 if (ioctl(fd, GET_DISK_INFO, &disk) < 0) {
84                         fprintf(stderr, Name ": cannot get device detail for device %d\n",
85                                 d);
86                         return 1;
87                 }
88                 dv = map_dev(disk.major, disk.minor);
89                 if (!dv) {
90                         fprintf(stderr, Name ": cannot find device file for device %d\n",
91                                 d);
92                         return 1;
93                 }
94                 fd2 = open(dv, O_RDWR);
95                 if (!fd2) {
96                         fprintf(stderr, Name ": cannot open device file %s\n", dv);
97                         return 1;
98                 }
99                 if (load_super(fd2, &super)) {
100                         fprintf(stderr, Name ": cannot find super block on %s\n", dv);
101                         close(fd2);
102                         return 1;
103                 }
104                 close(fd2);
105         }
106         /* Ok, looks good. Lets update the superblock and write it out to
107          * newdev.
108          */
109         
110         memset(&super.disks[d], 0, sizeof(super.disks[d]));
111         super.disks[d].number = d;
112         super.disks[d].major = major(stb.st_rdev);
113         super.disks[d].minor = minor(stb.st_rdev);
114         super.disks[d].raid_disk = d;
115         super.disks[d].state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
116
117         super.this_disk = super.disks[d];
118         super.sb_csum = calc_sb_csum(&super);
119         if (store_super(nfd, &super)) {
120                 fprintf(stderr, Name ": Cannot store new superblock on %s\n", newdev);
121                 close(nfd);
122                 return 1;
123         }
124         disk.number = d;
125         disk.major = major(stb.st_rdev);
126         disk.minor = minor(stb.st_rdev);
127         disk.raid_disk = d;
128         disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
129         close(nfd);
130         if (ioctl(fd, ADD_NEW_DISK, &disk) != 0) {
131                 fprintf(stderr, Name ": Cannot add new disk to this array\n");
132                 return 1;
133         }
134         /* Well, that seems to have worked.
135          * Now go through and update all superblocks
136          */
137
138         if (ioctl(fd, GET_ARRAY_INFO, &array) < 0) {
139                 fprintf(stderr, Name ": cannot get array info for %s\n", devname);
140                 return 1;
141         }
142
143         nd = d;
144         for (d=0 ; d < array.raid_disks ; d++) {
145                 mdu_disk_info_t disk;
146                 char *dv;
147
148                 disk.number = d;
149                 if (ioctl(fd, GET_DISK_INFO, &disk) < 0) {
150                         fprintf(stderr, Name ": cannot get device detail for device %d\n",
151                                 d);
152                         return 1;
153                 }
154                 dv = map_dev(disk.major, disk.minor);
155                 if (!dv) {
156                         fprintf(stderr, Name ": cannot find device file for device %d\n",
157                                 d);
158                         return 1;
159                 }
160                 fd2 = open(dv, O_RDWR);
161                 if (fd2 < 0) {
162                         fprintf(stderr, Name ": cannot open device file %s\n", dv);
163                         return 1;
164                 }
165                 if (load_super(fd2, &super)) {
166                         fprintf(stderr, Name ": cannot find super block on %s\n", dv);
167                         close(fd);
168                         return 1;
169                 }
170                 super.raid_disks = nd+1;
171                 super.nr_disks = nd+1;
172                 super.active_disks = nd+1;
173                 super.working_disks = nd+1;
174                 memset(&super.disks[nd], 0, sizeof(super.disks[nd]));
175                 super.disks[nd].number = nd;
176                 super.disks[nd].major = major(stb.st_rdev);
177                 super.disks[nd].minor = minor(stb.st_rdev);
178                 super.disks[nd].raid_disk = nd;
179                 super.disks[nd].state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
180
181                 super.this_disk = super.disks[d];
182                 super.sb_csum = calc_sb_csum(&super);
183                 if (store_super(fd2, &super)) {
184                         fprintf(stderr, Name ": Cannot store new superblock on %s\n", dv);
185                         close(fd2);
186                         return 1;
187                 }
188                 close(fd2);
189         }
190
191         return 0;
192 }