summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarel Zak <kzak@redhat.com>2009-09-16 14:40:41 +0200
committerKarel Zak <kzak@redhat.com>2009-09-16 14:40:41 +0200
commitcc33d69328271f795e5b9ca7bd3f6500e0399acf (patch)
treeff5ec4f280427b159d8cb1f222a9b69de5dc0a78
parent0d44d469e2fbac66299e4b53274da1201af518c0 (diff)
downloadutil-linux-old-cc33d69328271f795e5b9ca7bd3f6500e0399acf.tar.gz
libblkid: add topology support
Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--configure.ac1
-rw-r--r--shlibs/blkid/src/Makefile.am7
-rw-r--r--shlibs/blkid/src/blkid.h19
-rw-r--r--shlibs/blkid/src/blkid.sym5
-rw-r--r--shlibs/blkid/src/blkidP.h4
-rw-r--r--shlibs/blkid/src/probe.c15
-rw-r--r--shlibs/blkid/src/topology/Makefile.am7
-rw-r--r--shlibs/blkid/src/topology/topology.c298
8 files changed, 353 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac
index 091d76b8..1c914d19 100644
--- a/configure.ac
+++ b/configure.ac
@@ -922,6 +922,7 @@ shlibs/blkid/blkid.pc
shlibs/blkid/Makefile
shlibs/blkid/src/Makefile
shlibs/blkid/src/superblocks/Makefile
+shlibs/blkid/src/topology/Makefile
shlibs/uuid/uuid.pc
shlibs/uuid/Makefile
shlibs/uuid/man/Makefile
diff --git a/shlibs/blkid/src/Makefile.am b/shlibs/blkid/src/Makefile.am
index 10d1baa8..23a9161a 100644
--- a/shlibs/blkid/src/Makefile.am
+++ b/shlibs/blkid/src/Makefile.am
@@ -1,6 +1,6 @@
include $(top_srcdir)/config/include-Makefile.am
-SUBDIRS = superblocks .
+SUBDIRS = superblocks topology .
common_ldadd =
common_cflags =
@@ -32,7 +32,10 @@ libblkid_la_SOURCES = cache.c dev.c devname.c devno.c getsize.c llseek.c \
$(top_srcdir)/lib/canonicalize.c \
$(top_srcdir)/lib/md5.c
-libblkid_la_LIBADD = superblocks/libblkid_superblocks.la $(common_ldadd)
+libblkid_la_LIBADD = superblocks/libblkid_superblocks.la \
+ topology/libblkid_topology.la \
+ $(common_ldadd)
+
libblkid_la_DEPENDENCIES = $(libblkid_la_LIBADD) blkid.sym
libblkid_la_LDFLAGS = -Wl,--version-script=$(ul_libblkid_srcdir)/blkid.sym \
diff --git a/shlibs/blkid/src/blkid.h b/shlibs/blkid/src/blkid.h
index 326c37ce..6549845d 100644
--- a/shlibs/blkid/src/blkid.h
+++ b/shlibs/blkid/src/blkid.h
@@ -34,6 +34,13 @@ typedef struct blkid_struct_dev *blkid_dev;
typedef struct blkid_struct_cache *blkid_cache;
typedef struct blkid_struct_probe *blkid_probe;
+/**
+ * blkid_topology:
+ *
+ * device topology information
+ */
+typedef struct blkid_struct_topology *blkid_topology;
+
typedef int64_t blkid_loff_t;
typedef struct blkid_struct_tag_iterate *blkid_tag_iterate;
@@ -168,6 +175,18 @@ extern int blkid_probe_filter_superblocks_type(blkid_probe pr, int flag, char *n
extern int blkid_probe_filter_superblocks_usage(blkid_probe pr, int flag, int usage);
/*
+ * topology probing
+ */
+extern int blkid_probe_enable_topology(blkid_probe pr, int enable);
+
+/* binary interface */
+extern blkid_topology blkid_probe_get_topology(blkid_probe pr);
+
+extern unsigned long blkid_topology_get_alignment_offset(blkid_topology tp);
+extern unsigned long blkid_topology_get_minimum_io_size(blkid_topology tp);
+extern unsigned long blkid_topology_get_optimal_io_size(blkid_topology tp);
+
+/*
* NAME=value low-level interface
*/
extern int blkid_do_probe(blkid_probe pr);
diff --git a/shlibs/blkid/src/blkid.sym b/shlibs/blkid/src/blkid.sym
index 4c2f1c2e..32ef6cac 100644
--- a/shlibs/blkid/src/blkid.sym
+++ b/shlibs/blkid/src/blkid.sym
@@ -74,12 +74,17 @@ global:
blkid_devno_to_wholedisk;
blkid_do_fullprobe;
blkid_probe_enable_superblocks;
+ blkid_probe_enable_topology;
blkid_probe_filter_superblocks_type;
blkid_probe_filter_superblocks_usage;
blkid_probe_get_devno;
blkid_probe_get_sectorsize;
blkid_probe_get_size;
+ blkid_probe_get_topology;
blkid_probe_invert_superblocks_filter;
blkid_probe_reset_superblocks_filter;
blkid_probe_set_superblocks_flags;
+ blkid_topology_get_alignment_offset;
+ blkid_topology_get_minimum_io_size;
+ blkid_topology_get_optimal_io_size;
} BLKID_2.15;
diff --git a/shlibs/blkid/src/blkidP.h b/shlibs/blkid/src/blkidP.h
index c5617044..d590cd9d 100644
--- a/shlibs/blkid/src/blkidP.h
+++ b/shlibs/blkid/src/blkidP.h
@@ -91,7 +91,7 @@ typedef struct blkid_struct_tag *blkid_tag;
*/
enum {
BLKID_CHAIN_SUBLKS, /* FS/RAID superblocks (enabled by default) */
-/* BLKID_CHAIN_TOPLGY, Block device topology */
+ BLKID_CHAIN_TOPLGY, /* Block device topology */
/* BLKID_CHAIN_PARTS, Partition tables */
BLKID_NCHAINS /* number of chains */
@@ -407,6 +407,8 @@ extern int blkid_probe_set_value(blkid_probe pr, const char *name,
unsigned char *data, size_t len);
extern int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
const char *fmt, va_list ap);
+extern int blkid_probe_sprintf_value(blkid_probe pr, const char *name,
+ const char *fmt, ...);
extern void blkid_unparse_uuid(const unsigned char *uuid, char *str, size_t len);
diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c
index d4662322..beda26a2 100644
--- a/shlibs/blkid/src/probe.c
+++ b/shlibs/blkid/src/probe.c
@@ -97,12 +97,14 @@
/* chains */
extern const struct blkid_chaindrv superblocks_drv;
+extern const struct blkid_chaindrv topology_drv;
/*
* All supported chains
*/
static const struct blkid_chaindrv *chains_drvs[] = {
[BLKID_CHAIN_SUBLKS] = &superblocks_drv,
+ [BLKID_CHAIN_TOPLGY] = &topology_drv,
};
static void blkid_probe_reset_vals(blkid_probe pr);
@@ -808,6 +810,19 @@ int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
return 0;
}
+int blkid_probe_sprintf_value(blkid_probe pr, const char *name,
+ const char *fmt, ...)
+{
+ int rc;
+ va_list ap;
+
+ va_start(ap, fmt);
+ rc = blkid_probe_vsprintf_value(pr, name, fmt, ap);
+ va_end(ap);
+
+ return rc;
+}
+
/**
* blkid_probe_get_devno:
* @pr: probe
diff --git a/shlibs/blkid/src/topology/Makefile.am b/shlibs/blkid/src/topology/Makefile.am
new file mode 100644
index 00000000..9ba10e4d
--- /dev/null
+++ b/shlibs/blkid/src/topology/Makefile.am
@@ -0,0 +1,7 @@
+include $(top_srcdir)/config/include-Makefile.am
+
+AM_CPPFLAGS += -I$(ul_libblkid_srcdir)
+libblkid_topology_la_LIBADD =
+
+noinst_LTLIBRARIES = libblkid_topology.la
+libblkid_topology_la_SOURCES = topology.c
diff --git a/shlibs/blkid/src/topology/topology.c b/shlibs/blkid/src/topology/topology.c
new file mode 100644
index 00000000..8ebd5b08
--- /dev/null
+++ b/shlibs/blkid/src/topology/topology.c
@@ -0,0 +1,298 @@
+/*
+ * topology - gathers information about device topology
+ *
+ * Copyright 2009 Red Hat, Inc. All rights reserved.
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include "blkdev.h"
+#include "blkidP.h"
+
+/**
+ * SECTION:topology
+ * @title: Topology information
+ * @short_description: block device tolology information.
+ *
+ * The tolology chain provides details about Linux block devices, for more
+ * information see:
+ *
+ * Linux kernel Documentation/ABI/testing/sysfs-block
+ *
+ * NAME=value (tags) interface is enabled by blkid_probe_enable_topology(),
+ * and provides:
+ *
+ * @MINIMUM_IO_SIZE: minimum size which is the device's preferred unit of I/O
+ *
+ * @OPTIMAL_IO_SIZE: usually the stripe width for RAID or zero
+ *
+ * @ALIGNMENT_OFFSET: indicates how many bytes the beginning o the device is
+ * offset from the disk's natural alignment.
+ *
+ * Binary interface:
+ *
+ * blkid_probe_get_tolology()
+ *
+ * blkid_topology_get_'VALUENAME'()
+ */
+static int topology_probe(blkid_probe pr, struct blkid_chain *chn);
+static void topology_free(blkid_probe pr, void *data);
+
+/*
+ * Driver definition
+ */
+const struct blkid_chaindrv topology_drv = {
+ .id = BLKID_CHAIN_TOPLGY,
+ .name = "topology",
+ .dflt_enabled = FALSE,
+ .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
+ * @enable: TRUE/FALSE
+ *
+ * Enables/disables the topology probing for non-binary interface.
+ *
+ * Returns: 0 on success, or -1 in case of error.
+ */
+int blkid_probe_enable_topology(blkid_probe pr, int enable)
+{
+ if (!pr)
+ return -1;
+ pr->chains[BLKID_CHAIN_TOPLGY].enabled = enable;
+ return 0;
+}
+
+/**
+ * blkid_probe_get_topology:
+ * @pr: probe
+ *
+ * This is a binary interface for topology values. See also blkid_topology_*
+ * functions.
+ *
+ * This function is independent on blkid_do_[safe,full]probe() and
+ * blkid_probe_enable_topology() calls.
+ *
+ * Returns: blkid_tolopogy, or NULL in case of error.
+ */
+blkid_topology blkid_probe_get_topology(blkid_probe pr)
+{
+ return (blkid_topology) blkid_probe_get_binary_data(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 * DEFAULT_SECTOR_SIZE;
+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/<maj>:<min>/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;
+
+ if (!pr)
+ 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"));
+
+ if (chn->data)
+ /* reset binary data */
+ memset(chn->data, 0,
+ sizeof(struct blkid_struct_topology));
+ else {
+ chn->data = calloc(1,
+ sizeof(struct blkid_struct_topology));
+ if (!chn->data)
+ return -1;
+ }
+ }
+
+ DBG(DEBUG_LOWPROBE, printf("--> starting probing loop [TOPOLOGY]\n"));
+
+ 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 = topology_set_value(pr, chn, val, data);
+ if (rc)
+ break; /* error */
+ count++;
+ }
+
+
+ if (rc == 0 && count == 0)
+ rc = 1; /* no result */
+
+ DBG(DEBUG_LOWPROBE,
+ printf("<-- leaving probing loop [TOPOLOGY, rc=%d]\n", rc));
+ return rc;
+}
+
+static void topology_free(blkid_probe pr, void *data)
+{
+ free(data);
+}
+
+/**
+ * blkid_topology_get_alignment_offset:
+ * @tp: topology
+ *
+ * Returns: alignment offset in bytes or 0.
+ */
+unsigned long blkid_topology_get_alignment_offset(blkid_topology tp)
+{
+ return tp ? tp->alignment_offset : 0;
+}
+
+/**
+ * blkid_topology_get_minimum_io_size:
+ * @tp: topology
+ *
+ * Returns: minimum io size in bytes or 0.
+ */
+unsigned long blkid_topology_get_minimum_io_size(blkid_topology tp)
+{
+ return tp ? tp->minimum_io_size : 0;
+}
+
+/**
+ * blkid_topology_get_optimal_io_size
+ * @tp: topology
+ *
+ * Returns: optimal io size in bytes or 0.
+ */
+unsigned long blkid_topology_get_optimal_io_size(blkid_topology tp)
+{
+ return tp ? tp->optimal_io_size : 0;
+}
+