static int _find_config_bool(const void *start, node_lookup_fn find, const char *path, int fail) { const struct dm_config_node *n = find(start, path); const struct dm_config_value *v; int b; if (n) { v = n->v; switch (v->type) { case DM_CFG_INT: b = v->v.i ? 1 : 0; log_very_verbose("Setting %s to %d", path, b); return b; case DM_CFG_STRING: b = _str_to_bool(v->v.str, fail); log_very_verbose("Setting %s to %d", path, b); return b; default: ; } } log_very_verbose("%s not found in config: defaulting to %d", path, fail); return fail; }
int dm_dump_memory_debug(void) { unsigned long tot = 0; struct memblock *mb; char str[32]; size_t c; if (_head) log_very_verbose("You have a memory leak:"); for (mb = _head; mb; mb = mb->next) { for (c = 0; c < sizeof(str) - 1; c++) { if (c >= mb->length) str[c] = ' '; else if (*(char *)((char *)mb->magic + c) == '\0') str[c] = '\0'; else if (*(char *)((char *)mb->magic + c) < ' ') str[c] = '?'; else str[c] = *(char *)((char *)mb->magic + c); } str[sizeof(str) - 1] = '\0'; dm_log(_LOG_INFO, mb->file, mb->line, "block %d at %p, size %" PRIsize_t "\t [%s]", mb->id, mb->magic, mb->length, str); tot += mb->length; } if (_head) log_very_verbose("%ld bytes leaked in total", tot); return 1; }
static int64_t _find_config_int64(const void *start, node_lookup_fn find, const char *path, int64_t fail) { const struct dm_config_node *n = find(start, path); if (n && n->v && n->v->type == DM_CFG_INT) { log_very_verbose("Setting %s to %" PRId64, path, n->v->v.i); return n->v->v.i; } log_very_verbose("%s not found in config: defaulting to %" PRId64, path, fail); return fail; }
static int64_t _find_config_int64(const struct config_node *cn1, const struct config_node *cn2, const char *path, int64_t fail) { const struct config_node *n = _find_first_config_node(cn1, cn2, path); if (n && n->v && n->v->type == CFG_INT) { log_very_verbose("Setting %s to %" PRId64, path, n->v->v.i); return n->v->v.i; } log_very_verbose("%s not found in config: defaulting to %" PRId64, path, fail); return fail; }
static int _read_array(struct pfilter *pf, struct config_tree *cft, const char *path, void *data) { const struct config_node *cn; struct config_value *cv; if (!(cn = find_config_node(cft->root, path))) { log_very_verbose("Couldn't find %s array in '%s'", path, pf->file); return 0; } /* * iterate through the array, adding * devices as we go. */ for (cv = cn->v; cv; cv = cv->next) { if (cv->type != CFG_STRING) { log_verbose("Devices array contains a value " "which is not a string ... ignoring"); continue; } if (!dm_hash_insert(pf->devices, cv->v.str, data)) log_verbose("Couldn't add '%s' to filter ... ignoring", cv->v.str); /* Populate dev_cache ourselves */ dev_cache_get(cv->v.str, NULL); } return 1; }
static int lvchange_alloc(struct cmd_context *cmd, struct logical_volume *lv) { int want_contiguous = 0; alloc_policy_t alloc; want_contiguous = strcmp(arg_str_value(cmd, contiguous_ARG, "n"), "n"); alloc = want_contiguous ? ALLOC_CONTIGUOUS : ALLOC_INHERIT; alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, alloc); if (alloc == lv->alloc) { log_error("Allocation policy of logical volume \"%s\" is " "already %s", lv->name, get_alloc_string(alloc)); return 0; } lv->alloc = alloc; /* FIXME If contiguous, check existing extents already are */ log_verbose("Setting contiguous allocation policy for \"%s\" to %s", lv->name, get_alloc_string(alloc)); log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name); /* No need to suspend LV for this change */ if (!vg_write(lv->vg) || !vg_commit(lv->vg)) return_0; backup(lv->vg); return 1; }
static int _dev_read_ahead_dev(struct device *dev, uint32_t *read_ahead) { long read_ahead_long; if (dev->read_ahead != -1) { *read_ahead = (uint32_t) dev->read_ahead; return 1; } if (!dev_open(dev)) return_0; if (ioctl(dev->fd, BLKRAGET, &read_ahead_long) < 0) { log_sys_error("ioctl BLKRAGET", dev_name(dev)); if (!dev_close(dev)) stack; return 0; } if (!dev_close(dev)) stack; *read_ahead = (uint32_t) read_ahead_long; dev->read_ahead = read_ahead_long; log_very_verbose("%s: read_ahead is %u sectors", dev_name(dev), *read_ahead); return 1; }
static void _unlock_mem(struct cmd_context *cmd) { size_t unlock_mstats; log_very_verbose("Unlocking memory"); if (!_memlock_maps(cmd, LVM_MUNLOCK, &unlock_mstats)) stack; if (!_use_mlockall) { _restore_mmap(); if (close(_maps_fd)) log_sys_error("close", _procselfmaps); dm_free(_maps_buffer); _maps_buffer = NULL; if (_mstats < unlock_mstats) { if ((_mstats + lvm_getpagesize()) < unlock_mstats) log_error(INTERNAL_ERROR "Reserved memory (%ld) not enough: used %ld. Increase activation/reserved_memory?", (long)_mstats, (long)unlock_mstats); else /* FIXME Believed due to incorrect use of yes_no_prompt while locks held */ log_debug_mem("Suppressed internal error: Maps lock %ld < unlock %ld, a one-page difference.", (long)_mstats, (long)unlock_mstats); } } if (setpriority(PRIO_PROCESS, 0, _priority)) log_error("setpriority %u failed: %s", _priority, strerror(errno)); _release_memory(); }
struct dm_config_tree *config_file_open_and_read(const char *config_file, config_source_t source) { struct dm_config_tree *cft; struct stat info; if (!(cft = config_open(source, config_file, 0))) { log_error("config_tree allocation failed"); return NULL; } /* Is there a config file? */ if (stat(config_file, &info) == -1) { /* Profile file must be present! */ if (errno == ENOENT && (source != CONFIG_PROFILE)) return cft; log_sys_error("stat", config_file); goto bad; } log_very_verbose("Loading config file: %s", config_file); if (!config_file_read(cft)) { log_error("Failed to load config file %s", config_file); goto bad; } return cft; bad: config_destroy(cft); return NULL; }
static int _dev_get_size_dev(const struct device *dev, uint64_t *size) { int fd; const char *name = dev_name(dev); if ((fd = open(name, O_RDONLY)) < 0) { log_sys_error("open", name); return 0; } if (ioctl(fd, BLKGETSIZE64, size) < 0) { log_sys_error("ioctl BLKGETSIZE64", name); if (close(fd)) log_sys_error("close", name); return 0; } *size >>= BLKSIZE_SHIFT; /* Convert to sectors */ if (close(fd)) log_sys_error("close", name); log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size); return 1; }
static float _find_config_float(const void *start, node_lookup_fn find, const char *path, float fail) { const struct dm_config_node *n = find(start, path); if (n && n->v && n->v->type == DM_CFG_FLOAT) { log_very_verbose("Setting %s to %f", path, n->v->v.f); return n->v->v.f; } log_very_verbose("%s not found in config: defaulting to %f", path, fail); return fail; }
void *load_shared_library(struct cmd_context *cmd, const char *libname, const char *desc, int silent) { char path[PATH_MAX]; void *library; if (is_static()) { log_error("Not loading shared %s library %s in static mode.", desc, libname); return NULL; } get_shared_library_path(cmd, libname, path, sizeof(path)); log_very_verbose("Opening shared %s library %s", desc, path); if (!(library = dlopen(path, RTLD_LAZY | RTLD_GLOBAL))) { if (silent && ignorelockingfailure()) log_verbose("Unable to open external %s library %s: %s", desc, path, dlerror()); else log_error("Unable to open external %s library %s: %s", desc, path, dlerror()); } return library; }
static float _find_config_float(const struct config_node *cn1, const struct config_node *cn2, const char *path, float fail) { const struct config_node *n = _find_first_config_node(cn1, cn2, path); if (n && n->v && n->v->type == CFG_FLOAT) { log_very_verbose("Setting %s to %f", path, n->v->v.r); return n->v->v.r; } log_very_verbose("%s not found in config: defaulting to %f", path, fail); return fail; }
static const char *_find_config_str(const struct config_node *cn1, const struct config_node *cn2, const char *path, const char *fail) { const struct config_node *n = _find_first_config_node(cn1, cn2, path); /* Empty strings are ignored */ if ((n && n->v && n->v->type == CFG_STRING) && (*n->v->v.str)) { log_very_verbose("Setting %s to %s", path, n->v->v.str); return n->v->v.str; } if (fail) log_very_verbose("%s not found in config: defaulting to %s", path, fail); return fail; }
static void _write_history(void) { char hist_file[PATH_MAX]; if (!_hist_file(hist_file, sizeof(hist_file))) return; if (write_history(hist_file)) log_very_verbose("Couldn't write history to %s.", hist_file); }
static int _read_pvd(struct device *dev, struct pv_disk *pvd) { if (!dev_read(dev, UINT64_C(0), sizeof(*pvd), pvd)) { log_very_verbose("Failed to read PV data from %s", dev_name(dev)); return 0; } return munge_pvd(dev, pvd); }
int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out) { struct pfilter *pf = (struct pfilter *) f->private; struct config_tree *cft; struct stat info; int r = 0; if (!stat(pf->file, &info)) pf->ctime = info.st_ctime; else { log_very_verbose("%s: stat failed: %s", pf->file, strerror(errno)); return_0; } if (!(cft = create_config_tree(pf->file, 1))) return_0; if (!read_config_file(cft)) goto_out; _read_array(pf, cft, "persistent_filter_cache/valid_devices", PF_GOOD_DEVICE); /* We don't gain anything by holding invalid devices */ /* _read_array(pf, cft, "persistent_filter_cache/invalid_devices", PF_BAD_DEVICE); */ /* Did we find anything? */ if (dm_hash_get_num_entries(pf->devices)) { /* We populated dev_cache ourselves */ dev_cache_scan(0); r = 1; } log_very_verbose("Loaded persistent filter cache from %s", pf->file); out: if (r && cft_out) *cft_out = cft; else destroy_config_tree(cft); return r; }
int dm_dump_memory_debug(void) { unsigned long tot = 0; struct memblock *mb; char str[32]; if (_head) log_very_verbose("You have a memory leak:"); for (mb = _head; mb; mb = mb->next) { #ifdef VALGRIND_POOL /* * We can't look at the memory in case it has had * VALGRIND_MAKE_MEM_NOACCESS called on it. */ str[0] = '\0'; #else size_t c; for (c = 0; c < sizeof(str) - 1; c++) { if (c >= mb->length) str[c] = ' '; else if (((char *)mb->magic)[c] == '\0') str[c] = '\0'; else if (((char *)mb->magic)[c] < ' ') str[c] = '?'; else str[c] = ((char *)mb->magic)[c]; } str[sizeof(str) - 1] = '\0'; #endif LOG_MESG(_LOG_INFO, mb->file, mb->line, 0, "block %d at %p, size %" PRIsize_t "\t [%s]", mb->id, mb->magic, mb->length, str); tot += mb->length; } if (_head) log_very_verbose("%ld bytes leaked in total", tot); return 1; }
/* * This function is heart of NetBSD libdevmapper-> device-mapper kernel protocol * It creates proplib_dictionary from dm task structure and sends it to NetBSD * kernel driver. After succesfull ioctl it create dmi structure from returned * proplib dictionary. This way I keep number of changes in NetBSD version of * libdevmapper as small as posible. */ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command) { struct dm_ioctl *dmi; libdm_task_t task; task = libdm_task_create(_cmd_data_v4[dmt->type].name); /* Parse dmi from libdevmapper to dictionary */ if (_flatten(dmt, task) < 0) goto bad; if (dmt->type == DM_DEVICE_TABLE) libdm_task_set_status_flag(task); libdm_task_set_exists_flag(task); log_very_verbose("Ioctl type %s --- flags %d",_cmd_data_v4[dmt->type].name, libdm_task_get_flags(task)); /* Send dictionary to kernel and wait for reply. */ if (libdm_task_run(task) != 0) { if (errno == ENOENT && ((dmt->type == DM_DEVICE_INFO) || (dmt->type == DM_DEVICE_MKNODES) || (dmt->type == DM_DEVICE_STATUS))) { /* * Linux version doesn't fail when ENOENT is returned * for nonexisting device after info, deps, mknodes call. * It returns dmi sent to kernel with DM_EXISTS_FLAG = 0; */ dmi = nbsd_dm_dict_to_dmi(task, _cmd_data_v4[dmt->type].cmd); libdm_task_del_exists_flag(task); libdm_task_destroy(task); goto out; } else { log_error("ioctl %s call failed with errno %d\n", _cmd_data_v4[dmt->type].name, errno); libdm_task_destroy(task); goto bad; } } /* Parse kernel dictionary to dmi structure and return it to libdevmapper. */ dmi = nbsd_dm_dict_to_dmi(task, _cmd_data_v4[dmt->type].cmd); libdm_task_destroy(task); out: return dmi; bad: return NULL; }
static const char *_find_config_str(const void *start, node_lookup_fn find_fn, const char *path, const char *fail, int allow_empty) { const struct dm_config_node *n = find_fn(start, path); /* Empty strings are ignored if allow_empty is set */ if (n && n->v) { if ((n->v->type == DM_CFG_STRING) && (allow_empty || (*n->v->v.str))) { log_very_verbose("Setting %s to %s", path, n->v->v.str); return n->v->v.str; } if ((n->v->type != DM_CFG_STRING) || (!allow_empty && fail)) log_warn("WARNING: Ignoring unsupported value for %s.", path); } if (fail) log_very_verbose("%s not found in config: defaulting to %s", path, fail); return fail; }
static void _read_history(struct cmd_context *cmd) { char hist_file[PATH_MAX]; if (!_hist_file(hist_file, sizeof(hist_file))) return; if (read_history(hist_file)) log_very_verbose("Couldn't read history from %s.", hist_file); stifle_history(find_config_tree_int(cmd, shell_history_size_CFG, NULL)); }
int munge_pvd(struct device *dev, struct pv_disk *pvd) { _xlate_pvd(pvd); if (pvd->id[0] != 'H' || pvd->id[1] != 'M') { log_very_verbose("%s does not have a valid LVM1 PV identifier", dev_name(dev)); return 0; } if (!_munge_formats(pvd)) { log_very_verbose("format1: Unknown metadata version %d " "found on %s", pvd->version, dev_name(dev)); return 0; } /* If VG is exported, set VG name back to the real name */ _munge_exported_vg(pvd); return 1; }
/* * Calculate stripe width of md device using its sysfs files. */ unsigned long dev_md_stripe_width(const char *sysfs_dir, struct device *dev) { unsigned long chunk_size_sectors = 0UL; unsigned long stripe_width_sectors = 0UL; int level, raid_disks, data_disks; chunk_size_sectors = dev_md_chunk_size(sysfs_dir, dev); if (!chunk_size_sectors) return 0; level = dev_md_level(sysfs_dir, dev); if (level < 0) return 0; raid_disks = dev_md_raid_disks(sysfs_dir, dev); if (!raid_disks) return 0; /* The raid level governs the number of data disks. */ switch (level) { case 0: /* striped md does not have any parity disks */ data_disks = raid_disks; break; case 1: case 10: /* mirrored md effectively has 1 data disk */ data_disks = 1; break; case 4: case 5: /* both raid 4 and 5 have a single parity disk */ data_disks = raid_disks - 1; break; case 6: /* raid 6 has 2 parity disks */ data_disks = raid_disks - 2; break; default: log_error("Device %s has an unknown md raid level: %d", dev_name(dev), level); return 0; } stripe_width_sectors = chunk_size_sectors * data_disks; log_very_verbose("Device %s stripe-width is %lu bytes.", dev_name(dev), stripe_width_sectors << SECTOR_SHIFT); return stripe_width_sectors; }
static void _add_pv_to_list(struct cmd_context *cmd, struct dm_list *head, struct disk_list *data) { struct pv_disk *pvd; struct disk_list *diskl; dm_list_iterate_items(diskl, head) { pvd = &diskl->pvd; if (!strncmp((char *)data->pvd.pv_uuid, (char *)pvd->pv_uuid, sizeof(pvd->pv_uuid))) { if (!dev_subsystem_part_major(cmd->dev_types, data->dev)) { log_very_verbose("Ignoring duplicate PV %s on " "%s", pvd->pv_uuid, dev_name(data->dev)); return; } log_very_verbose("Duplicate PV %s - using %s %s", pvd->pv_uuid, dev_subsystem_name(cmd->dev_types, data->dev), dev_name(data->dev)); dm_list_del(&diskl->list); break; } }
static void _unlock_mem(void) { #ifdef MCL_CURRENT if (munlockall()) log_sys_error("munlockall", ""); else log_very_verbose("Unlocking memory"); #endif _release_memory(); if (setpriority(PRIO_PROCESS, 0, _priority)) log_error("setpriority %u failed: %s", _priority, strerror(errno)); }
static int _dev_get_size_dev(const struct device *dev, uint64_t *size) { int fd; const char *name = dev_name(dev); #ifdef __NetBSD__ struct disklabel lab; struct dkwedge_info dkw; struct stat stat; #endif if ((fd = open(name, O_RDONLY)) < 0) { #ifndef __NetBSD__ log_sys_error("open", name); #endif return 0; } #ifdef __NetBSD__ /* Get info about partition/wedge */ if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == -1) { if (ioctl(fd, DIOCGDINFO, &lab) == -1) { log_debug("Please implement DIOCGWEDGEINFO or " "DIOCGDINFO for disk device %s", name); close(fd); return 0; } else { if (fstat(fd, &stat) < 0) log_debug("fstat on device %s failure", name); *size = lab.d_partitions[DISKPART(stat.st_rdev)].p_size; } } else *size = dkw.dkw_size; #else if (ioctl(fd, BLKGETSIZE64, size) < 0) { log_sys_error("ioctl BLKGETSIZE64", name); if (close(fd)) log_sys_error("close", name); return 0; } *size >>= BLKSIZE_SHIFT; /* Convert to sectors */ #endif if (close(fd)) log_sys_error("close", name); log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size); return 1; }
/* * Retrieve raid_disks from md device using sysfs. */ static int dev_md_raid_disks(const char *sysfs_dir, struct device *dev) { const char *attribute = "raid_disks"; int raid_disks = 0; if (_md_sysfs_attribute_scanf(sysfs_dir, dev, attribute, "%d", &raid_disks) != 1) return 0; log_very_verbose("Device %s %s is %d.", dev_name(dev), attribute, raid_disks); return raid_disks; }
/* * Retrieve chunk size from md device using sysfs. */ static unsigned long dev_md_chunk_size(const char *sysfs_dir, struct device *dev) { const char *attribute = "chunk_size"; unsigned long chunk_size_bytes = 0UL; if (_md_sysfs_attribute_scanf(sysfs_dir, dev, attribute, "%lu", &chunk_size_bytes) != 1) return 0; log_very_verbose("Device %s %s is %lu bytes.", dev_name(dev), attribute, chunk_size_bytes); return chunk_size_bytes >> SECTOR_SHIFT; }
static int lvchange_tag(struct cmd_context *cmd, struct logical_volume *lv, int arg) { if (!change_tag(cmd, NULL, lv, NULL, arg)) return_0; log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name); /* No need to suspend LV for this change */ if (!vg_write(lv->vg) || !vg_commit(lv->vg)) return_0; backup(lv->vg); return 1; }
static int _dev_get_size_file(const struct device *dev, uint64_t *size) { const char *name = dev_name(dev); struct stat info; if (stat(name, &info)) { log_sys_error("stat", name); return 0; } *size = info.st_size; *size >>= SECTOR_SHIFT; /* Convert to sectors */ log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size); return 1; }