1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-30 17:18:21 +03:00

Add dm_device_get_name to get map name or block device name for given devno.

This is accomplished by reading associated sysfs information. For a dm device,
this is /sys/dev/block/major:minor/dm/name (supported in kernel version >= 2.6.29,
for older kernels, the behaviour is the same as for non-dm devices).

For a non-dm device, this is a readlink on /sys/dev/block/major:minor, e.g.
  /sys/dev/block/253:0 --> ../../devices/virtual/block/dm-0.
The last component of the path is a proper kernel name (block device name).

One can request to read only kernel names by setting the 'prefer_kernel_name'
argument if needed.
This commit is contained in:
Peter Rajnoha 2012-01-11 12:34:44 +00:00
parent 2e5ff5d11c
commit 17c3e42b21
3 changed files with 145 additions and 23 deletions

View File

@ -1,5 +1,6 @@
Version 1.02.68 -
==================================
Add dm_device_get_name to get map name or block device name for given devno.
Remove empty devices when clearing left-over inactive tables in deptree.
Add dm_uuid_prefix/dm_set_uuid_prefix to override hard-coded LVM- prefix.
Improve dmsetup man page about readahead parameter.

View File

@ -299,6 +299,21 @@ const char *dm_uuid_prefix(void);
*/
int dm_is_dm_major(uint32_t major);
/*
* Get associated device name for given major and minor number by reading
* the sysfs content. If this is a dm device, get associated dm name, the one
* that appears in /dev/mapper. DM names could be resolved this way only if
* kernel used >= 2.6.29, kernel name is found otherwise (e.g. dm-0).
* If prefer_kernel_name is set, the kernel name is always preferred over
* device-mapper name for dm devices no matter what the kernel version is.
* For non-dm devices, we always get associated kernel name, e.g sda, md0 etc.
* Returns 0 on error or if sysfs is not used (or configured incorrectly),
* otherwise returns 1 and the supplied buffer holds the device name.
*/
int dm_device_get_name(uint32_t major, uint32_t minor,
int prefer_kernel_name,
char *buf, size_t buf_size);
/*
* Determine whether a device has any holders (devices
* using this device). If sysfs is not used (or configured

View File

@ -1165,6 +1165,133 @@ const char *dm_uuid_prefix(void)
return _default_uuid_prefix;
}
static int _sysfs_get_dm_name(uint32_t major, uint32_t minor, char *buf, size_t buf_size)
{
char *sysfs_path, *temp_buf;
FILE *fp;
if (!(sysfs_path = dm_malloc(PATH_MAX)) ||
!(temp_buf = dm_malloc(PATH_MAX))) {
log_error("_sysfs_get_dm_name: failed to allocate temporary buffers");
if (sysfs_path)
dm_free(sysfs_path);
return 0;
}
if (dm_snprintf(sysfs_path, PATH_MAX, "%sdev/block/%" PRIu32 ":%" PRIu32
"/dm/name", _sysfs_dir, major, minor) < 0) {
log_error("_sysfs_get_dm_name: dm_snprintf failed");
goto error;
}
if (!(fp = fopen(sysfs_path, "r"))) {
if (errno != ENOENT)
log_sys_error("fopen", sysfs_path);
else
log_sys_debug("fopen", sysfs_path);
goto error;
}
if (!fgets(temp_buf, PATH_MAX, fp)) {
log_sys_error("fgets", sysfs_path);
goto error;
}
temp_buf[strlen(temp_buf) - 1] = '\0';
if (fclose(fp))
log_sys_error("fclose", sysfs_path);
if (buf_size < strlen(temp_buf) + 1) {
log_error("_sysfs_get_dm_name: supplied buffer too small");
goto error;
}
strncpy(buf, temp_buf, buf_size);
dm_free(sysfs_path);
dm_free(temp_buf);
return 1;
error:
dm_free(sysfs_path);
dm_free(temp_buf);
return 0;
}
static int _sysfs_get_kernel_name(uint32_t major, uint32_t minor, char *buf, size_t buf_size)
{
char *sysfs_path, *temp_buf, *name;
ssize_t size;
if (!(sysfs_path = dm_malloc(PATH_MAX)) ||
!(temp_buf = dm_malloc(PATH_MAX))) {
log_error("_sysfs_get_kernel_name: failed to allocate temporary buffers");
if (sysfs_path)
dm_free(sysfs_path);
return 0;
}
if (dm_snprintf(sysfs_path, PATH_MAX, "%sdev/block/%" PRIu32 ":%" PRIu32,
_sysfs_dir, major, minor) < 0) {
log_error("_sysfs_get_kernel_name: dm_snprintf failed");
goto error;
}
if ((size = readlink(sysfs_path, temp_buf, PATH_MAX)) < 0) {
if (errno != ENOENT)
log_sys_error("readlink", sysfs_path);
else
log_sys_debug("readlink", sysfs_path);
goto error;
}
temp_buf[size] = '\0';
if (!(name = strrchr(temp_buf, '/'))) {
log_error("Could not locate device kernel name in sysfs path %s", temp_buf);
goto error;
}
name += 1;
if (buf_size < strlen(name) + 1) {
log_error("_sysfs_get_kernel_name: output buffer too small");
goto error;
}
strncpy(buf, name, buf_size);
dm_free(sysfs_path);
dm_free(temp_buf);
return 1;
error:
dm_free(sysfs_path);
dm_free(temp_buf);
return 0;
}
int dm_device_get_name(uint32_t major, uint32_t minor, int prefer_kernel_name,
char *buf, size_t buf_size)
{
if (!*_sysfs_dir)
return 0;
/*
* device-mapper devices and prefer_kernel_name = 0
* get dm name by reading /sys/dev/block/major:minor/dm/name,
* fallback to _sysfs_get_kernel_name if not successful
*/
if (dm_is_dm_major(major) && !prefer_kernel_name) {
if (_sysfs_get_dm_name(major, minor, buf, buf_size))
return 1;
else
stack;
}
/*
* non-device-mapper devices or prefer_kernel_name = 1
* get kernel name using readlink /sys/dev/block/major:minor -> .../dm-X
*/
return _sysfs_get_kernel_name(major, minor, buf, buf_size);
}
int dm_device_has_holders(uint32_t major, uint32_t minor)
{
char sysfs_path[PATH_MAX];
@ -1235,32 +1362,11 @@ static int _mounted_fs_on_device(const char *kernel_dev_name)
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;
char kernel_dev_name[PATH_MAX];
/* 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");
if (!dm_device_get_name(major, minor, 1, kernel_dev_name, PATH_MAX))
return 0;
}
if ((size = readlink(sysfs_path, temp_path, PATH_MAX)) < 0) {
log_sys_error("readlink", sysfs_path);
return 0;
}
temp_path[size] = '\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);