]> err.no Git - util-linux/commitdiff
libblkid: add MD topology support (for old kernels)
authorKarel Zak <kzak@redhat.com>
Mon, 21 Sep 2009 09:52:26 +0000 (11:52 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 21 Sep 2009 11:45:48 +0000 (13:45 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
shlibs/blkid/src/topology/Makefile.am
shlibs/blkid/src/topology/md.c [new file with mode: 0644]
shlibs/blkid/src/topology/topology.c
shlibs/blkid/src/topology/topology.h

index ae72eb4daf30324b5ca5fbafd37cc715de7fba06..7464d2a8f1c8a1b27d8bf2b009a2d09416ee5068 100644 (file)
@@ -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 (file)
index 0000000..e084720
--- /dev/null
@@ -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 <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ *
+ */
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#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
+};
+
index 3a636f558324689176c14b6cf0572d1cac4595de..adb59f12944a7c37a919fe36fb8ab67506345854 100644 (file)
  * 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
 };
 
 
index 876ae653d3d901ccc1fba89a86dbb20ea0afe62f..ecebb33044d396fd4fbf71a39abbe2f2c9e0a761 100644 (file)
@@ -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 */