]> git.ipfire.org Git - thirdparty/mdadm.git/blob - mapfile.c
Free mdstat data structures properly.
[thirdparty/mdadm.git] / mapfile.c
1 /*
2 * mapfile - manage /var/run/mdadm.map. Part of:
3 * mdadm - manage Linux "md" devices aka RAID arrays.
4 *
5 * Copyright (C) 2006 Neil Brown <neilb@suse.de>
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@suse.de>
24 * Paper: Neil Brown
25 * Novell Inc
26 * GPO Box Q1283
27 * QVB Post Office, NSW 1230
28 * Australia
29 */
30
31 /* /var/run/mdadm.map is used to track arrays being created in --incremental
32 * more. It particularly allows lookup from UUID to array device, but
33 * also allows the array device name to be easily found.
34 *
35 * The map file is line based with space separated fields. The fields are:
36 * Device id - mdX or mdpX where is a number.
37 * metadata - 0.90 1.0 1.1 1.2
38 * UUID - uuid of the array
39 * path - path where device created: /dev/md/home
40 *
41 */
42
43
44 #include "mdadm.h"
45
46
47 int map_write(struct map_ent *mel)
48 {
49 FILE *f;
50 int err;
51 int subdir = 1;
52
53 f = fopen("/var/run/mdadm/map.new", "w");
54 if (!f) {
55 f = fopen("/var/run/mdadm.map.new", "w");
56 subdir = 0;
57 }
58 if (!f)
59 return 0;
60 while (mel) {
61 if (mel->devnum < 0)
62 fprintf(f, "mdp%d ", -1-mel->devnum);
63 else
64 fprintf(f, "md%d ", mel->devnum);
65 fprintf(f, "%d.%d ", mel->major, mel->minor);
66 fprintf(f, "%08x:%08x:%08x:%08x ", mel->uuid[0],
67 mel->uuid[1], mel->uuid[2], mel->uuid[3]);
68 fprintf(f, "%s\n", mel->path);
69 mel = mel->next;
70 }
71 fflush(f);
72 err = ferror(f);
73 fclose(f);
74 if (err) {
75 if (subdir)
76 unlink("/var/run/mdadm/map.new");
77 else
78 unlink("/var/run/mdadm.map.new");
79 return 0;
80 }
81 if (subdir)
82 return rename("/var/run/mdadm/map.new",
83 "/var/run/mdadm/map") == 0;
84 else
85 return rename("/var/run/mdadm.map.new",
86 "/var/run/mdadm.map") == 0;
87 }
88
89 void map_add(struct map_ent **melp,
90 int devnum, int major, int minor, int uuid[4], char *path)
91 {
92 struct map_ent *me = malloc(sizeof(*me));
93
94 me->devnum = devnum;
95 me->major = major;
96 me->minor = minor;
97 memcpy(me->uuid, uuid, 16);
98 me->path = strdup(path);
99 me->next = *melp;
100 *melp = me;
101 }
102
103 void map_read(struct map_ent **melp)
104 {
105 FILE *f;
106 char buf[8192];
107 char path[200];
108 int devnum, major, minor, uuid[4];
109 char nam[4];
110
111 *melp = NULL;
112
113 f = fopen("/var/run/mdadm/map", "r");
114 if (!f)
115 f = fopen("/var/run/mdadm.map", "r");
116 if (!f) {
117 RebuildMap();
118 f = fopen("/var/run/mdadm/map", "r");
119 }
120 if (!f)
121 f = fopen("/var/run/mdadm.map", "r");
122 if (!f)
123 return;
124
125 while (fgets(buf, sizeof(buf), f)) {
126 if (sscanf(buf, " md%1[p]%d %d.%d %x:%x:%x:%x %200s",
127 nam, &devnum, &major, &minor, uuid, uuid+1,
128 uuid+2, uuid+3, path) == 9) {
129 if (nam[0] == 'p')
130 devnum = -1 - devnum;
131 map_add(melp, devnum, major, minor, uuid, path);
132 }
133 }
134 fclose(f);
135 }
136
137 void map_free(struct map_ent *map)
138 {
139 while (map) {
140 struct map_ent *mp = map;
141 map = mp->next;
142 free(mp->path);
143 free(mp);
144 }
145 }
146
147 int map_update(struct map_ent **mpp, int devnum, int major, int minor,
148 int *uuid, char *path)
149 {
150 struct map_ent *map, *mp;
151 int rv;
152
153 if (mpp && *mpp)
154 map = *mpp;
155 else
156 map_read(&map);
157
158 for (mp = map ; mp ; mp=mp->next)
159 if (mp->devnum == devnum) {
160 mp->major = major;
161 mp->minor = minor;
162 memcpy(mp->uuid, uuid, 16);
163 free(mp->path);
164 mp->path = strdup(path);
165 break;
166 }
167 if (!mp)
168 map_add(&map, devnum, major, minor, uuid, path);
169 *mpp = NULL;
170 rv = map_write(map);
171 map_free(map);
172 return rv;
173 }
174
175 void map_delete(struct map_ent **mapp, int devnum)
176 {
177 struct map_ent *mp;
178
179 if (*mapp == NULL)
180 map_read(mapp);
181
182 for (mp = *mapp; mp; mp = *mapp) {
183 if (mp->devnum == devnum) {
184 *mapp = mp->next;
185 free(mp->path);
186 free(mp);
187 } else
188 mapp = & mp->next;
189 }
190 }
191
192 struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4])
193 {
194 struct map_ent *mp;
195 if (!*map)
196 map_read(map);
197
198 for (mp = *map ; mp ; mp = mp->next)
199 if (memcmp(uuid, mp->uuid, 16) == 0)
200 return mp;
201 return NULL;
202
203 }
204
205 void RebuildMap(void)
206 {
207 struct mdstat_ent *mdstat = mdstat_read(0, 0);
208 struct mdstat_ent *md;
209 struct map_ent *map = NULL;
210 int mdp = get_mdp_major();
211
212 for (md = mdstat ; md ; md = md->next) {
213 struct mdinfo *sra = sysfs_read(-1, md->devnum, GET_DEVS);
214 struct mdinfo *sd;
215
216 for (sd = sra->devs ; sd ; sd = sd->next) {
217 char dn[30];
218 int dfd;
219 int ok;
220 struct supertype *st;
221 char *path;
222 struct mdinfo info;
223
224 sprintf(dn, "%d:%d", sd->disk.major, sd->disk.minor);
225 dfd = dev_open(dn, O_RDONLY);
226 if (dfd < 0)
227 continue;
228 st = guess_super(dfd);
229 if ( st == NULL)
230 ok = -1;
231 else
232 ok = st->ss->load_super(st, dfd, NULL);
233 close(dfd);
234 if (ok != 0)
235 continue;
236 st->ss->getinfo_super(st, &info);
237 if (md->devnum > 0)
238 path = map_dev(MD_MAJOR, md->devnum, 0);
239 else
240 path = map_dev(mdp, (-1-md->devnum)<< 6, 0);
241 map_add(&map, md->devnum, st->ss->major,
242 st->minor_version,
243 info.uuid, path ? : "/unknown");
244 st->ss->free_super(st);
245 break;
246 }
247 }
248 free_mdstat(mdstat);
249 map_write(map);
250 map_free(map);
251 }