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.
*
@ -53,53 +53,6 @@ struct dso_state {
# define MKDEV(x,y) makedev((x),(y))
#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 */
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 */
}
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.
* TODO: work with read-only thin pool support
*/
static void _umount(struct dm_task *dmt, const char *device)
{
static const char mountinfo[] = "/proc/self/mountinfo";
static const size_t MINORS = 4096;
FILE *minfo = NULL;
char buffer[4096];
char target[PATH_MAX];
struct dm_info info;
unsigned maj, min;
dm_bitset_t minors; /* Bitset for active thin pool minors */
struct mountinfo_s data = {
.device = device,
};
if (!dm_task_get_info(dmt, &info))
if (!dm_task_get_info(dmt, &data.info))
return;
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);
goto out;
}
if (!(minfo = fopen(mountinfo, "r"))) {
syslog(LOG_ERR, "Could not read %s. Not umounting %s.\n", mountinfo, device);
goto out;
}
if (!_find_all_devs(minors, info.major, info.minor)) {
if (!_find_all_devs(data.minors, data.info.major, data.info.minor)) {
syslog(LOG_ERR, "Failed to detect mounted volumes for %s.\n", device);
goto out;
}
while (!feof(minfo)) {
/* read mountinfo line */
if (!fgets(buffer, sizeof(buffer), minfo))
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));
}
if (!dm_mountinfo_read(_umount_device, &data)) {
syslog(LOG_ERR, "Could not parse mountinfo file.\n");
goto out;
}
out:
if (minfo && fclose(minfo))
syslog(LOG_ERR, "Failed to close %s\n", mountinfo);
if (minors)
dm_bitset_destroy(minors);
if (data.minors)
dm_bitset_destroy(data.minors);
dmeventd_lvm2_lock();
}