Index: HelenOS.config
===================================================================
--- HelenOS.config	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ HelenOS.config	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -310,5 +310,5 @@
 
 % Support for SMP
-! [(PLATFORM=ia32&PROCESSOR!=athlon_xp)|PLATFORM=amd64|PLATFORM=sparc64|PLATFORM=ia64|(PLATFORM=mips32&MACHINE=msim)] CONFIG_SMP (y/n)
+! [(PLATFORM=ia32&PROCESSOR!=athlon_xp)|PLATFORM=amd64|PLATFORM=sparc64|PLATFORM=ia64|(PLATFORM=mips32&MACHINE=msim)|PLATFORM=abs32le] CONFIG_SMP (y/n)
 
 % Debug build
Index: defaults/special/Makefile.config
===================================================================
--- defaults/special/Makefile.config	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ defaults/special/Makefile.config	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -4,4 +4,7 @@
 # Compiler
 COMPILER = gcc_native
+
+# Support for SMP
+CONFIG_SMP = y
 
 # Debug build
Index: kernel/arch/abs32le/Makefile.inc
===================================================================
--- kernel/arch/abs32le/Makefile.inc	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/abs32le/Makefile.inc	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -41,4 +41,6 @@
 	arch/$(KARCH)/src/userspace.c \
 	arch/$(KARCH)/src/cpu/cpu.c \
+	arch/$(KARCH)/src/ddi/ddi.c \
+	arch/$(KARCH)/src/smp/smp.c \
 	arch/$(KARCH)/src/mm/as.c \
 	arch/$(KARCH)/src/mm/frame.c \
Index: kernel/arch/abs32le/include/asm.h
===================================================================
--- kernel/arch/abs32le/include/asm.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/abs32le/include/asm.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -49,5 +49,5 @@
 
 
-static inline void cpu_halt(void)
+static inline __attribute__((noreturn)) void cpu_halt(void)
 {
 	/* On real hardware this should stop processing further
Index: kernel/arch/abs32le/include/context.h
===================================================================
--- kernel/arch/abs32le/include/context.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/abs32le/include/context.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -36,16 +36,9 @@
 #define KERN_abs32le_CONTEXT_H_
 
-#ifdef KERNEL
-#include <arch/types.h>
-
 #define STACK_ITEM_SIZE  4
 #define SP_DELTA         0
 
-#define context_set(c, _pc, stack, size) \
-	do { \
-		(c)->pc = (uintptr_t) (_pc); \
-	} while (0)
-
-#endif /* KERNEL */
+#define context_set(ctx, pc, stack, size) \
+    context_set_generic(ctx, pc, stack, size)
 
 /*
Index: kernel/arch/abs32le/include/interrupt.h
===================================================================
--- kernel/arch/abs32le/include/interrupt.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/abs32le/include/interrupt.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -40,4 +40,6 @@
 #define IVT_ITEMS  0
 #define IVT_FIRST  0
+
+#define VECTOR_TLB_SHOOTDOWN_IPI  0
 
 /*
Index: kernel/arch/abs32le/src/abs32le.c
===================================================================
--- kernel/arch/abs32le/src/abs32le.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/abs32le/src/abs32le.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -39,5 +39,7 @@
 #include <arch/asm.h>
 
+#include <func.h>
 #include <config.h>
+#include <context.h>
 #include <interrupt.h>
 #include <ddi/irq.h>
@@ -107,4 +109,35 @@
 }
 
+void memsetb(void *dst, size_t cnt, uint8_t val)
+{
+	_memsetb(dst, cnt, val);
+}
+
+void memsetw(void *dst, size_t cnt, uint16_t val)
+{
+	_memsetw(dst, cnt, val);
+}
+
+void panic_printf(char *fmt, ...)
+{
+	va_list args;
+	
+	va_start(args, fmt);
+	vprintf(fmt, args);
+	va_end(args);
+	
+	halt();
+}
+
+int context_save_arch(context_t *ctx)
+{
+	return 1;
+}
+
+void context_restore_arch(context_t *ctx)
+{
+	while (true);
+}
+
 /** @}
  */
Index: kernel/arch/abs32le/src/ddi/ddi.c
===================================================================
--- kernel/arch/abs32le/src/ddi/ddi.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
+++ kernel/arch/abs32le/src/ddi/ddi.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup abs32leddi
+ * @{
+ */
+/** @file
+ *  @brief DDI.
+ */
+
+#include <ddi/ddi.h>
+#include <proc/task.h>
+#include <arch/types.h>
+
+/** Enable I/O space range for task.
+ *
+ */
+int ddi_iospace_enable_arch(task_t *task, uintptr_t ioaddr, size_t size)
+{
+	return 0;
+}
+
+/** @}
+ */
Index: kernel/arch/abs32le/src/debug/stacktrace.c
===================================================================
--- kernel/arch/abs32le/src/debug/stacktrace.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/abs32le/src/debug/stacktrace.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup ia32
+/** @addtogroup abs32le
  * @{
  */
@@ -38,16 +38,11 @@
 #include <typedefs.h>
 
-#define FRAME_OFFSET_FP_PREV	0
-#define FRAME_OFFSET_RA		1
-
 bool kernel_frame_pointer_validate(uintptr_t fp)
 {
-	return fp != 0;
+	return true;;
 }
 
 bool kernel_frame_pointer_prev(uintptr_t fp, uintptr_t *prev)
 {
-	uint32_t *stack = (void *) fp;
-	*prev = stack[FRAME_OFFSET_FP_PREV];
 	return true;
 }
@@ -55,6 +50,4 @@
 bool kernel_return_address_get(uintptr_t fp, uintptr_t *ra)
 {
-	uint32_t *stack = (void *) fp;
-	*ra = stack[FRAME_OFFSET_RA];
 	return true;
 }
@@ -62,17 +55,25 @@
 bool uspace_frame_pointer_validate(uintptr_t fp)
 {
-	return fp != 0;
+	return true;
 }
 
 bool uspace_frame_pointer_prev(uintptr_t fp, uintptr_t *prev)
 {
-	return !copy_from_uspace((void *) prev,
-	    (uint32_t *) fp + FRAME_OFFSET_FP_PREV, sizeof(*prev));
+	return true;
 }
 
 bool uspace_return_address_get(uintptr_t fp, uintptr_t *ra)
 {
-	return !copy_from_uspace((void *) ra, (uint32_t *) fp + FRAME_OFFSET_RA,
-	    sizeof(*ra));
+	return true;
+}
+
+uintptr_t frame_pointer_get(void)
+{
+	return 0;
+}
+
+uintptr_t program_counter_get(void)
+{
+	return 0;
 }
 
Index: kernel/arch/abs32le/src/smp/smp.c
===================================================================
--- kernel/arch/abs32le/src/smp/smp.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
+++ kernel/arch/abs32le/src/smp/smp.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup abs32le
+ * @{
+ */
+/** @file
+ */
+
+#include <smp/smp.h>
+
+void smp_init(void)
+{
+}
+
+void kmp(void *arg)
+{
+}
+
+/** @}
+ */
Index: kernel/arch/amd64/include/asm.h
===================================================================
--- kernel/arch/amd64/include/asm.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/amd64/include/asm.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -68,11 +68,11 @@
 }
 
-static inline void cpu_halt(void)
-{
-	asm volatile (
-		"0:\n"
-		"	hlt\n"
-		"	jmp 0b\n"
-	);
+static inline void __attribute__((noreturn)) cpu_halt(void)
+{
+	while (true) {
+		asm volatile (
+			"hlt\n"
+		);
+	}
 }
 
Index: kernel/arch/arm32/include/asm.h
===================================================================
--- kernel/arch/arm32/include/asm.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/arm32/include/asm.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -96,5 +96,5 @@
 }
 
-extern void cpu_halt(void);
+extern void cpu_halt(void) __attribute__((noreturn));
 extern void asm_delay_loop(uint32_t t);
 extern void userspace_asm(uintptr_t ustack, uintptr_t uspace_uarg,
Index: kernel/arch/arm32/src/arm32.c
===================================================================
--- kernel/arch/arm32/src/arm32.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/arm32/src/arm32.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -155,5 +155,6 @@
 void cpu_halt(void)
 {
-	machine_cpu_halt();
+	while (true)
+		machine_cpu_halt();
 }
 
@@ -162,5 +163,5 @@
 {
 	/* not implemented */
-	while (1);
+	while (true);
 }
 
Index: kernel/arch/ia32/include/asm.h
===================================================================
--- kernel/arch/ia32/include/asm.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/ia32/include/asm.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -60,11 +60,11 @@
  *
  */
-static inline void cpu_halt(void)
-{
-	asm volatile (
-		"0:\n"
-		"	hlt\n"
-		"	jmp 0b\n"
-	);
+static inline __attribute__((noreturn)) void cpu_halt(void)
+{
+	while (true) {
+		asm volatile (
+			"hlt\n"
+		);
+	}
 }
 
Index: kernel/arch/ia64/include/asm.h
===================================================================
--- kernel/arch/ia64/include/asm.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/ia64/include/asm.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -428,5 +428,5 @@
 }
 
-extern void cpu_halt(void);
+extern void cpu_halt(void) __attribute__((noreturn));
 extern void cpu_sleep(void);
 extern void asm_delay_loop(uint32_t t);
Index: kernel/arch/ia64/include/context.h
===================================================================
--- kernel/arch/ia64/include/context.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/ia64/include/context.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -48,8 +48,4 @@
  */
 #define SP_DELTA	(0 + ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT))
-
-#ifdef context_set
-#undef context_set
-#endif
 
 /* RSE stack starts at the bottom of memory stack. */
Index: kernel/arch/mips32/include/asm.h
===================================================================
--- kernel/arch/mips32/include/asm.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/mips32/include/asm.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -66,5 +66,5 @@
 }
 
-extern void cpu_halt(void);
+extern void cpu_halt(void) __attribute__((noreturn));
 extern void asm_delay_loop(uint32_t t);
 extern void userspace_asm(uintptr_t ustack, uintptr_t uspace_uarg,
Index: kernel/arch/mips32/include/context.h
===================================================================
--- kernel/arch/mips32/include/context.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/mips32/include/context.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup mips32	
+/** @addtogroup mips32
  * @{
  */
@@ -42,10 +42,12 @@
  * Put one item onto the stack to support get_stack_base() and align it up.
  */
-#define SP_DELTA	(0 + ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT))
-
+#define SP_DELTA  (0 + ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT))
 
 #ifndef __ASM__
 
 #include <arch/types.h>
+
+#define context_set(ctx, pc, stack, size) \
+    context_set_generic(ctx, pc, stack, size)
 
 /*
Index: kernel/arch/ppc32/include/asm.h
===================================================================
--- kernel/arch/ppc32/include/asm.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/ppc32/include/asm.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup ppc32	
+/** @addtogroup ppc32
  * @{
  */
@@ -146,37 +146,36 @@
 }
 
-void cpu_halt(void);
-void asm_delay_loop(uint32_t t);
-
+extern void cpu_halt(void) __attribute__((noreturn));
+extern void asm_delay_loop(uint32_t t);
 extern void userspace_asm(uintptr_t uspace_uarg, uintptr_t stack, uintptr_t entry);
 
 static inline void pio_write_8(ioport8_t *port, uint8_t v)
 {
-	*port = v;	
+	*port = v;
 }
 
 static inline void pio_write_16(ioport16_t *port, uint16_t v)
 {
-	*port = v;	
+	*port = v;
 }
 
 static inline void pio_write_32(ioport32_t *port, uint32_t v)
 {
-	*port = v;	
+	*port = v;
 }
 
 static inline uint8_t pio_read_8(ioport8_t *port)
 {
-	return *port; 
+	return *port;
 }
 
 static inline uint16_t pio_read_16(ioport16_t *port)
 {
-	return *port; 
+	return *port;
 }
 
 static inline uint32_t pio_read_32(ioport32_t *port)
 {
-	return *port; 
+	return *port;
 }
 
Index: kernel/arch/ppc32/include/context.h
===================================================================
--- kernel/arch/ppc32/include/context.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/ppc32/include/context.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup ppc32	
+/** @addtogroup ppc32
  * @{
  */
@@ -38,5 +38,8 @@
 #include <arch/types.h>
 
-#define SP_DELTA	16
+#define SP_DELTA  16
+
+#define context_set(ctx, pc, stack, size) \
+    context_set_generic(ctx, pc, stack, size)
 
 typedef struct {
@@ -68,5 +71,5 @@
 	
 	ipl_t ipl;
-} __attribute__ ((packed)) context_t;
+} __attribute__((packed)) context_t;
 
 #endif
Index: kernel/arch/sparc64/include/asm.h
===================================================================
--- kernel/arch/sparc64/include/asm.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/sparc64/include/asm.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -430,5 +430,5 @@
 }
 
