summaryrefslogtreecommitdiff
path: root/lib/device/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/device/device.c')
-rw-r--r--lib/device/device.c510
1 files changed, 0 insertions, 510 deletions
diff --git a/lib/device/device.c b/lib/device/device.c
deleted file mode 100644
index a87ae7f..0000000
--- a/lib/device/device.c
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
- * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
- *
- * This file is part of LVM2.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License v.2.1.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "lib.h"
-#include "lvm-types.h"
-#include "device.h"
-#include "metadata.h"
-#include "filter.h"
-#include "xlate.h"
-
-#include <libgen.h> /* dirname, basename */
-
-/* See linux/genhd.h and fs/partitions/msdos */
-
-#define PART_MAGIC 0xAA55
-#define PART_MAGIC_OFFSET UINT64_C(0x1FE)
-#define PART_OFFSET UINT64_C(0x1BE)
-
-struct partition {
- uint8_t boot_ind;
- uint8_t head;
- uint8_t sector;
- uint8_t cyl;
- uint8_t sys_ind; /* partition type */
- uint8_t end_head;
- uint8_t end_sector;
- uint8_t end_cyl;
- uint32_t start_sect;
- uint32_t nr_sects;
-} __attribute__((packed));
-
-static int _is_partitionable(struct device *dev)
-{
- int parts = max_partitions(MAJOR(dev->dev));
-
- /* All MD devices are partitionable via blkext (as of 2.6.28) */
- if (MAJOR(dev->dev) == md_major())
- return 1;
-
- if ((parts <= 1) || (MINOR(dev->dev) % parts))
- return 0;
-
- return 1;
-}
-
-static int _has_partition_table(struct device *dev)
-{
- int ret = 0;
- unsigned p;
- struct {
- uint8_t skip[PART_OFFSET];
- struct partition part[4];
- uint16_t magic;
- } __attribute__((packed)) buf; /* sizeof() == SECTOR_SIZE */
-
- if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf))
- return_0;
-
- /* FIXME Check for other types of partition table too */
-
- /* Check for msdos partition table */
- if (buf.magic == xlate16(PART_MAGIC)) {
- for (p = 0; p < 4; ++p) {
- /* Table is invalid if boot indicator not 0 or 0x80 */
- if (buf.part[p].boot_ind & 0x7f) {
- ret = 0;
- break;
- }
- /* Must have at least one non-empty partition */
- if (buf.part[p].nr_sects)
- ret = 1;
- }
- }
-
- return ret;
-}
-
-int is_partitioned_dev(struct device *dev)
-{
- if (!_is_partitionable(dev))
- return 0;
-
- return _has_partition_table(dev);
-}
-
-#if 0
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <ctype.h>
-
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <linux/fs.h>
-#include <linux/major.h>
-#include <linux/genhd.h>
-
-int _get_partition_type(struct dev_filter *filter, struct device *d);
-
-#define MINOR_PART(dev) (MINOR((dev)->dev) % max_partitions(MINOR((dev)->dev)))
-
-int is_extended_partition(struct device *d)
-{
- return (MINOR_PART(d) > 4) ? 1 : 0;
-}
-
-struct device *dev_primary(struct dev_mgr *dm, struct device *d)
-{
- struct device *ret;
-
- ret = dev_by_dev(dm, d->dev - MINOR_PART(dm, d));
- /* FIXME: Needs replacing with a 'refresh' */
- if (!ret) {
- init_dev_scan(dm);
- ret = dev_by_dev(dm, d->dev - MINOR_PART(dm, d));
- }
-
- return ret;
-
-}
-
-int partition_type_is_lvm(struct dev_mgr *dm, struct device *d)
-{
- int pt;
-
- pt = _get_partition_type(dm, d);
-
- if (!pt) {
- if (is_whole_disk(dm, d))
- /* FIXME: Overloaded pt=0 in error cases */
- return 1;
- else {
- log_error
- ("%s: missing partition table "
- "on partitioned device", d->name);
- return 0;
- }
- }
-
- if (is_whole_disk(dm, d)) {
- log_error("%s: looks to possess partition table", d->name);
- return 0;
- }
-
- /* check part type */
- if (pt != LVM_PARTITION && pt != LVM_NEW_PARTITION) {
- log_error("%s: invalid partition type 0x%x "
- "(must be 0x%x)", d->name, pt, LVM_NEW_PARTITION);
- return 0;
- }
-
- if (pt == LVM_PARTITION) {
- log_error
- ("%s: old LVM partition type found - please change to 0x%x",
- d->name, LVM_NEW_PARTITION);
- return 0;
- }
-
- return 1;
-}
-
-int _get_partition_type(struct dev_mgr *dm, struct device *d)
-{
- int pv_handle = -1;
- struct device *primary;
- ssize_t read_ret;
- ssize_t bytes_read = 0;
- char *buffer;
- unsigned short *s_buffer;
- struct partition *part;
- loff_t offset = 0;
- loff_t extended_offset = 0;
- int part_sought;
- int part_found = 0;
- int first_partition = 1;
- int extended_partition = 0;
- int p;
-
- if (!(primary = dev_primary(dm, d))) {
- log_error
- ("Failed to find main device containing partition %s",
- d->name);
- return 0;
- }
-
- if (!(buffer = dm_malloc(SECTOR_SIZE))) {
- log_error("Failed to allocate partition table buffer");
- return 0;
- }
-
- /* Get partition table */
- if ((pv_handle = open(primary->name, O_RDONLY)) < 0) {
- log_error("%s: open failed: %s", primary->name,
- strerror(errno));
- return 0;
- }
-
- s_buffer = (unsigned short *) buffer;
- part = (struct partition *) (buffer + 0x1be);
- part_sought = MINOR_PART(dm, d);
-
- do {
- bytes_read = 0;
-
- if (llseek(pv_handle, offset * SECTOR_SIZE, SEEK_SET) == -1) {
- log_error("%s: llseek failed: %s",
- primary->name, strerror(errno));
- return 0;
- }
-
- while ((bytes_read < SECTOR_SIZE) &&
- (read_ret =
- read(pv_handle, buffer + bytes_read,
- SECTOR_SIZE - bytes_read)) != -1)
- bytes_read += read_ret;
-
- if (read_ret == -1) {
- log_error("%s: read failed: %s", primary->name,
- strerror(errno));
- return 0;
- }
-
- if (s_buffer[255] == 0xAA55) {
- if (is_whole_disk(dm, d))
- return -1;
- } else
- return 0;
-
- extended_partition = 0;
-
- /* Loop through primary partitions */
- for (p = 0; p < 4; p++) {
- if (part[p].sys_ind == DOS_EXTENDED_PARTITION ||
- part[p].sys_ind == LINUX_EXTENDED_PARTITION
- || part[p].sys_ind == WIN98_EXTENDED_PARTITION) {
- extended_partition = 1;
- offset = extended_offset + part[p].start_sect;
- if (extended_offset == 0)
- extended_offset = part[p].start_sect;
- if (first_partition == 1)
- part_found++;
- } else if (first_partition == 1) {
- if (p == part_sought) {
- if (part[p].sys_ind == 0) {
- /* missing primary? */
- return 0;
- }
- } else
- part_found++;
- } else if (!part[p].sys_ind)
- part_found++;
-
- if (part_sought == part_found)
- return part[p].sys_ind;
-
- }
- first_partition = 0;
- }
- while (extended_partition == 1);
-
- return 0;
-}
-#endif
-
-#ifdef linux
-
-int get_primary_dev(const char *sysfs_dir,
- const struct device *dev, dev_t *result)
-{
- char path[PATH_MAX+1];
- char temp_path[PATH_MAX+1];
- char buffer[64];
- struct stat info;
- FILE *fp;
- uint32_t pri_maj, pri_min;
- int size, ret = 0;
-
- /* check if dev is a partition */
- if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/partition",
- sysfs_dir, (int)MAJOR(dev->dev), (int)MINOR(dev->dev)) < 0) {
- log_error("dm_snprintf partition failed");
- return ret;
- }
-
- if (stat(path, &info) == -1) {
- if (errno != ENOENT)
- log_sys_error("stat", path);
- return ret;
- }
-
- /*
- * extract parent's path from the partition's symlink, e.g.:
- * - readlink /sys/dev/block/259:0 = ../../block/md0/md0p1
- * - dirname ../../block/md0/md0p1 = ../../block/md0
- * - basename ../../block/md0/md0 = md0
- * Parent's 'dev' sysfs attribute = /sys/block/md0/dev
- */
- if ((size = readlink(dirname(path), temp_path, PATH_MAX)) < 0) {
- log_sys_error("readlink", path);
- return ret;
- }
-
- temp_path[size] = '\0';
-
- if (dm_snprintf(path, PATH_MAX, "%s/block/%s/dev",
- sysfs_dir, basename(dirname(temp_path))) < 0) {
- log_error("dm_snprintf dev failed");
- return ret;
- }
-
- /* finally, parse 'dev' attribute and create corresponding dev_t */
- if (stat(path, &info) == -1) {
- if (errno == ENOENT)
- log_error("sysfs file %s does not exist", path);
- else
- log_sys_error("stat", path);
- return ret;
- }
-
- fp = fopen(path, "r");
- if (!fp) {
- log_sys_error("fopen", path);
- return ret;
- }
-
- if (!fgets(buffer, sizeof(buffer), fp)) {
- log_sys_error("fgets", path);
- goto out;
- }
-
- if (sscanf(buffer, "%d:%d", &pri_maj, &pri_min) != 2) {
- log_error("sysfs file %s not in expected MAJ:MIN format: %s",
- path, buffer);
- goto out;
- }
- *result = MKDEV((dev_t)pri_maj, pri_min);
- ret = 1;
-
-out:
- if (fclose(fp))
- log_sys_error("fclose", path);
-
- return ret;
-}
-
-static unsigned long _dev_topology_attribute(const char *attribute,
- const char *sysfs_dir,
- struct device *dev)
-{
- static const char sysfs_fmt_str[] = "%s/dev/block/%d:%d/%s";
- char path[PATH_MAX+1], buffer[64];
- FILE *fp;
- struct stat info;
- dev_t uninitialized_var(primary);
- unsigned long result = 0UL;
-
- if (!attribute || !*attribute)
- return_0;
-
- if (!sysfs_dir || !*sysfs_dir)
- return_0;
-
- if (dm_snprintf(path, PATH_MAX, sysfs_fmt_str, sysfs_dir,
- (int)MAJOR(dev->dev), (int)MINOR(dev->dev),
- attribute) < 0) {
- log_error("dm_snprintf %s failed", attribute);
- return 0;
- }
-
- /*
- * 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) == -1) {
- if (errno != ENOENT) {
- log_sys_error("stat", path);
- return 0;
- }
- if (!get_primary_dev(sysfs_dir, dev, &primary))
- return 0;
-
- /* get attribute from partition's primary device */
- if (dm_snprintf(path, PATH_MAX, sysfs_fmt_str, sysfs_dir,
- (int)MAJOR(primary), (int)MINOR(primary),
- attribute) < 0) {
- log_error("primary dm_snprintf %s failed", attribute);
- return 0;
- }
- if (stat(path, &info) == -1) {
- if (errno != ENOENT)
- log_sys_error("stat", path);
- return 0;
- }
- }
-
- if (!(fp = fopen(path, "r"))) {
- log_sys_error("fopen", path);
- return 0;
- }
-
- if (!fgets(buffer, sizeof(buffer), fp)) {
- log_sys_error("fgets", path);
- goto out;
- }
-
- if (sscanf(buffer, "%lu", &result) != 1) {
- log_error("sysfs file %s not in expected format: %s", path,
- buffer);
- goto out;
- }
-
- log_very_verbose("Device %s %s is %lu bytes.",
- dev_name(dev), attribute, result);
-
-out:
- if (fclose(fp))
- log_sys_error("fclose", path);
-
- return result >> SECTOR_SHIFT;
-}
-
-unsigned long dev_alignment_offset(const char *sysfs_dir,
- struct device *dev)
-{
- return _dev_topology_attribute("alignment_offset",
- sysfs_dir, dev);
-}
-
-unsigned long dev_minimum_io_size(const char *sysfs_dir,
- struct device *dev)
-{
- return _dev_topology_attribute("queue/minimum_io_size",
- sysfs_dir, dev);
-}
-
-unsigned long dev_optimal_io_size(const char *sysfs_dir,
- struct device *dev)
-{
- return _dev_topology_attribute("queue/optimal_io_size",
- sysfs_dir, dev);
-}
-
-unsigned long dev_discard_max_bytes(const char *sysfs_dir,
- struct device *dev)
-{
- return _dev_topology_attribute("queue/discard_max_bytes",
- sysfs_dir, dev);
-}
-
-unsigned long dev_discard_granularity(const char *sysfs_dir,
- struct device *dev)
-{
- return _dev_topology_attribute("queue/discard_granularity",
- sysfs_dir, dev);
-}
-
-#else
-
-int get_primary_dev(const char *sysfs_dir,
- struct device *dev, dev_t *result)
-{
- return 0;
-}
-
-unsigned long dev_alignment_offset(const char *sysfs_dir,
- struct device *dev)
-{
- return 0UL;
-}
-
-unsigned long dev_minimum_io_size(const char *sysfs_dir,
- struct device *dev)
-{
- return 0UL;
-}
-
-unsigned long dev_optimal_io_size(const char *sysfs_dir,
- struct device *dev)
-{
- return 0UL;
-}
-
-unsigned long dev_discard_max_bytes(const char *sysfs_dir,
- struct device *dev)
-{
- return 0UL;
-}
-
-unsigned long dev_discard_granularity(const char *sysfs_dir,
- struct device *dev)
-{
- return 0UL;
-}
-
-#endif