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

« back to all changes in this revision

Viewing changes to {arch}/++pristine-trees/unlocked/mdadm/mdadm--debian/mdadm--debian--1.12.0/pkg-mdadm-devel@lists.alioth.debian.org--2005/mdadm--debian--1.12.0--patch-2/mdstat.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
 
 * mdstat - parse /proc/mdstat file. Part of:
3
 
 * mdadm - manage Linux "md" devices aka RAID arrays.
4
 
 *
5
 
 * Copyright (C) 2002 Neil Brown <neilb@cse.unsw.edu.au>
6
 
 *
7
 
 *
8
 
 *    This program is free software; you can redistribute it and/or modify
9
 
 *    it under the terms of the GNU General Public License as published by
10
 
 *    the Free Software Foundation; either version 2 of the License, or
11
 
 *    (at your option) any later version.
12
 
 *
13
 
 *    This program is distributed in the hope that it will be useful,
14
 
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
 *    GNU General Public License for more details.
17
 
 *
18
 
 *    You should have received a copy of the GNU General Public License
19
 
 *    along with this program; if not, write to the Free Software
20
 
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
 
 *
22
 
 *    Author: Neil Brown
23
 
 *    Email: <neilb@cse.unsw.edu.au>
24
 
 *    Paper: Neil Brown
25
 
 *           School of Computer Science and Engineering
26
 
 *           The University of New South Wales
27
 
 *           Sydney, 2052
28
 
 *           Australia
29
 
 */
30
 
 
31
 
/*
32
 
 * The /proc/mdstat file comes in at least 3 flavours:
33
 
 * In an unpatched 2.2 kernel (md 0.36.6):
34
 
 *  Personalities : [n raidx] ...
35
 
 *  read_ahead {not set|%d sectors}
36
 
 *  md0 : {in}active{ raidX /dev/hda...  %d blocks{ maxfault=%d}}
37
 
 *  md1 : .....
38
 
 *
39
 
 * Normally only 4 md lines, but all are listed.
40
 
 *
41
 
 * In a patched 2.2 kernel (md 0.90.0)
42
 
 *  Personalities : [raidx] ...
43
 
 *  read_ahead {not set|%d sectors}
44
 
 *  mdN : {in}active {(readonly)} raidX dev[%d]{(F)} ... %d blocks STATUS RESYNC
45
 
 *  ... Only initialised arrays listed
46
 
 *  unused: dev dev dev | <none>
47
 
 *
48
 
 * STATUS is personality dependant:
49
 
 *    linear:  %dk rounding
50
 
 *    raid0:   %dk chunks
51
 
 *    raid1:   [%d/%d] [U_U]   ( raid/working.  operational or not)
52
 
 *    raid5:   level 4/5, %dk chunk, algorithm %d [%d/%d] [U_U]
53
 
 *
54
 
 * RESYNC is  empty or:
55
 
 *    {resync|recovery}=%u%% finish=%u.%umin
56
 
 *  or
57
 
 *    resync=DELAYED
58
 
 *
59
 
 * In a 2.4 kernel (md 0.90.0/2.4)
60
 
 *  Personalities : [raidX] ...
61
 
 *  read_ahead {not set|%d sectors}
62
 
 *  mdN : {in}active {(read-only)} raidX dev[%d]{(F)} ...
63
 
 *       %d blocks STATUS
64
 
 *       RESYNC
65
 
 *  unused: dev dev .. | <none>
66
 
 *
67
 
 *  STATUS matches 0.90.0/2.2
68
 
 *  RESYNC includes [===>....],
69
 
 *          adds a space after {resync|recovery} and before and after '='
70
 
 *          adds a decimal to the recovery percent.
71
 
 *          adds (%d/%d) resync amount  and max_blocks, before finish.
72
 
 *          adds speed=%dK/sec after finish
73
 
 *
74
 
 *
75
 
 *
76
 
 * Out of this we want to extract:
77
 
 *   list of devices, active or not
78
 
 *   pattern of failed drives (so need number of drives)
79
 
 *   percent resync complete
80
 
 *
81
 
 * As continuation is indicated by leading space, we use
82
 
 *  conf_line from config.c to read logical lines
83
 
 *
84
 
 */
85
 
 
86
 
#include        "mdadm.h"
87
 
#include        "dlink.h"
88
 
#include        <sys/select.h>
89
 
 
90
 
void free_mdstat(struct mdstat_ent *ms)
91
 
{
92
 
        while (ms) {
93
 
                struct mdstat_ent *t;
94
 
                if (ms->dev) free(ms->dev);
95
 
                if (ms->level) free(ms->level);
96
 
                if (ms->pattern) free(ms->pattern);
97
 
                t = ms;
98
 
                ms = ms->next;
99
 
                free(t);
100
 
        }
101
 
}
102
 
 
103
 
static int mdstat_fd = -1;
104
 
