diff options
Diffstat (limited to 'lib/device/dev-type.c')
-rw-r--r-- | lib/device/dev-type.c | 169 |
1 files changed, 139 insertions, 30 deletions
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c index 001248d45..db4079225 100644 --- a/lib/device/dev-type.c +++ b/lib/device/dev-type.c @@ -25,6 +25,11 @@ #include <blkid.h> #endif +#ifdef UDEV_SYNC_SUPPORT +#include <libudev.h> +#include "dev-ext-udev-constants.h" +#endif + #include "device-types.h" struct dev_types *create_dev_types(const char *proc_dir, @@ -112,6 +117,10 @@ struct dev_types *create_dev_types(const char *proc_dir, if (!strncmp("drbd", line + i, 4) && isspace(*(line + i + 4))) dt->drbd_major = line_maj; + /* Look for DASD */ + if (!strncmp("dasd", line + i, 4) && isspace(*(line + i + 4))) + dt->dasd_major = line_maj; + /* Look for EMC powerpath */ if (!strncmp("emcpower", line + i, 8) && isspace(*(line + i + 8))) dt->emcpower_major = line_maj; @@ -216,12 +225,18 @@ int dev_subsystem_part_major(struct dev_types *dt, struct device *dev) const char *dev_subsystem_name(struct dev_types *dt, struct device *dev) { + if (MAJOR(dev->dev) == dt->device_mapper_major) + return "DM"; + if (MAJOR(dev->dev) == dt->md_major) return "MD"; if (MAJOR(dev->dev) == dt->drbd_major) return "DRBD"; + if (MAJOR(dev->dev) == dt->dasd_major) + return "DASD"; + if (MAJOR(dev->dev) == dt->emcpower_major) return "EMCPOWER"; @@ -272,6 +287,9 @@ static int _is_partitionable(struct dev_types *dt, struct device *dev) { int parts = major_max_partitions(dt, MAJOR(dev->dev)); + if (MAJOR(dev->dev) == dt->device_mapper_major) + return 1; + /* All MD devices are partitionable via blkext (as of 2.6.28) */ if (MAJOR(dev->dev) == dt->md_major) return 1; @@ -314,12 +332,66 @@ static int _has_partition_table(struct device *dev) return ret; } -int dev_is_partitioned(struct dev_types *dt, struct device *dev) +#ifdef UDEV_SYNC_SUPPORT +static int _udev_dev_is_partitioned(struct device *dev) +{ + struct dev_ext *ext; + + if (!(ext = dev_ext_get(dev))) + return_0; + + if (!udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_PART_TABLE_TYPE)) + return 0; + + if (udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_PART_ENTRY_DISK)) + return 0; + + return 1; +} +#else +static int _udev_dev_is_partitioned(struct device *dev) { + return 0; +} +#endif + +static int _native_dev_is_partitioned(struct dev_types *dt, struct device *dev) +{ + int r; + if (!_is_partitionable(dt, dev)) return 0; - return _has_partition_table(dev); + /* Unpartitioned DASD devices are not supported. */ + if (MAJOR(dev->dev) == dt->dasd_major) + return 1; + + if (!dev_open_readonly_quiet(dev)) { + log_debug_devs("%s: failed to open device, considering device " + "is partitioned", dev_name(dev)); + return 1; + } + + r = _has_partition_table(dev); + + if (!dev_close(dev)) + stack; + + return r; +} + +int dev_is_partitioned(struct dev_types *dt, struct device *dev) +{ + if (dev->ext.src == DEV_EXT_NONE) + return _native_dev_is_partitioned(dt, dev); + + if (dev->ext.src == DEV_EXT_UDEV) + return _udev_dev_is_partitioned(dev); + + log_error(INTERNAL_ERROR "Missing hook for partition table recognition " + "using external device info source %s", dev_ext_name(dev)); + + return 0; } /* @@ -361,7 +433,7 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result) */ if ((parts = dt->dev_type_array[major].max_partitions) > 1) { if ((residue = minor % parts)) { - *result = MKDEV((dev_t)major, (minor - residue)); + *result = MKDEV((dev_t)major, (dev_t)(minor - residue)); ret = 2; } else { *result = dev->dev; @@ -438,7 +510,7 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result) path, buffer); goto out; } - *result = MKDEV((dev_t)major, minor); + *result = MKDEV((dev_t)major, (dev_t)minor); ret = 2; out: if (fp && fclose(fp)) @@ -456,12 +528,14 @@ static inline int _type_in_flag_list(const char *type, uint32_t flag_list) ((flag_list & TYPE_DM_SNAPSHOT_COW) && !strcmp(type, "DM_snapshot_cow"))); } +#define MSG_FAILED_SIG_OFFSET "Failed to get offset of the %s signature on %s." +#define MSG_FAILED_SIG_LENGTH "Failed to get length of the %s signature on %s." +#define MSG_WIPING_SKIPPED " Wiping skipped." + static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name, uint32_t types_to_exclude, uint32_t types_no_prompt, int yes, force_t force) { - static const char _msg_failed_offset[] = "Failed to get offset of the %s signature on %s."; - static const char _msg_failed_length[] = "Failed to get length of the %s signature on %s."; static const char _msg_wiping[] = "Wiping %s signature on %s."; const char *offset = NULL, *type = NULL, *magic = NULL, *usage = NULL, *label = NULL, *uuid = NULL; @@ -470,23 +544,43 @@ static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name, if (!blkid_probe_lookup_value(probe, "TYPE", &type, NULL)) { if (_type_in_flag_list(type, types_to_exclude)) - return 1; + return 2; if (blkid_probe_lookup_value(probe, "SBMAGIC_OFFSET", &offset, NULL)) { - log_error(_msg_failed_offset, type, name); - return 0; + if (force < DONT_PROMPT) { + log_error(MSG_FAILED_SIG_OFFSET, type, name); + return 0; + } else { + log_error("WARNING: " MSG_FAILED_SIG_OFFSET MSG_WIPING_SKIPPED, type, name); + return 2; + } } if (blkid_probe_lookup_value(probe, "SBMAGIC", &magic, &len)) { - log_error(_msg_failed_length, type, name); - return 0; + if (force < DONT_PROMPT) { + log_error(MSG_FAILED_SIG_LENGTH, type, name); + return 0; + } else { + log_warn("WARNING: " MSG_FAILED_SIG_LENGTH MSG_WIPING_SKIPPED, type, name); + return 2; + } } } else if (!blkid_probe_lookup_value(probe, "PTTYPE", &type, NULL)) { if (blkid_probe_lookup_value(probe, "PTMAGIC_OFFSET", &offset, NULL)) { - log_error(_msg_failed_offset, type, name); - return 0; + if (force < DONT_PROMPT) { + log_error(MSG_FAILED_SIG_OFFSET, type, name); + return 0; + } else { + log_warn("WARNING: " MSG_FAILED_SIG_OFFSET MSG_WIPING_SKIPPED, type, name); + return 2; + } } if (blkid_probe_lookup_value(probe, "PTMAGIC", &magic, &len)) { - log_error(_msg_failed_length, type, name); - return 0; + if (force < DONT_PROMPT) { + log_error(MSG_FAILED_SIG_LENGTH, type, name); + return 0; + } else { + log_warn("WARNING: " MSG_FAILED_SIG_LENGTH MSG_WIPING_SKIPPED, type, name); + return 2; + } } usage = "partition table"; } else @@ -526,12 +620,17 @@ static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name, static int _wipe_known_signatures_with_blkid(struct device *dev, const char *name, uint32_t types_to_exclude, uint32_t types_no_prompt, - int yes, force_t force) + int yes, force_t force, int *wiped) { blkid_probe probe = NULL; - int found = 0, wiped = 0, left = 0; + int found = 0, left = 0, wiped_tmp; + int r_wipe; int r = 0; + if (!wiped) + wiped = &wiped_tmp; + *wiped = 0; + /* TODO: Should we check for valid dev - _dev_is_valid(dev)? */ if (!(probe = blkid_new_probe_from_filename(dev_name(dev)))) { @@ -552,15 +651,17 @@ static int _wipe_known_signatures_with_blkid(struct device *dev, const char *nam BLKID_SUBLKS_BADCSUM); while (!blkid_do_probe(probe)) { - found++; - if (_blkid_wipe(probe, dev, name, types_to_exclude, types_no_prompt, yes, force)) - wiped++; + if ((r_wipe = _blkid_wipe(probe, dev, name, types_to_exclude, types_no_prompt, yes, force)) == 1) + (*wiped)++; + /* do not count excluded types */ + if (r_wipe != 2) + found++; } if (!found) r = 1; - left = found - wiped; + left = found - *wiped; if (!left) r = 1; else @@ -575,7 +676,7 @@ out: #endif /* BLKID_WIPING_SUPPORT */ static int _wipe_signature(struct device *dev, const char *type, const char *name, - int wipe_len, int yes, force_t force, + int wipe_len, int yes, force_t force, int *wiped, int (*signature_detection_fn)(struct device *dev, uint64_t *offset_found)) { int wipe; @@ -605,17 +706,24 @@ static int _wipe_signature(struct device *dev, const char *type, const char *nam return 0; } + (*wiped)++; return 1; } static int _wipe_known_signatures_with_lvm(struct device *dev, const char *name, uint32_t types_to_exclude __attribute__((unused)), uint32_t types_no_prompt __attribute__((unused)), - int yes, force_t force) + int yes, force_t force, int *wiped) { - if (!_wipe_signature(dev, "software RAID md superblock", name, 4, yes, force, dev_is_md) || - !_wipe_signature(dev, "swap signature", name, 10, yes, force, dev_is_swap) || - !_wipe_signature(dev, "LUKS signature", name, 8, yes, force, dev_is_luks)) + int wiped_tmp; + + if (!wiped) + wiped = &wiped_tmp; + *wiped = 0; + + if (!_wipe_signature(dev, "software RAID md superblock", name, 4, yes, force, wiped, dev_is_md) || + !_wipe_signature(dev, "swap signature", name, 10, yes, force, wiped, dev_is_swap) || + !_wipe_signature(dev, "LUKS signature", name, 8, yes, force, wiped, dev_is_luks)) return 0; return 1; @@ -623,19 +731,20 @@ static int _wipe_known_signatures_with_lvm(struct device *dev, const char *name, int wipe_known_signatures(struct cmd_context *cmd, struct device *dev, const char *name, uint32_t types_to_exclude, - uint32_t types_no_prompt, int yes, force_t force) + uint32_t types_no_prompt, int yes, force_t force, + int *wiped) { #ifdef BLKID_WIPING_SUPPORT if (find_config_tree_bool(cmd, allocation_use_blkid_wiping_CFG, NULL)) return _wipe_known_signatures_with_blkid(dev, name, types_to_exclude, types_no_prompt, - yes, force); + yes, force, wiped); #endif return _wipe_known_signatures_with_lvm(dev, name, types_to_exclude, types_no_prompt, - yes, force); + yes, force, wiped); } #ifdef __linux__ @@ -715,7 +824,7 @@ static unsigned long _dev_topology_attribute(struct dev_types *dt, } log_very_verbose("Device %s: %s is %lu%s.", - dev_name(dev), attribute, result, default_value ? "" : " bytes"); + dev_name(dev), attribute, value, default_value ? "" : " bytes"); result = value >> SECTOR_SHIFT; |