]> git.ipfire.org Git - thirdparty/mdadm.git/blob - mapfile.c
mdopen: use small sequence number for uniquifying array names.
[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 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, "%s ", mel->metadata);
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
90 static int lfd = -1;
91 static int lsubdir = 0;
92 int map_lock(struct map_ent **melp)
93 {
94 if (lfd < 0) {
95 lfd = open("/var/run/mdadm/map.lock", O_CREAT|O_RDWR, 0600);
96 if (lfd < 0) {
97 lfd = open("/var/run/mdadm.map.lock", O_CREAT|O_RDWR, 0600);
98 lsubdir = 0;
99 } else
100 lsubdir = 1;
101 if (lfd < 0)
102 return -1;
103 if (lockf(lfd, F_LOCK, 0) != 0) {
104 close(lfd);
105 lfd = -1;
106 return -1;
107 }
108 }
109 if (*melp)
110 map_free(*melp);
111 map_read(melp);
112 return 0;
113 }
114
115 void map_unlock(struct map_ent **melp)
116 {
117 if (lfd >= 0)
118 close(lfd);
119 if (lsubdir)
120 unlink("/var/run/mdadm/map.lock");
121 else
122 unlink("/var/run/mdadm.map.lock");
123 lfd = -1;
124 }
125
126 void map_add(struct map_ent **melp,
127 int devnum, char *metadata, int uuid[4], char *path)
128 {
129 struct map_ent *me = malloc(sizeof(*me));
130
131 me->devnum = devnum;
132 strcpy(me->metadata, metadata);
133 memcpy(me->uuid, uuid, 16);
134 me->path = strdup(path);
135 me->next = *melp;
136 *melp = me;
137 }
138
139 void map_read(struct map_ent **melp)
140 {
141 FILE *f;
142 char buf[8192];
143 char path[200];
144 int devnum, uuid[4];
145 char metadata[30];
146 char nam[4];
147
148 *melp = NULL;
149
150 f = fopen("/var/run/mdadm/map", "r");
151 if (!f)
152 f = fopen("/var/run/mdadm.map", "r");
153 if (!f)
154 return;
155
156 while (fgets(buf, sizeof(buf), f)) {
157 if (sscanf(buf, " %3[mdp]%d %s %x:%x:%x:%x %200s",
158 nam, &devnum, metadata, uuid, uuid+1,
159 uuid+2, uuid+3, path) == 8) {
160 if (strncmp(nam, "md", 2) != 0)
161 continue;
162 if (nam[2] == 'p')
163 devnum = -1 - devnum;
164 map_add(melp, devnum, metadata, uuid, path);
165 }
166 }
167 fclose(f);
168 }
169
170 void map_free(struct map_ent *map)
171 {
172 while (map) {
173 struct map_ent *mp = map;
174 map = mp->next;
175 free(mp->path);
176 free(mp);
177 }
178 }
179
180 int map_update(struct map_ent **mpp, int devnum, char *metadata,
181 int *uuid, char *path)
182 {
183 struct map_ent *map, *mp;
184 int rv;
185
186 if (mpp && *mpp)
187 map = *mpp;
188 else
189 map_read(&map);
190
191 for (mp = map ; mp ; mp=mp->next)
192 if (mp->devnum == devnum) {
193 strcpy(mp->metadata, metadata);
194 memcpy(mp->uuid, uuid, 16);
195 free(mp->path);
196 mp->path = strdup(path);
197 break;
198 }
199 if (!mp)
200 map_add(&map, devnum, metadata, uuid, path);
201 if (mpp)
202 *mpp = NULL;
203 rv = map_write(map);
204 map_free(map);
205 return rv;
206 }
207
208 void map_delete(struct map_ent **mapp, int devnum)
209 {
210 struct map_ent *mp;
211
212 if (*mapp == NULL)
213 map_read(mapp);
214
215 for (mp = *mapp; mp; mp = *mapp) {
216 if (mp->devnum == devnum) {
217 *mapp = mp->next;
218 free(mp->path);
219 free(mp);
220 } else
221 mapp = & mp->next;
222 }
223 }
224
225 struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4])
226 {
227 struct map_ent *mp;
228 if (!*map)
229 map_read(map);
230
231 for (mp = *map ; mp ; mp = mp->next)
232 if (memcmp(uuid, mp->uuid, 16) == 0)
233 return mp;
234 return NULL;
235 }
236
237 struct map_ent *map_by_devnum(struct map_ent **map, int devnum)
238 {
239 struct map_ent *mp;
240 if (!*map)
241 map_read(map);
242
243 for (mp = *map ; mp ; mp = mp->next)
244 if (mp->devnum == devnum)
245 return mp;
246 return NULL;
247 }
248
249 struct map_ent *map_by_name(struct map_ent **map, char *name)
250 {
251 struct map_ent *mp;
252 if (!*map)
253 map_read(map);
254
255 for (mp = *map ; mp ; mp = mp->next) {
256 if (strncmp(mp->path, "/dev/md/", 8) != 0)
257 continue;
258 if (strcmp(mp->path+8, name) == 0)
259 return mp;
260 }
261 return NULL;
262 }