]> git.ipfire.org Git - thirdparty/mdadm.git/blob - mapfile.c
mdmon: pass symbolic name to mdmon instead of device name.
[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 X is a number.
37 * metadata - 0.90 1.0 1.1 1.2 ddf ...
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 for (; mel; mel = mel->next) {
61 if (mel->bad)
62 continue;
63 if (mel->devnum < 0)
64 fprintf(f, "mdp%d ", -1-mel->devnum);
65 else
66 fprintf(f, "md%d ", mel->devnum);
67 fprintf(f, "%s ", mel->metadata);
68 fprintf(f, "%08x:%08x:%08x:%08x ", mel->uuid[0],
69 mel->uuid[1], mel->uuid[2], mel->uuid[3]);
70 fprintf(f, "%s\n", mel->path);
71 }
72 fflush(f);
73 err = ferror(f);
74 fclose(f);
75 if (err) {
76 if (subdir)
77 unlink("/var/run/mdadm/map.new");
78 else
79 unlink("/var/run/mdadm.map.new");
80 return 0;
81 }
82 if (subdir)
83 return rename("/var/run/mdadm/map.new",
84 "/var/run/mdadm/map") == 0;
85 else
86 return rename("/var/run/mdadm.map.new",
87 "/var/run/mdadm.map") == 0;
88 }
89
90
91 static int lfd = -1;
92 static int lsubdir = 0;
93 int map_lock(struct map_ent **melp)
94 {
95 if (lfd < 0) {
96 lfd = open("/var/run/mdadm/map.lock", O_CREAT|O_RDWR, 0600);
97 if (lfd < 0) {
98 lfd = open("/var/run/mdadm.map.lock", O_CREAT|O_RDWR, 0600);
99 lsubdir = 0;
100 } else
101 lsubdir = 1;
102 if (lfd < 0)
103 return -1;
104 if (lockf(lfd, F_LOCK, 0) != 0) {
105 close(lfd);
106 lfd = -1;
107 return -1;
108 }
109 }
110 if (*melp)
111 map_free(*melp);
112 map_read(melp);
113 return 0;
114 }
115
116 void map_unlock(struct map_ent **melp)
117 {
118 if (lfd >= 0)
119 close(lfd);
120 if (lsubdir)
121 unlink("/var/run/mdadm/map.lock");
122 else
123 unlink("/var/run/mdadm.map.lock");
124 lfd = -1;
125 }
126
127 void map_add(struct map_ent **melp,
128 int devnum, char *metadata, int uuid[4], char *path)
129 {
130 struct map_ent *me = malloc(sizeof(*me));
131
132 me->devnum = devnum;
133 strcpy(me->metadata, metadata);
134 memcpy(me->uuid, uuid, 16);
135 me->path = strdup(path);
136 me->next = *melp;
137 me->bad = 0;
138 *melp = me;
139 }
140
141 void map_read(struct map_ent **melp)
142 {
143 FILE *f;
144 char buf[8192];
145 char path[200];
146 int devnum, uuid[4];
147 char metadata[30];
148 char nam[4];
149
150 *melp = NULL;
151
152 f = fopen("/var/run/mdadm/map", "r");
153 if (!f)
154 f = fopen("/var/run/mdadm.map", "r");
155 if (!f)
156 return;
157
158 while (fgets(buf, sizeof(buf), f)) {
159 if (sscanf(buf, " %3[mdp]%d %s %x:%x:%x:%x %200s",
160 nam, &devnum, metadata, uuid, uuid+1,
161 uuid+2, uuid+3, path) == 8) {
162 if (strncmp(nam, "md", 2) != 0)
163 continue;
164 if (nam[2] == 'p')
165 devnum = -1 - devnum;
166 map_add(melp, devnum, metadata, uuid, path);
167 }
168 }
169 fclose(f);
170 }
171
172 void map_free(struct map_ent *map)
173 {
174 while (map) {
175 struct map_ent *mp = map;
176 map = mp->next;
177 free(mp->path);
178 free(mp);
179 }
180 }
181
182 int map_update(struct map_ent **mpp, int devnum, char *metadata,
183 int *uuid, char *path)
184 {
185 struct map_ent *map, *mp;
186 int rv;
187
188 if (mpp && *mpp)
189 map = *mpp;
190 else
191 map_read(&map);
192
193 for (mp = map ; mp ; mp=mp->next)
194 if (mp->devnum == devnum) {
195 strcpy(mp->metadata, metadata);
196 memcpy(mp->uuid, uuid, 16);
197 free(mp->path);
198 mp->path = strdup(path);
199 break;
200 }
201 if (!mp)
202 map_add(&map, devnum, metadata, uuid, path);
203 if (mpp)
204 *mpp = NULL;
205 rv = map_write(map);
206 map_free(map);
207 return rv;
208 }
209
210 void map_delete(struct map_ent **mapp, int devnum)
211 {
212 struct map_ent *mp;
213
214 if (*mapp == NULL)
215 map_read(mapp);
216
217 for (mp = *mapp; mp; mp = *mapp) {
218 if (mp->devnum == devnum) {
219 *mapp = mp->next;
220 free(mp->path);
221 free(mp);
222 } else
223 mapp = & mp->next;
224 }
225 }
226
227 struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4])
228 {
229 struct map_ent *mp;
230 if (!*map)
231 map_read(map);
232
233 for (mp = *map ; mp ; mp = mp->next) {
234 if (memcmp(uuid, mp->uuid, 16) != 0)
235 continue;
236 if (!mddev_busy(mp->devnum)) {
237 mp->bad = 1;
238 continue;
239 }
240 return mp;
241 }
242 return NULL;
243 }
244
245 struct map_ent *map_by_devnum(struct map_ent **map, int devnum)
246 {
247 struct map_ent *mp;
248 if (!*map)
249 map_read(map);
250
251 for (mp = *map ; mp ; mp = mp->next) {
252 if (mp->devnum != devnum)
253 continue;
254 if (!mddev_busy(mp->devnum)) {
255 mp->bad = 1;
256 continue;
257 }
258 return mp;
259 }
260 return NULL;
261 }
262
263 struct map_ent *map_by_name(struct map_ent **map, char *name)
264 {
265 struct map_ent *mp;
266 if (!*map)
267 map_read(map);
268
269 for (mp = *map ; mp ; mp = mp->next) {
270 if (strncmp(mp->path, "/dev/md/", 8) != 0)
271 continue;
272 if (strcmp(mp->path+8, name) != 0)
273 continue;
274 if (!mddev_busy(mp->devnum)) {
275 mp->bad = 1;
276 continue;
277 }
278 return mp;
279 }
280 return NULL;
281 }