1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-10-27 01:55:10 +03:00

Add dm_device_has_holders fn to to check use of the device by another device.

Add dm_device_has_mounted_fs fn to check mounted filesystem on a device.

This requires sysfs directory to be correctly set via dm_set_sysfs_dir
(/sys by default). If sysfs dir is not used or it's set incorrectly,
dm_device_has_{holders,mounted_fs} will return 0!
This commit is contained in:
Peter Rajnoha 2011-09-22 17:23:35 +00:00
parent 07e237d6f4
commit 14254bd0be
4 changed files with 137 additions and 0 deletions

View File

@ -1,5 +1,7 @@
Version 1.02.68 -
==================================
Add dm_device_has_mounted_fs fn to check mounted filesystem on a device.
Add dm_device_has_holders fn to to check use of the device by another device.
Add dm_sysfs_dir to libdevmapper to retrieve sysfs location thas is set.
Add dm_set_sysfs_dir to libdevmapper to set sysfs location.
Add --retry option for dmsetup remove to retry removal if not successful.

View File

@ -266,6 +266,19 @@ const char *dm_sysfs_dir(void);
*/
int dm_is_dm_major(uint32_t major);
/*
* Determine whether a device has any holders (devices
* using this device). If sysfs is not used (or configured
* incorrectly), returns 0.
*/
int dm_device_has_holders(uint32_t major, uint32_t minor);
/*
* Determine whether a device contains mounted filesystem.
* If sysfs is not used (or configured incorrectly), returns 0.
*/
int dm_device_has_mounted_fs(uint32_t major, uint32_t minor);
/*
* Release library resources
*/
@ -1069,6 +1082,8 @@ void dm_unescape_colons_and_at_signs(char *src,
*/
int dm_create_dir(const char *dir);
int dm_is_empty_dir(const char *dir);
/*
* Close a stream, with nicer error checking than fclose's.
* Derived from gnulib's close-stream.c.

View File

@ -1056,6 +1056,106 @@ const char *dm_sysfs_dir(void)
return _sysfs_dir;
}
int dm_device_has_holders(uint32_t major, uint32_t minor)
{
char sysfs_path[PATH_MAX];
struct stat st;
if (!*_sysfs_dir)
return 0;
if (dm_snprintf(sysfs_path, PATH_MAX, "%sdev/block/%" PRIu32
":%" PRIu32 "/holders", _sysfs_dir, major, minor) < 0) {
log_error("sysfs_path dm_snprintf failed");
return 0;
}
if (stat(sysfs_path, &st)) {
log_sys_error("stat", sysfs_path);
return 0;
}
return !dm_is_empty_dir(sysfs_path);
}
static int _mounted_fs_on_device(const char *kernel_dev_name)
{
char sysfs_path[PATH_MAX];
struct dirent *dirent;
DIR *d;
struct stat st;
int r = 0;
if (dm_snprintf(sysfs_path, PATH_MAX, "%sfs", _sysfs_dir) < 0) {
log_error("sysfs_path dm_snprintf failed");
return 0;
}
if (!(d = opendir(sysfs_path))) {
if (errno != ENOENT)
log_sys_error("opendir", sysfs_path);
return 0;
}
while ((dirent = readdir(d))) {
if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, ".."))
continue;
if (dm_snprintf(sysfs_path, PATH_MAX, "%sfs/%s/%s",
_sysfs_dir, dirent->d_name, kernel_dev_name) < 0) {
log_error("sysfs_path dm_snprintf failed");
break;
}
if (!stat(sysfs_path, &st)) {
/* found! */
r = 1;
break;
}
else if (errno != ENOENT) {
log_sys_error("stat", sysfs_path);
break;
}
}
if (closedir(d))
log_error("_fs_present_on_device: %s: closedir failed", kernel_dev_name);
return r;
}
int dm_device_has_mounted_fs(uint32_t major, uint32_t minor)
{
char sysfs_path[PATH_MAX];
char temp_path[PATH_MAX];
char *kernel_dev_name;
ssize_t size;
if (!*_sysfs_dir)
return 0;
/* Get kernel device name first */
if (dm_snprintf(sysfs_path, PATH_MAX, "%sdev/block/%" PRIu32 ":%" PRIu32,
_sysfs_dir, major, minor) < 0) {
log_error("sysfs_path dm_snprintf failed");
return 0;
}
if ((size = readlink(sysfs_path, temp_path, PATH_MAX)) < 0) {
log_sys_error("readlink", sysfs_path);
return 0;
}
if (!(kernel_dev_name = strrchr(temp_path, '/'))) {
log_error("Could not locate device kernel name in sysfs path %s", temp_path);
return 0;
}
kernel_dev_name += 1;
/* Check /sys/fs/<fs_name>/<kernel_dev_name> presence */
return _mounted_fs_on_device(kernel_dev_name);
}
int dm_mknodes(const char *name)
{
struct dm_task *dmt;

View File

@ -76,6 +76,26 @@ int dm_create_dir(const char *dir)
return 0;
}
int dm_is_empty_dir(const char *dir)
{
struct dirent *dirent;
DIR *d;
if (!(d = opendir(dir))) {
log_sys_error("opendir", dir);
return 0;
}
while ((dirent = readdir(d)))
if (strcmp(dirent->d_name, ".") && strcmp(dirent->d_name, ".."))
break;
if (closedir(d))
log_sys_error("closedir", dir);
return dirent ? 0 : 1;
}
int dm_fclose(FILE *stream)
{
int prev_fail = ferror(stream);