~ubuntu-branches/ubuntu/dapper/mdadm/dapper

« back to all changes in this revision

Viewing changes to ,,mdadm--debian--1.12.0--patch-1--pkg-mdadm-devel@lists.alioth.debian.org--2005.1123495738.2396.13/Grow.c

  • Committer: Package Import Robot
  • Author(s): Fabio M. Di Nitto
  • Date: 2005-11-28 07:35:36 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20051128073536-ph8pstb6ams9huk4
Tags: 1.12.0-1ubuntu1
Resyncronize with Debian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}