]>
git.ipfire.org Git - thirdparty/mdadm.git/blob - mapfile.c
2 * mapfile - manage /var/run/mdadm/map. Part of:
3 * mdadm - manage Linux "md" devices aka RAID arrays.
5 * Copyright (C) 2006-2009 Neil Brown <neilb@suse.de>
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.
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.
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
23 * Email: <neilb@suse.de>
27 * QVB Post Office, NSW 1230
31 /* /var/run/mdadm/map is used to track arrays being created in --incremental
32 * mode. It particularly allows lookup from UUID to array device, but
33 * also allows the array device name to be easily found.
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
41 * The preferred location for the map file is /var/run/mdadm/map.
42 * However /var/run may not exist or be writable in early boot. And if
43 * no-one has created /var/run/mdadm, we still want to survive.
44 * So possible locations are:
45 * /var/run/mdadm/map /dev/.mdadm/map(changable at compile time).
46 * We read from the first one that exists and write to the first
57 #define mapnames(dir, base) { \
59 dir "/" base ".new", \
60 dir "/" base ".lock", \
64 char *mapname
[MAP_DIRS
][4] = {
65 mapnames("/var/run/mdadm", "map"),
66 mapnames(MAP_DIR
, MAP_FILE
),
69 int mapmode
[3] = { O_RDONLY
, O_RDWR
|O_CREAT
, O_RDWR
|O_CREAT
|O_TRUNC
};
70 char *mapsmode
[3] = { "r", "w", "w"};
72 FILE *open_map(int modenum
, int *choice
)
76 for (i
= 0 ; i
<= MAP_DIRS
; i
++) {
78 if ((mapmode
[modenum
] & O_CREAT
))
79 /* Attempt to create directory, don't worry about
82 (void)mkdir(mapname
[i
][MAP_DIRNAME
], 0755);
83 fd
= open(mapname
[i
][modenum
], mapmode
[modenum
], 0600);
86 return fdopen(fd
, mapsmode
[modenum
]);
92 int map_write(struct map_ent
*mel
)
98 f
= open_map(MAP_NEW
, &which
);
102 for (; mel
; mel
= mel
->next
) {
106 fprintf(f
, "mdp%d ", -1-mel
->devnum
);
108 fprintf(f
, "md%d ", mel
->devnum
);
109 fprintf(f
, "%s ", mel
->metadata
);
110 fprintf(f
, "%08x:%08x:%08x:%08x ", mel
->uuid
[0],
111 mel
->uuid
[1], mel
->uuid
[2], mel
->uuid
[3]);
112 fprintf(f
, "%s\n", mel
->path
?:"");
118 unlink(mapname
[which
][1]);
121 return rename(mapname
[which
][1],
122 mapname
[which
][0]) == 0;
126 static FILE *lf
= NULL
;
127 static int lwhich
= 0;
128 int map_lock(struct map_ent
**melp
)
132 lf
= open_map(MAP_LOCK
, &lwhich
);
135 if (flock(fileno(lf
), LOCK_EX
) != 0) {
140 if (fstat(fileno(lf
), &buf
) != 0 ||
142 /* The owner of the lock unlinked it,
143 * so we have a lock on a stale file,
156 void map_unlock(struct map_ent
**melp
)
159 /* must unlink before closing the file,
160 * as only the owner of the lock may
163 unlink(mapname
[lwhich
][2]);
169 void map_add(struct map_ent
**melp
,
170 int devnum
, char *metadata
, int uuid
[4], char *path
)
172 struct map_ent
*me
= malloc(sizeof(*me
));
175 strcpy(me
->metadata
, metadata
);
176 memcpy(me
->uuid
, uuid
, 16);
177 me
->path
= path
? strdup(path
) : NULL
;
183 void map_read(struct map_ent
**melp
)
195 f
= open_map(MAP_READ
, &which
);
198 f
= open_map(MAP_READ
, &which
);
203 while (fgets(buf
, sizeof(buf
), f
)) {
205 if (sscanf(buf
, " %3[mdp]%d %s %x:%x:%x:%x %200s",
206 nam
, &devnum
, metadata
, uuid
, uuid
+1,
207 uuid
+2, uuid
+3, path
) >= 7) {
208 if (strncmp(nam
, "md", 2) != 0)
211 devnum
= -1 - devnum
;
212 map_add(melp
, devnum
, metadata
, uuid
, path
);
218 void map_free(struct map_ent
*map
)
221 struct map_ent
*mp
= map
;
228 int map_update(struct map_ent
**mpp
, int devnum
, char *metadata
,
229 int *uuid
, char *path
)
231 struct map_ent
*map
, *mp
;
239 for (mp
= map
; mp
; mp
=mp
->next
)
240 if (mp
->devnum
== devnum
) {
241 strcpy(mp
->metadata
, metadata
);
242 memcpy(mp
->uuid
, uuid
, 16);
244 mp
->path
= path
? strdup(path
) : NULL
;
248 map_add(&map
, devnum
, metadata
, uuid
, path
);
256 void map_delete(struct map_ent
**mapp
, int devnum
)
263 for (mp
= *mapp
; mp
; mp
= *mapp
) {
264 if (mp
->devnum
== devnum
) {
273 void map_remove(struct map_ent
**mapp
, int devnum
)
275 if (devnum
== NoMdDev
)
278 map_delete(mapp
, devnum
);
283 struct map_ent
*map_by_uuid(struct map_ent
**map
, int uuid
[4])
289 for (mp
= *map
; mp
; mp
= mp
->next
) {
290 if (memcmp(uuid
, mp
->uuid
, 16) != 0)
292 if (!mddev_busy(mp
->devnum
)) {
301 struct map_ent
*map_by_devnum(struct map_ent
**map
, int devnum
)
307 for (mp
= *map
; mp
; mp
= mp
->next
) {
308 if (mp
->devnum
!= devnum
)
310 if (!mddev_busy(mp
->devnum
)) {
319 struct map_ent
*map_by_name(struct map_ent
**map
, char *name
)
325 for (mp
= *map
; mp
; mp
= mp
->next
) {
328 if (strncmp(mp
->path
, "/dev/md/", 8) != 0)
330 if (strcmp(mp
->path
+8, name
) != 0)
332 if (!mddev_busy(mp
->devnum
)) {
341 /* sets the proper subarray and container_dev according to the metadata
342 * version super_by_fd does this automatically, this routine is meant as
343 * a supplement for guess_super()
345 static void set_member_info(struct supertype
*st
, struct mdstat_ent
*ent
)
348 st
->subarray
[0] = '\0';
350 if (ent
->metadata_version
== NULL
||
351 strncmp(ent
->metadata_version
, "external:", 9) != 0)
354 if (is_subarray(&ent
->metadata_version
[9])) {
355 char version
[strlen(ent
->metadata_version
)+1];
357 char *name
= &version
[10];
359 strcpy(version
, ent
->metadata_version
);
360 subarray
= strrchr(version
, '/');
367 st
->container_dev
= devname2devnum(name
);
368 strncpy(st
->subarray
, subarray
, sizeof(st
->subarray
));
372 void RebuildMap(void)
374 struct mdstat_ent
*mdstat
= mdstat_read(0, 0);
375 struct mdstat_ent
*md
;
376 struct map_ent
*map
= NULL
;
377 int mdp
= get_mdp_major();
378 int require_homehost
;
379 char sys_hostname
[256];
380 char *homehost
= conf_get_homehost(&require_homehost
);
382 if (homehost
== NULL
|| strcmp(homehost
, "<system>")==0) {
383 if (gethostname(sys_hostname
, sizeof(sys_hostname
)) == 0) {
384 sys_hostname
[sizeof(sys_hostname
)-1] = 0;
385 homehost
= sys_hostname
;
389 for (md
= mdstat
; md
; md
= md
->next
) {
390 struct mdinfo
*sra
= sysfs_read(-1, md
->devnum
, GET_DEVS
);
396 for (sd
= sra
->devs
; sd
; sd
= sd
->next
) {
401 struct supertype
*st
;
405 sprintf(dn
, "%d:%d", sd
->disk
.major
, sd
->disk
.minor
);
406 dfd
= dev_open(dn
, O_RDONLY
);
409 st
= guess_super(dfd
);
413 set_member_info(st
, md
);
414 ok
= st
->ss
->load_super(st
, dfd
, NULL
);
419 st
->ss
->getinfo_super(st
, &info
);
421 path
= map_dev(MD_MAJOR
, md
->devnum
, 0);
423 path
= map_dev(mdp
, (-1-md
->devnum
)<< 6, 0);
425 strncmp(path
, "/dev/md/", 8) != 0) {
426 /* We would really like a name that provides
427 * an MD_DEVNAME for udev.
428 * The name needs to be unique both in /dev/md/
429 * and in this mapfile.
430 * It needs to match watch -I or -As would come
433 * Check if array is in mdadm.conf
435 * determine trustworthy from homehost etc
436 * find a unique name based on metadata name.
439 struct mddev_ident_s
*match
= conf_match(&info
, st
);
441 if (match
&& match
->devname
&& match
->devname
[0] == '/') {
442 path
= match
->devname
;
443 if (path
[0] != '/') {
444 strcpy(namebuf
, "/dev/md/");
445 strcat(namebuf
, path
);
453 if ((homehost
== NULL
||
454 st
->ss
->match_home(st
, homehost
) != 1) &&
455 st
->ss
->match_home(st
, "any") != 1 &&
457 || ! conf_name_is_free(info
.name
)))
458 /* require a numeric suffix */
461 /* allow name to be used as-is if no conflict */
466 if (!isdigit(name
[strlen(name
)-1]) &&
472 if (strchr(name
, ':'))
473 /* probably a uniquifying
474 * hostname prefix. Allow
481 sprintf(namebuf
, "/dev/md/%s%s%d",
484 sprintf(namebuf
, "/dev/md/%s",
487 if (lstat(namebuf
, &stb
) != 0 &&
489 !map_by_name(&map
, namebuf
+8)))
495 map_add(&map
, md
->devnum
,
498 st
->ss
->free_super(st
);
503 /* Only trigger a change if we wrote a new map file */
505 for (md
= mdstat
; md
; md
= md
->next
) {
506 struct mdinfo
*sra
= sysfs_read(-1, md
->devnum
,
509 sysfs_uevent(sra
, "change");