From: Karel Zak Date: Fri, 18 Sep 2009 08:19:59 +0000 (+0200) Subject: libblkid: allows more probing methods for topology chain X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bf539f48f37da7a3609350ce4e9839921527de23;p=util-linux libblkid: allows more probing methods for topology chain This patch moves the current topology code to the separate sysfs.c file. Signed-off-by: Karel Zak --- diff --git a/shlibs/blkid/src/topology/Makefile.am b/shlibs/blkid/src/topology/Makefile.am index 9ba10e4d..ae72eb4d 100644 --- a/shlibs/blkid/src/topology/Makefile.am +++ b/shlibs/blkid/src/topology/Makefile.am @@ -4,4 +4,6 @@ AM_CPPFLAGS += -I$(ul_libblkid_srcdir) libblkid_topology_la_LIBADD = noinst_LTLIBRARIES = libblkid_topology.la -libblkid_topology_la_SOURCES = topology.c +libblkid_topology_la_SOURCES = topology.c \ + topology.h \ + sysfs.c diff --git a/shlibs/blkid/src/topology/sysfs.c b/shlibs/blkid/src/topology/sysfs.c new file mode 100644 index 00000000..f4e63a2c --- /dev/null +++ b/shlibs/blkid/src/topology/sysfs.c @@ -0,0 +1,156 @@ +/* + * sysfs based topology -- gathers topology information from Linux sysfs + * + * Copyright (C) 2009 Karel Zak + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "topology.h" + +static unsigned long dev_topology_attribute(const char *attribute, + dev_t dev, dev_t *primary) +{ + const char *sysfs_fmt_str = "/sys/dev/block/%d:%d/%s"; + char path[PATH_MAX]; + int len; + FILE *fp = NULL; + struct stat info; + unsigned long result = 0UL; + + len = snprintf(path, sizeof(path), sysfs_fmt_str, + major(dev), minor(dev), attribute); + if (len < 0 || len + 1 > sizeof(path)) + goto err; + + /* + * 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 (stat(path, &info) < 0) { + if (!*primary && + blkid_devno_to_wholedisk(dev, NULL, 0, primary)) + goto err; + + /* get attribute from partition's primary device */ + len = snprintf(path, sizeof(path), sysfs_fmt_str, + major(*primary), minor(*primary), attribute); + if (len < 0 || len + 1 > sizeof(path)) + goto err; + } + + fp = fopen(path, "r"); + if (!fp) { + DBG(DEBUG_LOWPROBE, printf( + "topology: %s: fopen failed, errno=%d\n", path, errno)); + goto err; + } + + if (fscanf(fp, "%lu", &result) != 1) { + DBG(DEBUG_LOWPROBE, printf( + "topology: %s: unexpected file format\n", path)); + goto err; + } + + fclose(fp); + + DBG(DEBUG_LOWPROBE, + printf("topology: attribute %s = %lu\n", attribute, result)); + + return result; +err: + if (fp) + fclose(fp); + DBG(DEBUG_LOWPROBE, + printf("topology: failed to read %s attribute\n", attribute)); + return 0; +} + +/* + * Sysfs topology values + */ +static struct topology_val { + const char *val_name; /* NAME=value */ + const char *sysfs_name; /* /sys/dev/block/:/NAME */ + const size_t bin_offset; /* blkid_struct_topology member */ +} topology_vals[] = { + { "ALIGNMENT_OFFSET", "alignment_offset", + offsetof(struct blkid_struct_topology, alignment_offset) }, + { "MINIMUM_IO_SIZE", "queue/minimum_io_size", + offsetof(struct blkid_struct_topology, minimum_io_size) }, + {"OPTIMAL_IO_SIZE", "queue/optimal_io_size", + offsetof(struct blkid_struct_topology, optimal_io_size) } +}; + +static int set_value(blkid_probe pr, struct blkid_chain *chn, + struct topology_val *val, unsigned long data) +{ + if (chn->binary) { + unsigned long *v = + (unsigned long *) (chn->data + val->bin_offset); + *v = data; + return 0; + } + return blkid_probe_sprintf_value(pr, val->val_name, "%llu", data); +} + + +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; + struct blkid_chain *chn; + + dev = blkid_probe_get_devno(pr); + if (!dev) + goto nothing; /* probably not a block device */ + + chn = blkid_probe_get_chain(pr); + if (!chn) + goto err; + + 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; + + rc = set_value(pr, chn, val, data); + if (rc) + goto err; + count++; + } + + if (count) + return 0; +nothing: + return 1; +err: + return -1; +} + +const struct blkid_idinfo sysfs_tp_idinfo = +{ + .name = "sysfs", + .probefunc = probe_sysfs_tp, + .magics = BLKID_NONE_MAGIC +}; + diff --git a/shlibs/blkid/src/topology/topology.c b/shlibs/blkid/src/topology/topology.c index b4240543..26930cfa 100644 --- a/shlibs/blkid/src/topology/topology.c +++ b/shlibs/blkid/src/topology/topology.c @@ -5,25 +5,13 @@ * * This file may be redistributed under the terms of the * GNU Lesser General Public License. - * - * NOTE: this chain supports one probing method only, so it's implemented - * without array of probing functions (idinfos array). - * - * This chain does not support probing functions filtering. The chain - * could be enable or disabled only. */ #include #include #include -#include -#include -#include -#include -#include -#include "blkdev.h" -#include "blkidP.h" +#include "topology.h" /** * SECTION:topology @@ -54,6 +42,15 @@ static int topology_probe(blkid_probe pr, struct blkid_chain *chn); static void topology_free(blkid_probe pr, void *data); +/* + * Topology chain probing functions + */ +static const struct blkid_idinfo *idinfos[] = +{ + &sysfs_tp_idinfo +}; + + /* * Driver definition */ @@ -61,20 +58,13 @@ const struct blkid_chaindrv topology_drv = { .id = BLKID_CHAIN_TOPLGY, .name = "topology", .dflt_enabled = FALSE, + .idinfos = idinfos, + .nidinfos = ARRAY_SIZE(idinfos), .probe = topology_probe, .safeprobe = topology_probe, .free_data = topology_free }; -/* - * Binary interface - */ -struct blkid_struct_topology { - unsigned long alignment_offset; - unsigned long minimum_io_size; - unsigned long optimal_io_size; -}; - /** * blkid_probe_enable_topology: * @pr: probe @@ -110,109 +100,17 @@ blkid_topology blkid_probe_get_topology(blkid_probe pr) &pr->chains[BLKID_CHAIN_TOPLGY]); } -static unsigned long -dev_topology_attribute(const char *attribute, dev_t dev, dev_t *primary) -{ - const char *sysfs_fmt_str = "/sys/dev/block/%d:%d/%s"; - char path[PATH_MAX]; - int len; - FILE *fp = NULL; - struct stat info; - unsigned long result = 0UL; - - len = snprintf(path, sizeof(path), sysfs_fmt_str, - major(dev), minor(dev), attribute); - if (len < 0 || len + 1 > sizeof(path)) - goto err; - - /* - * 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 (stat(path, &info) < 0) { - if (!*primary && - blkid_devno_to_wholedisk(dev, NULL, 0, primary)) - goto err; - - /* get attribute from partition's primary device */ - len = snprintf(path, sizeof(path), sysfs_fmt_str, - major(*primary), minor(*primary), attribute); - if (len < 0 || len + 1 > sizeof(path)) - goto err; - } - - fp = fopen(path, "r"); - if (!fp) { - DBG(DEBUG_LOWPROBE, printf( - "topology: %s: fopen failed, errno=%d\n", path, errno)); - goto err; - } - - if (fscanf(fp, "%lu", &result) != 1) { - DBG(DEBUG_LOWPROBE, printf( - "topology: %s: unexpected file format\n", path)); - goto err; - } - - fclose(fp); - - DBG(DEBUG_LOWPROBE, - printf("topology: attribute %s = %lu (sectors)\n", attribute, result)); - - return result; -err: - if (fp) - fclose(fp); - DBG(DEBUG_LOWPROBE, - printf("topology: failed to read %s attribute\n", attribute)); - return 0; -} - -/* - * Topology values - */ -static struct topology_val { - const char *val_name; /* NAME=value */ - const char *sysfs_name; /* /sys/dev/block/:/NAME */ - const size_t bin_offset; /* blkid_struct_topology member */ -} topology_vals[] = { - { "ALIGNMENT_OFFSET", "alignment_offset", - offsetof(struct blkid_struct_topology, alignment_offset) }, - { "MINIMUM_IO_SIZE", "queue/minimum_io_size", - offsetof(struct blkid_struct_topology, minimum_io_size) }, - {"OPTIMAL_IO_SIZE", "queue/optimal_io_size", - offsetof(struct blkid_struct_topology, optimal_io_size) } -}; - -static int topology_set_value(blkid_probe pr, struct blkid_chain *chn, - struct topology_val *val, unsigned long data) -{ - if (chn->binary) { - unsigned long *v = - (unsigned long *) (chn->data + val->bin_offset); - *v = data; - return 0; - } - return blkid_probe_sprintf_value(pr, val->val_name, "%llu", data); -} - /* * The blkid_do_probe() backend. */ static int topology_probe(blkid_probe pr, struct blkid_chain *chn) { - dev_t dev, pri_dev = 0; - int i, rc = 0, count = 0; + int i = 0; - if (!pr) + if (!pr || chn->idx < -1) + return -1; + if (chn->idx < -1) return -1; - - blkid_probe_chain_reset_vals(pr, chn); - - dev = blkid_probe_get_devno(pr); - if (!dev) - return 1; /* no result */ if (chn->binary) { DBG(DEBUG_LOWPROBE, printf("initialize topology binary data\n")); @@ -229,33 +127,36 @@ static int topology_probe(blkid_probe pr, struct blkid_chain *chn) } } - DBG(DEBUG_LOWPROBE, printf("--> starting probing loop [TOPOLOGY]\n")); + blkid_probe_chain_reset_vals(pr, chn); + + DBG(DEBUG_LOWPROBE, + printf("--> starting probing loop [TOPOLOGY idx=%d]\n", + chn->idx)); - for (i = 0; i < ARRAY_SIZE(topology_vals); i++) { - struct topology_val *val = &topology_vals[i]; - unsigned long data; + i = chn->idx + 1; - /* - * 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; + for ( ; i < ARRAY_SIZE(idinfos); i++) { + const struct blkid_idinfo *id = idinfos[i]; - rc = topology_set_value(pr, chn, val, data); - if (rc) - break; /* error */ - count++; - } + chn->idx = i; + if (id->probefunc) { + DBG(DEBUG_LOWPROBE, printf( + "%s: call probefunc()\n", id->name)); + if (id->probefunc(pr, NULL) != 0) + continue; + } - if (rc == 0 && count == 0) - rc = 1; /* no result */ + DBG(DEBUG_LOWPROBE, + printf("<-- leaving probing loop (type=%s) [TOPOLOGY idx=%d]\n", + id->name, chn->idx)); + return 0; + } DBG(DEBUG_LOWPROBE, - printf("<-- leaving probing loop [TOPOLOGY, rc=%d]\n", rc)); - return rc; + printf("<-- leaving probing loop (failed) [TOPOLOGY idx=%d]\n", + chn->idx)); + return 1; } static void topology_free(blkid_probe pr, void *data) diff --git a/shlibs/blkid/src/topology/topology.h b/shlibs/blkid/src/topology/topology.h new file mode 100644 index 00000000..ecb28454 --- /dev/null +++ b/shlibs/blkid/src/topology/topology.h @@ -0,0 +1,21 @@ +#ifndef BLKID_TOPOLOGY_H +#define BLKID_TOPOLOGY_H + +#include "blkidP.h" + +/* + * Binary interface + */ +struct blkid_struct_topology { + unsigned long alignment_offset; + unsigned long minimum_io_size; + unsigned long optimal_io_size; +}; + +/* + * topology probers + */ +extern const struct blkid_idinfo sysfs_tp_idinfo; + +#endif /* BLKID_TOPOLOGY_H */ +