mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
dev-type: dev_get_primary_dev fn: use dev_types and provide better return codes
The dev_get_primary_dev fn now returns: 0 if the dev is already a primary dev 1 if the dev is a partition, primary dev is returned in "result" (output arg) -1 on error This way, we can better differentiate between the error state and the state in which the dev supplied is not a partition in the caller (this was same return value before). Also, if we already have information about the device type, we can check its major number against the list of known device types (cmd->dev_types) directly, so we don't need to go through the sysfs - we only check the major:minor pair which is a bit more straightforward and faster. If the dev_types does not have any info about this device type, the code just fallbacks to the original sysfs interface to get the partition info.
This commit is contained in:
parent
c6f48b7c1a
commit
65d0089c64
@ -141,7 +141,7 @@ static int _md_sysfs_attribute_snprintf(char *path, size_t size,
|
||||
|
||||
if (MAJOR(dev) == dt->blkext_major) {
|
||||
/* lookup parent MD device from blkext partition */
|
||||
if (!dev_get_primary_dev(dt, blkdev, &dev))
|
||||
if (dev_get_primary_dev(dt, blkdev, &dev) < 1)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,7 @@ int dev_subsystem_part_major(struct dev_types *dt, struct device *dev)
|
||||
return 1;
|
||||
|
||||
if ((MAJOR(dev->dev) == dt->blkext_major) &&
|
||||
(dev_get_primary_dev(dt, dev, &primary_dev)) &&
|
||||
(dev_get_primary_dev(dt, dev, &primary_dev) > 0) &&
|
||||
(MAJOR(primary_dev) == dt->md_major))
|
||||
return 1;
|
||||
|
||||
@ -318,28 +318,60 @@ int dev_is_partitioned(struct dev_types *dt, struct device *dev)
|
||||
return _has_partition_table(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get primary dev for the dev supplied.
|
||||
* Returns:
|
||||
* 0 if the dev is already a primary dev
|
||||
* 1 if the dev is a partition, primary dev in result
|
||||
* -1 on error
|
||||
*/
|
||||
int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
|
||||
{
|
||||
const char *sysfs_dir = dm_sysfs_dir();
|
||||
int major = (int) MAJOR(dev->dev);
|
||||
int minor = (int) MINOR(dev->dev);
|
||||
char path[PATH_MAX+1];
|
||||
char temp_path[PATH_MAX+1];
|
||||
char buffer[64];
|
||||
struct stat info;
|
||||
FILE *fp;
|
||||
uint32_t pri_maj, pri_min;
|
||||
int size, ret = 0;
|
||||
FILE *fp = NULL;
|
||||
int parts, residue, size, ret = -1;
|
||||
|
||||
/*
|
||||
* Try to get the primary dev out of the
|
||||
* list of known device types first.
|
||||
*/
|
||||
if ((parts = dt->dev_type_array[major].max_partitions) > 1) {
|
||||
if ((residue = minor % parts)) {
|
||||
*result = MKDEV((dev_t)major, (minor - residue));
|
||||
ret = 1;
|
||||
} else {
|
||||
*result = dev->dev;
|
||||
ret = 0; /* dev is not a partition! */
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we can't get the primary dev out of the list of known device
|
||||
* types, try to look at sysfs directly then. This is more complex
|
||||
* way and it also requires certain sysfs layout to be present
|
||||
* which might not be there in old kernels!
|
||||
*/
|
||||
|
||||
/* check if dev is a partition */
|
||||
if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/partition",
|
||||
sysfs_dir, (int)MAJOR(dev->dev), (int)MINOR(dev->dev)) < 0) {
|
||||
sysfs_dir, major, minor) < 0) {
|
||||
log_error("dm_snprintf partition failed");
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (stat(path, &info) == -1) {
|
||||
if (errno != ENOENT)
|
||||
log_sys_error("stat", path);
|
||||
return ret;
|
||||
*result = dev->dev;
|
||||
ret = 0; goto out; /* dev is not a partition! */
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -351,7 +383,7 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
|
||||
*/
|
||||
if ((size = readlink(dirname(path), temp_path, PATH_MAX)) < 0) {
|
||||
log_sys_error("readlink", path);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
temp_path[size] = '\0';
|
||||
@ -359,7 +391,7 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
|
||||
if (dm_snprintf(path, PATH_MAX, "%s/block/%s/dev",
|
||||
sysfs_dir, basename(dirname(temp_path))) < 0) {
|
||||
log_error("dm_snprintf dev failed");
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* finally, parse 'dev' attribute and create corresponding dev_t */
|
||||
@ -368,13 +400,13 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
|
||||
log_error("sysfs file %s does not exist", path);
|
||||
else
|
||||
log_sys_error("stat", path);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fp = fopen(path, "r");
|
||||
if (!fp) {
|
||||
log_sys_error("fopen", path);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!fgets(buffer, sizeof(buffer), fp)) {
|
||||
@ -382,16 +414,15 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sscanf(buffer, "%d:%d", &pri_maj, &pri_min) != 2) {
|
||||
if (sscanf(buffer, "%d:%d", &major, &minor) != 2) {
|
||||
log_error("sysfs file %s not in expected MAJ:MIN format: %s",
|
||||
path, buffer);
|
||||
goto out;
|
||||
}
|
||||
*result = MKDEV((dev_t)pri_maj, pri_min);
|
||||
*result = MKDEV((dev_t)major, minor);
|
||||
ret = 1;
|
||||
|
||||
out:
|
||||
if (fclose(fp))
|
||||
if (fp && fclose(fp))
|
||||
log_sys_error("fclose", path);
|
||||
|
||||
return ret;
|
||||
@ -615,7 +646,7 @@ static unsigned long _dev_topology_attribute(struct dev_types *dt,
|
||||
log_sys_error("stat", path);
|
||||
return 0;
|
||||
}
|
||||
if (!dev_get_primary_dev(dt, dev, &primary))
|
||||
if (dev_get_primary_dev(dt, dev, &primary) < 0)
|
||||
return 0;
|
||||
|
||||
/* get attribute from partition's primary device */
|
||||
|
Loading…
Reference in New Issue
Block a user