-extern void cpu_halt(void);
+extern void cpu_halt(void) __attribute__((noreturn));
 extern void cpu_sleep(void);
 extern void asm_delay_loop(const uint32_t usec);
Index: kernel/arch/sparc64/include/context.h
===================================================================
--- kernel/arch/sparc64/include/context.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/arch/sparc64/include/context.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -42,8 +42,4 @@
 #define SP_DELTA	(STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE)
 
-#ifdef context_set
-#undef context_set
-#endif
-
 #define context_set(c, _pc, stack, size)			\
 	(c)->pc = ((uintptr_t) _pc) - 8;			\
Index: kernel/generic/include/context.h
===================================================================
--- kernel/generic/include/context.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/generic/include/context.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup generic	
+/** @addtogroup generic
  * @{
  */
@@ -39,13 +39,10 @@
 #include <arch/context.h>
 
+#define context_set_generic(ctx, _pc, stack, size) \
+	(ctx)->pc = (uintptr_t) (_pc); \
+	(ctx)->sp = ((uintptr_t) (stack)) + (size) - SP_DELTA;
 
-#ifndef context_set
-#define context_set(c, _pc, stack, size) 	\
-	(c)->pc = (uintptr_t) (_pc);		\
-	(c)->sp = ((uintptr_t) (stack)) + (size) - SP_DELTA;
-#endif /* context_set */
-
-extern int context_save_arch(context_t *c) __attribute__ ((returns_twice));
-extern void context_restore_arch(context_t *c) __attribute__ ((noreturn));
+extern int context_save_arch(context_t *ctx) __attribute__((returns_twice));
+extern void context_restore_arch(context_t *ctx) __attribute__((noreturn));
 
 /** Save register context.
@@ -73,9 +70,10 @@
  * saved like that would therefore lead to a disaster.
  *
- * @param c		Context structure.
+ * @param ctx Context structure.
  *
- * @return		context_save() returns 1, context_restore() returns 0.
+ * @return context_save() returns 1, context_restore() returns 0.
+ *
  */
-#define context_save(c)   context_save_arch(c)
+#define context_save(ctx)  context_save_arch(ctx)
 
 /** Restore register context.
@@ -88,9 +86,9 @@
  * being return value.
  *
- * @param c		Context structure.
+ * @param ctx Context structure.
  */
-static inline void context_restore(context_t *c)
+static inline void context_restore(context_t *ctx)
 {
-	context_restore_arch(c);
+	context_restore_arch(ctx);
 }
 
Index: kernel/generic/include/func.h
===================================================================
--- kernel/generic/include/func.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/generic/include/func.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -41,5 +41,5 @@
 extern atomic_t haltstate;
 
-extern void halt(void);
+extern void halt(void) __attribute__((noreturn));
 extern unative_t atoi(const char *text);
 extern void order(const uint64_t val, uint64_t *rv, char *suffix);
Index: kernel/generic/include/stacktrace.h
===================================================================
--- kernel/generic/include/stacktrace.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ kernel/generic/include/stacktrace.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -60,5 +60,5 @@
  */
 extern uintptr_t frame_pointer_get(void);
-extern uintptr_t program_counter_get();
+extern uintptr_t program_counter_get(void);
 
 extern bool kernel_frame_pointer_validate(uintptr_t);
Index: tools/toolchain.sh
===================================================================
--- tools/toolchain.sh	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ tools/toolchain.sh	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -142,5 +142,5 @@
 	
 	BINUTILS_VERSION="2.20"
-	GCC_VERSION="4.4.2"
+	GCC_VERSION="4.4.3"
 	
 	BINUTILS="binutils-${BINUTILS_VERSION}.tar.bz2"
@@ -165,7 +165,7 @@
 	echo ">>> Downloading tarballs"
 	download_check "${BINUTILS_SOURCE}" "${BINUTILS}" "ee2d3e996e9a2d669808713360fa96f8"
