daemon: Fix /dev/mapper paths from mounts and mountpoints (RHBZ#646432).

Make the LV paths returned by these two commands canonical.
This commit is contained in:
Richard W.M. Jones
2010-10-27 14:51:17 +01:00
parent 2f52a40bed
commit fea2e61ac1
3 changed files with 57 additions and 35 deletions

View File

@@ -124,6 +124,9 @@ extern struct optgroup optgroups[];
/* Use this as a replacement for sync(2). */
extern int sync_disks (void);
/*-- in lvm.c --*/
extern int lv_canonical (const char *device, char **ret);
/*-- in proto.c --*/
extern void main_loop (int sock) __attribute__((noreturn));

View File

@@ -664,7 +664,8 @@ do_vgscan (void)
return 0;
}
/* Test if a device is a logical volume (RHBZ#619793).
/* Convert a non-canonical LV path like /dev/mapper/vg-lv or /dev/dm-0
* to a canonical one.
*
* This is harder than it should be. A LV device like /dev/VG/LV is
* really a symlink to a device-mapper device like /dev/dm-0. However
@@ -675,9 +676,16 @@ do_vgscan (void)
*
* Note use of 'stat' instead of 'lstat' so that symlinks are fully
* resolved.
*
* Returns:
* 1 = conversion was successful, path is an LV
* '*ret' is set to the updated path if 'ret' is non-NULL.
* 0 = path is not an LV
* -1 = error, reply_with_* has been called
*
*/
int
do_is_lv (const char *device)
lv_canonical (const char *device, char **ret)
{
struct stat stat1, stat2;
@@ -700,6 +708,14 @@ do_is_lv (const char *device)
return -1;
}
if (stat1.st_rdev == stat2.st_rdev) { /* found it */
if (ret) {
*ret = strdup (lvs[i]);
if (*ret == NULL) {
reply_with_perror ("strdup");
free_strings (lvs);
return -1;
}
}
free_strings (lvs);
return 1;
}
@@ -710,44 +726,26 @@ do_is_lv (const char *device)
return 0;
}
/* Similar to is_lv above (RHBZ#638899). */
/* Test if a device is a logical volume (RHBZ#619793). */
int
do_is_lv (const char *device)
{
return lv_canonical (device, NULL);
}
/* Return canonical name of LV to caller (RHBZ#638899). */
char *
do_lvm_canonical_lv_name (const char *device)
{
struct stat stat1, stat2;
char *canonical;
int r = lv_canonical (device, &canonical);
if (r == -1)
return NULL;
int r = stat (device, &stat1);
if (r == -1) {
reply_with_perror ("stat: %s", device);
if (r == 0) {
reply_with_error ("%s: not a logical volume", device);
return NULL;
}
char **lvs = do_lvs ();
if (lvs == NULL)
return NULL;
size_t i;
for (i = 0; lvs[i] != NULL; ++i) {
r = stat (lvs[i], &stat2);
if (r == -1) {
reply_with_perror ("stat: %s", lvs[i]);
free_strings (lvs);
return NULL;
}
if (stat1.st_rdev == stat2.st_rdev) { /* found it */
char *r = strdup (lvs[i]);
if (r == NULL) {
reply_with_perror ("strdup");
free_strings (lvs);
}
free_strings (lvs);
return r;
}
}
free_strings (lvs);
/* not found */
reply_with_error ("%s: not a logical volume", device);
return NULL;
return canonical; /* caller frees */
}

View File

@@ -149,6 +149,7 @@ mounts_or_mountpoints (int mp)
char *p, *pend, *p2;
int len;
char matching[5 + sysroot_len];
size_t i;
r = command (&out, &err, "mount", NULL);
if (r == -1) {
@@ -204,6 +205,26 @@ mounts_or_mountpoints (int mp)
if (add_string (&ret, &size, &alloc, NULL) == -1)
return NULL;
/* Convert /dev/mapper LV paths into canonical paths (RHBZ#646432). */
for (i = 0; ret[i] != NULL; i += mp ? 2 : 1) {
if (STRPREFIX (ret[i], "/dev/mapper/") || STRPREFIX (ret[i], "/dev/dm-")) {
char *canonical;
r = lv_canonical (ret[i], &canonical);
if (r == -1) {
free_strings (ret);
return NULL;
}
if (r == 1) {
free (ret[i]);
ret[i] = canonical;
}
/* Ignore the case where r == 0. This might happen where
* eg. a LUKS /dev/mapper device is mounted, but that won't
* correspond to any LV.
*/
}
}
return ret;
}