From 25d1e630f6e32f05454ba38e5c4fdd03b66de589 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 3 Mar 2010 13:12:02 +0100 Subject: [PATCH] libblkid: support alignment_offset=-1 Unfortunately, Linux kernel uses "signed int" for alignment_offset and the offset could be -1 for devices with undefined alignment (if no compatible sizes and alignments exist for stacked devices). There is no way how libblkid caller can respond to the value -1, so we are going to hide this corner case... TODO: maybe we can export an extra boolean value 'misaligned' rather then complete hide this problem. We will see... Signed-off-by: Karel Zak --- shlibs/blkid/src/blkidP.h | 4 +- shlibs/blkid/src/devno.c | 20 +++++- shlibs/blkid/src/partitions/partitions.c | 4 +- shlibs/blkid/src/topology/ioctl.c | 15 +++-- shlibs/blkid/src/topology/sysfs.c | 86 +++++++++++------------- shlibs/blkid/src/topology/topology.c | 18 ++++- shlibs/blkid/src/topology/topology.h | 2 +- 7 files changed, 89 insertions(+), 60 deletions(-) diff --git a/shlibs/blkid/src/blkidP.h b/shlibs/blkid/src/blkidP.h index c9b2bcd1..1de6dd06 100644 --- a/shlibs/blkid/src/blkidP.h +++ b/shlibs/blkid/src/blkidP.h @@ -333,8 +333,10 @@ struct dir_list { extern void blkid__scan_dir(char *, dev_t, struct dir_list **, char **); extern int blkid_driver_has_major(const char *drvname, int major); extern int blkid_devno_has_attribute(dev_t devno, const char *attribute); -extern int blkid_devno_get_attribute(dev_t devno, const char *attribute, +extern int blkid_devno_get_u64_attribute(dev_t devno, const char *attribute, uint64_t *result); +extern int blkid_devno_get_s64_attribute(dev_t devno, const char *attribute, + int64_t *result); /* lseek.c */ extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence); diff --git a/shlibs/blkid/src/devno.c b/shlibs/blkid/src/devno.c index 1b64ec1e..a667becf 100644 --- a/shlibs/blkid/src/devno.c +++ b/shlibs/blkid/src/devno.c @@ -478,7 +478,7 @@ int blkid_devno_has_attribute(dev_t devno, const char *attribute) return 0; } -int blkid_devno_get_attribute(dev_t devno, const char *attribute, uint64_t *result) +int blkid_devno_get_u64_attribute(dev_t devno, const char *attribute, uint64_t *result) { FILE *f; char path[PATH_MAX]; @@ -496,6 +496,24 @@ int blkid_devno_get_attribute(dev_t devno, const char *attribute, uint64_t *resu return rc == 1 ? 0 : -1; } +int blkid_devno_get_s64_attribute(dev_t devno, const char *attribute, int64_t *result) +{ + FILE *f; + char path[PATH_MAX]; + int rc = 0; + + if (!mk_devno_attribute_path(path, sizeof(path), devno, attribute)) + return -1; + + f = fopen(path, "r"); + if (f) { + rc = fscanf(f, "%" SCNd64, result); + fclose(f); + } + + return rc == 1 ? 0 : -1; +} + #ifdef TEST_PROGRAM int main(int argc, char** argv) { diff --git a/shlibs/blkid/src/partitions/partitions.c b/shlibs/blkid/src/partitions/partitions.c index 9c3296e9..0f342fc8 100644 --- a/shlibs/blkid/src/partitions/partitions.c +++ b/shlibs/blkid/src/partitions/partitions.c @@ -828,9 +828,9 @@ blkid_partition blkid_partlist_devno_to_partition(blkid_partlist ls, dev_t devno uint64_t start, size; int i; - if (blkid_devno_get_attribute(devno, "start", &start)) + if (blkid_devno_get_u64_attribute(devno, "start", &start)) return NULL; - if (blkid_devno_get_attribute(devno, "size", &size)) + if (blkid_devno_get_u64_attribute(devno, "size", &size)) return NULL; for (i = 0; i < ls->nparts; i++) { diff --git a/shlibs/blkid/src/topology/ioctl.c b/shlibs/blkid/src/topology/ioctl.c index 709b2f45..e85ecdf9 100644 --- a/shlibs/blkid/src/topology/ioctl.c +++ b/shlibs/blkid/src/topology/ioctl.c @@ -26,11 +26,12 @@ static struct topology_val { long ioc; - /* function to set probing resut */ - int (*set_result)(blkid_probe, unsigned long); + /* functions to set probing resut */ + int (*set_ulong)(blkid_probe, unsigned long); + int (*set_int)(blkid_probe, int); } topology_vals[] = { - { BLKALIGNOFF, blkid_topology_set_alignment_offset }, + { BLKALIGNOFF, NULL, blkid_topology_set_alignment_offset }, { BLKIOMIN, blkid_topology_set_minimum_io_size }, { BLKIOOPT, blkid_topology_set_optimal_io_size }, { BLKPBSZGET, blkid_topology_set_physical_sector_size } @@ -44,12 +45,16 @@ static int probe_ioctl_tp(blkid_probe pr, const struct blkid_idmag *mag) for (i = 0; i < ARRAY_SIZE(topology_vals); i++) { struct topology_val *val = &topology_vals[i]; + int rc = 1; unsigned int data; - int rc; if (ioctl(pr->fd, val->ioc, &data) == -1) goto nothing; - rc = val->set_result(pr, (unsigned long) data); + + if (val->set_int) + rc = val->set_int(pr, (int) data); + else + rc = val->set_ulong(pr, (unsigned long) data); if (rc) goto err; count++; diff --git a/shlibs/blkid/src/topology/sysfs.c b/shlibs/blkid/src/topology/sysfs.c index ce870f22..25e2b0aa 100644 --- a/shlibs/blkid/src/topology/sysfs.c +++ b/shlibs/blkid/src/topology/sysfs.c @@ -19,51 +19,20 @@ #include "topology.h" -static unsigned long dev_topology_attribute(const char *attribute, - dev_t dev, dev_t *primary) -{ - uint64_t result; - - /* - * check if the desired sysfs attribute exists - * - if not: either the kernel doesn't have topology support or the - * device could be a partition - */ - if (!blkid_devno_has_attribute(dev, attribute)) { - if (!*primary && - blkid_devno_to_wholedisk(dev, NULL, 0, primary)) - goto err; - - /* get attribute from partition's primary device */ - dev = *primary; - } - - if (blkid_devno_get_attribute(dev, attribute, &result)) - goto err; - - DBG(DEBUG_LOWPROBE, - printf("topology: attribute %s = %" PRIu64 "\n", attribute, result)); - - return result; -err: - DBG(DEBUG_LOWPROBE, - printf("topology: failed to read %s attribute\n", attribute)); - return 0; -} - /* * Sysfs topology values (since 2.6.31, May 2009). */ static struct topology_val { - /* /sys/dev/block/:/NAME */ - const char *sysfs_name; + /* /sys/dev/block/:/ */ + const char *attr; - /* function to set probing resut */ - int (*set_result)(blkid_probe, unsigned long); + /* functions to set probing resut */ + int (*set_ulong)(blkid_probe, unsigned long); + int (*set_int)(blkid_probe, int); } topology_vals[] = { - { "alignment_offset", blkid_topology_set_alignment_offset }, + { "alignment_offset", NULL, blkid_topology_set_alignment_offset }, { "queue/minimum_io_size", blkid_topology_set_minimum_io_size }, { "queue/optimal_io_size", blkid_topology_set_optimal_io_size }, { "queue/physical_block_size", blkid_topology_set_physical_sector_size }, @@ -72,7 +41,7 @@ static struct topology_val { static int probe_sysfs_tp(blkid_probe pr, const struct blkid_idmag *mag) { dev_t dev, pri_dev = 0; - int i, rc = 0, count = 0; + int i, count = 0; dev = blkid_probe_get_devno(pr); if (!dev) @@ -80,17 +49,38 @@ static int probe_sysfs_tp(blkid_probe pr, const struct blkid_idmag *mag) for (i = 0; i < ARRAY_SIZE(topology_vals); i++) { struct topology_val *val = &topology_vals[i]; - unsigned long data; - - /* - * Don't bother reporting any of the topology information - * if it's zero. - */ - data = dev_topology_attribute(val->sysfs_name, dev, &pri_dev); - if (!data) - continue; + dev_t attr_dev = dev; + int rc = 1; + + if (!blkid_devno_has_attribute(dev, val->attr)) { + /* get attribute from partition's primary device */ + if (!pri_dev && + blkid_devno_to_wholedisk(dev, NULL, 0, &pri_dev)) + continue; + attr_dev = pri_dev; + } + + if (val->set_ulong) { + uint64_t data = 0; + + if (blkid_devno_get_u64_attribute(attr_dev, + val->attr, &data)) + continue; + if (!data) + continue; + rc = val->set_ulong(pr, (unsigned long) data); + + } else if (val->set_int) { + int64_t data = 0; + + if (blkid_devno_get_s64_attribute(attr_dev, + val->attr, &data)) + continue; + if (!data) + continue; + rc = val->set_int(pr, (int) data); + } - rc = val->set_result(pr, data); if (rc) goto err; count++; diff --git a/shlibs/blkid/src/topology/topology.c b/shlibs/blkid/src/topology/topology.c index db97c5fb..fa49fd09 100644 --- a/shlibs/blkid/src/topology/topology.c +++ b/shlibs/blkid/src/topology/topology.c @@ -242,12 +242,26 @@ static int topology_is_complete(blkid_probe pr) return __blkid_probe_lookup_value(pr, "MINIMUM_IO_SIZE") ? TRUE : FALSE; } -int blkid_topology_set_alignment_offset(blkid_probe pr, unsigned long val) +int blkid_topology_set_alignment_offset(blkid_probe pr, int val) { + unsigned long xval; + + /* Welcome to Hell. The kernel is able to returns -1 as an + * alignment_offset if no compatible sizes and alignments + * exist for stacked devices. + * + * There is no way how libblkid caller can respond to the value -1, so + * we will hide this corner case... + * + * (TODO: maybe we can export an extra boolean value 'misaligned' rather + * then complete hide this problem.) + */ + xval = val < 0 ? 0 : val; + return topology_set_value(pr, "ALIGNMENT_OFFSET", offsetof(struct blkid_struct_topology, alignment_offset), - val); + xval); } int blkid_topology_set_minimum_io_size(blkid_probe pr, unsigned long val) diff --git a/shlibs/blkid/src/topology/topology.h b/shlibs/blkid/src/topology/topology.h index d4879204..b7429d90 100644 --- a/shlibs/blkid/src/topology/topology.h +++ b/shlibs/blkid/src/topology/topology.h @@ -3,7 +3,7 @@ #include "blkidP.h" -extern int blkid_topology_set_alignment_offset(blkid_probe pr, unsigned long val); +extern int blkid_topology_set_alignment_offset(blkid_probe pr, int val); extern int blkid_topology_set_minimum_io_size(blkid_probe pr, unsigned long val); extern int blkid_topology_set_optimal_io_size(blkid_probe pr, unsigned long val); extern int blkid_topology_set_physical_sector_size(blkid_probe pr, unsigned long val); -- 2.39.5