From f912ab262005ed175e4f52580b11a361458cae19 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 21 Sep 2009 11:52:26 +0200 Subject: [PATCH] libblkid: add MD topology support (for old kernels) Signed-off-by: Karel Zak --- shlibs/blkid/src/topology/Makefile.am | 3 +- shlibs/blkid/src/topology/md.c | 149 ++++++++++++++++++++++++++ shlibs/blkid/src/topology/topology.c | 9 +- shlibs/blkid/src/topology/topology.h | 1 + 4 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 shlibs/blkid/src/topology/md.c diff --git a/shlibs/blkid/src/topology/Makefile.am b/shlibs/blkid/src/topology/Makefile.am index ae72eb4d..7464d2a8 100644 --- a/shlibs/blkid/src/topology/Makefile.am +++ b/shlibs/blkid/src/topology/Makefile.am @@ -6,4 +6,5 @@ libblkid_topology_la_LIBADD = noinst_LTLIBRARIES = libblkid_topology.la libblkid_topology_la_SOURCES = topology.c \ topology.h \ - sysfs.c + sysfs.c \ + md.c diff --git a/shlibs/blkid/src/topology/md.c b/shlibs/blkid/src/topology/md.c new file mode 100644 index 00000000..e084720f --- /dev/null +++ b/shlibs/blkid/src/topology/md.c @@ -0,0 +1,149 @@ +/* + * Linux Software RAID (md) topology + * -- this is fallback for old systems where the toplogy information are not + * exporte dy 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 + +#include "topology.h" + +#ifndef MD_MAJOR +#define MD_MAJOR 9 +#endif + +#define GET_ARRAY_INFO _IOR (MD_MAJOR, 0x11, struct md_array_info) + +struct md_array_info { + /* + * Generic constant information + */ + uint32_t major_version; + uint32_t minor_version; + uint32_t patch_version; + uint32_t ctime; + uint32_t level; + uint32_t size; + uint32_t nr_disks; + uint32_t raid_disks; + uint32_t md_minor; + uint32_t not_persistent; + + /* + * Generic state information + */ + uint32_t utime; /* 0 Superblock update time */ + uint32_t state; /* 1 State bits (clean, ...) */ + uint32_t active_disks; /* 2 Number of currently active disks */ + uint32_t working_disks; /* 3 Number of working disks */ + uint32_t failed_disks; /* 4 Number of failed disks */ + uint32_t spare_disks; /* 5 Number of spare disks */ + + /* + * Personality information + */ + uint32_t layout; /* 0 the array's physical layout */ + uint32_t chunk_size; /* 1 chunk size in bytes */ + +}; + +static int is_md_device(dev_t devno) +{ + if (major(devno) == MD_MAJOR) + return 1; + if (blkid_driver_has_major("md", major(devno))) + return 1; + return 0; +} + +static int probe_md_tp(blkid_probe pr, const struct blkid_idmag *mag) +{ + int fd = -1; + dev_t disk = 0; + dev_t devno = blkid_probe_get_devno(pr); + struct md_array_info md; + + if (!devno) + goto nothing; /* probably not a block device */ + + if (!is_md_device(devno)) + goto nothing; + + if (blkid_devno_to_wholedisk(devno, NULL, 0, &disk)) + goto nothing; + + if (disk == devno) + fd = pr->fd; + else { + char *diskpath = blkid_devno_to_devname(disk); + + if (!diskpath) + goto nothing; + + fd = open(diskpath, O_RDONLY); + free(diskpath); + + if (fd == -1) + goto nothing; + } + + memset(&md, 0, sizeof(md)); + + if (ioctl(fd, GET_ARRAY_INFO, &md)) + goto nothing; + + if (fd != pr->fd) + close(fd); + + /* + * Ignore levels we don't want aligned (e.g. linear) + * and deduct disk(s) from stripe width on RAID4/5/6 + */ + switch (md.level) { + case 6: + md.raid_disks--; + /* fallthrough */ + case 5: + case 4: + md.raid_disks--; + /* fallthrough */ + case 1: + case 0: + case 10: + break; + default: + goto nothing; + } + + blkid_topology_set_minimum_io_size(pr, md.chunk_size); + blkid_topology_set_optimal_io_size(pr, md.chunk_size * md.raid_disks); + + return 0; + +nothing: + if (fd != -1 && fd != pr->fd) + close(fd); + return 1; +} + +const struct blkid_idinfo md_tp_idinfo = +{ + .name = "md", + .probefunc = probe_md_tp, + .magics = BLKID_NONE_MAGIC +}; + diff --git a/shlibs/blkid/src/topology/topology.c b/shlibs/blkid/src/topology/topology.c index 3a636f55..adb59f12 100644 --- a/shlibs/blkid/src/topology/topology.c +++ b/shlibs/blkid/src/topology/topology.c @@ -27,9 +27,11 @@ * 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 + * @MINIMUM_IO_SIZE: minimum size which is the device's preferred unit of I/O. + * For RAID arrays it is often the stripe chunk size. * - * @OPTIMAL_IO_SIZE: usually the stripe width for RAID or zero + * @OPTIMAL_IO_SIZE: usually the stripe width for RAID or zero. For RAID arrays + * it is usually the stripe width or the internal track size. * * @ALIGNMENT_OFFSET: indicates how many bytes the beginning o the device is * offset from the disk's natural alignment. @@ -57,7 +59,8 @@ struct blkid_struct_topology { */ static const struct blkid_idinfo *idinfos[] = { - &sysfs_tp_idinfo + &sysfs_tp_idinfo, + &md_tp_idinfo }; diff --git a/shlibs/blkid/src/topology/topology.h b/shlibs/blkid/src/topology/topology.h index 876ae653..ecebb330 100644 --- a/shlibs/blkid/src/topology/topology.h +++ b/shlibs/blkid/src/topology/topology.h @@ -11,6 +11,7 @@ extern int blkid_topology_set_optimal_io_size(blkid_probe pr, unsigned long val) * topology probers */ extern const struct blkid_idinfo sysfs_tp_idinfo; +extern const struct blkid_idinfo md_tp_idinfo; #endif /* BLKID_TOPOLOGY_H */ -- 2.39.5