static int _native_check_pv_min_size(struct device *dev) { uint64_t size; int ret = 0; /* Check it's accessible */ if (!dev_open_readonly_quiet(dev)) { log_debug_devs("%s: Skipping: open failed", dev_name(dev)); return 0; } /* Check it's not too small */ if (!dev_get_size(dev, &size)) { log_debug_devs("%s: Skipping: dev_get_size failed", dev_name(dev)); goto out; } if (size < pv_min_size()) { log_debug_devs("%s: Skipping: %s", dev_name(dev), _too_small_to_hold_pv_msg); goto out; } ret = 1; out: if (!dev_close(dev)) stack; return ret; }
static int _udev_check_pv_min_size(struct device *dev) { struct dev_ext *ext; const char *size_str; char *endp; uint64_t size; if (!(ext = dev_ext_get(dev))) return_0; if (!(size_str = udev_device_get_sysattr_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_SYSFS_ATTR_SIZE))) { log_debug_devs("%s: Skipping: failed to get size from sysfs [%s:%p]", dev_name(dev), dev_ext_name(dev), dev->ext.handle); return 0; } errno = 0; size = strtoull(size_str, &endp, 10); if (errno || !endp || *endp) { log_debug_devs("%s: Skipping: failed to parse size from sysfs [%s:%p]", dev_name(dev), dev_ext_name(dev), dev->ext.handle); return 0; } if (size < pv_min_size()) { log_debug_devs("%s: Skipping: %s [%s:%p]", dev_name(dev), _too_small_to_hold_pv_msg, dev_ext_name(dev), dev->ext.handle); return 0; } return 1; }
static int _dev_discard_blocks(struct device *dev, uint64_t offset_bytes, uint64_t size_bytes) { uint64_t discard_range[2]; if (!dev_open(dev)) return_0; discard_range[0] = offset_bytes; discard_range[1] = size_bytes; log_debug_devs("Discarding %" PRIu64 " bytes offset %" PRIu64 " bytes on %s.", size_bytes, offset_bytes, dev_name(dev)); if (ioctl(dev->fd, BLKDISCARD, &discard_range) < 0) { log_error("%s: BLKDISCARD ioctl at offset %" PRIu64 " size %" PRIu64 " failed: %s.", dev_name(dev), offset_bytes, size_bytes, strerror(errno)); if (!dev_close(dev)) stack; /* It doesn't matter if discard failed, so return success. */ return 1; } if (!dev_close(dev)) stack; return 1; }
struct dev_ext *dev_ext_get(struct device *dev) { struct dev_ext *ext; void *handle_ptr; handle_ptr = dev->ext.handle; if (!(ext = _ext_registry[dev->ext.src].dev_ext_get(dev))) log_error("Failed to get external handle for device %s [%s].", dev_name(dev), dev_ext_name(dev)); else if (handle_ptr != dev->ext.handle) log_debug_devs("%s %s [%s:%p]", _ext_attached_msg, dev_name(dev), dev_ext_name(dev), dev->ext.handle); return ext; }
static void _close(struct device *dev) { if (close(dev->fd)) log_sys_error("close", dev_name(dev)); dev->fd = -1; dev->block_size = -1; dm_list_del(&dev->open_list); log_debug_devs("Closed %s", dev_name(dev)); if (dev->flags & DEV_ALLOCED) { dm_free((void *) dm_list_item(dev->aliases.n, struct str_list)-> str); dm_free(dev->aliases.n); dm_free(dev); }
/* * Get the sector size from an _open_ device. */ static int _get_block_size(struct device *dev, unsigned int *size) { const char *name = dev_name(dev); if (dev->block_size == -1) { if (ioctl(dev_fd(dev), BLKBSZGET, &dev->block_size) < 0) { log_sys_error("ioctl BLKBSZGET", name); return 0; } log_debug_devs("%s: block size is %u bytes", name, dev->block_size); } *size = (unsigned int) dev->block_size; return 1; }
int dev_ext_release(struct device *dev) { int r; void *handle_ptr; if (!dev->ext.enabled || !dev->ext.handle) return 1; handle_ptr = dev->ext.handle; if (!(r = _ext_registry[dev->ext.src].dev_ext_release(dev))) log_error("Failed to release external handle for device %s [%s:%p].", dev_name(dev), dev_ext_name(dev), dev->ext.handle); else log_debug_devs("External handle detached from device %s [%s:%p]", dev_name(dev), dev_ext_name(dev), handle_ptr); return r; }
static int _native_dev_is_partitioned(struct dev_types *dt, struct device *dev) { int r; if (!_is_partitionable(dt, dev)) return 0; /* 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_open_flags(struct device *dev, int flags, int direct, int quiet) { struct stat buf; const char *name; int need_excl = 0, need_rw = 0; if ((flags & O_ACCMODE) == O_RDWR) need_rw = 1; if ((flags & O_EXCL)) need_excl = 1; if (dev->fd >= 0) { if (((dev->flags & DEV_OPENED_RW) || !need_rw) && ((dev->flags & DEV_OPENED_EXCL) || !need_excl)) { dev->open_count++; return 1; } if (dev->open_count && !need_excl) { log_debug_devs("%s already opened read-only. Upgrading " "to read-write.", dev_name(dev)); dev->open_count++; } dev_close_immediate(dev); // FIXME: dev with DEV_ALLOCED is released // but code is referencing it } if (critical_section()) /* FIXME Make this log_error */ log_verbose("dev_open(%s) called while suspended", dev_name(dev)); if (dev->flags & DEV_REGULAR) name = dev_name(dev); else if (!(name = dev_name_confirmed(dev, quiet))) return_0; #ifdef O_DIRECT_SUPPORT if (direct) { if (!(dev->flags & DEV_O_DIRECT_TESTED)) dev->flags |= DEV_O_DIRECT; if ((dev->flags & DEV_O_DIRECT)) flags |= O_DIRECT; } #endif #ifdef O_NOATIME /* Don't update atime on device inodes */ if (!(dev->flags & DEV_REGULAR)) flags |= O_NOATIME; #endif if ((dev->fd = open(name, flags, 0777)) < 0) { #ifdef O_DIRECT_SUPPORT if (direct && !(dev->flags & DEV_O_DIRECT_TESTED)) { flags &= ~O_DIRECT; if ((dev->fd = open(name, flags, 0777)) >= 0) { dev->flags &= ~DEV_O_DIRECT; log_debug_devs("%s: Not using O_DIRECT", name); goto opened; } } #endif if (quiet) log_sys_debug("open", name); else log_sys_error("open", name); return 0; } #ifdef O_DIRECT_SUPPORT opened: if (direct) dev->flags |= DEV_O_DIRECT_TESTED; #endif dev->open_count++; dev->flags &= ~DEV_ACCESSED_W; if (need_rw) dev->flags |= DEV_OPENED_RW; else dev->flags &= ~DEV_OPENED_RW; if (need_excl) dev->flags |= DEV_OPENED_EXCL; else dev->flags &= ~DEV_OPENED_EXCL; if (!(dev->flags & DEV_REGULAR) && ((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) { log_error("%s: fstat failed: Has device name changed?", name); dev_close_immediate(dev); return 0; } #ifndef O_DIRECT_SUPPORT if (!(dev->flags & DEV_REGULAR)) dev_flush(dev); #endif if ((flags & O_CREAT) && !(flags & O_TRUNC)) dev->end = lseek(dev->fd, (off_t) 0, SEEK_END); dm_list_add(&_open_devices, &dev->open_list); log_debug_devs("Opened %s %s%s%s", dev_name(dev), dev->flags & DEV_OPENED_RW ? "RW" : "RO", dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "", dev->flags & DEV_O_DIRECT ? " O_DIRECT" : ""); return 1; }