Index: uspace/app/bdsh/cmds/modules/mkfile/mkfile.c
===================================================================
--- uspace/app/bdsh/cmds/modules/mkfile/mkfile.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/app/bdsh/cmds/modules/mkfile/mkfile.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -54,4 +54,5 @@
 static struct option const long_options[] = {
 	{"size", required_argument, 0, 's'},
+	{"sparse", no_argument, 0, 'p'},
 	{"help", no_argument, 0, 'h'},
 	{0, 0, 0, 0}
@@ -69,4 +70,5 @@
 		"  -h, --help       A short option summary\n"
 		"  -s, --size sz    Size of the file\n"
+		"  -p, --sparse     Create a sparse file\n"
 		"\n"
 		"Size is a number followed by 'k', 'm' or 'g' for kB, MB, GB.\n"
@@ -115,7 +117,8 @@
 	ssize_t file_size;
 	ssize_t total_written;
-	ssize_t to_write, rc;
+	ssize_t to_write, rc, rc2 = 0;
 	char *file_name;
 	void *buffer;
+	bool create_sparse = false;
 
 	file_size = 0;
@@ -124,9 +127,12 @@
 
 	for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
-		c = getopt_long(argc, argv, "s:h", long_options, &opt_ind);
+		c = getopt_long(argc, argv, "ps:h", long_options, &opt_ind);
 		switch (c) {
 		case 'h':
 			help_cmd_mkfile(HELP_LONG);
 			return CMD_SUCCESS;
+		case 'p':
+			create_sparse = true;
+			break;
 		case 's':
 			file_size = read_size(optarg);
@@ -154,4 +160,14 @@
 		printf("%s: failed to create file %s.\n", cmdname, file_name);
 		return CMD_FAILURE;
+	}
+
+	if (create_sparse && file_size > 0) {
+		const char byte = 0x00;
+
+		if ((rc2 = lseek(fd, file_size - 1, SEEK_SET)) < 0)
+			goto exit;
+
+		rc2 = write(fd, &byte, sizeof(char));
+		goto exit;
 	}
 
@@ -174,11 +190,12 @@
 	}
 
+	free(buffer);
+exit:
 	rc = close(fd);
-	if (rc != 0) {
+
+	if (rc != 0 || rc2 < 0) {
 		printf("%s: Error writing file (%zd).\n", cmdname, rc);
 		return CMD_FAILURE;
 	}
-
-	free(buffer);
 
 	return CMD_SUCCESS;
Index: uspace/app/bdsh/cmds/modules/mount/mount.c
===================================================================
--- uspace/app/bdsh/cmds/modules/mount/mount.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/app/bdsh/cmds/modules/mount/mount.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -43,4 +43,5 @@
 static struct option const long_options[] = {
 	{ "help", no_argument, 0, 'h' },
+	{ "instance", required_argument, 0, 'i' },
 	{ 0, 0, 0, 0 }
 };
@@ -68,15 +69,28 @@
 	const char *dev = "";
 	int rc, c, opt_ind;
+	unsigned int instance = 0;
+	bool instance_set = false;
+	char **t_argv;
 
 	argc = cli_count_args(argv);
 
 	for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
-		c = getopt_long(argc, argv, "h", long_options, &opt_ind);
+		c = getopt_long(argc, argv, "i:h", long_options, &opt_ind);
 		switch (c) {
 		case 'h':
 			help_cmd_mount(HELP_LONG);
 			return CMD_SUCCESS;
+		case 'i':
+			instance = (unsigned int) strtol(optarg, NULL, 10);
+			instance_set = true;
+			break;
 		}
 	}
+
+	if (instance_set) {
+		argc -= 2;
+		t_argv = &argv[2];
+	} else
+		t_argv = &argv[0];
 
 	if ((argc < 3) || (argc > 5)) {
@@ -86,12 +100,12 @@
 	}
 	if (argc > 3)
-		dev = argv[3];
+		dev = t_argv[3];
 	if (argc == 5)
-		mopts = argv[4];
+		mopts = t_argv[4];
 
-	rc = mount(argv[1], argv[2], dev, mopts, 0);
+	rc = mount(t_argv[1], t_argv[2], dev, mopts, 0, instance);
 	if (rc != EOK) {
 		printf("Unable to mount %s filesystem to %s on %s (rc=%d)\n",
-		    argv[1], argv[2], argv[3], rc);
+		    t_argv[1], t_argv[2], t_argv[3], rc);
 		return CMD_FAILURE;
 	}
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/app/init/init.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -121,5 +121,5 @@
 	
 	int rc = mount(fstype, ROOT_MOUNT_POINT, ROOT_DEVICE, opts,
-	    IPC_FLAG_BLOCKING);
+	    IPC_FLAG_BLOCKING, 0);
 	return mount_report("Root filesystem", ROOT_MOUNT_POINT, fstype,
 	    ROOT_DEVICE, rc);
@@ -138,5 +138,5 @@
 {
 	int rc = mount(LOCFS_FS_TYPE, LOCFS_MOUNT_POINT, "", "",
-	    IPC_FLAG_BLOCKING);
+	    IPC_FLAG_BLOCKING, 0);
 	return mount_report("Location service filesystem", LOCFS_MOUNT_POINT,
 	    LOCFS_FS_TYPE, NULL, rc);
