diff --git a/daemons/clvmd/lvm-functions.c b/daemons/clvmd/lvm-functions.c index 166cd7f13..8e68ed983 100644 --- a/daemons/clvmd/lvm-functions.c +++ b/daemons/clvmd/lvm-functions.c @@ -919,7 +919,7 @@ int init_clvm(int using_gulm, char **argv) init_syslog(LOG_DAEMON); openlog("clvmd", LOG_PID, LOG_DAEMON); - if (!(cmd = create_toolcontext(1, NULL))) { + if (!(cmd = create_toolcontext(1, NULL, 0))) { log_error("Failed to allocate command context"); return 0; } diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c index 9b3e27f4e..918362cef 100644 --- a/lib/commands/toolcontext.c +++ b/lib/commands/toolcontext.c @@ -58,6 +58,8 @@ # include #endif +static const size_t linebuffer_size = 4096; + static int _get_env_vars(struct cmd_context *cmd) { const char *e; @@ -1148,7 +1150,8 @@ static void _init_globals(struct cmd_context *cmd) /* Entry point */ struct cmd_context *create_toolcontext(unsigned is_long_lived, - const char *system_dir) + const char *system_dir, + unsigned set_buffering) { struct cmd_context *cmd; @@ -1183,6 +1186,22 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived, /* FIXME Make this configurable? */ reset_lvm_errno(1); + /* Set in/out stream buffering before glibc */ + if (set_buffering) { + /* Allocate 2 buffers */ + if (!(cmd->linebuffer = dm_malloc(2 * linebuffer_size))) { + log_error("Failed to allocate line buffer."); + goto out; + } + if ((setvbuf(stdin, cmd->linebuffer, _IOLBF, linebuffer_size) || + setvbuf(stdout, cmd->linebuffer + linebuffer_size, + _IOLBF, linebuffer_size))) { + log_sys_error("setvbuf", ""); + goto out; + } + /* Buffers are used for lines without '\n' */ + } + /* * Environment variable LVM_SYSTEM_DIR overrides this below. */ @@ -1419,6 +1438,15 @@ void destroy_toolcontext(struct cmd_context *cmd) _destroy_tag_configs(cmd); if (cmd->libmem) dm_pool_destroy(cmd->libmem); + + if (cmd->linebuffer) { + /* Reset stream buffering to defaults */ + setlinebuf(stdin); + fflush(stdout); + setlinebuf(stdout); + dm_free(cmd->linebuffer); + } + dm_free(cmd); release_log_memory(); diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h index 4628c7c25..1c3368e69 100644 --- a/lib/commands/toolcontext.h +++ b/lib/commands/toolcontext.h @@ -66,6 +66,7 @@ struct cmd_context { const char *kernel_vsn; unsigned rand_seed; + char *linebuffer; const char *cmd_line; struct command *command; char **argv; @@ -109,7 +110,8 @@ struct cmd_context { * The environment variable LVM_SYSTEM_DIR always takes precedence. */ struct cmd_context *create_toolcontext(unsigned is_long_lived, - const char *system_dir); + const char *system_dir, + unsigned set_buffering); void destroy_toolcontext(struct cmd_context *cmd); int refresh_toolcontext(struct cmd_context *cmd); int refresh_filters(struct cmd_context *cmd); diff --git a/liblvm/lvm_base.c b/liblvm/lvm_base.c index 9e1a8ecd8..f44b786cb 100644 --- a/liblvm/lvm_base.c +++ b/liblvm/lvm_base.c @@ -34,7 +34,7 @@ lvm_t lvm_init(const char *system_dir) /* create context */ /* FIXME: split create_toolcontext */ /* FIXME: make all globals configurable */ - cmd = create_toolcontext(0, system_dir); + cmd = create_toolcontext(0, system_dir, 1); if (!cmd) return NULL; diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index 197cd1431..3e13a27d6 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -1282,7 +1282,7 @@ struct cmd_context *init_lvm(void) if (!udev_init_library_context()) stack; - if (!(cmd = create_toolcontext(0, NULL))) + if (!(cmd = create_toolcontext(0, NULL, 1))) return_NULL; _cmdline.arg_props = &_arg_props[0];