~ubuntu-branches/ubuntu/hardy/mdadm/hardy-updates

« back to all changes in this revision

Viewing changes to {arch}/++pristine-trees/unlocked/mdadm/mdadm--integration/mdadm--integration--1.12.0/pkg-mdadm-devel@lists.alioth.debian.org--2005/mdadm--integration--1.12.0--patch-4/Grow.c

  • Committer: Package Import Robot
  • Author(s): Scott James Remnant
  • Date: 2006-07-11 17:23:21 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20060711172321-070tz7lox9adujtw
Tags: 2.4.1-6ubuntu1
* Merge from debian unstable, remaining changes:
  - integration with initramfs-tools,
  - autocreate devices when udev is in use,
  - use lstat in mdopen.

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
 
}