-	download_check "${GCC_SOURCE}" "${GCC_CORE}" "d50ec5af20508974411d0c83c5f4e396"
-	download_check "${GCC_SOURCE}" "${GCC_OBJC}" "d8d26187d386a0591222a580b5a5b3d3"
-	download_check "${GCC_SOURCE}" "${GCC_CPP}" "43b1e4879eb282dc4b05e4c016d356d7"
+	download_check "${GCC_SOURCE}" "${GCC_CORE}" "054b66f315b3d04ad06544ce26e72365"
+	download_check "${GCC_SOURCE}" "${GCC_OBJC}" "34711c4de46eaf79aa018206dbec4389"
+	download_check "${GCC_SOURCE}" "${GCC_CPP}" "cd179ec4f05ee17ce76464da25a2674c"
 	
 	echo ">>> Removing previous content"
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/app/init/init.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -94,14 +94,5 @@
 static bool mount_devfs(void)
 {
-	char null[MAX_DEVICE_NAME];
-	int null_id = devmap_null_create();
-	
-	if (null_id == -1) {
-		printf(NAME ": Unable to create null device\n");
-		return false;
-	}
-	
-	snprintf(null, MAX_DEVICE_NAME, "null/%d", null_id);
-	int rc = mount("devfs", DEVFS_MOUNT_POINT, null, "", IPC_FLAG_BLOCKING);
+	int rc = mount("devfs", DEVFS_MOUNT_POINT, "", "", IPC_FLAG_BLOCKING);
 	
 	switch (rc) {
@@ -111,17 +102,13 @@
 	case EBUSY:
 		printf(NAME ": Device filesystem already mounted\n");
-		devmap_null_destroy(null_id);
 		return false;
 	case ELIMIT:
 		printf(NAME ": Unable to mount device filesystem\n");
-		devmap_null_destroy(null_id);
 		return false;
 	case ENOENT:
 		printf(NAME ": Unknown filesystem type (devfs)\n");
-		devmap_null_destroy(null_id);
 		return false;
 	default:
 		printf(NAME ": Error mounting device filesystem (%d)\n", rc);
-		devmap_null_destroy(null_id);
 		return false;
 	}
@@ -184,8 +171,8 @@
 {
 	char *argv[3];
-	char hid_in[MAX_DEVICE_NAME];
+	char hid_in[DEVMAP_NAME_MAXLEN];
 	int rc;
 	
-	snprintf(hid_in, MAX_DEVICE_NAME, "%s/%s", DEVFS_MOUNT_POINT, dev);
+	snprintf(hid_in, DEVMAP_NAME_MAXLEN, "%s/%s", DEVFS_MOUNT_POINT, dev);
 	
 	printf(NAME ": Spawning %s with %s\n", SRV_CONSOLE, hid_in);
@@ -209,8 +196,8 @@
 {
 	char *argv[4];
-	char term[MAX_DEVICE_NAME];
+	char term[DEVMAP_NAME_MAXLEN];
 	int rc;
 	
-	snprintf(term, MAX_DEVICE_NAME, "%s/%s", DEVFS_MOUNT_POINT, dev);
+	snprintf(term, DEVMAP_NAME_MAXLEN, "%s/%s", DEVFS_MOUNT_POINT, dev);
 	
 	printf(NAME ": Spawning %s with %s %s\n", APP_GETTERM, term, app);
Index: uspace/app/init/init.h
===================================================================
--- uspace/app/init/init.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/app/init/init.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -39,6 +39,4 @@
 #define NAME  "init"
 
-#define MAX_DEVICE_NAME  32
-
 #endif
 
Index: uspace/app/tester/vfs/vfs1.c
===================================================================
--- uspace/app/tester/vfs/vfs1.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/app/tester/vfs/vfs1.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -79,15 +79,8 @@
 	TPRINTF("Created directory %s\n", MOUNT_POINT);
 	
-	char null[MAX_DEVICE_NAME];
-	int null_id = devmap_null_create();
-	
-	if (null_id == -1)
-		return "Unable to create null device";
-	
-	snprintf(null, MAX_DEVICE_NAME, "null/%d", null_id);
-	int rc = mount(FS_TYPE, MOUNT_POINT, null, OPTIONS, FLAGS);
+	int rc = mount(FS_TYPE, MOUNT_POINT, "", OPTIONS, FLAGS);
 	switch (rc) {
 	case EOK:
-		TPRINTF("Mounted /dev/%s as %s on %s\n", null, FS_TYPE, MOUNT_POINT);
+		TPRINTF("Mounted %s on %s\n", FS_TYPE, MOUNT_POINT);
 		break;
 	case EBUSY:
Index: uspace/lib/libc/arch/ia64/include/fibril.h
===================================================================
--- uspace/lib/libc/arch/ia64/include/fibril.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/lib/libc/arch/ia64/include/fibril.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -52,8 +52,4 @@
 /* Stack is divided into two equal parts (for memory stack and register stack). */
 #define PSTHREAD_INITIAL_STACK_DIVISION 2  
-
-#ifdef context_set
-#undef context_set
-#endif
 
 #define context_set(c, _pc, stack, size, tls) 								\
Index: uspace/lib/libc/arch/sparc64/include/fibril.h
===================================================================
--- uspace/lib/libc/arch/sparc64/include/fibril.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/lib/libc/arch/sparc64/include/fibril.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -42,8 +42,4 @@
 #define SP_DELTA	(STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE)
 
-#ifdef context_set
-#undef context_set
-#endif
-
 #define context_set(c, _pc, stack, size, ptls) \
 	do { \
Index: uspace/lib/libc/generic/async.c
===================================================================
--- uspace/lib/libc/generic/async.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/lib/libc/generic/async.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -1287,11 +1287,46 @@
 }
 
+/** Wrapper for forwarding any read request
+ *
+ *
+ */
+int async_data_read_forward_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
+    ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr)
+{
+	ipc_callid_t callid;
+	if (!async_data_read_receive(&callid, NULL)) {
+		ipc_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+	
+	aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
+	    dataptr);
+	if (msg == 0) {
+		ipc_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+	
+	int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
+	    IPC_FF_ROUTE_FROM_ME);
+	if (retval != EOK) {
+		async_wait_for(msg, NULL);
+		ipc_answer_0(callid, retval);
+		return retval;
+	}
+	
+	ipcarg_t rc;
+	async_wait_for(msg, &rc);
+	
+	return (int) rc;
+}
+
 /** Wrapper for making IPC_M_DATA_WRITE calls using the async framework.
  *
- * @param phoneid	Phone that will be used to contact the receiving side.
- * @param src		Address of the beginning of the source buffer.
- * @param size		Size of the source buffer.
- *
- * @return		Zero on success or a negative error code from errno.h.
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param src     Address of the beginning of the source buffer.
+ * @param size    Size of the source buffer.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
  */
 int async_data_write_start(int phoneid, const void *src, size_t size)
@@ -1308,10 +1343,11 @@
  * So far, this wrapper is to be used from within a connection fibril.
  *
- * @param callid	Storage where the hash of the IPC_M_DATA_WRITE call will
- * 			be stored.
- * @param size		Storage where the suggested size will be stored. May be
- *			NULL
- *
- * @return		Non-zero on success, zero on failure.
+ * @param callid Storage where the hash of the IPC_M_DATA_WRITE call will
+ *               be stored.
+ * @param size   Storage where the suggested size will be stored. May be
+ *               NULL
+ *
+ * @return Non-zero on success, zero on failure.
+ *
  */
 int async_data_write_receive(ipc_callid_t *callid, size_t *size)
@@ -1320,10 +1356,12 @@
 	
 	assert(callid);
-
+	
 	*callid = async_get_call(&data);
 	if (IPC_GET_METHOD(data) != IPC_M_DATA_WRITE)
 		return 0;
+	
 	if (size)
 		*size = (size_t) IPC_GET_ARG2(data);
+	
 	return 1;
 }
@@ -1334,9 +1372,10 @@
  * so that the user doesn't have to remember the meaning of each IPC argument.
  *
- * @param callid	Hash of the IPC_M_DATA_WRITE call to answer.
- * @param dst		Final destination address for the IPC_M_DATA_WRITE call.
- * @param size		Final size for the IPC_M_DATA_WRITE call.
- *
- * @return		Zero on success or a value from @ref errno.h on failure.
+ * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
+ * @param dst    Final destination address for the IPC_M_DATA_WRITE call.
+ * @param size   Final size for the IPC_M_DATA_WRITE call.
+ *
+ * @return Zero on success or a value from @ref errno.h on failure.
+ *
  */
 int async_data_write_finalize(ipc_callid_t callid, void *dst, size_t size)
@@ -1345,20 +1384,28 @@
 }
 
-/** Wrapper for receiving blobs via the async_data_write_*
+/** Wrapper for receiving binary data or strings
  *
  * This wrapper only makes it more comfortable to use async_data_write_*
- * functions to receive blobs.
- *
- * @param blob     Pointer to data pointer (which should be later disposed
- *                 by free()). If the operation fails, the pointer is not
- *                 touched.
- * @param max_size Maximum size (in bytes) of the blob to receive. 0 means
- *                 no limit.
- * @param received If not NULL, the size of the received data is stored here.
+ * functions to receive binary data or strings.
+ *
+ * @param data       Pointer to data pointer (which should be later disposed
+ *                   by free()). If the operation fails, the pointer is not
+ *                   touched.
+ * @param nullterm   If true then the received data is always zero terminated.
+ *                   This also causes to allocate one extra byte beyond the
+ *                   raw transmitted data.
+ * @param min_size   Minimum size (in bytes) of the data to receive.
+ * @param max_size   Maximum size (in bytes) of the data to receive. 0 means
+ *                   no limit.
+ * @param granulariy If non-zero then the size of the received data has to
+ *                   be divisible by this value.
+ * @param received   If not NULL, the size of the received data is stored here.
  *
  * @return Zero on success or a value from @ref errno.h on failure.
  *
  */
-int async_data_blob_receive(char **blob, const size_t max_size, size_t *received)
+int async_data_write_accept(void **data, const bool nullterm,
+    const size_t min_size, const size_t max_size, const size_t granularity,
+    size_t *received)
 {
 	ipc_callid_t callid;
@@ -1369,4 +1416,9 @@
 	}
 	
+	if (size < min_size) {
+		ipc_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+	
 	if ((max_size > 0) && (size > max_size)) {
 		ipc_answer_0(callid, EINVAL);
@@ -1374,17 +1426,31 @@
 	}
 	
-	char *data = (char *) malloc(size);
-	if (data == NULL) {
+	if ((granularity > 0) && ((size % granularity) != 0)) {
+		ipc_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+	
+	void *_data;
+	
+	if (nullterm)
+		_data = malloc(size + 1);
+	else
+		_data = malloc(size);
+	
+	if (_data == NULL) {
 		ipc_answer_0(callid, ENOMEM);
 		return ENOMEM;
 	}
 	
-	int rc = async_data_write_finalize(callid, data, size);
+	int rc = async_data_write_finalize(callid, _data, size);
 	if (rc != EOK) {
-		free(data);
+		free(_data);
 		return rc;
 	}
 	
-	*blob = data;
+	if (nullterm)
+		((char *) _data)[size] = 0;
+	
+	*data = _data;
 	if (received != NULL)
 		*received = size;
@@ -1393,47 +1459,50 @@
 }
 
-/** Wrapper for receiving strings via the async_data_write_*
- *
- * This wrapper only makes it more comfortable to use async_data_write_*
- * functions to receive strings.
- *
- * @param str      Pointer to string pointer (which should be later disposed
- *                 by free()). If the operation fails, the pointer is not
- *                 touched.
- * @param max_size Maximum size (in bytes) of the string to receive. 0 means
- *                 no limit.
- *
- * @return Zero on success or a value from @ref errno.h on failure.
- *
- */
-int async_data_string_receive(char **str, const size_t max_size)
+/** Wrapper for voiding any data that is about to be received
+ *
+ * This wrapper can be used to void any pending data
+ *
+ * @param retval Error value from @ref errno.h to be returned to the caller.
+ *
+ */
+void async_data_write_void(const int retval)
 {
 	ipc_callid_t callid;
-	size_t size;
-	if (!async_data_write_receive(&callid, &size)) {
+	async_data_write_receive(&callid, NULL);
+	ipc_answer_0(callid, retval);
+}
+
+/** Wrapper for forwarding any data that is about to be received
+ *
+ *
+ */
+int async_data_write_forward_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
+    ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr)
+{
+	ipc_callid_t callid;
+	if (!async_data_write_receive(&callid, NULL)) {
 		ipc_answer_0(callid, EINVAL);
 		return EINVAL;
 	}
 	
-	if ((max_size > 0) && (size > max_size)) {
+	aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
+	    dataptr);
+	if (msg == 0) {
 		ipc_answer_0(callid, EINVAL);
 		return EINVAL;
 	}
 	
-	char *data = (char *) malloc(size + 1);
-	if (data == NULL) {
-		ipc_answer_0(callid, ENOMEM);
-		return ENOMEM;
-	}
-	
-	int rc = async_data_write_finalize(callid, data, size);
-	if (rc != EOK) {
-		free(data);
-		return rc;
-	}
-	
-	data[size] = 0;
-	*str = data;
-	return EOK;
+	int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
+	    IPC_FF_ROUTE_FROM_ME);
+	if (retval != EOK) {
+		async_wait_for(msg, NULL);
+		ipc_answer_0(callid, retval);
+		return retval;
+	}
+	
+	ipcarg_t rc;
+	async_wait_for(msg, &rc);
+	
+	return (int) rc;
 }
 
Index: uspace/lib/libc/generic/clipboard.c
===================================================================
--- uspace/lib/libc/generic/clipboard.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/lib/libc/generic/clipboard.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -84,5 +84,5 @@
 		clip_connect();
 		
-		aid_t req = async_send_1(clip_phone, CLIPBOARD_PUT_DATA, CLIPBOARD_TAG_BLOB, NULL);
+		aid_t req = async_send_1(clip_phone, CLIPBOARD_PUT_DATA, CLIPBOARD_TAG_DATA, NULL);
 		ipcarg_t rc = async_data_write_start(clip_phone, (void *) str, size);
 		if (rc != EOK) {
@@ -139,5 +139,5 @@
 			*str = sbuf;
 			return EOK;
-		case CLIPBOARD_TAG_BLOB:
+		case CLIPBOARD_TAG_DATA:
 			sbuf = malloc(size + 1);
 			if (sbuf == NULL)
Index: uspace/lib/libc/generic/vfs/vfs.c
===================================================================
--- uspace/lib/libc/generic/vfs/vfs.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/lib/libc/generic/vfs/vfs.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -120,25 +120,44 @@
     const char *opts, unsigned int flags)
 {
-	int res;
-	ipcarg_t rc;
-	ipcarg_t rc_orig;
-	aid_t req;
+	int null_id = -1;
+	char null[DEVMAP_NAME_MAXLEN];
+	
+	if (str_cmp(fqdn, "") == 0) {
+		/* No device specified, create a fresh
+		   null/%d device instead */
+		null_id = devmap_null_create();
+		
+		if (null_id == -1)
+			return ENOMEM;
+		
+		snprintf(null, DEVMAP_NAME_MAXLEN, "null/%d", null_id);
+		fqdn = null;
+	}
+	
 	dev_handle_t dev_handle;
-	
-	res = devmap_device_get_handle(fqdn, &dev_handle, flags);
-	if (res != EOK)
+	int res = devmap_device_get_handle(fqdn, &dev_handle, flags);
+	if (res != EOK) {
+		if (null_id != -1)
+			devmap_null_destroy(null_id);
+		
 		return res;
+	}
 	
 	size_t mpa_size;
 	char *mpa = absolutize(mp, &mpa_size);
-	if (!mpa)
-		return ENOMEM;
-	
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
-	
-	req = async_send_2(vfs_phone, VFS_IN_MOUNT, dev_handle, flags, NULL);
-	rc = async_data_write_start(vfs_phone, (void *) mpa, mpa_size);
+	if (!mpa) {
+		if (null_id != -1)
+			devmap_null_destroy(null_id);
+		
+		return ENOMEM;
+	}
+	
+	futex_down(&vfs_phone_futex);
+	async_serialize_start();
+	vfs_connect();
+	
+	ipcarg_t rc_orig;
+	aid_t req = async_send_2(vfs_phone, VFS_IN_MOUNT, dev_handle, flags, NULL);
+	ipcarg_t rc = async_data_write_start(vfs_phone, (void *) mpa, mpa_size);
 	if (rc != EOK) {
 		async_wait_for(req, &rc_orig);
@@ -146,4 +165,8 @@
 		futex_up(&vfs_phone_futex);
 		free(mpa);
+		
+		if (null_id != -1)
+			devmap_null_destroy(null_id);
+		
 		if (rc_orig == EOK)
 			return (int) rc;
@@ -158,10 +181,14 @@
 		futex_up(&vfs_phone_futex);
 		free(mpa);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-
+		
+		if (null_id != -1)
+			devmap_null_destroy(null_id);
+		
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	
 	rc = async_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
 	if (rc != EOK) {
@@ -170,10 +197,14 @@
 		futex_up(&vfs_phone_futex);
 		free(mpa);
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-
+		
+		if (null_id != -1)
+			devmap_null_destroy(null_id);
+		
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	
 	/* Ask VFS whether it likes fs_name. */
 	rc = async_req_0_0(vfs_phone, IPC_M_PING);
@@ -183,4 +214,8 @@
 		futex_up(&vfs_phone_futex);
 		free(mpa);
+		
+		if (null_id != -1)
+			devmap_null_destroy(null_id);
+		
 		if (rc_orig == EOK)
 			return (int) rc;
@@ -193,4 +228,7 @@
 	futex_up(&vfs_phone_futex);
 	free(mpa);
+	
+	if ((rc != EOK) && (null_id != -1))
+		devmap_null_destroy(null_id);
 	
 	return (int) rc;
Index: uspace/lib/libc/include/async.h
===================================================================
--- uspace/lib/libc/include/async.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/lib/libc/include/async.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -277,13 +277,82 @@
 extern int async_share_out_receive(ipc_callid_t *, size_t *, int *);
 extern int async_share_out_finalize(ipc_callid_t, void *);
+
+/*
+ * User-friendly wrappers for async_data_read_forward_fast().
+ */
+#define async_data_read_forward_0_0(phoneid, method, answer) \
+	async_data_read_forward_fast((phoneid), (method), 0, 0, 0, 0, NULL)
+#define async_data_read_forward_0_1(phoneid, method, answer) \
+	async_data_read_forward_fast((phoneid), (method), 0, 0, 0, 0, (answer))
+#define async_data_read_forward_1_0(phoneid, method, arg1, answer) \
+	async_data_read_forward_fast((phoneid), (method), (arg1), 0, 0, 0, NULL)
+#define async_data_read_forward_1_1(phoneid, method, arg1, answer) \
+	async_data_read_forward_fast((phoneid), (method), (arg1), 0, 0, 0, (answer))
+#define async_data_read_forward_2_0(phoneid, method, arg1, arg2, answer) \
+	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL)
+#define async_data_read_forward_2_1(phoneid, method, arg1, arg2, answer) \
+	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
+	    (answer))
+#define async_data_read_forward_3_0(phoneid, method, arg1, arg2, arg3, answer) \
+	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, \
+	    NULL)
+#define async_data_read_forward_3_1(phoneid, method, arg1, arg2, arg3, answer) \
+	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, \
+	    (answer))
+#define async_data_read_forward_4_0(phoneid, method, arg1, arg2, arg3, arg4, answer) \
+	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
+	    (arg4), NULL)
+#define async_data_read_forward_4_1(phoneid, method, arg1, arg2, arg3, arg4, answer) \
+	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
+	    (arg4), (answer))
+
 extern int async_data_read_start(int, void *, size_t);
 extern int async_data_read_receive(ipc_callid_t *, size_t *);
 extern int async_data_read_finalize(ipc_callid_t, const void *, size_t);
