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

« 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): 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
 * 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
}