/* * 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); #ifdef __NetBSD__ struct disklabel lab; prop_dictionary_t disk_dict, geom_dict; uint32_t secsize; #endif if ((dev->block_size == -1)) { #ifdef __NetBSD__ if (prop_dictionary_recv_ioctl(dev_fd(dev), DIOCGDISKINFO, &disk_dict)) { if (ioctl(dev_fd(dev), DIOCGDINFO, &lab) < 0) { dev->block_size = DEV_BSIZE; } else dev->block_size = lab.d_secsize; } else { geom_dict = prop_dictionary_get(disk_dict, "geometry"); prop_dictionary_get_uint32(geom_dict, "sector-size", &secsize); dev->block_size = secsize; } #else if (ioctl(dev_fd(dev), BLKBSZGET, &dev->block_size) < 0) { log_sys_error("ioctl BLKBSZGET", name); return 0; } #endif log_debug("%s: block size is %u bytes", name, dev->block_size); } *size = (unsigned int) dev->block_size; return 1; }
/* * 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); #ifdef __NetBSD__ struct disklabel lab; #elif __DragonFly__ struct partinfo pinfo; #endif if ((dev->block_size == -1)) { #ifdef __NetBSD__ if (ioctl(dev_fd(dev), DIOCGDINFO, &lab) < 0) { dev->block_size = DEV_BSIZE; } else dev->block_size = lab.d_secsize; #elif __DragonFly__ if (ioctl(dev_fd(dev), DIOCGPART, &pinfo) < 0) { dev->block_size = DEV_BSIZE; } else dev->block_size = pinfo.media_blksize; #else if (ioctl(dev_fd(dev), BLKBSZGET, &dev->block_size) < 0) { log_sys_error("ioctl BLKBSZGET", name); return 0; } #endif log_debug("%s: block size is %u bytes", name, dev->block_size); } *size = (unsigned int) dev->block_size; return 1; }
/*----------------------------------------------------------------- * The standard io loop that keeps submitting an io until it's * all gone. *---------------------------------------------------------------*/ static int _io(struct device_area *where, char *buffer, int should_write) { int fd = dev_fd(where->dev); ssize_t n = 0; size_t total = 0; if (fd < 0) { log_error("Attempt to read an unopened device (%s).", dev_name(where->dev)); return 0; } /* * Skip all writes in test mode. */ if (should_write && test_mode()) return 1; if (where->size > SSIZE_MAX) { log_error("Read size too large: %" PRIu64, where->size); return 0; } if (lseek(fd, (off_t) where->start, SEEK_SET) < 0) { log_error("%s: lseek %" PRIu64 " failed: %s", dev_name(where->dev), (uint64_t) where->start, strerror(errno)); return 0; } while (total < (size_t) where->size) { do n = should_write ? write(fd, buffer, (size_t) where->size - total) : read(fd, buffer, (size_t) where->size - total); while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN))); if (n < 0) log_error_once("%s: %s failed after %" PRIu64 " of %" PRIu64 " at %" PRIu64 ": %s", dev_name(where->dev), should_write ? "write" : "read", (uint64_t) total, (uint64_t) where->size, (uint64_t) where->start, strerror(errno)); if (n <= 0) break; total += n; buffer += n; } return (total == (size_t) where->size); }
/* * 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("%s: block size is %u bytes", name, dev->block_size); } *size = (unsigned int) dev->block_size; return 1; }
int read_config_fd(struct config_tree *cft, struct device *dev, off_t offset, size_t size, off_t offset2, size_t size2, checksum_fn_t checksum_fn, uint32_t checksum) { struct cs *c = (struct cs *) cft; struct parser *p; int r = 0; int use_mmap = 1; off_t mmap_offset = 0; char *buf = NULL; if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) return_0; p->mem = c->mem; /* Only use mmap with regular files */ if (!(dev->flags & DEV_REGULAR) || size2) use_mmap = 0; if (use_mmap) { mmap_offset = offset % lvm_getpagesize(); /* memory map the file */ p->fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ, MAP_PRIVATE, dev_fd(dev), offset - mmap_offset); if (p->fb == (caddr_t) (-1)) { log_sys_error("mmap", dev_name(dev)); goto out; } p->fb = p->fb + mmap_offset; } else { if (!(buf = dm_malloc(size + size2))) return_0; if (!dev_read_circular(dev, (uint64_t) offset, size, (uint64_t) offset2, size2, buf)) { goto out; } p->fb = buf; } if (checksum_fn && checksum != (checksum_fn(checksum_fn(INITIAL_CRC, (const uint8_t *)p->fb, size), (const uint8_t *)(p->fb + size), size2))) { log_error("%s: Checksum error", dev_name(dev)); goto out; } p->fe = p->fb + size + size2; if (!_parse_config_file(p, cft)) goto_out; r = 1; out: if (!use_mmap) dm_free(buf); else { /* unmap the file */ if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) { log_sys_error("munmap", dev_name(dev)); r = 0; } } return r; }
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, off_t offset, size_t size, off_t offset2, size_t size2, checksum_fn_t checksum_fn, uint32_t checksum) { char *fb, *fe; int r = 0; int use_mmap = 1; off_t mmap_offset = 0; char *buf = NULL; struct config_source *cs = dm_config_get_custom(cft); if ((cs->type != CONFIG_FILE) && (cs->type != CONFIG_PROFILE)) { log_error(INTERNAL_ERROR "config_file_read_fd: expected file or profile config source, " "found %s config source.", _config_source_names[cs->type]); return 0; } /* Only use mmap with regular files */ if (!(dev->flags & DEV_REGULAR) || size2) use_mmap = 0; if (use_mmap) { mmap_offset = offset % lvm_getpagesize(); /* memory map the file */ fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ, MAP_PRIVATE, dev_fd(dev), offset - mmap_offset); if (fb == (caddr_t) (-1)) { log_sys_error("mmap", dev_name(dev)); goto out; } fb = fb + mmap_offset; } else { if (!(buf = dm_malloc(size + size2))) { log_error("Failed to allocate circular buffer."); return 0; } if (!dev_read_circular(dev, (uint64_t) offset, size, (uint64_t) offset2, size2, buf)) { goto out; } fb = buf; } if (checksum_fn && checksum != (checksum_fn(checksum_fn(INITIAL_CRC, (const uint8_t *)fb, size), (const uint8_t *)(fb + size), size2))) { log_error("%s: Checksum error", dev_name(dev)); goto out; } fe = fb + size + size2; if (!dm_config_parse(cft, fb, fe)) goto_out; r = 1; out: if (!use_mmap) dm_free(buf); else { /* unmap the file */ if (munmap(fb - mmap_offset, size + mmap_offset)) { log_sys_error("munmap", dev_name(dev)); r = 0; } } return r; }