summaryrefslogtreecommitdiffstats
path: root/libdm/libdm-common.c
diff options
context:
space:
mode:
authorPeter Rajnoha <prajnoha@redhat.com>2011-09-22 17:23:35 +0000
committerPeter Rajnoha <prajnoha@redhat.com>2011-09-22 17:23:35 +0000
commit14254bd0be6b4979c4a2d90d4b12e70af0a61396 (patch)
tree9c6cbfa0c593ee2c2fe0e4f74cefda2df8f34796 /libdm/libdm-common.c
parent07e237d6f449ff2cdb09584cdd80baac0c4a5822 (diff)
downloadlvm2-14254bd0be6b4979c4a2d90d4b12e70af0a61396.tar.gz
lvm2-14254bd0be6b4979c4a2d90d4b12e70af0a61396.tar.xz
lvm2-14254bd0be6b4979c4a2d90d4b12e70af0a61396.zip
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!
Diffstat (limited to 'libdm/libdm-common.c')
-rw-r--r--libdm/libdm-common.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c
index cbdbc22c..b62b712f 100644
--- a/libdm/libdm-common.c
+++ b/libdm/libdm-common.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;