struct mdstat_ent *mdstat_read(int hold)
105
 
{
106
 
        FILE *f;
107
 
        struct mdstat_ent *all, **end;
108
 
        char *line;
109
 
 
110
 
        if (hold && mdstat_fd != -1) {
111
 
                lseek(mdstat_fd, 0L, 0);
112
 
                f = fdopen(dup(mdstat_fd), "r");
113
 
        } else
114
 
                f = fopen("/proc/mdstat", "r");
115
 
        if (f == NULL)
116
 
                return NULL;
117
 
 
118
 
        all = NULL;
119
 
        end = &all;
120
 
        for (; (line = conf_line(f)) ; free_line(line)) {
121
 
                struct mdstat_ent *ent;
122
 
                char *w;
123
 
                int devnum;
124
 
                char *ep;
125
 
 
126
 
                if (strcmp(line, "Personalities")==0)
127
 
                        continue;
128
 
                if (strcmp(line, "read_ahead")==0)
129
 
                        continue;
130
 
                if (strcmp(line, "unused")==0)
131
 
                        continue;
132
 
                /* Better be an md line.. */
133
 
                if (strncmp(line, "md", 2)!= 0)
134
 
                        continue;
135
 
                if (strncmp(line, "md_d", 4) == 0)
136
 
                        devnum = -1-strtoul(line+4, &ep, 10);
137
 
                else if (strncmp(line, "md", 2) == 0)
138
 
                        devnum = strtoul(line+2, &ep, 10);
139
 
                else
140
 
                        continue;
141
 
                if (ep == NULL || *ep ) {
142
 
                        /* fprintf(stderr, Name ": bad /proc/mdstat line starts: %s\n", line); */
143
 
                        continue;
144
 
                }
145
 
 
146
 
                ent = malloc(sizeof(*ent));
147
 
                if (!ent) {
148
 
                        fprintf(stderr, Name ": malloc failed reading /proc/mdstat.\n");
149
 
                        free_line(line);
150
 
                        break;
151
 
                }
152
 
                ent->dev = ent->level = ent->pattern= NULL;
153
 
                ent->next = NULL;
154
 
                ent->percent = -1;
155
 
                ent->active = -1;
156
 
                ent->resync = 0;
157
 
 
158
 
                ent->dev = strdup(line);
159
 
                ent->devnum = devnum;
160
 
                
161
 
                for (w=dl_next(line); w!= line ; w=dl_next(w)) {
162
 
                        int l = strlen(w);
163
 
                        char *eq;
164
 
                        if (strcmp(w, "active")==0)
165
 
                                ent->active = 1;
166
 
                        else if (strcmp(w, "inactive")==0)
167
 
                                ent->active = 0;
168
 
                        else if (ent->active >=0 &&
169
 
                                 ent->level == NULL &&
170
 
                                 w[0] != '(' /*readonly*/)
171
 
                                ent->level = strdup(w);
172
 
                        else if (!ent->pattern &&
173
 
                                 w[0] == '[' &&
174
 
                                 (w[1] == 'U' || w[1] == '_')) {
175
 
                                ent->pattern = strdup(w+1);
176
 
                                if (ent->pattern[l-2]==']')
177
 
                                        ent->pattern[l-2] = '\0';
178
 
                        } else if (ent->percent == -1 &&
179
 
                                   strncmp(w, "re", 2)== 0 &&
180
 
                                   w[l-1] == '%' &&
181
 
                                   (eq=strchr(w, '=')) != NULL ) {
182
 
                                ent->percent = atoi(eq+1);
183
 
                                if (strncmp(w,"resync", 4)==0)
184
 
                                        ent->resync = 1;
185
 
                        } else if (ent->percent == -1 &&
186
 
                                   strncmp(w, "resync", 4)==0) {
187
 
                                ent->resync = 1;
188
 
                        } else if (ent->percent == -1 &&
189
 
                                   w[0] >= '0' && 
190
 
                                   w[0] <= '9' &&
191
 
                                   w[l-1] == '%') {
192
 
                                ent->percent = atoi(w);
193
 
                        }
194
 
                }
195
 
                *end = ent;
196
 
                end = &ent->next;
197
 
        }
198
 
        if (hold && mdstat_fd == -1)
199
 
                mdstat_fd = dup(fileno(f));
200
 
        fclose(f);
201
 
        return all;
202
 
}
203
 
 
204
 
void mdstat_wait(int seconds)
205
 
{
206
 
        fd_set fds;
207
 
        struct timeval tm;
208
 
        FD_ZERO(&fds);
209
 
        if (mdstat_fd >= 0)
210
 
                FD_SET(mdstat_fd, &fds);
211
 
        tm.tv_sec = seconds;
212
 
        tm.tv_usec = 0;
213
 
        select(mdstat_fd >2 ? mdstat_fd+1:3, NULL, NULL, &fds, &tm);
214
 
}