+
+extern int async_data_read_forward_fast(int, ipcarg_t, ipcarg_t, ipcarg_t,
+    ipcarg_t, ipcarg_t, ipc_call_t *);
+
+/*
+ * User-friendly wrappers for async_data_write_forward_fast().
+ */
+#define async_data_write_forward_0_0(phoneid, method, answer) \
+	async_data_write_forward_fast((phoneid), (method), 0, 0, 0, 0, NULL)
+#define async_data_write_forward_0_1(phoneid, method, answer) \
+	async_data_write_forward_fast((phoneid), (method), 0, 0, 0, 0, (answer))
+#define async_data_write_forward_1_0(phoneid, method, arg1, answer) \
+	async_data_write_forward_fast((phoneid), (method), (arg1), 0, 0, 0, NULL)
+#define async_data_write_forward_1_1(phoneid, method, arg1, answer) \
+	async_data_write_forward_fast((phoneid), (method), (arg1), 0, 0, 0, \
+	    (answer))
+#define async_data_write_forward_2_0(phoneid, method, arg1, arg2, answer) \
+	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
+	    NULL)
+#define async_data_write_forward_2_1(phoneid, method, arg1, arg2, answer) \
+	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
+	    (answer))
+#define async_data_write_forward_3_0(phoneid, method, arg1, arg2, arg3, answer) \
+	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
+	    0, NULL)
+#define async_data_write_forward_3_1(phoneid, method, arg1, arg2, arg3, answer) \
+	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
+	    0, (answer))
+#define async_data_write_forward_4_0(phoneid, method, arg1, arg2, arg3, arg4, answer) \
+	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
+	    (arg4), NULL)
+#define async_data_write_forward_4_1(phoneid, method, arg1, arg2, arg3, arg4, answer) \
+	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
+	    (arg4), (answer))
+
 extern int async_data_write_start(int, const void *, size_t);
 extern int async_data_write_receive(ipc_callid_t *, size_t *);
 extern int async_data_write_finalize(ipc_callid_t, void *, size_t);
 
