mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-22 17:35:59 +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:
parent
1f92ab6e8a
commit
def057522f
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user