diff --git a/include/admin.h b/include/admin.h
index ec89f00bbfd189d9b52547aaa6cd1e355136e4e0..28de68c8207aa55dd0346669ee686afa7220da7e 100644
--- a/include/admin.h
+++ b/include/admin.h
@@ -28,6 +28,6 @@
  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-int admin_init(void);
+int admin_init(const char *bind_ipaddr, int admin_port);
 
 #endif /* TARANTOOL_ADMIN_H_INCLUDED */
diff --git a/include/recovery.h b/include/recovery.h
index aaffab17f5bed002eb3917936e3d8ff9d1cabdc7..4f92bb3f24273af8af465f1ed2071c43865bc3ea 100644
--- a/include/recovery.h
+++ b/include/recovery.h
@@ -108,9 +108,7 @@ extern struct recovery_state *recovery_state;
 
 void recovery_init(const char *snap_dirname, const char *xlog_dirname,
 		   row_handler row_handler, void *row_handler_param,
-		   int rows_per_wal, const char *wal_mode,
-		   double wal_fsync_delay,
-		   int flags);
+		   int rows_per_wal, int flags);
 void recovery_update_mode(struct recovery_state *r,
 			  const char *wal_mode, double fsync_delay);
 void recovery_update_io_rate_limit(struct recovery_state *r,
diff --git a/include/tarantool.h b/include/tarantool.h
index a80218ce046fb12adc93d14eb89e55b478a59202..a5bbfb4215c10cc60e412bdf3f5ffff3f0426a48 100644
--- a/include/tarantool.h
+++ b/include/tarantool.h
@@ -55,6 +55,7 @@ extern bool init_storage, booting;
 extern char *binary_filename;
 extern char *custom_proc_title;
 i32 reload_cfg(struct tbuf *out);
+void show_cfg(struct tbuf *out);
 int snapshot(void * /* ev */, int /* events */);
 const char *tarantool_version(void);
 double tarantool_uptime(void);
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5681bc660baeada50356560d9092f2820f590f1e..dd88ac6c0a40244727949da7da1021328bc2e63e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -75,7 +75,6 @@ set (recompiled_sources
      ${CMAKE_SOURCE_DIR}/src/lua/init.m
      ${CMAKE_SOURCE_DIR}/src/say.m
      ${CMAKE_SOURCE_DIR}/src/assoc.m
-     ${CMAKE_SOURCE_DIR}/src/admin.m
      ${CMAKE_SOURCE_DIR}/src/replication.m
      ${CMAKE_SOURCE_DIR}/src/fiber.m)
 
@@ -94,6 +93,7 @@ set (common_sources
      stat.m
      log_io.m
      recovery.m
+     admin.m
      cpu_feature.m
      replica.m
      iproto.m
diff --git a/src/admin.m b/src/admin.m
index 517e1586bfac8657290d1fa4e9073ef89836d0b9..9da50c51ab234660a3eeb6673eb658e483ca0211 100644
--- a/src/admin.m
+++ b/src/admin.m
@@ -42,7 +42,6 @@
 #include <tarantool.h>
 #include "lua/init.h"
 #include <recovery.h>
-#include TARANTOOL_CONFIG
 #include <tbuf.h>
 #include <util.h>
 #include <errinj.h>
@@ -72,7 +71,7 @@ static const char *help =
 static const char *unknown_command = "unknown command. try typing help." CRLF;
 
 
-#line 76 "src/admin.m"
+#line 75 "src/admin.m"
 static const int admin_start = 1;
 static const int admin_first_final = 135;
 static const int admin_error = 0;
@@ -80,7 +79,7 @@ static const int admin_error = 0;
 static const int admin_en_main = 1;
 
 
-#line 75 "src/admin.rl"
+#line 74 "src/admin.rl"
 
 
 struct salloc_stat_admin_cb_ctx {
@@ -217,12 +216,12 @@ admin_dispatch(struct coio *coio, struct iobuf *iobuf, lua_State *L)
 	p = in->pos;
 
 	
-#line 221 "src/admin.m"
+#line 220 "src/admin.m"
 	{
 	cs = admin_start;
 	}
 
-#line 226 "src/admin.m"
+#line 225 "src/admin.m"
 	{
 	if ( p == pe )
 		goto _test_eof;
@@ -285,15 +284,15 @@ case 6:
 	}
 	goto st0;
 tr13:
-#line 320 "src/admin.rl"
+#line 307 "src/admin.rl"
 	{slab_validate(); ok(out);}
 	goto st135;
 tr20:
-#line 308 "src/admin.rl"
+#line 295 "src/admin.rl"
 	{return -1;}
 	goto st135;
 tr25:
-#line 235 "src/admin.rl"
+#line 222 "src/admin.rl"
 	{
 			start(out);
 			tbuf_append(out, help, strlen(help));
@@ -301,9 +300,9 @@ tr25:
 		}
 	goto st135;
 tr36:
-#line 294 "src/admin.rl"
+#line 281 "src/admin.rl"
 	{strend = p;}
-#line 241 "src/admin.rl"
+#line 228 "src/admin.rl"
 	{
 			strstart[strend-strstart]='\0';
 			start(out);
@@ -312,7 +311,7 @@ tr36:
 		}
 	goto st135;
 tr43:
-#line 248 "src/admin.rl"
+#line 235 "src/admin.rl"
 	{
 			if (reload_cfg(err))
 				fail(out, err);
@@ -321,11 +320,11 @@ tr43:
 		}
 	goto st135;
 tr67:
-#line 318 "src/admin.rl"
+#line 305 "src/admin.rl"
 	{coredump(60); ok(out);}
 	goto st135;
 tr76:
-#line 255 "src/admin.rl"
+#line 242 "src/admin.rl"
 	{
 			int ret = snapshot(NULL, 0);
 
@@ -340,9 +339,9 @@ tr76:
 		}
 	goto st135;
 tr98:
-#line 304 "src/admin.rl"
+#line 291 "src/admin.rl"
 	{ state = false; }
-#line 268 "src/admin.rl"
+#line 255 "src/admin.rl"
 	{
 			strstart[strend-strstart] = '\0';
 			if (errinj_set_byname(strstart, state)) {
@@ -354,9 +353,9 @@ tr98:
 		}
 	goto st135;
 tr101:
-#line 303 "src/admin.rl"
+#line 290 "src/admin.rl"
 	{ state = true; }
-#line 268 "src/admin.rl"
+#line 255 "src/admin.rl"
 	{
 			strstart[strend-strstart] = '\0';
 			if (errinj_set_byname(strstart, state)) {
@@ -368,35 +367,23 @@ tr101:
 		}
 	goto st135;
 tr117:
-#line 211 "src/admin.rl"
+#line 210 "src/admin.rl"
 	{
-			tarantool_cfg_iterator_t *i;
-			char *key, *value;
-
 			start(out);
-			tbuf_printf(out, "configuration:" CRLF);
-			i = tarantool_cfg_iterator_init();
-			while ((key = tarantool_cfg_iterator_next(i, &cfg, &value)) != NULL) {
-				if (value) {
-					tbuf_printf(out, "  %s: \"%s\"" CRLF, key, value);
-					free(value);
-				} else {
-					tbuf_printf(out, "  %s: (null)" CRLF, key);
-				}
-			}
+			show_cfg(out);
 			end(out);
 		}
 	goto st135;
 tr131:
-#line 311 "src/admin.rl"
+#line 298 "src/admin.rl"
 	{start(out); fiber_info(out); end(out);}
 	goto st135;
 tr137:
-#line 310 "src/admin.rl"
+#line 297 "src/admin.rl"
 	{start(out); tarantool_info(out); end(out);}
 	goto st135;
 tr146:
-#line 229 "src/admin.rl"
+#line 216 "src/admin.rl"
 	{
 			start(out);
 			errinj_info(out);
@@ -404,33 +391,33 @@ tr146:
 		}
 	goto st135;
 tr152:
-#line 314 "src/admin.rl"
+#line 301 "src/admin.rl"
 	{start(out); palloc_stat(out); end(out);}
 	goto st135;
 tr160:
-#line 313 "src/admin.rl"
+#line 300 "src/admin.rl"
 	{start(out); show_slab(out); end(out);}
 	goto st135;
 tr164:
-#line 315 "src/admin.rl"
+#line 302 "src/admin.rl"
 	{start(out); show_stat(out);end(out);}
 	goto st135;
 st135:
 	if ( ++p == pe )
 		goto _test_eof135;
 case 135:
-#line 423 "src/admin.m"
+#line 410 "src/admin.m"
 	goto st0;
 tr14:
-#line 320 "src/admin.rl"
+#line 307 "src/admin.rl"
 	{slab_validate(); ok(out);}
 	goto st7;
 tr21:
-#line 308 "src/admin.rl"
+#line 295 "src/admin.rl"
 	{return -1;}
 	goto st7;
 tr26:
-#line 235 "src/admin.rl"
+#line 222 "src/admin.rl"
 	{
 			start(out);
 			tbuf_append(out, help, strlen(help));
@@ -438,9 +425,9 @@ tr26:
 		}
 	goto st7;
 tr37:
-#line 294 "src/admin.rl"
+#line 281 "src/admin.rl"
 	{strend = p;}
-#line 241 "src/admin.rl"
+#line 228 "src/admin.rl"
 	{
 			strstart[strend-strstart]='\0';
 			start(out);
@@ -449,7 +436,7 @@ tr37:
 		}
 	goto st7;
 tr44:
-#line 248 "src/admin.rl"
+#line 235 "src/admin.rl"
 	{
 			if (reload_cfg(err))
 				fail(out, err);
@@ -458,11 +445,11 @@ tr44:
 		}
 	goto st7;
 tr68:
-#line 318 "src/admin.rl"
+#line 305 "src/admin.rl"
 	{coredump(60); ok(out);}
 	goto st7;
 tr77:
-#line 255 "src/admin.rl"
+#line 242 "src/admin.rl"
 	{
 			int ret = snapshot(NULL, 0);
 
@@ -477,9 +464,9 @@ tr77:
 		}
 	goto st7;
 tr99:
-#line 304 "src/admin.rl"
+#line 291 "src/admin.rl"
 	{ state = false; }
-#line 268 "src/admin.rl"
+#line 255 "src/admin.rl"
 	{
 			strstart[strend-strstart] = '\0';
 			if (errinj_set_byname(strstart, state)) {
@@ -491,9 +478,9 @@ tr99:
 		}
 	goto st7;
 tr102:
-#line 303 "src/admin.rl"
+#line 290 "src/admin.rl"
 	{ state = true; }
-#line 268 "src/admin.rl"
+#line 255 "src/admin.rl"
 	{
 			strstart[strend-strstart] = '\0';
 			if (errinj_set_byname(strstart, state)) {
@@ -505,35 +492,23 @@ tr102:
 		}
 	goto st7;
 tr118:
-#line 211 "src/admin.rl"
+#line 210 "src/admin.rl"
 	{
-			tarantool_cfg_iterator_t *i;
-			char *key, *value;
-
 			start(out);
-			tbuf_printf(out, "configuration:" CRLF);
-			i = tarantool_cfg_iterator_init();
-			while ((key = tarantool_cfg_iterator_next(i, &cfg, &value)) != NULL) {
-				if (value) {
-					tbuf_printf(out, "  %s: \"%s\"" CRLF, key, value);
-					free(value);
-				} else {
-					tbuf_printf(out, "  %s: (null)" CRLF, key);
-				}
-			}
+			show_cfg(out);
 			end(out);
 		}
 	goto st7;
 tr132:
-#line 311 "src/admin.rl"
+#line 298 "src/admin.rl"
 	{start(out); fiber_info(out); end(out);}
 	goto st7;
 tr138:
-#line 310 "src/admin.rl"
+#line 297 "src/admin.rl"
 	{start(out); tarantool_info(out); end(out);}
 	goto st7;
 tr147:
-#line 229 "src/admin.rl"
+#line 216 "src/admin.rl"
 	{
 			start(out);
 			errinj_info(out);
@@ -541,22 +516,22 @@ tr147:
 		}
 	goto st7;
 tr153:
-#line 314 "src/admin.rl"
+#line 301 "src/admin.rl"
 	{start(out); palloc_stat(out); end(out);}
 	goto st7;
 tr161:
-#line 313 "src/admin.rl"
+#line 300 "src/admin.rl"
 	{start(out); show_slab(out); end(out);}
 	goto st7;
 tr165:
-#line 315 "src/admin.rl"
+#line 302 "src/admin.rl"
 	{start(out); show_stat(out);end(out);}
 	goto st7;
 st7:
 	if ( ++p == pe )
 		goto _test_eof7;
 case 7:
-#line 560 "src/admin.m"
+#line 535 "src/admin.m"
 	if ( (*p) == 10 )
 		goto st135;
 	goto st0;
@@ -709,28 +684,28 @@ case 23:
 	}
 	goto tr33;
 tr33:
-#line 294 "src/admin.rl"
+#line 281 "src/admin.rl"
 	{strstart = p;}
 	goto st24;
 st24:
 	if ( ++p == pe )
 		goto _test_eof24;
 case 24:
-#line 720 "src/admin.m"
+#line 695 "src/admin.m"
 	switch( (*p) ) {
 		case 10: goto tr36;
 		case 13: goto tr37;
 	}
 	goto st24;
 tr34:
-#line 294 "src/admin.rl"
+#line 281 "src/admin.rl"
 	{strstart = p;}
 	goto st25;
 st25:
 	if ( ++p == pe )
 		goto _test_eof25;
 case 25:
-#line 734 "src/admin.m"
+#line 709 "src/admin.m"
 	switch( (*p) ) {
 		case 10: goto tr36;
 		case 13: goto tr37;
@@ -1180,28 +1155,28 @@ case 73:
 		goto tr91;
 	goto st0;
 tr91:
-#line 302 "src/admin.rl"
+#line 289 "src/admin.rl"
 	{ strstart = p; }
 	goto st74;
 st74:
 	if ( ++p == pe )
 		goto _test_eof74;
 case 74:
-#line 1191 "src/admin.m"
+#line 1166 "src/admin.m"
 	if ( (*p) == 32 )
 		goto tr92;
 	if ( 33 <= (*p) && (*p) <= 126 )
 		goto st74;
 	goto st0;
 tr92:
-#line 302 "src/admin.rl"
+#line 289 "src/admin.rl"
 	{ strend = p; }
 	goto st75;
 st75:
 	if ( ++p == pe )
 		goto _test_eof75;
 case 75:
-#line 1205 "src/admin.m"
+#line 1180 "src/admin.m"
 	switch( (*p) ) {
 		case 32: goto st75;
 		case 111: goto st76;
@@ -1893,7 +1868,7 @@ case 134:
 	_out: {}
 	}
 
-#line 326 "src/admin.rl"
+#line 313 "src/admin.rl"
 
 
 	in->pos = pe;
@@ -1930,11 +1905,11 @@ admin_handler(va_list ap)
 }
 
 void
-admin_init(void)
+admin_init(const char *bind_ipaddr, int admin_port)
 {
 	static struct coio_service admin;
-	coio_service_init(&admin, "admin", cfg.bind_ipaddr,
-			  cfg.admin_port, admin_handler, NULL);
+	coio_service_init(&admin, "admin", bind_ipaddr,
+			  admin_port, admin_handler, NULL);
 	evio_service_start(&admin.evio_service);
 }
 
diff --git a/src/admin.rl b/src/admin.rl
index cef2a70e5116ea4ccda1870bd6064a00a0245a62..2bbf3aff44c67aa0ee067beb5eb8820cee9fbb0e 100644
--- a/src/admin.rl
+++ b/src/admin.rl
@@ -40,7 +40,6 @@
 #include <tarantool.h>
 #include "lua/init.h"
 #include <recovery.h>
-#include TARANTOOL_CONFIG
 #include <tbuf.h>
 #include <util.h>
 #include <errinj.h>
@@ -209,20 +208,8 @@ admin_dispatch(struct coio *coio, struct iobuf *iobuf, lua_State *L)
 
 	%%{
 		action show_configuration {
-			tarantool_cfg_iterator_t *i;
-			char *key, *value;
-
 			start(out);
-			tbuf_printf(out, "configuration:" CRLF);
-			i = tarantool_cfg_iterator_init();
-			while ((key = tarantool_cfg_iterator_next(i, &cfg, &value)) != NULL) {
-				if (value) {
-					tbuf_printf(out, "  %s: \"%s\"" CRLF, key, value);
-					free(value);
-				} else {
-					tbuf_printf(out, "  %s: (null)" CRLF, key);
-				}
-			}
+			show_cfg(out);
 			end(out);
 		}
 
@@ -359,11 +346,11 @@ admin_handler(va_list ap)
 }
 
 void
-admin_init(void)
+admin_init(const char *bind_ipaddr, int admin_port)
 {
 	static struct coio_service admin;
-	coio_service_init(&admin, "admin", cfg.bind_ipaddr,
-			  cfg.admin_port, admin_handler, NULL);
+	coio_service_init(&admin, "admin", bind_ipaddr,
+			  admin_port, admin_handler, NULL);
 	evio_service_start(&admin.evio_service);
 }
 
diff --git a/src/box/box.h b/src/box/box.h
index 7fb12efb31165d1b8dc5444be3f35782488b61ef..32ae1c9c5f841820c0fe6f9119913c0d6c5cd316 100644
--- a/src/box/box.h
+++ b/src/box/box.h
@@ -33,8 +33,7 @@ struct txn;
 struct tbuf;
 struct port;
 
-typedef void (*box_process_func)(struct txn *,
-				 struct port *, u32, struct tbuf *);
+typedef void (*box_process_func)(struct port *, u32, struct tbuf *);
 extern box_process_func box_process;
 
 #endif /* INCLUDES_TARANTOOL_BOX_H */
diff --git a/src/box/box.m b/src/box/box.m
index 219b5f091c947ed2210d51be830d10f6fca0983d..1b368e7cb5c7d835e9aabc29f02bb91633f7053c 100644
--- a/src/box/box.m
+++ b/src/box/box.m
@@ -31,7 +31,7 @@
 
 #include <cfg/warning.h>
 #include <errcode.h>
-#include <fiber.h>
+#include "palloc.h"
 #include <recovery.h>
 #include <log_io.h>
 #include <pickle.h>
@@ -49,13 +49,11 @@
 #include "txn.h"
 #include "coio.h"
 
-static void box_process_replica(struct txn *txn, struct port *port,
+static void box_process_replica(struct port *port,
 				u32 op, struct tbuf *request_data);
-static void box_process_ro(struct txn *txn, struct port *port,
+static void box_process_ro(struct port *port,
 			   u32 op, struct tbuf *request_data);
-static void box_process_ro(struct txn *txn, struct port *port,
-			   u32 op, struct tbuf *request_data);
-static void box_process_rw(struct txn *txn, struct port *port,
+static void box_process_rw(struct port *port,
 			   u32 op, struct tbuf *request_data);
 box_process_func box_process = box_process_ro;
 
@@ -79,9 +77,10 @@ box_snap_row(const struct tbuf *t)
 }
 
 static void
-box_process_rw(struct txn *txn, struct port *port,
+box_process_rw(struct port *port,
 	       u32 op, struct tbuf *data)
 {
+	struct txn *txn = txn_begin();
 	ev_tstamp start = ev_now(), stop;
 
 	@try {
@@ -103,49 +102,44 @@ box_process_rw(struct txn *txn, struct port *port,
 }
 
 static void
-box_process_replica(struct txn *txn, struct port *port,
-	       u32 op, struct tbuf *request_data)
+box_process_replica(struct port *port, u32 op, struct tbuf *request_data)
 {
 	if (!request_is_select(op)) {
-		txn_rollback(txn);
 		tnt_raise(ClientError, :ER_NONMASTER,
 			  cfg.replication_source);
 	}
-	return box_process_rw(txn, port, op, request_data);
+	return box_process_rw(port, op, request_data);
 }
 
 static void
-box_process_ro(struct txn *txn, struct port *port,
+box_process_ro(struct port *port,
 	       u32 op, struct tbuf *request_data)
 {
-	if (!request_is_select(op)) {
-		txn_rollback(txn);
+	if (!request_is_select(op))
 		tnt_raise(LoggedError, :ER_SECONDARY);
-	}
-	return box_process_rw(txn, port, op, request_data);
+	return box_process_rw(port, op, request_data);
 }
-
-
 static void
 iproto_primary_port_handler(struct obuf *out, u32 op,
 			    struct tbuf *request_data)
 {
-	box_process(txn_begin(), port_iproto_create(out), op, request_data);
+	box_process(port_iproto_create(out), op, request_data);
 }
 
 static void
 iproto_secondary_port_handler(struct obuf *out, u32 op,
 			      struct tbuf *request_data)
 {
-	box_process_ro(txn_begin(), port_iproto_create(out), op, request_data);
+	box_process_ro(port_iproto_create(out), op, request_data);
 }
 
+
 static void
 box_xlog_sprint(struct tbuf *buf, const struct tbuf *t)
 {
 	struct header_v11 *row = header_v11(t);
 
-	struct tbuf *b = palloc(fiber->gc_pool, sizeof(*b));
+	struct tbuf *b = palloc(buf->pool, sizeof(*b));
 	b->data = t->data + sizeof(struct header_v11);
 	b->size = row->len;
 	u16 tag, op;
@@ -302,9 +296,7 @@ recover_row(void *param __attribute__((unused)), struct tbuf *t)
 			recover_snap_row(t);
 		} else if (tag == XLOG) {
 			u16 op = read_u16(t);
-			struct txn *txn = txn_begin();
-			txn->txn_flags |= BOX_NOT_STORE;
-			box_process_rw(txn, &port_null, op, t);
+			box_process_rw(&port_null, op, t);
 		} else {
 			say_error("unknown row tag: %i", (int)tag);
 			return -1;
@@ -373,6 +365,9 @@ box_leave_local_standby_mode(void *data __attribute__((unused)))
 {
 	recovery_finalize(recovery_state);
 
+	recovery_update_mode(recovery_state, cfg.wal_mode,
+			     cfg.wal_fsync_delay);
+
 	box_enter_master_or_replica_mode(&cfg);
 }
 
@@ -487,8 +482,7 @@ mod_init(void)
 	/* recovery initialization */
 	recovery_init(cfg.snap_dir, cfg.wal_dir,
 		      recover_row, NULL,
-		      cfg.rows_per_wal, cfg.wal_mode,
-		      cfg.wal_fsync_delay,
+		      cfg.rows_per_wal,
 		      init_storage ? RECOVER_READONLY : 0);
 	recovery_update_io_rate_limit(recovery_state, cfg.snap_io_rate_limit);
 	recovery_setup_panic(recovery_state, cfg.panic_on_snap_error, cfg.panic_on_wal_error);
diff --git a/src/box/box_lua.m b/src/box/box_lua.m
index 617bada74c8298e2ce758ddfcea70267c85deb49..6bf6cec5369e6dc7d4d0f4540b06a566db414362 100644
--- a/src/box/box_lua.m
+++ b/src/box/box_lua.m
@@ -1123,10 +1123,9 @@ static int lbox_process(lua_State *L)
 	int top = lua_gettop(L); /* to know how much is added by rw_callback */
 
 	size_t allocated_size = palloc_allocated(fiber->gc_pool);
-	struct txn *txn = txn_begin();
 	struct port *port_lua = port_lua_create(L);
 	@try {
-		box_process(txn, port_lua, op, &req);
+		box_process(port_lua, op, &req);
 	} @finally {
 		/*
 		 * This only works as long as port_lua doesn't
diff --git a/src/box/memcached.m b/src/box/memcached.m
index e562fac93675f1a5843c57358b20e5f9a86c234b..5c1a71cc7beabb212a41586238b1f68353160124 100644
--- a/src/box/memcached.m
+++ b/src/box/memcached.m
@@ -118,7 +118,7 @@ store(void *key, u32 exptime, u32 flags, u32 bytes, const char *data)
 	 * Use a box dispatch wrapper which handles correctly
 	 * read-only/read-write modes.
 	 */
-	box_process(txn_begin(), &port_null, REPLACE, req);
+	box_process(&port_null, REPLACE, req);
 }
 
 static void
@@ -133,7 +133,7 @@ delete(void *key)
 	tbuf_append(req, &key_len, sizeof(key_len));
 	tbuf_append_field(req, key);
 
-	box_process(txn_begin(), &port_null, DELETE, req);
+	box_process(&port_null, DELETE, req);
 }
 
 static struct tuple *
diff --git a/src/iobuf.m b/src/iobuf.m
index 0c414f7c0142699b63778ce1b88461b2fa18fd19..85050a02c8442cdfe4999889763a489f295e6abe 100644
--- a/src/iobuf.m
+++ b/src/iobuf.m
@@ -150,7 +150,7 @@ obuf_dup(struct obuf *buf, void *data, size_t size)
 	 * @pre buf->pos points at an array of allocated buffers.
 	 * The array ends with a zero-initialized buffer.
          */
-	if (iov->iov_len + size > capacity) {
+	while (iov->iov_len + size > capacity) {
 		/*
 		 * The data doesn't fit into this buffer.
 		 * It could be because the buffer is not
@@ -158,13 +158,14 @@ obuf_dup(struct obuf *buf, void *data, size_t size)
 		 * Copy as much as possible into already
 		 * allocated buffers.
 		 */
-		while (iov->iov_len < capacity) {
+		if (iov->iov_len < capacity) {
 			/*
 			 * This buffer is allocated, but can't
 			 * fit all the data. Copy as much data as
 			 * possible.
 			 */
 			size_t fill = capacity - iov->iov_len;
+			assert(fill < size);
 			memcpy(iov->iov_base + iov->iov_len, data, fill);
 
 			iov->iov_len += fill;
@@ -172,22 +173,27 @@ obuf_dup(struct obuf *buf, void *data, size_t size)
 			data += fill;
 			size -= fill;
 
-			if (size == 0)          /* Nothing more to do. */
-				return;
 			buf->pos++;
 			iov = &buf->iov[buf->pos];
 			capacity = buf->capacity[buf->pos];
+			/*
+			 * Check if the remainder can fit
+			 * without allocations.
+			 */
+		} else {
+			assert(capacity == 0);
+			/**
+			 * Still some data to copy. We have to get
+			 * a new buffer. Before we allocate
+			 * a buffer for this position, ensure
+			 * there is an unallocated buffer in the
+			 * next one, since it works as an end
+			 * marker for the loop above.
+			 */
+			obuf_init_pos(buf, buf->pos + 1);
+			obuf_alloc_pos(buf, buf->pos, size);
+			break;
 		}
-		assert(capacity == 0);
-		/**
-		 * Still some data to copy. We have to get a new
-		 * buffer. Before we allocate a buffer for this
-		 * position, ensure there is an unallocated buffer
-		 * in the next one, since it works as an end marker
-		 * for the loop above.
-		 */
-		obuf_init_pos(buf, buf->pos + 1);
-		obuf_alloc_pos(buf, buf->pos, size);
 	}
 	memcpy(iov->iov_base + iov->iov_len, data, size);
 	iov->iov_len += size;
diff --git a/src/iproto.m b/src/iproto.m
index b892725d864361c731693494f52f23d2ea0a1826..5d625740bfd23c943149f68d9b2d53b709833b27 100644
--- a/src/iproto.m
+++ b/src/iproto.m
@@ -35,6 +35,8 @@
 #include <say.h>
 #include "coio_buf.h"
 #include "tbuf.h"
+#include "box/box.h"
+#include "box/port.h"
 
 const uint32_t msg_ping = 0xff00;
 
diff --git a/src/recovery.m b/src/recovery.m
index 5d1cb4607cbe595987ffc93c70f8c1a836018962..1af7f72ea8a0bbaa6046d0717106065e7369de77 100644
--- a/src/recovery.m
+++ b/src/recovery.m
@@ -114,6 +114,15 @@ wait_lsn_set(struct wait_lsn *wait_lsn, int64_t lsn)
 	wait_lsn->lsn = lsn;
 }
 
+
+/* Alert the waiter, if any. */
+static inline void
+wakeup_lsn_waiter(struct recovery_state *r)
+{
+	if (r->wait_lsn.waiter && r->confirmed_lsn >= r->wait_lsn.lsn)
+		fiber_wakeup(r->wait_lsn.waiter);
+}
+
 void
 confirm_lsn(struct recovery_state *r, int64_t lsn, bool is_commit)
 {
@@ -130,18 +139,26 @@ confirm_lsn(struct recovery_state *r, int64_t lsn, bool is_commit)
 			r->confirmed_lsn = lsn;
 		 }
 	} else {
+		 /*
+		 * There can be holes in
+		 * confirmed_lsn, in case of disk write failure, but
+		 * wal_writer never confirms LSNs out order.
+		 */
 		assert(false);
 		say_error("LSN is used twice or COMMIT order is broken: "
 			  "confirmed: %jd, new: %jd",
 			  (intmax_t) r->confirmed_lsn, (intmax_t) lsn);
 	}
-	/*
-	 * Alert the waiter, if any. There can be holes in
-	 * confirmed_lsn, in case of disk write failure, but
-	 * wal_writer never confirms LSNs out order.
-	 */
-	if (r->wait_lsn.waiter && r->confirmed_lsn >= r->wait_lsn.lsn)
-		fiber_call(r->wait_lsn.waiter);
+	wakeup_lsn_waiter(r);
+}
+
+void
+set_lsn(struct recovery_state *r, int64_t lsn)
+{
+	r->lsn = lsn;
+	r->confirmed_lsn = lsn;
+	say_debug("set_lsn(%p, %" PRIi64, r, r->lsn);
+	wakeup_lsn_waiter(r);
 }
 
 /** Wait until the given LSN makes its way to disk. */
@@ -167,13 +184,6 @@ next_lsn(struct recovery_state *r)
 	return r->lsn;
 }
 
-void
-set_lsn(struct recovery_state *r, int64_t lsn)
-{
-	r->lsn = lsn;
-	say_debug("set_lsn(%p, %" PRIi64, r, r->lsn);
-	confirm_lsn(r, r->lsn, true);
-}
 
 /* }}} */
 
@@ -189,13 +199,12 @@ recovery_stop_local(struct recovery_state *r);
 void
 recovery_init(const char *snap_dirname, const char *wal_dirname,
 	      row_handler row_handler, void *row_handler_param,
-	      int rows_per_wal, const char *wal_mode,
-	      double wal_fsync_delay, int flags)
+	      int rows_per_wal, int flags)
 {
 	assert(recovery_state == NULL);
 	recovery_state = p0alloc(eter_pool, sizeof(struct recovery_state));
 	struct recovery_state *r = recovery_state;
-	recovery_update_mode(r, wal_mode, wal_fsync_delay);
+	recovery_update_mode(r, "none", 0);
 
 	if (rows_per_wal <= 1)
 		panic("unacceptable value of 'rows_per_wal'");
@@ -209,7 +218,6 @@ recovery_init(const char *snap_dirname, const char *wal_dirname,
 	r->wal_dir->dirname = strdup(wal_dirname);
 	r->wal_dir->open_wflags = r->wal_mode == WAL_FSYNC ? WAL_SYNC_FLAG : 0;
 	r->rows_per_wal = rows_per_wal;
-	r->wal_fsync_delay = wal_fsync_delay;
 	wait_lsn_clear(&r->wait_lsn);
 	r->flags = flags;
 }
diff --git a/src/replication.m b/src/replication.m
index 557de40e581660d31572118dfe7ca364924a0c35..a404a3abaab341ea31e48963fd4bb6f5fb63593b 100644
--- a/src/replication.m
+++ b/src/replication.m
@@ -646,8 +646,7 @@ replication_relay_loop(int client_sock)
 	/* Initialize the recovery process */
 	recovery_init(cfg.snap_dir, cfg.wal_dir,
 		      replication_relay_send_row, (void *)(intptr_t) client_sock,
-		      INT32_MAX, "fsync_delay", 0,
-		      RECOVER_READONLY);
+		      INT32_MAX, RECOVER_READONLY);
 	/*
 	 * Note that recovery starts with lsn _NEXT_ to
 	 * the confirmed one.
diff --git a/src/tarantool.m b/src/tarantool.m
index 2645af068f5b041b0ddaec933987eff41ad9ed8f..a805c32a855cdded9d2e906dd38e709ae8510adf 100644
--- a/src/tarantool.m
+++ b/src/tarantool.m
@@ -253,6 +253,25 @@ reload_cfg(struct tbuf *out)
 	return 0;
 }
 
+/** Print the configuration file in YAML format. */
+void
+show_cfg(struct tbuf *out)
+{
+	tarantool_cfg_iterator_t *i;
+	char *key, *value;
+
+	tbuf_printf(out, "configuration:" CRLF);
+	i = tarantool_cfg_iterator_init();
+	while ((key = tarantool_cfg_iterator_next(i, &cfg, &value)) != NULL) {
+		if (value) {
+			tbuf_printf(out, "  %s: \"%s\"" CRLF, key, value);
+			free(value);
+		} else {
+			tbuf_printf(out, "  %s: (null)" CRLF, key);
+		}
+	}
+}
+
 const char *
 tarantool_version(void)
 {
@@ -811,7 +830,7 @@ main(int argc, char **argv)
 		tarantool_L = tarantool_lua_init();
 		mod_init();
 		tarantool_lua_load_cfg(tarantool_L, &cfg);
-		admin_init();
+		admin_init(cfg.bind_ipaddr, cfg.admin_port);
 		replication_init();
 		/*
 		 * Load user init script.  The script should have access