1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

dmeventd: use dm_mountinfo_read

Reuse mountinfo reading code from libdm.
This commit is contained in:
Zdenek Kabelac 2013-05-20 13:10:07 +02:00
parent 7fab9a9dda
commit 810bc4f8c1

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved. * Copyright (C) 2011-2013 Red Hat, Inc. All rights reserved.
* *
* This file is part of LVM2. * This file is part of LVM2.
* *
@ -53,53 +53,6 @@ struct dso_state {
# define MKDEV(x,y) makedev((x),(y)) # define MKDEV(x,y) makedev((x),(y))
#endif #endif
/* Macros to make string defines */
#define TO_STRING_EXP(A) #A
#define TO_STRING(A) TO_STRING_EXP(A)
static int _is_octal(int a)
{
return (((a) & ~7) == '0');
}
/* Convert mangled mountinfo into normal ASCII string */
static void _unmangle_mountinfo_string(const char *src, char *buf)
{
if (!src)
return;
while (*src) {
if ((*src == '\\') &&
_is_octal(src[1]) && _is_octal(src[2]) && _is_octal(src[3])) {
*buf++ = 64 * (src[1] & 7) + 8 * (src[2] & 7) + (src[3] & 7);
src += 4;
} else
*buf++ = *src++;
}
*buf = '\0';
}
/* Parse one line of mountinfo */
static int _parse_mountinfo_line(const char *line, unsigned *maj, unsigned *min, char *buf)
{
char root[PATH_MAX + 1];
char target[PATH_MAX + 1];
/* TODO: maybe detect availability of %ms glib support ? */
if (sscanf(line, "%*u %*u %u:%u %" TO_STRING(PATH_MAX)
"s %" TO_STRING(PATH_MAX) "s",
maj, min, root, target) < 4)
return 0;
_unmangle_mountinfo_string(target, buf);
#if THIN_DEBUG
syslog(LOG_DEBUG, "Mounted %u:%u %s", *maj, *min, buf);
#endif
return 1;
}
/* Get dependencies for device, and try to find matching device */ /* Get dependencies for device, and try to find matching device */
static int _has_deps(const char *name, int tp_major, int tp_minor, int *dev_minor) static int _has_deps(const char *name, int tp_major, int tp_minor, int *dev_minor)
{ {
@ -238,62 +191,62 @@ static int _run(const char *cmd, ...)
return 1; /* all good */ return 1; /* all good */
} }
struct mountinfo_s {
struct dm_info info;
dm_bitset_t minors; /* Bitset for active thin pool minors */
const char *device;
};
static int _umount_device(char *buffer, unsigned major, unsigned minor,
char *target, void *cb_data)
{
struct mountinfo_s *data = cb_data;
if ((major == data->info.major) && dm_bit(data->minors, minor)) {
syslog(LOG_INFO, "Unmounting thin volume %s from %s.\n",
data->device, target);
if (!_run(UMOUNT_COMMAND, "-fl", target, NULL))
syslog(LOG_ERR, "Failed to umount thin %s from %s: %s.\n",
data->device, target, strerror(errno));
}
return 1;
}
/* /*
* Find all thin pool users and try to umount them. * Find all thin pool users and try to umount them.
* TODO: work with read-only thin pool support * TODO: work with read-only thin pool support
*/ */
static void _umount(struct dm_task *dmt, const char *device) static void _umount(struct dm_task *dmt, const char *device)
{ {
static const char mountinfo[] = "/proc/self/mountinfo";
static const size_t MINORS = 4096; static const size_t MINORS = 4096;
FILE *minfo = NULL; struct mountinfo_s data = {
char buffer[4096]; .device = device,
char target[PATH_MAX]; };
struct dm_info info;
unsigned maj, min;
dm_bitset_t minors; /* Bitset for active thin pool minors */
if (!dm_task_get_info(dmt, &info)) if (!dm_task_get_info(dmt, &data.info))
return; return;
dmeventd_lvm2_unlock(); dmeventd_lvm2_unlock();
if (!(minors = dm_bitset_create(NULL, MINORS))) { if (!(data.minors = dm_bitset_create(NULL, MINORS))) {
syslog(LOG_ERR, "Failed to allocate bitset. Not unmounting %s.\n", device); syslog(LOG_ERR, "Failed to allocate bitset. Not unmounting %s.\n", device);
goto out; goto out;
} }
if (!(minfo = fopen(mountinfo, "r"))) { if (!_find_all_devs(data.minors, data.info.major, data.info.minor)) {
syslog(LOG_ERR, "Could not read %s. Not umounting %s.\n", mountinfo, device);
goto out;
}
if (!_find_all_devs(minors, info.major, info.minor)) {
syslog(LOG_ERR, "Failed to detect mounted volumes for %s.\n", device); syslog(LOG_ERR, "Failed to detect mounted volumes for %s.\n", device);
goto out; goto out;
} }
while (!feof(minfo)) { if (!dm_mountinfo_read(_umount_device, &data)) {
/* read mountinfo line */ syslog(LOG_ERR, "Could not parse mountinfo file.\n");
if (!fgets(buffer, sizeof(buffer), minfo)) goto out;
break; /* eof, likely */
if (_parse_mountinfo_line(buffer, &maj, &min, target) &&
(maj == info.major) && dm_bit(minors, min)) {
syslog(LOG_INFO, "Unmounting thin volume %s from %s.\n",
device, target);
if (!_run(UMOUNT_COMMAND, "-fl", target, NULL))
syslog(LOG_ERR, "Failed to umount thin %s from %s: %s.\n",
device, target, strerror(errno));
}
} }
out: out:
if (minfo && fclose(minfo)) if (data.minors)
syslog(LOG_ERR, "Failed to close %s\n", mountinfo); dm_bitset_destroy(data.minors);
if (minors)
dm_bitset_destroy(minors);
dmeventd_lvm2_lock(); dmeventd_lvm2_lock();
} }