(root)/
util-linux-2.39/
libblkid/
src/
topology/
md.c
       1  /*
       2   * Linux Software RAID (md) topology
       3   * -- this is fallback for old systems where the topology information is not
       4   *    exported by sysfs
       5   *
       6   * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
       7   *
       8   * This file may be redistributed under the terms of the
       9   * GNU Lesser General Public License.
      10   *
      11   */
      12  #include <errno.h>
      13  #include <fcntl.h>
      14  #include <stdint.h>
      15  #include <stdio.h>
      16  #include <stdlib.h>
      17  #include <string.h>
      18  #include <sys/ioctl.h>
      19  #include <sys/stat.h>
      20  #include <sys/types.h>
      21  #include <unistd.h>
      22  
      23  #include "topology.h"
      24  
      25  #ifndef MD_MAJOR
      26  #define MD_MAJOR	9
      27  #endif
      28  
      29  #ifndef _IOT__IOTBASE_uint32_t
      30  #define _IOT__IOTBASE_uint32_t IOT_SIMPLE(uint32_t)
      31  #endif
      32  #define _IOT_md_array_info _IOT (_IOTS(uint32_t), 18, 0, 0, 0, 0)
      33  #define GET_ARRAY_INFO          _IOR (MD_MAJOR, 0x11, struct md_array_info)
      34  
      35  struct md_array_info {
      36  	/*
      37  	 * Generic constant information
      38  	 */
      39  	uint32_t major_version;
      40  	uint32_t minor_version;
      41  	uint32_t patch_version;
      42  	uint32_t ctime;
      43  	uint32_t level;
      44  	uint32_t size;
      45  	uint32_t nr_disks;
      46  	uint32_t raid_disks;
      47  	uint32_t md_minor;
      48  	uint32_t not_persistent;
      49  
      50  	/*
      51  	 * Generic state information
      52  	 */
      53  	uint32_t utime;	  /*  0 Superblock update time		  */
      54  	uint32_t state;	  /*  1 State bits (clean, ...)		  */
      55  	uint32_t active_disks;  /*  2 Number of currently active disks  */
      56  	uint32_t working_disks; /*  3 Number of working disks		  */
      57  	uint32_t failed_disks;  /*  4 Number of failed disks		  */
      58  	uint32_t spare_disks;	  /*  5 Number of spare disks		  */
      59  
      60  	/*
      61  	 * Personality information
      62  	 */
      63  	uint32_t layout;	  /*  0 the array's physical layout	  */
      64  	uint32_t chunk_size;	  /*  1 chunk size in bytes		  */
      65  
      66  };
      67  
      68  static int is_md_device(dev_t devno)
      69  {
      70  	if (major(devno) == MD_MAJOR)
      71  		return 1;
      72  	return blkid_driver_has_major("md", major(devno));
      73  }
      74  
      75  static int probe_md_tp(blkid_probe pr,
      76  		const struct blkid_idmag *mag __attribute__((__unused__)))
      77  {
      78  	int fd = -1;
      79  	dev_t disk = 0;
      80  	dev_t devno = blkid_probe_get_devno(pr);
      81  	struct md_array_info md;
      82  
      83  	if (!devno)
      84  		goto nothing;		/* probably not a block device */
      85  
      86  	if (!is_md_device(devno))
      87  		goto nothing;
      88  
      89  	if (blkid_devno_to_wholedisk(devno, NULL, 0, &disk))
      90  		goto nothing;
      91  
      92  	if (disk == devno)
      93  		fd = pr->fd;
      94  	else {
      95  		char *diskpath = blkid_devno_to_devname(disk);
      96  
      97  		if (!diskpath)
      98  			goto nothing;
      99  
     100  		fd = open(diskpath, O_RDONLY|O_CLOEXEC);
     101  		free(diskpath);
     102  
     103                  if (fd == -1)
     104  			goto nothing;
     105  	}
     106  
     107  	memset(&md, 0, sizeof(md));
     108  
     109  	if (ioctl(fd, GET_ARRAY_INFO, &md))
     110  		goto nothing;
     111  
     112  	if (fd >= 0 && fd != pr->fd) {
     113  		close(fd);
     114  		fd = -1;
     115  	}
     116  
     117  	/*
     118  	 * Ignore levels we don't want aligned (e.g. linear)
     119  	 * and deduct disk(s) from stripe width on RAID4/5/6
     120  	 */
     121  	switch (md.level) {
     122  	case 6:
     123  		md.raid_disks--;
     124  		/* fallthrough */
     125  	case 5:
     126  	case 4:
     127  		md.raid_disks--;
     128  		/* fallthrough */
     129  	case 1:
     130  	case 0:
     131  	case 10:
     132  		break;
     133  	default:
     134  		goto nothing;
     135  	}
     136  
     137  	blkid_topology_set_minimum_io_size(pr, md.chunk_size);
     138  	blkid_topology_set_optimal_io_size(pr, (unsigned long) md.chunk_size * md.raid_disks);
     139  
     140  	return 0;
     141  
     142  nothing:
     143  	if (fd >= 0 && fd != pr->fd)
     144  		close(fd);
     145  	return 1;
     146  }
     147  
     148  const struct blkid_idinfo md_tp_idinfo =
     149  {
     150  	.name		= "md",
     151  	.probefunc	= probe_md_tp,
     152  	.magics		= BLKID_NONE_MAGIC
     153  };
     154