(root)/
util-linux-2.39/
libblkid/
src/
topology/
lvm.c
       1  /*
       2   * lvm 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/stat.h>
      19  #include <sys/types.h>
      20  #include <unistd.h>
      21  
      22  #include "topology.h"
      23  
      24  #ifndef LVM_BLK_MAJOR
      25  # define LVM_BLK_MAJOR     58
      26  #endif
      27  
      28  static int is_lvm_device(dev_t devno)
      29  {
      30  	if (major(devno) == LVM_BLK_MAJOR)
      31  		return 1;
      32  	return blkid_driver_has_major("lvm", major(devno));
      33  }
      34  
      35  static int probe_lvm_tp(blkid_probe pr,
      36  		const struct blkid_idmag *mag __attribute__((__unused__)))
      37  {
      38  	const char * const paths[] = {
      39  		"/usr/local/sbin/lvdisplay",
      40  		"/usr/sbin/lvdisplay",
      41  		"/sbin/lvdisplay"
      42  	};
      43  	int lvpipe[] = { -1, -1 }, stripes = 0, stripesize = 0;
      44  	FILE *stream = NULL;
      45  	char *cmd = NULL, *devname = NULL, buf[1024];
      46  	size_t i;
      47  	dev_t devno = blkid_probe_get_devno(pr);
      48  
      49  	if (!devno)
      50  		goto nothing;		/* probably not a block device */
      51  	if (!is_lvm_device(devno))
      52  		goto nothing;
      53  
      54  	for (i = 0; i < ARRAY_SIZE(paths); i++) {
      55  		struct stat sb;
      56  		if (stat(paths[i], &sb) == 0) {
      57  			cmd = (char *) paths[i];
      58  			break;
      59  		}
      60  	}
      61  
      62  	if (!cmd)
      63  		goto nothing;
      64  
      65  	devname = blkid_devno_to_devname(devno);
      66  	if (!devname)
      67  		goto nothing;
      68  
      69  	if (pipe(lvpipe) < 0) {
      70  		DBG(LOWPROBE, ul_debug("Failed to open pipe: errno=%d", errno));
      71  		goto nothing;
      72  	}
      73  
      74  	switch (fork()) {
      75  	case 0:
      76  	{
      77  		char *lvargv[3];
      78  
      79  		/* Plumbing */
      80  		close(lvpipe[0]);
      81  
      82  		if (lvpipe[1] != STDOUT_FILENO)
      83  			dup2(lvpipe[1], STDOUT_FILENO);
      84  
      85  		if (drop_permissions() != 0)
      86  			 exit(1);
      87  
      88  		lvargv[0] = cmd;
      89  		lvargv[1] = devname;
      90  		lvargv[2] = NULL;
      91  
      92  		execv(lvargv[0], lvargv);
      93  
      94  		DBG(LOWPROBE, ul_debug("Failed to execute %s: errno=%d", cmd, errno));
      95  		exit(1);
      96  	}
      97  	case -1:
      98  		DBG(LOWPROBE, ul_debug("Failed to forking: errno=%d", errno));
      99  		goto nothing;
     100  	default:
     101  		break;
     102  	}
     103  
     104  	stream = fdopen(lvpipe[0], "r" UL_CLOEXECSTR);
     105  	if (!stream)
     106  		goto nothing;
     107  
     108  	while (fgets(buf, sizeof(buf), stream) != NULL) {
     109  		if (!strncmp(buf, "Stripes", 7))
     110  			ignore_result( sscanf(buf, "Stripes %d", &stripes) );
     111  
     112  		if (!strncmp(buf, "Stripe size", 11))
     113  			ignore_result( sscanf(buf, "Stripe size (KByte) %d", &stripesize) );
     114  	}
     115  
     116  	if (!stripes)
     117  		goto nothing;
     118  
     119  	blkid_topology_set_minimum_io_size(pr, stripesize << 10);
     120  	blkid_topology_set_optimal_io_size(pr, (stripes * stripesize) << 10);
     121  
     122  	free(devname);
     123  	fclose(stream);
     124  	close(lvpipe[1]);
     125  	return 0;
     126  
     127  nothing:
     128  	free(devname);
     129  	if (stream)
     130  		fclose(stream);
     131  	else if (lvpipe[0] != -1)
     132  		close(lvpipe[0]);
     133  	if (lvpipe[1] != -1)
     134  		close(lvpipe[1]);
     135  	return 1;
     136  }
     137  
     138  const struct blkid_idinfo lvm_tp_idinfo =
     139  {
     140  	.name		= "lvm",
     141  	.probefunc	= probe_lvm_tp,
     142  	.magics		= BLKID_NONE_MAGIC
     143  };
     144