回到lvm2_main():
以上部分大概是看输入的命令能否转化为lvm1的命令执行,以及是否支持readline,还有对命令解析判断是否可执行。_noroot_warning是对非root用户执行lvm命令的警告。
前面的都准备就绪了,终于到lvm_run_command了,执行用户输入的命令。先看看他的全貌:
比较主要的就两个函数把,就是
_find_command和ret = cmd->command->fn(cmd, argc, argv)。顾名思义,先找到要执行的代码函数所在的位置,然后进行操作。
(cmd->cmd_line = _copy_command_line(cmd, argc, argv)是把命令携带的参数进行copy,在命令执行之前,调用
_process_command_line(cmd, &argc, &argv)对命令的参数进行处理。
在_find_command中,就是将name和静态变量_cmdline的元素进行比较,找到对应的命令入口。
然后调用ret = cmd->command->fn(cmd, argc, argv);执行cmd对应的函数。至此,lvm初始化及其对命令的解析完毕,转入到不同命令的执行中。
- if (_lvm1_fallback(cmd)) {
- /* Attempt to run equivalent LVM1 tool instead */
- if (!alias) {
- argv++;
- argc--;
- alias = 0;
- }
- if (!argc) {
- log_error("Falling back to LVM1 tools, but no "
- "command specified.");
- return ECMD_FAILED;
- }
- _exec_lvm1_command(argv);
- return ECMD_FAILED;
- }
- #ifdef READLINE_SUPPORT
- if (!alias && argc == 1) {
- _nonroot_warning();
- ret = lvm_shell(cmd, &_cmdline);
- goto out;
- }
- #endif
- if (!alias) {
- if (argc < 2) {
- log_fatal("Please supply an LVM command.");
- _display_help();
- ret = EINVALID_CMD_LINE;
- goto out;
- }
- argc--;
- argv++;
- }
- _nonroot_warning();
- ret = lvm_run_command(cmd, argc, argv);
- if ((ret == ENO_SUCH_CMD) && (!alias))
- ret = _run_script(cmd, argc, argv);
- if (ret == ENO_SUCH_CMD)
- log_error("No such command. Try 'help'.");
- if ((ret != ECMD_PROCESSED) && !error_message_produced()) {
- log_debug("Internal error: Failed command did not use log_error");
- log_error("Command failed with status code %d.", ret);
- }
- int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
- {
- int ret = 0;
- int locking_type;
- init_error_message_produced(0);
- /* each command should start out with sigint flag cleared */
- sigint_clear();
- if (!(cmd->cmd_line = _copy_command_line(cmd, argc, argv)))
- return ECMD_FAILED;
- log_debug("Parsing: %s", cmd->cmd_line);
- if (!(cmd->command = _find_command(argv[0])))
- return ENO_SUCH_CMD;
- if (!_process_command_line(cmd, &argc, &argv)) {
- log_error("Error during parsing of command line.");
- return EINVALID_CMD_LINE;
- }
- set_cmd_name(cmd->command->name);
- if (arg_count(cmd, config_ARG))
- if ((ret = _override_settings(cmd)))
- goto_out;
- if (arg_count(cmd, config_ARG) || !cmd->config_valid || config_files_changed(cmd)) {
- /* Reinitialise various settings inc. logging, filters */
- if (!refresh_toolcontext(cmd)) {
- log_error("Updated config file invalid. Aborting.");
- return ECMD_FAILED;
- }
- }
- if ((ret = _get_settings(cmd)))
- goto_out;
- _apply_settings(cmd);
- log_debug("Processing: %s", cmd->cmd_line);
- #ifdef O_DIRECT_SUPPORT
- log_debug("O_DIRECT will be used");
- #endif
- if ((ret = _process_common_commands(cmd)))
- goto_out;
- if (arg_count(cmd, nolocking_ARG))
- locking_type = 0;
- else
- locking_type = find_config_tree_int(cmd,
- "global/locking_type", 1);
- if (!init_locking(locking_type, cmd)) {
- log_error("Locking type %d initialisation failed.",
- locking_type);
- ret = ECMD_FAILED;
- goto out;
- }
- ret = cmd->command->fn(cmd, argc, argv);
- fin_locking();
- out:
- if (test_mode()) {
- log_verbose("Test mode: Wiping internal cache");
- lvmcache_destroy(cmd, 1);
- }
- if (cmd->cft_override) {
- destroy_config_tree(cmd->cft_override);
- cmd->cft_override = NULL;
- /* Move this? */
- if (!refresh_toolcontext(cmd))
- stack;
- }
- /* FIXME Move this? */
- cmd->current_settings = cmd->default_settings;
- _apply_settings(cmd);
- /*
- * free off any memory the command used.
- */
- dm_pool_empty(cmd->mem);
- if (ret == EINVALID_CMD_LINE && !_cmdline.interactive)
- _short_usage(cmd->command->name);
- log_debug("Completed: %s", cmd->cmd_line);
- return ret;
- }
- static struct command *_find_command(const char *name)
- {
- int i;
- char *base;
- base = last_path_component(name);
- for (i = 0; i < _cmdline.num_commands; i++) {
- if (!strcmp(base, _cmdline.commands[i].name))
- break;
- }
- if (i >= _cmdline.num_commands)
- return 0;
- return _cmdline.commands + i;
- }
然后调用ret = cmd->command->fn(cmd, argc, argv);执行cmd对应的函数。至此,lvm初始化及其对命令的解析完毕,转入到不同命令的执行中。