-extern int async_data_blob_receive(char **, const size_t, size_t *);
-extern int async_data_string_receive(char **, const size_t);
+extern int async_data_write_accept(void **, const bool, const size_t,
+    const size_t, const size_t, size_t *);
+extern void async_data_write_void(const int);
+
+extern int async_data_write_forward_fast(int, ipcarg_t, ipcarg_t, ipcarg_t,
+    ipcarg_t, ipcarg_t, ipc_call_t *);
 
 #endif
Index: uspace/lib/libc/include/fibril.h
===================================================================
--- uspace/lib/libc/include/fibril.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/lib/libc/include/fibril.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -40,13 +40,11 @@
 #include <libarch/tls.h>
 
-#ifndef context_set
-#define context_set(c, _pc, stack, size, ptls) \
+#define context_set_generic(c, _pc, stack, size, ptls) \
 	(c)->pc = (sysarg_t) (_pc); \
 	(c)->sp = ((sysarg_t) (stack)) + (size) - SP_DELTA; \
 	(c)->tls = (sysarg_t) (ptls);
-#endif /* context_set */
 
-#define FIBRIL_SERIALIZED	1
-#define FIBRIL_WRITER 		2
+#define FIBRIL_SERIALIZED  1
+#define FIBRIL_WRITER      2
 
 typedef enum {
@@ -59,5 +57,5 @@
 typedef sysarg_t fid_t;
 
-struct fibril {
+typedef struct fibril {
 	link_t link;
 	context_t ctx;
@@ -70,12 +68,11 @@
 	int retval;
 	int flags;
-};
-typedef struct fibril fibril_t;
+} fibril_t;
 
 /** Fibril-local variable specifier */
 #define fibril_local __thread
 
-extern int context_save(context_t *c) __attribute__ ((returns_twice));
-extern void context_restore(context_t *c) __attribute__ ((noreturn));
+extern int context_save(context_t *ctx) __attribute__((returns_twice));
+extern void context_restore(context_t *ctx) __attribute__((noreturn));
 
 extern fid_t fibril_create(int (*func)(void *), void *arg);
@@ -90,5 +87,6 @@
 extern void fibril_dec_sercount(void);
 
-static inline int fibril_yield(void) {
+static inline int fibril_yield(void)
+{
 	return fibril_switch(FIBRIL_PREEMPT);
 }
Index: uspace/lib/libc/include/ipc/clipboard.h
===================================================================
--- uspace/lib/libc/include/ipc/clipboard.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/lib/libc/include/ipc/clipboard.h	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -46,5 +46,5 @@
 typedef enum {
 	CLIPBOARD_TAG_NONE,
-	CLIPBOARD_TAG_BLOB
+	CLIPBOARD_TAG_DATA
 } clipboard_tag_t;
 
Index: uspace/lib/libfs/libfs.c
===================================================================
--- uspace/lib/libfs/libfs.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/lib/libfs/libfs.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -161,5 +161,5 @@
 	/* Accept the phone */
 	callid = async_get_call(&call);
-	int mountee_phone = (int)IPC_GET_ARG1(call);
+	int mountee_phone = (int) IPC_GET_ARG1(call);
 	if ((IPC_GET_METHOD(call) != IPC_M_CONNECTION_CLONE) ||
 	    (mountee_phone < 0)) {
@@ -172,17 +172,9 @@
 	ipc_answer_0(callid, EOK);
 	
-	res = async_data_write_receive(&callid, NULL);
-	if (!res) {
-		ipc_hangup(mountee_phone);
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	
 	fs_node_t *fn;
 	res = ops->node_get(&fn, mp_dev_handle, mp_fs_index);
 	if ((res != EOK) || (!fn)) {
 		ipc_hangup(mountee_phone);
-		ipc_answer_0(callid, combine_rc(res, ENOENT));
+		async_data_write_void(combine_rc(res, ENOENT));
 		ipc_answer_0(rid, combine_rc(res, ENOENT));
 		return;
@@ -192,5 +184,5 @@
 		ipc_hangup(mountee_phone);
 		(void) ops->node_put(fn);
-		ipc_answer_0(callid, EBUSY);
+		async_data_write_void(EBUSY);
 		ipc_answer_0(rid, EBUSY);
 		return;
@@ -201,5 +193,5 @@
 		ipc_hangup(mountee_phone);
 		(void) ops->node_put(fn);
-		ipc_answer_0(callid, rc);
+		async_data_write_void(rc);
 		ipc_answer_0(rid, rc);
 		return;
@@ -207,8 +199,6 @@
 	
 	ipc_call_t answer;
-	aid_t msg = async_send_1(mountee_phone, VFS_OUT_MOUNTED, mr_dev_handle,
-	    &answer);
-	ipc_forward_fast(callid, mountee_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
-	async_wait_for(msg, &rc);
+	rc = async_data_write_forward_1_1(mountee_phone, VFS_OUT_MOUNTED,
+	    mr_dev_handle, &answer);
 	
 	if (rc == EOK) {
Index: pace/lib/libpci/Makefile.build
===================================================================
--- uspace/lib/libpci/Makefile.build	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ 	(revision )
@@ -1,64 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-## Setup toolchain
-#
-
-include Makefile.common
-include $(LIBC_PREFIX)/Makefile.toolchain
-
-## Sources
-#
-
-SOURCES = \
-	access.c \
-	generic.c \
-	names.c \
-	i386-ports.c
-
-OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
-
-.PHONY: all
-
-all: $(LIBPCI)
-
--include $(DEPEND)
-
-$(LIBPCI): $(OBJECTS)
-	$(AR) rc $@ $(OBJECTS)
-
-%.o: %.c $(DEPEND)
-	$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
-ifeq ($(PRECHECK),y)
-	$(JOBFILE) $(JOB) $< $@ cc core $(DEFS) $(CFLAGS)
-endif
-
-$(DEPEND):
-	makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(SOURCES) > $@ 2> /dev/null
-	-[ -f $(DEPEND_PREV) ] && diff -q $(DEPEND_PREV) $@ && mv -f $(DEPEND_PREV) $@
Index: pace/lib/libpci/Makefile.common
===================================================================
--- uspace/lib/libpci/Makefile.common	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-
-## Common names
-#
-
-LIBC_PREFIX = ../../../../../lib/libc
-DEPEND = Makefile.depend
-DEPEND_PREV = $(DEPEND).prev
-JOB = libpci.job
-LIBPCI = libpci.a
Index: uspace/srv/clip/clip.c
===================================================================
--- uspace/srv/clip/clip.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/srv/clip/clip.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -64,6 +64,6 @@
 		ipc_answer_0(rid, EOK);
 		break;
-	case CLIPBOARD_TAG_BLOB:
-		rc = async_data_blob_receive(&data, 0, &size);
+	case CLIPBOARD_TAG_DATA:
+		rc = async_data_write_accept((void **) &data, false, 0, 0, 0, &size);
 		if (rc != EOK) {
 			ipc_answer_0(rid, rc);
@@ -78,5 +78,5 @@
 		clip_data = data;
 		clip_size = size;
-		clip_tag = CLIPBOARD_TAG_BLOB;
+		clip_tag = CLIPBOARD_TAG_DATA;
 		
 		fibril_mutex_unlock(&clip_mtx);
@@ -97,5 +97,5 @@
 	/* Check for clipboard data tag compatibility */
 	switch (IPC_GET_ARG1(*request)) {
-	case CLIPBOARD_TAG_BLOB:
+	case CLIPBOARD_TAG_DATA:
 		if (!async_data_read_receive(&callid, &size)) {
 			ipc_answer_0(callid, EINVAL);
@@ -104,6 +104,6 @@
 		}
 		
-		if (clip_tag != CLIPBOARD_TAG_BLOB) {
-			/* So far we only understand BLOB */
+		if (clip_tag != CLIPBOARD_TAG_DATA) {
+			/* So far we only understand binary data */
 			ipc_answer_0(callid, EOVERFLOW);
 			ipc_answer_0(rid, EOVERFLOW);
Index: uspace/srv/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/srv/devmap/devmap.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -396,5 +396,6 @@
 	 * Get driver name
 	 */
-	int rc = async_data_string_receive(&driver->name, DEVMAP_NAME_MAXLEN);
+	int rc = async_data_write_accept((void **) &driver->name, true, 0,
+	    DEVMAP_NAME_MAXLEN, 0, NULL);
 	if (rc != EOK) {
 		free(driver);
@@ -510,5 +511,6 @@
 	/* Get fqdn */
 	char *fqdn;
-	int rc = async_data_string_receive(&fqdn, DEVMAP_NAME_MAXLEN);
+	int rc = async_data_write_accept((void **) &fqdn, true, 0,
+	    DEVMAP_NAME_MAXLEN, 0, NULL);
 	if (rc != EOK) {
 		free(device);
@@ -622,5 +624,6 @@
 	
 	/* Get fqdn */
-	int rc = async_data_string_receive(&fqdn, DEVMAP_NAME_MAXLEN);
+	int rc = async_data_write_accept((void **) &fqdn, true, 0,
+	    DEVMAP_NAME_MAXLEN, 0, NULL);
 	if (rc != EOK) {
 		ipc_answer_0(iid, rc);
@@ -683,5 +686,6 @@
 	
 	/* Get device name */
-	int rc = async_data_string_receive(&name, DEVMAP_NAME_MAXLEN);
+	int rc = async_data_write_accept((void **) &name, true, 0,
+	    DEVMAP_NAME_MAXLEN, 0, NULL);
 	if (rc != EOK) {
 		ipc_answer_0(iid, rc);
Index: uspace/srv/fs/devfs/devfs_ops.c
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/srv/fs/devfs/devfs_ops.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -419,5 +419,6 @@
 	
 	/* Accept the mount options */
-	ipcarg_t retval = async_data_string_receive(&opts, 0);
+	ipcarg_t retval = async_data_write_accept((void **) &opts, true, 0, 0,
+	    0, NULL);
 	if (retval != EOK) {
 		ipc_answer_0(rid, retval);
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/srv/fs/fat/fat_ops.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -974,27 +974,13 @@
 	uint16_t bps;
 	uint16_t rde;
-	int rc;
-
-	/* accept the mount options */
-	ipc_callid_t callid;
-	size_t size;
-	if (!async_data_write_receive(&callid, &size)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	char *opts = malloc(size + 1);
-	if (!opts) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	ipcarg_t retval = async_data_write_finalize(callid, opts, size);
-	if (retval != EOK) {
-		ipc_answer_0(rid, retval);
-		free(opts);
-		return;
-	}
-	opts[size] = '\0';
+	
+	/* Accept the mount options */
+	char *opts;
+	int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
+	
+	if (rc != EOK) {
+		ipc_answer_0(rid, rc);
+		return;
+	}
 
 	/* Check for option enabling write through. */
Index: uspace/srv/fs/tmpfs/tmpfs_ops.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -443,30 +443,14 @@
 	fs_node_t *rootfn;
 	int rc;
-
-	/* accept the mount options */
-	ipc_callid_t callid;
-	size_t size;
-	if (!async_data_write_receive(&callid, &size)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	char *opts = malloc(size + 1);
-	if (!opts) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	ipcarg_t retval = async_data_write_finalize(callid, opts, size);
-	if (retval != EOK) {
-		ipc_answer_0(rid, retval);
-		free(opts);
-		return;
-	}
-	opts[size] = '\0';
-
-	/*
-	 * Check if this device is not already mounted.
-	 */
+	
+	/* Accept the mount options. */
+	char *opts;
+	rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
+	if (rc != EOK) {
+		ipc_answer_0(rid, rc);
+		return;
+	}
+
+	/* Check if this device is not already mounted. */
 	rc = tmpfs_root_get(&rootfn, dev_handle);
 	if ((rc == EOK) && (rootfn)) {
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/srv/hid/console/console.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -475,20 +475,12 @@
 static void cons_write(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
 {
-	ipc_callid_t callid;
+	void *buf;
 	size_t size;
-	if (!async_data_write_receive(&callid, &size)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
+	int rc = async_data_write_accept(&buf, false, 0, 0, 0, &size);
+	
+	if (rc != EOK) {
+		ipc_answer_0(rid, rc);
 		return;
 	}
-	
-	char *buf = (char *) malloc(size);
-	if (buf == NULL) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	
-	(void) async_data_write_finalize(callid, buf, size);
 	
 	async_serialize_start();
Index: pace/srv/hid/kbd/port/i8042.h
===================================================================
--- uspace/srv/hid/kbd/port/i8042.h	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ 	(revision )
@@ -1,55 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */
-
-/** @file
- * @brief i8042 port driver.
- */
-
-#ifndef KBD_PORT_i8042_H_
-#define KBD_PORT_i8042_H_
-
-#include <libarch/ddi.h>
-#include <libarch/types.h>
-
-struct i8042 {
-	ioport8_t data;
-	uint8_t pad[3];
-	ioport8_t status;
-} __attribute__ ((packed));
-typedef struct i8042 i8042_t;
-
-#endif
-
-/**
- * @}
- */ 
Index: uspace/srv/loader/main.c
===================================================================
--- uspace/srv/loader/main.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/srv/loader/main.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -125,24 +125,15 @@
 static void ldr_set_cwd(ipc_callid_t rid, ipc_call_t *request)
 {
-	ipc_callid_t callid;
-	size_t len;
-	
-	if (!async_data_write_receive(&callid, &len)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	
-	cwd = malloc(len + 1);
-	if (!cwd) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	
-	async_data_write_finalize(callid, cwd, len);
-	cwd[len] = '\0';
-	
-	ipc_answer_0(rid, EOK);
+	char *buf;
+	int rc = async_data_write_accept((void **) &buf, true, 0, 0, 0, NULL);
+	
+	if (rc == EOK) {
+		if (cwd != NULL)
+			free(cwd);
+		
+		cwd = buf;
+	}
+	
+	ipc_answer_0(rid, rc);
 }
 
@@ -154,31 +145,15 @@
 static void ldr_set_pathname(ipc_callid_t rid, ipc_call_t *request)
 {
-	ipc_callid_t callid;
-	size_t len;
-	char *name_buf;
-	
-	if (!async_data_write_receive(&callid, &len)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	
-	name_buf = malloc(len + 1);
-	if (!name_buf) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	
-	async_data_write_finalize(callid, name_buf, len);
-	ipc_answer_0(rid, EOK);
-	
-	if (pathname != NULL) {
-		free(pathname);
-		pathname = NULL;
-	}
-	
-	name_buf[len] = '\0';
-	pathname = name_buf;
+	char *buf;
+	int rc = async_data_write_accept((void **) &buf, true, 0, 0, 0, NULL);
+	
+	if (rc == EOK) {
+		if (pathname != NULL)
+			free(pathname);
+		
+		pathname = buf;
+	}
+	
+	ipc_answer_0(rid, rc);
 }
 
@@ -190,73 +165,60 @@
 static void ldr_set_args(ipc_callid_t rid, ipc_call_t *request)
 {
-	ipc_callid_t callid;
-	size_t buf_size, arg_size;
-	char *p;
-	int n;
-	
-	if (!async_data_write_receive(&callid, &buf_size)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	
-	if (arg_buf != NULL) {
-		free(arg_buf);
-		arg_buf = NULL;
-	}
-	
-	if (argv != NULL) {
-		free(argv);
-		argv = NULL;
-	}
-	
-	arg_buf = malloc(buf_size + 1);
-	if (!arg_buf) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	
-	async_data_write_finalize(callid, arg_buf, buf_size);
-	
-	arg_buf[buf_size] = '\0';
-	
-	/*
-	 * Count number of arguments
-	 */
-	p = arg_buf;
-	n = 0;
-	while (p < arg_buf + buf_size) {
-		arg_size = str_size(p);
-		p = p + arg_size + 1;
-		++n;
-	}
-	
-	/* Allocate argv */
-	argv = malloc((n + 1) * sizeof(char *));
-	
-	if (argv == NULL) {
-		free(arg_buf);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-
-	/*
-	 * Fill argv with argument pointers
-	 */
-	p = arg_buf;
-	n = 0;
-	while (p < arg_buf + buf_size) {
-		argv[n] = p;
-		
-		arg_size = str_size(p);
-		p = p + arg_size + 1;
-		++n;
-	}
-	
-	argc = n;
-	argv[n] = NULL;
-
-	ipc_answer_0(rid, EOK);
+	char *buf;
+	size_t buf_size;
+	int rc = async_data_write_accept((void **) &buf, true, 0, 0, 0, &buf_size);
+	
+	if (rc == EOK) {
+		/*
+		 * Count number of arguments
+		 */
+		char *cur = buf;
+		int count = 0;
+		
+		while (cur < buf + buf_size) {
+			size_t arg_size = str_size(cur);
+			cur += arg_size + 1;
+			count++;
+		}
+		
+		/*
+		 * Allocate new argv
+		 */
+		char **_argv = (char **) malloc((count + 1) * sizeof(char *));
+		if (_argv == NULL) {
+			free(buf);
+			ipc_answer_0(rid, ENOMEM);
+			return;
+		}
+		
+		/*
+		 * Fill the new argv with argument pointers
+		 */
+		cur = buf;
+		count = 0;
+		while (cur < buf + buf_size) {
+			_argv[count] = cur;
+			
+			size_t arg_size = str_size(cur);
+			cur += arg_size + 1;
+			count++;
+		}
+		_argv[count] = NULL;
+		
+		/*
+		 * Copy temporary data to global variables
+		 */
+		if (arg_buf != NULL)
+			free(arg_buf);
+		
+		if (argv != NULL)
+			free(argv);
+		
+		argc = count;
+		arg_buf = buf;
+		argv = _argv;
+	}
+	
+	ipc_answer_0(rid, rc);
 }
 
@@ -268,57 +230,44 @@
 static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request)
 {
-	ipc_callid_t callid;
+	fdi_node_t *buf;
 	size_t buf_size;
-	if (!async_data_write_receive(&callid, &buf_size)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	
-	if ((buf_size % sizeof(fdi_node_t)) != 0) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	
-	if (fil_buf != NULL) {
-		free(fil_buf);
-		fil_buf = NULL;
-	}
-	
-	if (filv != NULL) {
-		free(filv);
-		filv = NULL;
-	}
-	
-	fil_buf = malloc(buf_size);
-	if (!fil_buf) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	
-	async_data_write_finalize(callid, fil_buf, buf_size);
-	
-	int count = buf_size / sizeof(fdi_node_t);
-	
-	/* Allocate filvv */
-	filv = malloc((count + 1) * sizeof(fdi_node_t *));
-	
-	if (filv == NULL) {
-		free(fil_buf);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	
-	/*
-	 * Fill filv with argument pointers
-	 */
-	int i;
-	for (i = 0; i < count; i++)
-		filv[i] = &fil_buf[i];
-	
-	filc = count;
-	filv[count] = NULL;
+	int rc = async_data_write_accept((void **) &buf, false, 0, 0,
+	    sizeof(fdi_node_t), &buf_size);
+	
+	if (rc == EOK) {
+		int count = buf_size / sizeof(fdi_node_t);
+		
+		/*
+		 * Allocate new filv
+		 */
+		fdi_node_t **_filv = (fdi_node_t *) malloc((count + 1) * sizeof(fdi_node_t *));
+		if (_filv == NULL) {
+			free(buf);
+			ipc_answer_0(rid, ENOMEM);
+			return;
+		}
+		
+		/*
+		 * Fill the new filv with argument pointers
+		 */
+		int i;
+		for (i = 0; i < count; i++)
+			_filv[i] = &buf[i];
+		
+		_filv[count] = NULL;
+		
+		/*
+		 * Copy temporary data to global variables
+		 */
+		if (fil_buf != NULL)
+			free(fil_buf);
+		
+		if (filv != NULL)
+			free(filv);
+		
+		filc = count;
+		fil_buf = buf;
+		filv = _filv;
+	}
 	
 	ipc_answer_0(rid, EOK);
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/srv/vfs/vfs_ops.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -266,118 +266,36 @@
 	
 	/* We want the client to send us the mount point. */
-	ipc_callid_t callid;
-	size_t size;
-	if (!async_data_write_receive(&callid, &size)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	
-	/* Check whether size is reasonable wrt. the mount point. */
-	if ((size < 1) || (size > MAX_PATH_LEN)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	
-	/* Allocate buffer for the mount point data being received. */
-	char *mp = malloc(size + 1);
-	if (!mp) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	
-	/* Deliver the mount point. */
-	ipcarg_t retval = async_data_write_finalize(callid, mp, size);
-	if (retval != EOK) {
-		ipc_answer_0(rid, retval);
+	char *mp;
+	int rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
+	    0, NULL);
+	if (rc != EOK) {
+		ipc_answer_0(rid, rc);
+		return;
+	}
+	
+	/* Now we expect to receive the mount options. */
+	char *opts;
+	rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN,
+	    0, NULL);
+	if (rc != EOK) {
 		free(mp);
-		return;
-	}
-	mp[size] = '\0';
-	
-	/* Now we expect to receive the mount options. */
-	if (!async_data_write_receive(&callid, &size)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		free(mp);
-		return;
-	}
-
-	/* Check the offered options size. */
-	if (size > MAX_MNTOPTS_LEN) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		free(mp);
-		return;
-	}
-
-	/* Allocate buffer for the mount options. */
-	char *opts = (char *) malloc(size + 1);
-	if (!opts) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		free(mp);
-		return;
-	}
-
-	/* Deliver the mount options. */
-	retval = async_data_write_finalize(callid, opts, size);
-	if (retval != EOK) {
-		ipc_answer_0(rid, retval);
+		ipc_answer_0(rid, rc);
+		return;
+	}
+	
+	/*
+	 * Now, we expect the client to send us data with the name of the file
+	 * system.
+	 */
+	char *fs_name;
+	rc = async_data_write_accept((void **) &fs_name, true, 0, FS_NAME_MAXLEN,
+	    0, NULL);
+	if (rc != EOK) {
 		free(mp);
 		free(opts);
-		return;
-	}
-	opts[size] = '\0';
-	
-	/*
-	 * Now, we expect the client to send us data with the name of the file
-	 * system.
-	 */
-	if (!async_data_write_receive(&callid, &size)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		free(mp);
-		free(opts);
-		return;
-	}
-	
-	/*
-	 * Don't receive more than is necessary for storing a full file system
-	 * name.
-	 */
-	if ((size < 1) || (size > FS_NAME_MAXLEN)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		free(mp);
-		free(opts);
-		return;
-	}
-	
-	/*
-	 * Allocate buffer for file system name.
-	 */
-	char *fs_name = (char *) malloc(size + 1);
-	if (fs_name == NULL) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		free(mp);
-		free(opts);
-		return;
-	}
-	
-	/* Deliver the file system name. */
-	retval = async_data_write_finalize(callid, fs_name, size);
-	if (retval != EOK) {
-		ipc_answer_0(rid, retval);
-		free(mp);
-		free(opts);
-		free(fs_name);
-		return;
-	}
-	fs_name[size] = '\0';
-
+		ipc_answer_0(rid, rc);
+		return;
+	}
+	
 	/*
 	 * Wait for IPC_M_PING so that we can return an error if we don't know
@@ -385,5 +303,5 @@
 	 */
 	ipc_call_t data;
-	callid = async_get_call(&data);
+	ipc_callid_t callid = async_get_call(&data);
 	if (IPC_GET_METHOD(data) != IPC_M_PING) {
 		ipc_answer_0(callid, ENOTSUP);
@@ -442,5 +360,6 @@
 	 * Receive the mount point path.
 	 */
-	rc = async_data_string_receive(&mp, MAX_PATH_LEN);
+	rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
+	    0, NULL);
 	if (rc != EOK)
 		ipc_answer_0(rid, rc);
@@ -606,25 +525,10 @@
 		lflag |= L_EXCLUSIVE;
 	
-	ipc_callid_t callid;
-	if (!async_data_write_receive(&callid, &len)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	
-	char *path = malloc(len + 1);
-	if (!path) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	
-	int rc;
-	if ((rc = async_data_write_finalize(callid, path, len))) {
-		ipc_answer_0(rid, rc);
-		free(path);
-		return;
-	}
-	path[len] = '\0';
+	char *path;
+	int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
+	if (rc != EOK) {
+		ipc_answer_0(rid, rc);
+		return;
+	}
 	
 	/*
@@ -894,20 +798,4 @@
 	
 	/*
-	 * Now we need to receive a call with client's
-	 * IPC_M_DATA_READ/IPC_M_DATA_WRITE request.
-	 */
-	ipc_callid_t callid;
-	int res;
-	if (read)
-		res = async_data_read_receive(&callid, NULL);
-	else 
-		res = async_data_write_receive(&callid, NULL);
-	if (!res) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	
-	/*
 	 * Lock the open file structure so that no other thread can manipulate
 	 * the same open file at a time.
@@ -933,30 +821,32 @@
 	}
 	
-	int fs_phone = vfs_grab_phone(file->node->fs_handle);	
-	
-	/* Make a VFS_READ/VFS_WRITE request at the destination FS server. */
-	aid_t msg;
-	ipc_call_t answer;
-	if (!read && file->append)
-		file->pos = file->node->size;
-	msg = async_send_3(fs_phone, read ? VFS_OUT_READ : VFS_OUT_WRITE,
-	    file->node->dev_handle, file->node->index, file->pos, &answer);
-	
-	/*
-	 * Forward the IPC_M_DATA_READ/IPC_M_DATA_WRITE request to the
+	int fs_phone = vfs_grab_phone(file->node->fs_handle);
+	
+	/*
+	 * Make a VFS_READ/VFS_WRITE request at the destination FS server
+	 * and forward the IPC_M_DATA_READ/IPC_M_DATA_WRITE request to the
 	 * destination FS server. The call will be routed as if sent by
 	 * ourselves. Note that call arguments are immutable in this case so we
 	 * don't have to bother.
 	 */
-	ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
-
-	/* Wait for reply from the FS server. */
 	ipcarg_t rc;
-	async_wait_for(msg, &rc);
+	ipc_call_t answer;
+	if (read) {
+		if (file->append)
+			file->pos = file->node->size;
+		
+		rc = async_data_read_forward_3_1(fs_phone, VFS_OUT_READ,
+		    file->node->dev_handle, file->node->index, file->pos,
+		    &answer);
+	} else {
+		rc = async_data_write_forward_3_1(fs_phone, VFS_OUT_WRITE,
+		    file->node->dev_handle, file->node->index, file->pos,
+		    &answer);
+	}
 	
 	vfs_release_phone(fs_phone);
 	
 	size_t bytes = IPC_GET_ARG1(answer);
-
+	
 	if (file->node->type == VFS_NODE_DIRECTORY)
 		fibril_rwlock_read_unlock(&namespace_rwlock);
@@ -1120,26 +1010,12 @@
 void vfs_stat(ipc_callid_t rid, ipc_call_t *request)
 {
-	size_t len;
+	char *path;
+	int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
+	if (rc != EOK) {
+		ipc_answer_0(rid, rc);
+		return;
+	}
+	
 	ipc_callid_t callid;
-
-	if (!async_data_write_receive(&callid, &len)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	char *path = malloc(len + 1);
-	if (!path) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	int rc;
-	if ((rc = async_data_write_finalize(callid, path, len))) {
-		ipc_answer_0(rid, rc);
-		free(path);
-		return;
-	}
-	path[len] = '\0';
-
 	if (!async_data_read_receive(&callid, NULL)) {
 		free(path);
@@ -1187,27 +1063,12 @@
 {
 	int mode = IPC_GET_ARG1(*request);
-
-	size_t len;
-	ipc_callid_t callid;
-
-	if (!async_data_write_receive(&callid, &len)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	char *path = malloc(len + 1);
-	if (!path) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	int rc;
-	if ((rc = async_data_write_finalize(callid, path, len))) {
-		ipc_answer_0(rid, rc);
-		free(path);
-		return;
-	}
-	path[len] = '\0';
-
+	
+	char *path;
+	int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
+	if (rc != EOK) {
+		ipc_answer_0(rid, rc);
+		return;
+	}
+	
 	/* Ignore mode for now. */
 	(void) mode;
@@ -1224,26 +1085,11 @@
 {
 	int lflag = IPC_GET_ARG1(*request);
-
-	size_t len;
-	ipc_callid_t callid;
-
-	if (!async_data_write_receive(&callid, &len)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	char *path = malloc(len + 1);
-	if (!path) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	int rc;
-	if ((rc = async_data_write_finalize(callid, path, len))) {
-		ipc_answer_0(rid, rc);
-		free(path);
-		return;
-	}
-	path[len] = '\0';
+	
+	char *path;
+	int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
+	if (rc != EOK) {
+		ipc_answer_0(rid, rc);
+		return;
+	}
 	
 	fibril_rwlock_write_lock(&namespace_rwlock);
@@ -1274,52 +1120,27 @@
 void vfs_rename(ipc_callid_t rid, ipc_call_t *request)
 {
-	size_t olen, nlen;
-	ipc_callid_t callid;
-	int rc;
-
 	/* Retrieve the old path. */
-	if (!async_data_write_receive(&callid, &olen)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	char *old = malloc(olen + 1);
-	if (!old) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	if ((rc = async_data_write_finalize(callid, old, olen))) {
-		ipc_answer_0(rid, rc);
+	char *old;
+	int rc = async_data_write_accept((void **) &old, true, 0, 0, 0, NULL);
+	if (rc != EOK) {
+		ipc_answer_0(rid, rc);
+		return;
+	}
+	
+	/* Retrieve the new path. */
+	char *new;
+	rc = async_data_write_accept((void **) &new, true, 0, 0, 0, NULL);
+	if (rc != EOK) {
 		free(old);
-		return;
-	}
-	old[olen] = '\0';
-	
-	/* Retrieve the new path. */
-	if (!async_data_write_receive(&callid, &nlen)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		free(old);
-		return;
-	}
-	char *new = malloc(nlen + 1);
-	if (!new) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		free(old);
-		return;
-	}
-	if ((rc = async_data_write_finalize(callid, new, nlen))) {
-		ipc_answer_0(rid, rc);
-		free(old);
-		free(new);
-		return;
-	}
-	new[nlen] = '\0';
-
+		ipc_answer_0(rid, rc);
+		return;
+	}
+	
+	size_t olen;
+	size_t nlen;
 	char *oldc = canonify(old, &olen);
 	char *newc = canonify(new, &nlen);
-	if (!oldc || !newc) {
+	
+	if ((!oldc) || (!newc)) {
 		ipc_answer_0(rid, EINVAL);
 		free(old);
@@ -1327,6 +1148,8 @@
 		return;
 	}
+	
 	oldc[olen] = '\0';
 	newc[nlen] = '\0';
+	
 	if ((!str_lcmp(newc, oldc, str_length(oldc))) &&
 	    ((newc[str_length(oldc)] == '/') ||
@@ -1349,4 +1172,5 @@
 	vfs_lookup_res_t new_par_lr;
 	fibril_rwlock_write_lock(&namespace_rwlock);
+	
 	/* Lookup the node belonging to the old file name. */
 	rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL);
@@ -1358,4 +1182,5 @@
 		return;
 	}
+	
 	vfs_node_t *old_node = vfs_node_get(&old_lr);
 	if (!old_node) {
@@ -1366,4 +1191,5 @@
 		return;
 	}
+	
 	/* Determine the path to the parent of the node with the new name. */
 	char *parentc = str_dup(newc);
@@ -1375,4 +1201,5 @@
 		return;
 	}
+	
 	char *lastsl = str_rchr(parentc + 1, '/');
 	if (lastsl)
@@ -1380,4 +1207,5 @@
 	else
 		parentc[1] = '\0';
+	
 	/* Lookup parent of the new file name. */
 	rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL);
@@ -1390,4 +1218,5 @@
 		return;
 	}
+	
 	/* Check whether linking to the same file system instance. */
 	if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
@@ -1399,7 +1228,9 @@
 		return;
 	}
+	
 	/* Destroy the old link for the new name. */
 	vfs_node_t *new_node = NULL;
 	rc = vfs_lookup_internal(newc, L_UNLINK, &new_lr, NULL);
+	
 	switch (rc) {
 	case ENOENT:
@@ -1426,4 +1257,5 @@
 		return;
 	}
+	
 	/* Create the new link for the new name. */
 	rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index);
@@ -1437,7 +1269,9 @@
 		return;
 	}
+	
 	fibril_mutex_lock(&nodes_mutex);
 	old_node->lnkcnt++;
 	fibril_mutex_unlock(&nodes_mutex);
+	
 	/* Destroy the link for the old name. */
 	rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL);
@@ -1452,4 +1286,5 @@
 		return;
 	}
+	
 	fibril_mutex_lock(&nodes_mutex);
 	old_node->lnkcnt--;
@@ -1457,6 +1292,8 @@
 	fibril_rwlock_write_unlock(&namespace_rwlock);
 	vfs_node_put(old_node);
+	
 	if (new_node)
 		vfs_node_put(new_node);
+	
 	free(old);
 	free(new);
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision 3f93cdbe3a5df29d2432f1019f5de8b577780b68)
+++ uspace/srv/vfs/vfs_register.c	(revision 25e963a4ef2317193f84850c7106d029ba6f8086)
@@ -110,78 +110,43 @@
 void vfs_register(ipc_callid_t rid, ipc_call_t *request)
 {
-	ipc_callid_t callid;
-	ipc_call_t call;
-	int rc;
-	size_t size;
-
 	dprintf("Processing VFS_REGISTER request received from %p.\n",
 	    request->in_phone_hash);
-
-	/*
-	 * The first call has to be IPC_M_DATA_SEND in which we receive the
-	 * VFS info structure from the client FS.
-	 */
-	if (!async_data_write_receive(&callid, &size)) {
-		/*
-		 * The client doesn't obey the same protocol as we do.
-		 */
-		dprintf("Receiving of VFS info failed.\n");
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-	
-	dprintf("VFS info received, size = %d\n", size);
-	
-	/*
-	 * We know the size of the VFS info structure. See if the client
-	 * understands this easy concept too.
-	 */
-	if (size != sizeof(vfs_info_t)) {
-		/*
-		 * The client is sending us something, which cannot be
-		 * the info structure.
-		 */
-		dprintf("Received VFS info has bad size.\n");
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(rid, EINVAL);
-		return;
-	}
-
-	/*
-	 * Allocate and initialize a buffer for the fs_info structure.
-	 */
-	fs_info_t *fs_info;
-	fs_info = (fs_info_t *) malloc(sizeof(fs_info_t));
-	if (!fs_info) {
-		dprintf("Could not allocate memory for FS info.\n");
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	link_initialize(&fs_info->fs_link);
-	fibril_mutex_initialize(&fs_info->phone_lock);
-		
-	rc = async_data_write_finalize(callid, &fs_info->vfs_info, size);
+	
+	vfs_info_t *vfs_info;
+	int rc = async_data_write_accept((void **) &vfs_info, false,
+	    sizeof(vfs_info_t), sizeof(vfs_info_t), 0, NULL);
+	
 	if (rc != EOK) {
 		dprintf("Failed to deliver the VFS info into our AS, rc=%d.\n",
 		    rc);
-		free(fs_info);
-		ipc_answer_0(callid, rc);
 		ipc_answer_0(rid, rc);
 		return;
 	}
-
+	
+	/*
+	 * Allocate and initialize a buffer for the fs_info structure.
+	 */
+	fs_info_t *fs_info = (fs_info_t *) malloc(sizeof(fs_info_t));
+	if (!fs_info) {
+		dprintf("Could not allocate memory for FS info.\n");
+		ipc_answer_0(rid, ENOMEM);
+		return;
+	}
+	
+	link_initialize(&fs_info->fs_link);
+	fibril_mutex_initialize(&fs_info->phone_lock);
+	fs_info->vfs_info = *vfs_info;
+	free(vfs_info);
+	
 	dprintf("VFS info delivered.\n");
-		
+	
 	if (!vfs_info_sane(&fs_info->vfs_info)) {
 		free(fs_info);
-		ipc_answer_0(callid, EINVAL);
 		ipc_answer_0(rid, EINVAL);
 		return;
 	}
-		
+	
 	fibril_mutex_lock(&fs_head_lock);
-
+	
 	/*
 	 * Check for duplicit registrations.
@@ -194,9 +159,8 @@
 		fibril_mutex_unlock(&fs_head_lock);
 		free(fs_info);
-		ipc_answer_0(callid, EEXISTS);
 		ipc_answer_0(rid, EEXISTS);
 		return;
 	}
-
+	
 	/*
 	 * Add fs_info to the list of registered FS's.
@@ -210,5 +174,6 @@
 	 * which to forward VFS requests to it.
 	 */
-	callid = async_get_call(&call);
+	ipc_call_t call;
+	ipc_callid_t callid = async_get_call(&call);
 	if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
 		dprintf("Unexpected call, method = %d\n", IPC_GET_METHOD(call));
@@ -222,11 +187,12 @@
 	fs_info->phone = IPC_GET_ARG5(call);
 	ipc_answer_0(callid, EOK);
-
+	
 	dprintf("Callback connection to FS created.\n");
-
+	
 	/*
 	 * The client will want us to send him the address space area with PLB.
 	 */
-
+	
+	size_t size;
 	if (!async_share_in_receive(&callid, &size)) {
 		dprintf("Unexpected call, method = %d\n", IPC_GET_METHOD(call));
@@ -253,5 +219,5 @@
 		return;
 	}
-
+	
 	/*
 	 * Commit to read-only sharing the PLB with the client.
@@ -259,7 +225,7 @@
 	(void) async_share_in_finalize(callid, plb,
 	    AS_AREA_READ | AS_AREA_CACHEABLE);
-
+	
 	dprintf("Sharing PLB.\n");
-
+	
 	/*
 	 * That was it. The FS has been registered.