@@ -261,5 +261,5 @@
 static bool mount_tmpfs(void)
 {
-	int rc = mount(TMPFS_FS_TYPE, TMPFS_MOUNT_POINT, "", "", 0);
+	int rc = mount(TMPFS_FS_TYPE, TMPFS_MOUNT_POINT, "", "", 0, 0);
 	return mount_report("Temporary filesystem", TMPFS_MOUNT_POINT,
 	    TMPFS_FS_TYPE, NULL, rc);
@@ -268,5 +268,5 @@
 static bool mount_data(void)
 {
-	int rc = mount(DATA_FS_TYPE, DATA_MOUNT_POINT, DATA_DEVICE, "wtcache", 0);
+	int rc = mount(DATA_FS_TYPE, DATA_MOUNT_POINT, DATA_DEVICE, "wtcache", 0, 0);
 	return mount_report("Data filesystem", DATA_MOUNT_POINT, DATA_FS_TYPE,
 	    DATA_DEVICE, rc);
Index: uspace/app/vuhid/Makefile
===================================================================
--- uspace/app/vuhid/Makefile	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/app/vuhid/Makefile	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -47,5 +47,6 @@
 
 SOURCES_INTERFACES = \
-	hids/bootkbd.c
+	hids/bootkbd.c \
+	hids/logitech_wireless.c
 
 SOURCES = \
@@ -53,4 +54,5 @@
 	device.c \
 	ifaces.c \
+	life.c \
 	stdreq.c \
 	$(SOURCES_INTERFACES)
Index: uspace/app/vuhid/hids/bootkbd.c
===================================================================
--- uspace/app/vuhid/hids/bootkbd.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/app/vuhid/hids/bootkbd.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -93,34 +93,11 @@
 	     0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
-static size_t in_data_count = sizeof(in_data)/INPUT_SIZE;
-// FIXME - locking
-static size_t in_data_position = 0;
-
-static int on_data_in(vuhid_interface_t *iface,
-    void *buffer, size_t buffer_size, size_t *act_buffer_size)
-{
-	static size_t last_pos = (size_t) -1;
-	size_t pos = in_data_position;
-	if (pos >= in_data_count) {
-		return EBADCHECKSUM;
-	}
-
-	if (last_pos == pos) {
-		return ENAK;
-	}
-
-	if (buffer_size > INPUT_SIZE) {
-		buffer_size = INPUT_SIZE;
-	}
-
-	if (act_buffer_size != NULL) {
-		*act_buffer_size = buffer_size;
-	}
-
-	memcpy(buffer, in_data + pos * INPUT_SIZE, buffer_size);
-	last_pos = pos;
-
-	return EOK;
-}
+static vuhid_interface_life_t boot_life = {
+	.data_in = in_data,
+	.data_in_count = sizeof(in_data)/INPUT_SIZE,
+	.data_in_pos_change_delay = 500,
+	.msg_born = "Boot keyboard comes to life...",
+	.msg_die = "Boot keyboard died."
+};
 
 static int on_data_out(vuhid_interface_t *iface,
@@ -141,17 +118,4 @@
 }
 
-
-static void live(vuhid_interface_t *iface)
-{
-	async_usleep(1000 * 1000 * 5);
-	usb_log_debug("Boot keyboard comes to life...\n");
-	while (in_data_position < in_data_count) {
-		async_usleep(1000 * 500);
-		in_data_position++;
-	}
-	usb_log_debug("Boot keyboard died.\n");
-}
-
-
 vuhid_interface_t vuhid_interface_bootkbd = {
 	.id = "boot",
@@ -164,11 +128,12 @@
 
 	.in_data_size = INPUT_SIZE,
-	.on_data_in = on_data_in,
+	.on_data_in = interface_live_on_data_in,
 
 	.out_data_size = 1,
 	.on_data_out = on_data_out,
 
-	.live = live,
+	.live = interface_life_live,
 
+	.interface_data = &boot_life,
 	.vuhid_data = NULL
 };
Index: uspace/app/vuhid/hids/logitech_wireless.c
===================================================================
--- uspace/app/vuhid/hids/logitech_wireless.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
+++ uspace/app/vuhid/hids/logitech_wireless.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 usbvirthid
+ * @{
+ */
+/** @file
+ * Logitech wireless mouse-keyboard combo simulation (see issue 349).
+ */
+#include "../virthid.h"
+#include <errno.h>
+#include <usb/debug.h>
+#include <usb/hid/hid.h>
+#include <usb/hid/usages/core.h>
+
+static uint8_t iface1_report_descriptor[] = {
+	0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x85, 0x02, 0x09, 0x01,
+	0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x10, 0x15, 0x00,
+	0x25, 0x01, 0x95, 0x10, 0x75, 0x01, 0x81, 0x02, 0x05, 0x01,
+	0x16, 0x01, 0xF8, 0x26, 0xFF, 0x07, 0x75, 0x0C, 0x95, 0x02,
+	0x09, 0x30, 0x09, 0x31, 0x81, 0x06, 0x15, 0x81, 0x25, 0x7F,
+	0x75, 0x08, 0x95, 0x01, 0x09, 0x38, 0x81, 0x06, 0x05, 0x0C,
+	0x0A, 0x38, 0x02, 0x95, 0x01, 0x81, 0x06, 0xC0, 0xC0, 0x05,
+	0x0C, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x03, 0x75, 0x10, 0x95,
+	0x02, 0x15, 0x01, 0x26, 0x8C, 0x02, 0x19, 0x01, 0x2A, 0x8C,
+	0x02, 0x81, 0x00, 0xC0, 0x05, 0x01, 0x09, 0x80, 0xA1, 0x01,
+	0x85, 0x04, 0x75, 0x02, 0x95, 0x01, 0x15, 0x01, 0x25, 0x03,
+	0x09, 0x82, 0x09, 0x81, 0x09, 0x83, 0x81, 0x60, 0x75, 0x06,
+	0x81, 0x03, 0xC0, 0x06, 0xBC, 0xFF, 0x09, 0x88, 0xA1, 0x01,
+	0x85, 0x08, 0x19, 0x01, 0x29, 0xFF, 0x15, 0x01, 0x26, 0xFF,
+	0x00, 0x75, 0x08, 0x95, 0x01, 0x81, 0x00, 0xC0
+};
+#define iface1_input_size 8
+static uint8_t iface1_in_data[] = {
+		/*0, 0, 0, 0, 0, 0, 0, 0,
+		0, 9, 0, 0, 0, 0, 0, 0,
+		0, 0, 9, 0, 0, 0, 0, 0,
+		0, 9, 9, 0, 0, 0, 0, 0,*/
+		0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static vuhid_interface_life_t iface1_life = {
+	.data_in = iface1_in_data,
+	.data_in_count = sizeof(iface1_in_data)/iface1_input_size,
+	.data_in_pos_change_delay = 50,
+	.msg_born = "Mouse of Logitech Unifying Receiver comes to life...",
+	.msg_die = "Mouse of Logitech Unifying Receiver disconnected."
+};
+
+
+vuhid_interface_t vuhid_interface_logitech_wireless_1 = {
+	.id = "lw1",
+	.name = "Logitech Unifying Receiver, interface 1 (mouse)",
+	.usb_subclass = USB_HID_SUBCLASS_BOOT,
+	.usb_protocol = USB_HID_PROTOCOL_MOUSE,
+
+	.report_descriptor = iface1_report_descriptor,
+	.report_descriptor_size = sizeof(iface1_report_descriptor),
+
+	.in_data_size = iface1_input_size,
+	.on_data_in = interface_live_on_data_in,
+
+	.out_data_size = 0,
+	.on_data_out = NULL,
+
+	.live = interface_life_live,
+
+	.interface_data = &iface1_life,
+	.vuhid_data = NULL
+};
+
+/**
+ * @}
+ */
Index: uspace/app/vuhid/ifaces.c
===================================================================
--- uspace/app/vuhid/ifaces.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/app/vuhid/ifaces.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -38,7 +38,9 @@
 
 extern vuhid_interface_t vuhid_interface_bootkbd;
+extern vuhid_interface_t vuhid_interface_logitech_wireless_1;
 
 vuhid_interface_t *available_hid_interfaces[] = {
 	&vuhid_interface_bootkbd,
+	&vuhid_interface_logitech_wireless_1,
 	NULL
 };
Index: uspace/app/vuhid/life.c
===================================================================
--- uspace/app/vuhid/life.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
+++ uspace/app/vuhid/life.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 usbvirthid
+ * @{
+ */
+/**
+ * @file
+ *
+ */
+#include <errno.h>
+#include <usb/debug.h>
+#include "virthid.h"
+
+
+void interface_life_live(vuhid_interface_t *iface)
+{
+	vuhid_interface_life_t *data = iface->interface_data;
+	data->data_in_pos = 0;
+	data->data_in_last_pos = (size_t) -1;
+	async_usleep(1000 * 1000 * 5);
+	usb_log_debug("%s\n", data->msg_born);
+	while (data->data_in_pos < data->data_in_count) {
+		async_usleep(1000 * data->data_in_pos_change_delay);
+		// FIXME: proper locking
+		data->data_in_pos++;
+	}
+	usb_log_debug("%s\n", data->msg_die);
+}
+
+
+
+int interface_live_on_data_in(vuhid_interface_t *iface,
+    void *buffer, size_t buffer_size, size_t *act_buffer_size)
+{
+	vuhid_interface_life_t *life = iface->interface_data;
+	size_t pos = life->data_in_pos;
+	if (pos >= life->data_in_count) {
+		return EBADCHECKSUM;
+	}
+
+	if (pos == life->data_in_last_pos) {
+		return ENAK;
+	}
+
+	if (buffer_size > iface->in_data_size) {
+		buffer_size = iface->in_data_size;
+	}
+
+	if (act_buffer_size != NULL) {
+		*act_buffer_size = buffer_size;
+	}
+
+	memcpy(buffer, life->data_in + pos * iface->in_data_size, buffer_size);
+	life->data_in_last_pos = pos;
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/app/vuhid/virthid.h
===================================================================
--- uspace/app/vuhid/virthid.h	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/app/vuhid/virthid.h	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -82,4 +82,27 @@
 
 typedef struct {
+	/** Buffer with data from device to the host. */
+	uint8_t *data_in;
+	/** Number of items in @c data_in.
+	 * The total size of @c data_in buffer shall be
+	 * <code>data_in_count * vuhid_interface_t.in_data_size</code>.
+	 */
+	size_t data_in_count;
+
+	/** Current position in the data buffer. */
+	size_t data_in_pos;
+	/** Previous position. */
+	size_t data_in_last_pos;
+
+	/** Delay between transition to "next" input buffer (in ms). */
+	size_t data_in_pos_change_delay;
+
+	/** Message to print when interface becomes alive. */
+	const char *msg_born;
+	/** Message to print when interface dies. */
+	const char *msg_die;
+} vuhid_interface_life_t;
+
+typedef struct {
 	uint8_t length;
 	uint8_t type;
@@ -94,4 +117,8 @@
 void wait_for_interfaces_death(usbvirt_device_t *);
 
+void interface_life_live(vuhid_interface_t *);
+int interface_live_on_data_in(vuhid_interface_t *, void *, size_t, size_t *);
+
+
 #endif
 /**
Index: uspace/drv/bus/usb/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -75,5 +75,4 @@
 /** Default idle rate for mouses. */
 static const uint8_t IDLE_RATE = 0;
-static const size_t USB_MOUSE_BUTTON_COUNT = 3;
 
 /*----------------------------------------------------------------------------*/
@@ -397,4 +396,46 @@
 /*----------------------------------------------------------------------------*/
 
+/** Get highest index of a button mentioned in given report.
+ *
+ * @param report HID report.
+ * @param report_id Report id we are interested in.
+ * @return Highest button mentioned in the report.
+ * @retval 1 No button was mentioned.
+ *
+ */
+static size_t usb_mouse_get_highest_button(usb_hid_report_t *report, uint8_t report_id)
+{
+	size_t highest_button = 0;
+
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
+	usb_hid_report_path_set_report_id(path, report_id);
+
+	usb_hid_report_field_t *field = NULL;
+
+	/* Break from within. */
+	while (1) {
+		field = usb_hid_report_get_sibling(
+		    report, field, path,
+		    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
+		    USB_HID_REPORT_TYPE_INPUT);
+		/* No more buttons? */
+		if (field == NULL) {
+			break;
+		}
+
+		size_t current_button = field->usage - field->usage_minimum;
+		if (current_button > highest_button) {
+			highest_button = current_button;
+		}
+	}
+
+	usb_hid_report_path_free(path);
+
+	return highest_button;
+}
+
+/*----------------------------------------------------------------------------*/
+
 int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
 {
@@ -414,13 +455,21 @@
 	}
 	
-	mouse_dev->buttons = (int32_t *)calloc(USB_MOUSE_BUTTON_COUNT, 
-	    sizeof(int32_t));
+	// FIXME: This may not be optimal since stupid hardware vendor may
+	// use buttons 1, 2, 3 and 6000 and we would allocate array of
+	// 6001*4B and use only 4 items in it.
+	// Since I doubt that hardware producers would do that, I think
+	// that the current solution is good enough.
+	/* Adding 1 because we will be accessing buttons[highest]. */
+	mouse_dev->buttons_count = usb_mouse_get_highest_button(hid_dev->report,
+	    hid_dev->report_id) + 1;
+	mouse_dev->buttons = calloc(mouse_dev->buttons_count, sizeof(int32_t));
 	
 	if (mouse_dev->buttons == NULL) {
-		usb_log_fatal("No memory!\n");
+		usb_log_error(NAME ": out of memory, giving up on device!\n");
 		free(mouse_dev);
 		return ENOMEM;
 	}
-	
+
+
 	// save the Mouse device structure into the HID device structure
 	*data = mouse_dev;
Index: uspace/drv/bus/usb/usbhid/mouse/mousedev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/mouse/mousedev.h	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.h	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -50,5 +50,7 @@
 	async_sess_t *wheel_sess;
 	
+	/* Mouse buttons statuses. */
 	int32_t *buttons;
+	size_t buttons_count;
 	
 	ddf_dev_ops_t ops;
Index: uspace/drv/bus/usb/usbhub/usbhub.c
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/drv/bus/usb/usbhub/usbhub.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -130,6 +130,4 @@
 
 	opResult = ddf_fun_bind(hub_fun);
-	assert(opResult == EOK);
-	opResult = ddf_fun_add_to_category(hub_fun, "hub");
 	assert(opResult == EOK);
 
Index: uspace/drv/bus/usb/vhc/connhost.c
===================================================================
--- uspace/drv/bus/usb/vhc/connhost.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/drv/bus/usb/vhc/connhost.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -440,5 +440,7 @@
 	int rc = vhc_virtdev_add_transfer(vhc, transfer);
 	if (rc != EOK) {
-		free(transfer->setup_buffer);
+		if (transfer->setup_buffer != NULL) {
+			free(transfer->setup_buffer);
+		}
 		free(transfer);
 		return rc;
Index: uspace/lib/c/arch/ia64/include/ddi.h
===================================================================
--- uspace/lib/c/arch/ia64/include/ddi.h	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/lib/c/arch/ia64/include/ddi.h	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -52,8 +52,12 @@
 static inline void pio_write_8(ioport8_t *port, uint8_t v)
 {
-	uintptr_t prt = (uintptr_t) port;
+	if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
+		uintptr_t prt = (uintptr_t) port;
 
-	*((ioport8_t *)(IA64_IOSPACE_ADDRESS +
-	    ((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
+		*((ioport8_t *)(IA64_IOSPACE_ADDRESS +
+		    ((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
+	} else {
+		*port = v;
+	}
 
 	asm volatile ("mf\n" ::: "memory");
@@ -62,8 +66,12 @@
 static inline void pio_write_16(ioport16_t *port, uint16_t v)
 {
-	uintptr_t prt = (uintptr_t) port;
+	if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
+		uintptr_t prt = (uintptr_t) port;
 
-	*((ioport16_t *)(IA64_IOSPACE_ADDRESS +
-	    ((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
+		*((ioport16_t *)(IA64_IOSPACE_ADDRESS +
+		    ((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
+	} else {
+		*port = v;
+	}
 
 	asm volatile ("mf\n" ::: "memory");
@@ -72,8 +80,12 @@
 static inline void pio_write_32(ioport32_t *port, uint32_t v)
 {
-	uintptr_t prt = (uintptr_t) port;
+	if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
+		uintptr_t prt = (uintptr_t) port;
 
-	*((ioport32_t *)(IA64_IOSPACE_ADDRESS +
-	    ((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
+		*((ioport32_t *)(IA64_IOSPACE_ADDRESS +
+		    ((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
+	} else {
+		*port = v;
+	}
 
 	asm volatile ("mf\n" ::: "memory");
@@ -82,30 +94,54 @@
 static inline uint8_t pio_read_8(ioport8_t *port)
 {
-	uintptr_t prt = (uintptr_t) port;
+	uint8_t v;
 
 	asm volatile ("mf\n" ::: "memory");
 
-	return *((ioport8_t *)(IA64_IOSPACE_ADDRESS +
-	    ((prt & 0xfff) | ((prt >> 2) << 12))));
+	if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
+		uintptr_t prt = (uintptr_t) port;
+
+		v = *((ioport8_t *)(IA64_IOSPACE_ADDRESS +
+		    ((prt & 0xfff) | ((prt >> 2) << 12))));
+	} else {
+		v = *port;
+	}
+
+	return v;
 }
 
 static inline uint16_t pio_read_16(ioport16_t *port)
 {
-	uintptr_t prt = (uintptr_t) port;
+	uint16_t v;
 
 	asm volatile ("mf\n" ::: "memory");
 
-	return *((ioport16_t *)(IA64_IOSPACE_ADDRESS +
-	    ((prt & 0xfff) | ((prt >> 2) << 12))));
+	if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
+		uintptr_t prt = (uintptr_t) port;
+
+		v = *((ioport16_t *)(IA64_IOSPACE_ADDRESS +
+		    ((prt & 0xfff) | ((prt >> 2) << 12))));
+	} else {
+		v = *port;
+	}
+
+	return v;
 }
 
 static inline uint32_t pio_read_32(ioport32_t *port)
 {
-	uintptr_t prt = (uintptr_t) port;
+	uint32_t v;
 
 	asm volatile ("mf\n" ::: "memory");
 
-	return *((ioport32_t *)(IA64_IOSPACE_ADDRESS +
-	    ((prt & 0xfff) | ((prt >> 2) << 12))));
+	if (port < (ioport32_t *) port) {
+		uintptr_t prt = (uintptr_t) port;
+
+		v = *((ioport32_t *)(IA64_IOSPACE_ADDRESS +
+		    ((prt & 0xfff) | ((prt >> 2) << 12))));
+	} else {
+		v = *port;
+	}
+
+	return v;
 }
 
Index: uspace/lib/c/generic/adt/hash_table.c
===================================================================
--- uspace/lib/c/generic/adt/hash_table.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/lib/c/generic/adt/hash_table.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -190,5 +190,5 @@
 }
 
-/** Apply fucntion to all items in hash table.
+/** Apply function to all items in hash table.
  *
  * @param h   Hash table.
Index: uspace/lib/c/generic/adt/list.c
===================================================================
--- uspace/lib/c/generic/adt/list.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/lib/c/generic/adt/list.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -33,5 +33,5 @@
 /**
  * @file
- * @brief	Functions completing doubly linked circular list implementaion.
+ * @brief	Functions completing doubly linked circular list implementation.
  *
  * This file contains some of the functions implementing doubly linked circular lists.
Index: uspace/lib/c/generic/malloc.c
===================================================================
--- uspace/lib/c/generic/malloc.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/lib/c/generic/malloc.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -873,4 +873,7 @@
 void free(const void *addr)
 {
+	if (addr == NULL)
+		return;
+
 	futex_down(&malloc_futex);
 	
Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -143,5 +143,5 @@
 
 int mount(const char *fs_name, const char *mp, const char *fqsn,
-    const char *opts, unsigned int flags)
+    const char *opts, unsigned int flags, unsigned int instance)
 {
 	int null_id = -1;
@@ -181,5 +181,6 @@
 
 	sysarg_t rc_orig;
-	aid_t req = async_send_2(exch, VFS_IN_MOUNT, service_id, flags, NULL);
+	aid_t req = async_send_3(exch, VFS_IN_MOUNT, service_id, flags,
+	    instance, NULL);
 	sysarg_t rc = async_data_write_start(exch, (void *) mpa, mpa_size);
 	if (rc != EOK) {
Index: uspace/lib/c/include/ipc/vfs.h
===================================================================
--- uspace/lib/c/include/ipc/vfs.h	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/lib/c/include/ipc/vfs.h	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -56,4 +56,5 @@
 	/** Unique identifier of the fs. */
 	char name[FS_NAME_MAXLEN + 1];
+	unsigned int instance;
 	bool concurrent_read_write;
 	bool write_retains_size;
Index: uspace/lib/c/include/vfs/vfs.h
===================================================================
--- uspace/lib/c/include/vfs/vfs.h	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/lib/c/include/vfs/vfs.h	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -49,5 +49,5 @@
 
 extern int mount(const char *, const char *, const char *, const char *,
-    unsigned int);
+    unsigned int, unsigned int);
 extern int unmount(const char *);
 
Index: uspace/lib/fs/libfs.c
===================================================================
--- uspace/lib/fs/libfs.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/lib/fs/libfs.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -877,4 +877,82 @@
 }
 
+static FIBRIL_MUTEX_INITIALIZE(instances_mutex);
+static LIST_INITIALIZE(instances_list);
+
+typedef struct {
+	service_id_t service_id;
+	link_t link;
+	void *data;
+} fs_instance_t;
+
+int fs_instance_create(service_id_t service_id, void *data)
+{
+	fs_instance_t *inst = malloc(sizeof(fs_instance_t));
+	if (!inst)
+		return ENOMEM;
+
+	link_initialize(&inst->link);
+	inst->service_id = service_id;
+	inst->data = data;
+
+	fibril_mutex_lock(&instances_mutex);
+	list_foreach(instances_list, link) {
+		fs_instance_t *cur = list_get_instance(link, fs_instance_t,
+		    link);
+
+		if (cur->service_id == service_id) {
+			fibril_mutex_unlock(&instances_mutex);
+			free(inst);
+			return EEXIST;
+		}
+
+		/* keep the list sorted */
+		if (cur->service_id < service_id) {
+			list_insert_before(&inst->link, &cur->link);
+			fibril_mutex_unlock(&instances_mutex);
+			return EOK;
+		}
+	}
+	list_append(&inst->link, &instances_list);
+	fibril_mutex_unlock(&instances_mutex);
+
+	return EOK;
+}
+
+int fs_instance_get(service_id_t service_id, void **idp)
+{
+	fibril_mutex_lock(&instances_mutex);
+	list_foreach(instances_list, link) {
+		fs_instance_t *inst = list_get_instance(link, fs_instance_t,
+		    link);
+
+		if (inst->service_id == service_id) {
+			*idp = inst->data;
+			fibril_mutex_unlock(&instances_mutex);
+			return EOK;
+		}
+	}
+	fibril_mutex_unlock(&instances_mutex);
+	return ENOENT;
+}
+
+int fs_instance_destroy(service_id_t service_id)
+{
+	fibril_mutex_lock(&instances_mutex);
+	list_foreach(instances_list, link) {
+		fs_instance_t *inst = list_get_instance(link, fs_instance_t,
+		    link);
+
+		if (inst->service_id == service_id) {
+			list_remove(&inst->link);
+			fibril_mutex_unlock(&instances_mutex);
+			free(inst);
+			return EOK;
+		}
+	}
+	fibril_mutex_unlock(&instances_mutex);
+	return ENOENT;
+}
+
 /** @}
  */
Index: uspace/lib/fs/libfs.h
===================================================================
--- uspace/lib/fs/libfs.h	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/lib/fs/libfs.h	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -105,4 +105,8 @@
 extern void fs_node_initialize(fs_node_t *);
 
+extern int fs_instance_create(service_id_t, void *);
+extern int fs_instance_get(service_id_t, void **);
+extern int fs_instance_destroy(service_id_t);
+
 #endif
 
Index: uspace/lib/usbhid/src/hidpath.c
===================================================================
--- uspace/lib/usbhid/src/hidpath.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/lib/usbhid/src/hidpath.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -76,7 +76,8 @@
                                     int32_t usage_page, int32_t usage)
 {	
-	usb_hid_report_usage_path_t *item;
-
-	if(!(item=malloc(sizeof(usb_hid_report_usage_path_t)))) {
+	usb_hid_report_usage_path_t *item
+		= malloc(sizeof(usb_hid_report_usage_path_t));
+
+	if (item == NULL) {
 		return ENOMEM;
 	}
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/devman/main.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -490,4 +490,6 @@
 	if (rc == EOK) {
 		loc_service_add_to_cat(fun->service_id, cat_id);
+		log_msg(LVL_NOTE, "Function `%s' added to category `%s'.",
+		    fun->pathname, cat_name);
 	} else {
 		log_msg(LVL_ERROR, "Failed adding function `%s' to category "
@@ -495,11 +497,8 @@
 	}
 	
-	log_msg(LVL_NOTE, "Function `%s' added to category `%s'.",
-	    fun->pathname, cat_name);
-
 	fibril_rwlock_read_unlock(&device_tree.rwlock);
 	fun_del_ref(fun);
-
-	async_answer_0(callid, EOK);
+	
+	async_answer_0(callid, rc);
 }
 
Index: uspace/srv/fs/cdfs/cdfs.c
===================================================================
--- uspace/srv/fs/cdfs/cdfs.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/fs/cdfs/cdfs.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -52,4 +52,5 @@
 	.concurrent_read_write = false,
 	.write_retains_size = false,
+	.instance = 0,
 };
 
@@ -58,4 +59,13 @@
 	printf("%s: HelenOS cdfs file system server\n", NAME);
 	
+	if (argc == 3) {
+		if (!str_cmp(argv[1], "--instance"))
+			cdfs_vfs_info.instance = strtol(argv[2], NULL, 10);
+		else {
+			printf(NAME " Unrecognized parameters");
+			return -1;
+		}
+	}
+
 	if (!cdfs_init()) {
 		printf("%s: failed to initialize cdfs\n", NAME);
Index: uspace/srv/fs/exfat/exfat.c
===================================================================
--- uspace/srv/fs/exfat/exfat.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/fs/exfat/exfat.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -54,5 +54,6 @@
 	.name = NAME,
 	.concurrent_read_write = false,
-	.write_retains_size = false,	
+	.write_retains_size = false,
+	.instance = 0,
 };
 
@@ -60,4 +61,13 @@
 {
 	printf(NAME ": HelenOS exFAT file system server\n");
+
+	if (argc == 3) {
+		if (!str_cmp(argv[1], "--instance"))
+			exfat_vfs_info.instance = strtol(argv[2], NULL, 10);
+		else {
+			printf(NAME " Unrecognized parameters");
+			return -1;
+		}
+	}
 
 	int rc = exfat_idx_init();
Index: uspace/srv/fs/ext2fs/ext2fs.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/fs/ext2fs/ext2fs.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -52,4 +52,5 @@
 vfs_info_t ext2fs_vfs_info = {
 	.name = NAME,
+	.instance = 0,
 };
 
@@ -57,4 +58,13 @@
 {
 	printf(NAME ": HelenOS EXT2 file system server\n");
+
+	if (argc == 3) {
+		if (!str_cmp(argv[1], "--instance"))
+			ext2fs_vfs_info.instance = strtol(argv[2], NULL, 10);
+		else {
+			printf(NAME " Unrecognized parameters");
+			return -1;
+		}
+	}
 	
 	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
Index: uspace/srv/fs/fat/fat.c
===================================================================
--- uspace/srv/fs/fat/fat.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/fs/fat/fat.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -54,5 +54,6 @@
 	.name = NAME,
 	.concurrent_read_write = false,
-	.write_retains_size = false,	
+	.write_retains_size = false,
+	.instance = 0,
 };
 
@@ -61,4 +62,13 @@
 	printf(NAME ": HelenOS FAT file system server\n");
 	
+	if (argc == 3) {
+		if (!str_cmp(argv[1], "--instance"))
+			fat_vfs_info.instance = strtol(argv[2], NULL, 10);
+		else {
+			printf(NAME " Unrecognized parameters");
+			return -1;
+		}
+	}
+
 	int rc = fat_idx_init();
 	if (rc != EOK)
Index: uspace/srv/fs/fat/fat.h
===================================================================
--- uspace/srv/fs/fat/fat.h	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/fs/fat/fat.h	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -230,4 +230,8 @@
 } fat_node_t;
 
+typedef struct {
+	bool lfn_enabled;
+} fat_instance_t;
+
 extern vfs_out_ops_t fat_ops;
 extern libfs_ops_t fat_libfs_ops;
Index: uspace/srv/fs/fat/fat_directory.c
===================================================================
--- uspace/srv/fs/fat/fat_directory.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/fs/fat/fat_directory.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -262,5 +262,10 @@
 {
 	int rc;
-	bool enable_lfn = true; /* TODO: make this a mount option */
+	void *data;
+	fat_instance_t *instance;
+
+	rc = fs_instance_get(di->nodep->idx->service_id, &data);
+	assert(rc == EOK);
+	instance = (fat_instance_t *) data;
 	
 	if (fat_valid_short_name(name)) {
@@ -277,5 +282,5 @@
 		rc = fat_directory_write_dentry(di, de);
 		return rc;
-	} else if (enable_lfn && fat_valid_name(name)) {
+	} else if (instance->lfn_enabled && fat_valid_name(name)) {
 		/* We should create long entries to store name */
 		int long_entry_count;
@@ -292,5 +297,5 @@
 		if (lfn_size % FAT_LFN_ENTRY_SIZE)
 			long_entry_count++;
-		rc = fat_directory_lookup_free(di, long_entry_count+1);
+		rc = fat_directory_lookup_free(di, long_entry_count + 1);
 		if (rc != EOK)
 			return rc;
@@ -328,5 +333,5 @@
 		FAT_LFN_ORDER(d) |= FAT_LFN_LAST;
 
-		rc = fat_directory_seek(di, start_pos+long_entry_count);
+		rc = fat_directory_seek(di, start_pos + long_entry_count);
 		return rc;
 	}
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/fs/fat/fat_ops.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -871,22 +871,37 @@
     aoff64_t *size, unsigned *linkcnt)
 {
-	enum cache_mode cmode;
+	enum cache_mode cmode = CACHE_MODE_WB;
 	fat_bs_t *bs;
-	int rc;
-
-	/* Check for option enabling write through. */
-	if (str_cmp(opts, "wtcache") == 0)
-		cmode = CACHE_MODE_WT;
-	else
-		cmode = CACHE_MODE_WB;
+	fat_instance_t *instance;
+	int rc;
+
+	instance = malloc(sizeof(fat_instance_t));
+	if (!instance)
+		return ENOMEM;
+	instance->lfn_enabled = true;
+
+	/* Parse mount options. */
+	char *mntopts = (char *) opts;
+	char *saveptr;
+	char *opt;
+	while ((opt = strtok_r(mntopts, " ,", &saveptr)) != NULL) {
+		if (str_cmp(opt, "wtcache") == 0)
+			cmode = CACHE_MODE_WT;
+		else if (str_cmp(opt, "nolfn") == 0)
+			instance->lfn_enabled = false;
+		mntopts = NULL;
+	}
 
 	/* initialize libblock */
 	rc = block_init(EXCHANGE_SERIALIZE, service_id, BS_SIZE);
-	if (rc != EOK)
-		return rc;
+	if (rc != EOK) {
+		free(instance);
+		return rc;
+	}
 
 	/* prepare the boot block */
 	rc = block_bb_read(service_id, BS_BLOCK);
 	if (rc != EOK) {
+		free(instance);
 		block_fini(service_id);
 		return rc;
@@ -897,4 +912,5 @@
 	
 	if (BPS(bs) != BS_SIZE) {
+		free(instance);
 		block_fini(service_id);
 		return ENOTSUP;
@@ -904,4 +920,5 @@
 	rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, cmode);
 	if (rc != EOK) {
+		free(instance);
 		block_fini(service_id);
 		return rc;
@@ -911,4 +928,5 @@
 	rc = fat_sanity_check(bs, service_id);
 	if (rc != EOK) {
+		free(instance);
 		(void) block_cache_fini(service_id);
 		block_fini(service_id);
@@ -918,4 +936,5 @@
 	rc = fat_idx_init_by_service_id(service_id);
 	if (rc != EOK) {
+		free(instance);
 		(void) block_cache_fini(service_id);
 		block_fini(service_id);
@@ -926,4 +945,5 @@
 	fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t));
 	if (!rfn) {
+		free(instance);
 		(void) block_cache_fini(service_id);
 		block_fini(service_id);
@@ -935,4 +955,5 @@
 	fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
 	if (!rootp) {
+		free(instance);
 		free(rfn);
 		(void) block_cache_fini(service_id);
@@ -945,4 +966,5 @@
 	fat_idx_t *ridxp = fat_idx_get_by_pos(service_id, FAT_CLST_ROOTPAR, 0);
 	if (!ridxp) {
+		free(instance);
 		free(rfn);
 		free(rootp);
@@ -964,4 +986,6 @@
 		rc = fat_clusters_get(&clusters, bs, service_id, rootp->firstc);
 		if (rc != EOK) {
+			fibril_mutex_unlock(&ridxp->lock);
+			free(instance);
 			free(rfn);
 			free(rootp);
@@ -974,4 +998,16 @@
 	} else
 		rootp->size = RDE(bs) * sizeof(fat_dentry_t);
+
+	rc = fs_instance_create(service_id, instance);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&ridxp->lock);
+		free(instance);
+		free(rfn);
+		free(rootp);
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		fat_idx_fini_by_service_id(service_id);
+		return rc;
+	}
 
 	rootp->idx = ridxp;
@@ -1024,4 +1060,10 @@
 	(void) block_cache_fini(service_id);
 	block_fini(service_id);
+
+	void *data;
+	if (fs_instance_get(service_id, &data) == EOK) {
+		fs_instance_destroy(service_id);
+		free(data);
+	}
 
 	return EOK;
Index: uspace/srv/fs/locfs/locfs.c
===================================================================
--- uspace/srv/fs/locfs/locfs.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/fs/locfs/locfs.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -55,4 +55,5 @@
 	.concurrent_read_write = false,
 	.write_retains_size = false,
+	.instance = 0,
 };
 
@@ -61,4 +62,14 @@
 	printf("%s: HelenOS Device Filesystem\n", NAME);
 	
+	if (argc == 3) {
+		if (!str_cmp(argv[1], "--instance"))
+			locfs_vfs_info.instance = strtol(argv[2], NULL, 10);
+		else {
+			printf(NAME " Unrecognized parameters");
+			return -1;
+		}
+	}
+
+
 	if (!locfs_init()) {
 		printf("%s: failed to initialize locfs\n", NAME);
Index: uspace/srv/fs/locfs/locfs_ops.c
===================================================================
--- uspace/srv/fs/locfs/locfs_ops.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/fs/locfs/locfs_ops.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -593,4 +593,8 @@
 		sysarg_t rc;
 		async_wait_for(msg, &rc);
+
+		/* Do not propagate EHANGUP back to VFS. */
+		if ((int) rc == EHANGUP)
+			rc = ENOTSUP;
 		
 		*rbytes = IPC_GET_ARG1(answer);
@@ -655,4 +659,8 @@
 		sysarg_t rc;
 		async_wait_for(msg, &rc);
+
+		/* Do not propagate EHANGUP back to VFS. */
+		if ((int) rc == EHANGUP)
+			rc = ENOTSUP;
 		
 		*wbytes = IPC_GET_ARG1(answer);
Index: uspace/srv/fs/mfs/mfs.c
===================================================================
--- uspace/srv/fs/mfs/mfs.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/fs/mfs/mfs.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -39,4 +39,6 @@
 
 #include <ipc/services.h>
+#include <stdlib.h>
+#include <str.h>
 #include <ns.h>
 #include <async.h>
@@ -52,4 +54,5 @@
 	.concurrent_read_write = false,
 	.write_retains_size = false,
+	.instance = 0,
 };
 
@@ -59,4 +62,14 @@
 
 	printf(NAME ": HelenOS Minix file system server\n");
+
+	if (argc == 3) {
+		if (!str_cmp(argv[1], "--instance"))
+			mfs_vfs_info.instance = strtol(argv[2], NULL, 10);
+		else {
+			printf(NAME " Unrecognized parameters");
+			rc = -1;
+			goto err;
+		}
+	}
 
 	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
Index: uspace/srv/fs/mfs/mfs.h
===================================================================
--- uspace/srv/fs/mfs/mfs.h	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/fs/mfs/mfs.h	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -131,5 +131,4 @@
 
 struct mfs_instance {
-	link_t link;
 	service_id_t service_id;
 	struct mfs_sb_info *sbi;
Index: uspace/srv/fs/mfs/mfs_ops.c
===================================================================
--- uspace/srv/fs/mfs/mfs_ops.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/fs/mfs/mfs_ops.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -73,6 +73,4 @@
 
 
-static LIST_INITIALIZE(inst_list);
-static FIBRIL_MUTEX_INITIALIZE(inst_list_mutex);
 static hash_table_t open_nodes;
 static FIBRIL_MUTEX_INITIALIZE(open_nodes_lock);
@@ -178,6 +176,4 @@
 		goto out_error;
 	}
-
-	instance->open_nodes_cnt = 0;
 
 	sb = malloc(MFS_SUPERBLOCK_SIZE);
@@ -271,12 +267,17 @@
 	}
 
-	/*Initialize the instance structure and add it to the list*/
-	link_initialize(&instance->link);
+	/*Initialize the instance structure and remember it*/
 	instance->service_id = service_id;
 	instance->sbi = sbi;
-
-	fibril_mutex_lock(&inst_list_mutex);
-	list_append(&instance->link, &inst_list);
-	fibril_mutex_unlock(&inst_list_mutex);
+	instance->open_nodes_cnt = 0;
+	rc = fs_instance_create(service_id, instance);
+	if (rc != EOK) {
+		free(instance);
+		free(sbi);
+		block_cache_fini(service_id);
+		block_fini(service_id);
+		mfsdebug("fs instance creation failed\n");
+		return rc;
+	}
 
 	mfsdebug("mount successful\n");
@@ -323,9 +324,6 @@
 	block_fini(service_id);
 
-	/* Remove the instance from the list */
-	fibril_mutex_lock(&inst_list_mutex);
-	list_remove(&inst->link);
-	fibril_mutex_unlock(&inst_list_mutex);
-
+	/* Remove and destroy the instance */
+	(void) fs_instance_destroy(service_id);
 	free(inst->sbi);
 	free(inst);
@@ -1020,28 +1018,15 @@
 mfs_instance_get(service_id_t service_id, struct mfs_instance **instance)
 {
-	struct mfs_instance *instance_ptr;
-
-	fibril_mutex_lock(&inst_list_mutex);
-
-	if (list_empty(&inst_list)) {
-		fibril_mutex_unlock(&inst_list_mutex);
-		return EINVAL;
-	}
-
-	list_foreach(inst_list, link) {
-		instance_ptr = list_get_instance(link, struct mfs_instance,
-						 link);
-
-		if (instance_ptr->service_id == service_id) {
-			*instance = instance_ptr;
-			fibril_mutex_unlock(&inst_list_mutex);
-			return EOK;
-		}
-	}
-
-	mfsdebug("Instance not found\n");
-
-	fibril_mutex_unlock(&inst_list_mutex);
-	return EINVAL;
+	void *data;
+	int rc;
+
+	rc = fs_instance_get(service_id, &data);
+	if (rc == EOK) {
+		*instance = (struct mfs_instance *) data;
+	} else {
+		mfsdebug("instance not found\n");
+	}
+
+	return rc;
 }
 
Index: uspace/srv/fs/tmpfs/tmpfs.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/fs/tmpfs/tmpfs.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -59,4 +59,5 @@
 	.concurrent_read_write = false,
 	.write_retains_size = false,
+	.instance = 0,
 };
 
@@ -64,4 +65,13 @@
 {
 	printf(NAME ": HelenOS TMPFS file system server\n");
+
+	if (argc == 3) {
+		if (!str_cmp(argv[1], "--instance"))
+			tmpfs_vfs_info.instance = strtol(argv[2], NULL, 10);
+		else {
+			printf(NAME " Unrecognized parameters");
+			return -1;
+		}
+	}
 	
 	if (!tmpfs_init()) {
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/hid/console/console.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -344,4 +344,19 @@
 }
 
+static console_t *cons_get_active_uspace(void)
+{
+	fibril_mutex_lock(&switch_mtx);
+
+	console_t *active_uspace = active_console;
+	if (active_uspace == kernel_console) {
+		active_uspace = prev_console;
+	}
+	assert(active_uspace != kernel_console);
+
+	fibril_mutex_unlock(&switch_mtx);
+
+	return active_uspace;
+}
+
 static ssize_t limit(ssize_t val, ssize_t lo, ssize_t hi)
 {
@@ -466,5 +481,13 @@
 				event->c = c;
 				
-				prodcons_produce(&active_console->input_pc, &event->link);
+				/* Kernel console does not read events
+				 * from us, so we will redirect them
+				 * to the (last) active userspace console
+				 * if necessary.
+				 */
+				console_t *target_console = cons_get_active_uspace();
+
+				prodcons_produce(&target_console->input_pc,
+				    &event->link);
 			}
 			
@@ -904,4 +927,5 @@
 		atomic_set(&consoles[i].refcnt, 0);
 		fibril_mutex_initialize(&consoles[i].mtx);
+		prodcons_initialize(&consoles[i].input_pc);
 		
 		if (graphics_state == GRAPHICS_FULL) {
@@ -942,5 +966,4 @@
 		}
 		
-		prodcons_initialize(&consoles[i].input_pc);
 		cons_redraw_state(&consoles[i]);
 		
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/vfs/vfs.h	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -171,5 +171,5 @@
 extern void vfs_exchange_release(async_exch_t *);
 
-extern fs_handle_t fs_name_to_handle(char *, bool);
+extern fs_handle_t fs_name_to_handle(unsigned int instance, char *, bool);
 extern vfs_info_t *fs_handle_to_info(fs_handle_t);
 
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/vfs/vfs_ops.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -146,5 +146,6 @@
 
 			rindex = (fs_index_t) IPC_GET_ARG1(answer);
-			rsize = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(answer), IPC_GET_ARG3(answer));
+			rsize = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(answer),
+			    IPC_GET_ARG3(answer));
 			rlnkcnt = (unsigned) IPC_GET_ARG4(answer);
 			
@@ -276,8 +277,8 @@
 	
 	/*
-	 * For now, don't make use of ARG3, but it can be used to
-	 * carry mount options in the future.
-	 */
-	
+	 * Instance number is passed as ARG3.
+	 */
+	unsigned int instance = IPC_GET_ARG3(*request);
+
 	/* We want the client to send us the mount point. */
 	char *mp;
@@ -335,5 +336,5 @@
 	fs_handle_t fs_handle;
 recheck:
-	fs_handle = fs_name_to_handle(fs_name, false);
+	fs_handle = fs_name_to_handle(instance, fs_name, false);
 	if (!fs_handle) {
 		if (flags & IPC_FLAG_BLOCKING) {
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision dcc44ca1ab4f31d537b8abf1b1d6de5dfd97884b)
+++ uspace/srv/vfs/vfs_register.c	(revision 1db44ea7ee4de819d854c7584806a032b665d2a0)
@@ -154,5 +154,6 @@
 	 * Check for duplicit registrations.
 	 */
-	if (fs_name_to_handle(fs_info->vfs_info.name, false)) {
+	if (fs_name_to_handle(fs_info->vfs_info.instance,
+	    fs_info->vfs_info.name, false)) {
 		/*
 		 * We already register a fs like this.
@@ -297,5 +298,5 @@
  *
  */
-fs_handle_t fs_name_to_handle(char *name, bool lock)
+fs_handle_t fs_name_to_handle(unsigned int instance, char *name, bool lock)
 {
 	int handle = 0;
@@ -306,5 +307,6 @@
 	list_foreach(fs_list, cur) {
 		fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
-		if (str_cmp(fs->vfs_info.name, name) == 0) {
+		if (str_cmp(fs->vfs_info.name, name) == 0 &&
+		    instance == fs->vfs_info.instance) {
 			handle = fs->fs_handle;
 			break;
