mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Handle new sysfs subsystem/block/devices directory structure.
This commit is contained in:
parent
5ca98cc229
commit
6aca8e9297
@ -1,5 +1,6 @@
|
|||||||
Version 2.02.29 -
|
Version 2.02.29 -
|
||||||
==================================
|
==================================
|
||||||
|
Handle new sysfs subsystem/block/devices directory structure.
|
||||||
Tests are run with LVM_SYSTEM_DIR pointing to private root and /dev dirs.
|
Tests are run with LVM_SYSTEM_DIR pointing to private root and /dev dirs.
|
||||||
Fix a bug in lvm_dump.sh checks for lvm/dmsetup binaries.
|
Fix a bug in lvm_dump.sh checks for lvm/dmsetup binaries.
|
||||||
Fix underquotations in lvm_dump.sh.
|
Fix underquotations in lvm_dump.sh.
|
||||||
|
@ -20,12 +20,14 @@
|
|||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
|
||||||
static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
|
static int _locate_sysfs_blocks(const char *proc, char *path, size_t len,
|
||||||
|
unsigned *sysfs_depth)
|
||||||
{
|
{
|
||||||
char proc_mounts[PATH_MAX];
|
char proc_mounts[PATH_MAX];
|
||||||
int r = 0;
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *split[4], buffer[PATH_MAX + 16];
|
char *split[4], buffer[PATH_MAX + 16];
|
||||||
|
const char *sys_mnt = NULL;
|
||||||
|
struct stat info;
|
||||||
|
|
||||||
if (!*proc) {
|
if (!*proc) {
|
||||||
log_verbose("No proc filesystem found: skipping sysfs filter");
|
log_verbose("No proc filesystem found: skipping sysfs filter");
|
||||||
@ -46,10 +48,7 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
|
|||||||
while (fgets(buffer, sizeof(buffer), fp)) {
|
while (fgets(buffer, sizeof(buffer), fp)) {
|
||||||
if (dm_split_words(buffer, 4, 0, split) == 4 &&
|
if (dm_split_words(buffer, 4, 0, split) == 4 &&
|
||||||
!strcmp(split[2], "sysfs")) {
|
!strcmp(split[2], "sysfs")) {
|
||||||
if (dm_snprintf(path, len, "%s/%s", split[1],
|
sys_mnt = split[1];
|
||||||
"block") >= 0) {
|
|
||||||
r = 1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,7 +56,70 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
|
|||||||
if (fclose(fp))
|
if (fclose(fp))
|
||||||
log_sys_error("fclose", proc_mounts);
|
log_sys_error("fclose", proc_mounts);
|
||||||
|
|
||||||
return r;
|
if (!sys_mnt) {
|
||||||
|
log_error("Failed to find sysfs mount point");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unified classification directory for all kernel subsystems
|
||||||
|
*
|
||||||
|
* /sys/subsystem/block/devices
|
||||||
|
* |-- sda -> ../../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda
|
||||||
|
* |-- sda1 -> ../../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1
|
||||||
|
* `-- sr0 -> ../../../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
if (dm_snprintf(path, len, "%s/%s", sys_mnt,
|
||||||
|
"subsystem/block/devices") >= 0) {
|
||||||
|
if (!stat(path, &info)) {
|
||||||
|
*sysfs_depth = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* block subsystem as a class
|
||||||
|
*
|
||||||
|
* /sys/class/block
|
||||||
|
* |-- sda -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda
|
||||||
|
* |-- sda1 -> ../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1
|
||||||
|
* `-- sr0 -> ../../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
if (dm_snprintf(path, len, "%s/%s", sys_mnt, "class/block") >= 0) {
|
||||||
|
if (!stat(path, &info)) {
|
||||||
|
*sysfs_depth = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* old block subsystem layout with nested directories
|
||||||
|
*
|
||||||
|
* /sys/block/
|
||||||
|
* |-- sda
|
||||||
|
* | |-- capability
|
||||||
|
* | |-- dev
|
||||||
|
* ...
|
||||||
|
* | |-- sda1
|
||||||
|
* | | |-- dev
|
||||||
|
* ...
|
||||||
|
* |
|
||||||
|
* `-- sr0
|
||||||
|
* |-- capability
|
||||||
|
* |-- dev
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
if (dm_snprintf(path, len, "%s/%s", sys_mnt, "block") >= 0) {
|
||||||
|
if (!stat(path, &info)) {
|
||||||
|
*sysfs_depth = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------
|
/*----------------------------------------------------------------
|
||||||
@ -72,11 +134,14 @@ struct entry {
|
|||||||
struct dev_set {
|
struct dev_set {
|
||||||
struct dm_pool *mem;
|
struct dm_pool *mem;
|
||||||
const char *sys_block;
|
const char *sys_block;
|
||||||
|
unsigned sysfs_depth;
|
||||||
int initialised;
|
int initialised;
|
||||||
struct entry *slots[SET_BUCKETS];
|
struct entry *slots[SET_BUCKETS];
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dev_set *_dev_set_create(struct dm_pool *mem, const char *sys_block)
|
static struct dev_set *_dev_set_create(struct dm_pool *mem,
|
||||||
|
const char *sys_block,
|
||||||
|
unsigned sysfs_depth)
|
||||||
{
|
{
|
||||||
struct dev_set *ds;
|
struct dev_set *ds;
|
||||||
|
|
||||||
@ -85,6 +150,7 @@ static struct dev_set *_dev_set_create(struct dm_pool *mem, const char *sys_bloc
|
|||||||
|
|
||||||
ds->mem = mem;
|
ds->mem = mem;
|
||||||
ds->sys_block = dm_pool_strdup(mem, sys_block);
|
ds->sys_block = dm_pool_strdup(mem, sys_block);
|
||||||
|
ds->sysfs_depth = sysfs_depth;
|
||||||
ds->initialised = 0;
|
ds->initialised = 0;
|
||||||
|
|
||||||
return ds;
|
return ds;
|
||||||
@ -168,13 +234,13 @@ static int _read_dev(const char *file, dev_t *result)
|
|||||||
/*
|
/*
|
||||||
* Recurse through sysfs directories, inserting any devs found.
|
* Recurse through sysfs directories, inserting any devs found.
|
||||||
*/
|
*/
|
||||||
static int _read_devs(struct dev_set *ds, const char *dir)
|
static int _read_devs(struct dev_set *ds, const char *dir, unsigned sysfs_depth)
|
||||||
{
|
{
|
||||||
struct dirent *d;
|
struct dirent *d;
|
||||||
DIR *dr;
|
DIR *dr;
|
||||||
unsigned char dtype;
|
|
||||||
struct stat info;
|
struct stat info;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
|
char file[PATH_MAX];
|
||||||
dev_t dev = { 0 };
|
dev_t dev = { 0 };
|
||||||
int r = 1;
|
int r = 1;
|
||||||
|
|
||||||
@ -194,30 +260,21 @@ static int _read_devs(struct dev_set *ds, const char *dir)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
dtype = d->d_type;
|
/* devices have a "dev" file */
|
||||||
|
if (dm_snprintf(file, sizeof(file), "%s/dev", path) < 0) {
|
||||||
if (dtype == DT_UNKNOWN) {
|
log_error("sysfs path name too long: %s in %s",
|
||||||
if (lstat(path, &info) >= 0) {
|
d->d_name, dir);
|
||||||
if (S_ISLNK(info.st_mode))
|
continue;
|
||||||
dtype = DT_LNK;
|
|
||||||
else if (S_ISDIR(info.st_mode))
|
|
||||||
dtype = DT_DIR;
|
|
||||||
else if (S_ISREG(info.st_mode))
|
|
||||||
dtype = DT_REG;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dtype == DT_DIR) {
|
if (!stat(file, &info)) {
|
||||||
if (!_read_devs(ds, path)) {
|
/* recurse if we found a device and expect subdirs */
|
||||||
r = 0;
|
if (sysfs_depth)
|
||||||
break;
|
_read_devs(ds, path, sysfs_depth - 1);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((dtype == DT_REG && !strcmp(d->d_name, "dev")))
|
/* add the device we have found */
|
||||||
if (!_read_dev(path, &dev) || !_set_insert(ds, dev)) {
|
if (_read_dev(file, &dev))
|
||||||
r = 0;
|
_set_insert(ds, dev);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +286,7 @@ static int _read_devs(struct dev_set *ds, const char *dir)
|
|||||||
|
|
||||||
static int _init_devs(struct dev_set *ds)
|
static int _init_devs(struct dev_set *ds)
|
||||||
{
|
{
|
||||||
if (!_read_devs(ds, ds->sys_block)) {
|
if (!_read_devs(ds, ds->sys_block, ds->sysfs_depth)) {
|
||||||
ds->initialised = -1;
|
ds->initialised = -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -267,11 +324,12 @@ static void _destroy(struct dev_filter *f)
|
|||||||
struct dev_filter *sysfs_filter_create(const char *proc)
|
struct dev_filter *sysfs_filter_create(const char *proc)
|
||||||
{
|
{
|
||||||
char sys_block[PATH_MAX];
|
char sys_block[PATH_MAX];
|
||||||
|
unsigned sysfs_depth;
|
||||||
struct dm_pool *mem;
|
struct dm_pool *mem;
|
||||||
struct dev_set *ds;
|
struct dev_set *ds;
|
||||||
struct dev_filter *f;
|
struct dev_filter *f;
|
||||||
|
|
||||||
if (!_locate_sysfs_blocks(proc, sys_block, sizeof(sys_block)))
|
if (!_locate_sysfs_blocks(proc, sys_block, sizeof(sys_block), &sysfs_depth))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!(mem = dm_pool_create("sysfs", 256))) {
|
if (!(mem = dm_pool_create("sysfs", 256))) {
|
||||||
@ -279,7 +337,7 @@ struct dev_filter *sysfs_filter_create(const char *proc)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(ds = _dev_set_create(mem, sys_block))) {
|
if (!(ds = _dev_set_create(mem, sys_block, sysfs_depth))) {
|
||||||
log_error("sysfs dev_set creation failed");
|
log_error("sysfs dev_set creation failed");
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user