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);
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];
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)
{
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++) {
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 }
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++;
#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/<maj>:<min>/NAME */
- const char *sysfs_name;
+ /* /sys/dev/block/<maj>:<min>/<ATTR> */
+ 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 },
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)
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++;
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)
#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);