📄 libdm-iface.c
字号:
do { names = (void *) names + next; if (names->dev == dev) { strncpy(buf, names->name, len); r = 1; break; } next = names->next; } while (next); out: dm_task_destroy(dmt); return r;}static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count){ const size_t min_size = 16 * 1024; const int (*version)[3]; struct dm_ioctl *dmi; struct target *t; struct dm_target_msg *tmsg; size_t len = sizeof(struct dm_ioctl); void *b, *e; int count = 0; for (t = dmt->head; t; t = t->next) { len += sizeof(struct dm_target_spec); len += strlen(t->params) + 1 + ALIGNMENT; count++; } if (count && (dmt->sector || dmt->message)) { log_error("targets and message are incompatible"); return NULL; } if (count && dmt->newname) { log_error("targets and newname are incompatible"); return NULL; } if (count && dmt->geometry) { log_error("targets and geometry are incompatible"); return NULL; } if (dmt->newname && (dmt->sector || dmt->message)) { log_error("message and newname are incompatible"); return NULL; } if (dmt->newname && dmt->geometry) { log_error("geometry and newname are incompatible"); return NULL; } if (dmt->geometry && (dmt->sector || dmt->message)) { log_error("geometry and message are incompatible"); return NULL; } if (dmt->sector && !dmt->message) { log_error("message is required with sector"); return NULL; } if (dmt->newname) len += strlen(dmt->newname) + 1; if (dmt->message) len += sizeof(struct dm_target_msg) + strlen(dmt->message) + 1; if (dmt->geometry) len += strlen(dmt->geometry) + 1; /* * Give len a minimum size so that we have space to store * dependencies or status information. */ if (len < min_size) len = min_size; /* Increase buffer size if repeating because buffer was too small */ while (repeat_count--) len *= 2; if (!(dmi = dm_malloc(len))) return NULL; memset(dmi, 0, len); version = &_cmd_data_v4[dmt->type].version; dmi->version[0] = (*version)[0]; dmi->version[1] = (*version)[1]; dmi->version[2] = (*version)[2]; dmi->data_size = len; dmi->data_start = sizeof(struct dm_ioctl); if (dmt->minor >= 0) { if (dmt->major <= 0) { log_error("Missing major number for persistent device."); goto bad; } dmi->flags |= DM_PERSISTENT_DEV_FLAG; dmi->dev = MKDEV(dmt->major, dmt->minor); } /* Does driver support device number referencing? */ if (_dm_version_minor < 3 && !dmt->dev_name && !dmt->uuid && dmi->dev) { if (!_lookup_dev_name(dmi->dev, dmi->name, sizeof(dmi->name))) { log_error("Unable to find name for device (%" PRIu32 ":%" PRIu32 ")", dmt->major, dmt->minor); goto bad; } log_verbose("device (%" PRIu32 ":%" PRIu32 ") is %s " "for compatibility with old kernel", dmt->major, dmt->minor, dmi->name); } if (dmt->dev_name) strncpy(dmi->name, dmt->dev_name, sizeof(dmi->name)); if (dmt->uuid) strncpy(dmi->uuid, dmt->uuid, sizeof(dmi->uuid)); if (dmt->type == DM_DEVICE_SUSPEND) dmi->flags |= DM_SUSPEND_FLAG; if (dmt->no_flush) dmi->flags |= DM_NOFLUSH_FLAG; if (dmt->read_only) dmi->flags |= DM_READONLY_FLAG; if (dmt->skip_lockfs) dmi->flags |= DM_SKIP_LOCKFS_FLAG; dmi->target_count = count; dmi->event_nr = dmt->event_nr; b = (void *) (dmi + 1); e = (void *) ((char *) dmi + len); for (t = dmt->head; t; t = t->next) if (!(b = _add_target(t, b, e))) goto bad; if (dmt->newname) strcpy(b, dmt->newname); if (dmt->message) { tmsg = (struct dm_target_msg *) b; tmsg->sector = dmt->sector; strcpy(tmsg->message, dmt->message); } if (dmt->geometry) strcpy(b, dmt->geometry); return dmi; bad: dm_free(dmi); return NULL;}static int _process_mapper_dir(struct dm_task *dmt){ struct dirent *dirent; DIR *d; const char *dir; int r = 1; dir = dm_dir(); if (!(d = opendir(dir))) { log_sys_error("opendir", dir); return 0; } while ((dirent = readdir(d))) { if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..") || !strcmp(dirent->d_name, "control")) continue; dm_task_set_name(dmt, dirent->d_name); dm_task_run(dmt); } if (closedir(d)) log_sys_error("closedir", dir); return r;}static int _process_all_v4(struct dm_task *dmt){ struct dm_task *task; struct dm_names *names; unsigned next = 0; int r = 1; if (!(task = dm_task_create(DM_DEVICE_LIST))) return 0; if (!dm_task_run(task)) { r = 0; goto out; } if (!(names = dm_task_get_names(task))) { r = 0; goto out; } if (!names->dev) goto out; do { names = (void *) names + next; if (!dm_task_set_name(dmt, names->name)) { r = 0; goto out; } if (!dm_task_run(dmt)) r = 0; next = names->next; } while (next); out: dm_task_destroy(task); return r;}static int _mknodes_v4(struct dm_task *dmt){ (void) _process_mapper_dir(dmt); return _process_all_v4(dmt);}static int _create_and_load_v4(struct dm_task *dmt){ struct dm_task *task; int r; /* Use new task struct to create the device */ if (!(task = dm_task_create(DM_DEVICE_CREATE))) { log_error("Failed to create device-mapper task struct"); return 0; } /* Copy across relevant fields */ if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) { dm_task_destroy(task); return 0; } if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) { dm_task_destroy(task); return 0; } task->major = dmt->major; task->minor = dmt->minor; task->uid = dmt->uid; task->gid = dmt->gid; task->mode = dmt->mode; r = dm_task_run(task); dm_task_destroy(task); if (!r) return r; /* Next load the table */ if (!(task = dm_task_create(DM_DEVICE_RELOAD))) { log_error("Failed to create device-mapper task struct"); return 0; } /* Copy across relevant fields */ if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) { dm_task_destroy(task); return 0; } task->read_only = dmt->read_only; task->head = dmt->head; task->tail = dmt->tail; r = dm_task_run(task); task->head = NULL; task->tail = NULL; dm_task_destroy(task); if (!r) goto revert; /* Use the original structure last so the info will be correct */ dmt->type = DM_DEVICE_RESUME; dm_free(dmt->uuid); dmt->uuid = NULL; r = dm_task_run(dmt); if (r) return r; revert: dmt->type = DM_DEVICE_REMOVE; dm_free(dmt->uuid); dmt->uuid = NULL; if (!dm_task_run(dmt)) log_error("Failed to revert device creation."); return r;}static int _reload_with_suppression_v4(struct dm_task *dmt){ struct dm_task *task; struct target *t1, *t2; int r; /* New task to get existing table information */ if (!(task = dm_task_create(DM_DEVICE_TABLE))) { log_error("Failed to create device-mapper task struct"); return 0; } /* Copy across relevant fields */ if (dmt->dev_name && !dm_task_set_name(task, dmt->dev_name)) { dm_task_destroy(task); return 0; } if (dmt->uuid && !dm_task_set_uuid(task, dmt->uuid)) { dm_task_destroy(task); return 0; } task->major = dmt->major; task->minor = dmt->minor; r = dm_task_run(task); if (!r) { dm_task_destroy(task); return r; } if ((task->dmi.v4->flags & DM_READONLY_FLAG) ? 1 : 0 != dmt->read_only) goto no_match; t1 = dmt->head; t2 = task->head; while (t1 && t2) { while (t2->params[strlen(t2->params) - 1] == ' ') t2->params[strlen(t2->params) - 1] = '\0'; if ((t1->start != t2->start) || (t1->length != t2->length) || (strcmp(t1->type, t2->type)) || (strcmp(t1->params, t2->params))) goto no_match; t1 = t1->next; t2 = t2->next; } if (!t1 && !t2) { dmt->dmi.v4 = task->dmi.v4; task->dmi.v4 = NULL; dm_task_destroy(task); return 1; }no_match: dm_task_destroy(task); /* Now do the original reload */ dmt->suppress_identical_reload = 0; r = dm_task_run(dmt); return r;}static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command, unsigned repeat_count){ struct dm_ioctl *dmi; dmi = _flatten(dmt, repeat_count); if (!dmi) { log_error("Couldn't create ioctl argument."); return NULL; } if (dmt->type == DM_DEVICE_TABLE) dmi->flags |= DM_STATUS_TABLE_FLAG; dmi->flags |= DM_EXISTS_FLAG; /* FIXME */ if (dmt->no_open_count) dmi->flags |= DM_SKIP_BDGET_FLAG; log_debug("dm %s %s %s%s%s %s%.0d%s%.0d%s" "%s%c%c%s %.0" PRIu64 " %s [%u]", _cmd_data_v4[dmt->type].name, dmi->name, dmi->uuid, dmt->newname ? " " : "", dmt->newname ? dmt->newname : "", dmt->major > 0 ? "(" : "", dmt->major > 0 ? dmt->major : 0, dmt->major > 0 ? ":" : "", dmt->minor > 0 ? dmt->minor : 0, dmt->major > 0 && dmt->minor == 0 ? "0" : "", dmt->major > 0 ? ") " : "", dmt->no_open_count ? 'N' : 'O', dmt->no_flush ? 'N' : 'F', dmt->skip_lockfs ? "S " : "", dmt->sector, dmt->message ? dmt->message : "", dmi->data_size);#ifdef DM_IOCTLS if (ioctl(_control_fd, command, dmi) < 0) { if (errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) || (dmt->type == DM_DEVICE_MKNODES) || (dmt->type == DM_DEVICE_STATUS))) dmi->flags &= ~DM_EXISTS_FLAG; /* FIXME */ else { if (_log_suppress) log_verbose("device-mapper: %s ioctl " "failed: %s", _cmd_data_v4[dmt->type].name, strerror(errno)); else log_error("device-mapper: %s ioctl " "failed: %s", _cmd_data_v4[dmt->type].name, strerror(errno)); dm_free(dmi); return NULL; } }#else /* Userspace alternative for testing */#endif return dmi;}void dm_task_update_nodes(void){ update_devs();}int dm_task_run(struct dm_task *dmt){ struct dm_ioctl *dmi; unsigned command;#ifdef DM_COMPAT if (_dm_version == 1) return _dm_task_run_v1(dmt);#endif if ((unsigned) dmt->type >= (sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) { log_error("Internal error: unknown device-mapper task %d", dmt->type); return 0; } command = _cmd_data_v4[dmt->type].cmd; /* Old-style creation had a table supplied */ if (dmt->type == DM_DEVICE_CREATE && dmt->head) return _create_and_load_v4(dmt); if (dmt->type == DM_DEVICE_MKNODES && !dmt->dev_name && !dmt->uuid && dmt->major <= 0) return _mknodes_v4(dmt); if ((dmt->type == DM_DEVICE_RELOAD) && dmt->suppress_identical_reload) return _reload_with_suppression_v4(dmt); if (!_open_control()) return 0;repeat_ioctl: if (!(dmi = _do_dm_ioctl(dmt, command, _ioctl_buffer_double_factor))) return 0; if (dmi->flags & DM_BUFFER_FULL_FLAG) { switch (dmt->type) { case DM_DEVICE_LIST_VERSIONS: case DM_DEVICE_LIST: case DM_DEVICE_DEPS: case DM_DEVICE_STATUS: case DM_DEVICE_TABLE: case DM_DEVICE_WAITEVENT: _ioctl_buffer_double_factor++; dm_free(dmi); goto repeat_ioctl; default: log_error("WARNING: libdevmapper buffer too small for data"); } } switch (dmt->type) { case DM_DEVICE_CREATE: add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev), dmt->uid, dmt->gid, dmt->mode); break; case DM_DEVICE_REMOVE: /* FIXME Kernel needs to fill in dmi->name */ if (dmt->dev_name) rm_dev_node(dmt->dev_name); break; case DM_DEVICE_RENAME: /* FIXME Kernel needs to fill in dmi->name */ if (dmt->dev_name) rename_dev_node(dmt->dev_name, dmt->newname); break; case DM_DEVICE_MKNODES: if (dmi->flags & DM_EXISTS_FLAG) add_dev_node(dmi->name, MAJOR(dmi->dev), MINOR(dmi->dev), dmt->uid, dmt->gid, dmt->mode); else if (dmt->dev_name) rm_dev_node(dmt->dev_name); break; case DM_DEVICE_STATUS: case DM_DEVICE_TABLE: case DM_DEVICE_WAITEVENT: if (!_unmarshal_status(dmt, dmi)) goto bad; break; } /* Was structure reused? */ if (dmt->dmi.v4) dm_free(dmt->dmi.v4); dmt->dmi.v4 = dmi; return 1; bad: dm_free(dmi); return 0;}void dm_lib_release(void){ if (_control_fd != -1) { close(_control_fd); _control_fd = -1; } update_devs();}void dm_lib_exit(void){ dm_lib_release(); if (_dm_bitset) dm_bitset_destroy(_dm_bitset); _dm_bitset = NULL; dm_dump_memory(); _version_ok = 1; _version_checked = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -