Index: uspace/lib/ext4/libext4_block_group.c
===================================================================
--- uspace/lib/ext4/libext4_block_group.c	(revision cfa1a8a78358769cc6887ad85112d4e22b218b83)
+++ uspace/lib/ext4/libext4_block_group.c	(revision 3711e7ecc46c08bafffe8145e4284827e7a1deb0)
@@ -36,6 +36,12 @@
  */
 
-#include "libext4_block_group.h"
+#include <byteorder.h>
+#include "libext4.h"
 
+uint64_t ext4_block_group_get_inode_table_first_block(ext4_block_group_t *bg)
+{
+	return ((uint64_t)uint32_t_le2host(bg->inode_table_first_hi) << 32) |
+			uint32_t_le2host(bg->inode_table_first_lo);
+}
 
 /**
Index: uspace/lib/ext4/libext4_block_group.h
===================================================================
--- uspace/lib/ext4/libext4_block_group.h	(revision cfa1a8a78358769cc6887ad85112d4e22b218b83)
+++ uspace/lib/ext4/libext4_block_group.h	(revision 3711e7ecc46c08bafffe8145e4284827e7a1deb0)
@@ -34,6 +34,7 @@
 #define LIBEXT4_LIBEXT4_BLOCK_GROUP_H_
 
+#include <libblock.h>
 #include <sys/types.h>
-
+#include "libext4_block_group.h"
 /*
  * Structure of a blocks group descriptor
@@ -42,5 +43,5 @@
 	uint32_t block_bitmap_lo; // Blocks bitmap block
 	uint32_t inode_bitmap_lo; // Inodes bitmap block
-	uint32_t inode_table_lo; // Inodes table block
+	uint32_t inode_table_first_lo; // Inodes table block
 	uint16_t free_blocks_count_lo; // Free blocks count
 	uint16_t free_inodes_count_lo; // Free inodes count
@@ -52,5 +53,5 @@
 	uint32_t block_bitmap_hi; // Blocks bitmap block MSB
 	uint32_t inode_bitmap_hi; // Inodes bitmap block MSB
-	uint32_t inode_table_hi; // Inodes table block MSB
+	uint32_t inode_table_first_hi; // Inodes table block MSB
 	uint16_t free_blocks_count_hi; // Free blocks count MSB
 	uint16_t free_inodes_count_hi; // Free inodes count MSB
@@ -58,5 +59,15 @@
 	uint16_t itable_unused_hi;  // Unused inodes count MSB
 	uint32_t reserved2[3]; // Padding
-} ext4_group_desc_t;
+} ext4_block_group_t;
+
+typedef struct ext4_block_group_ref {
+	block_t *block; // Reference to a block containing this block group descr
+	ext4_block_group_t *block_group;
+} ext4_block_group_ref_t;
+
+// TODO check value
+#define EXT4_BLOCK_GROUP_DESCRIPTOR_SIZE 32
+
+extern uint64_t ext4_block_group_get_inode_table_first_block(ext4_block_group_t *);
 
 #endif
Index: uspace/lib/ext4/libext4_directory.c
===================================================================
--- uspace/lib/ext4/libext4_directory.c	(revision cfa1a8a78358769cc6887ad85112d4e22b218b83)
+++ uspace/lib/ext4/libext4_directory.c	(revision 3711e7ecc46c08bafffe8145e4284827e7a1deb0)
@@ -36,5 +36,5 @@
  */
 
-#include "libext4_directory.h"
+#include "libext4.h"
 
 
Index: uspace/lib/ext4/libext4_filesystem.c
===================================================================
--- uspace/lib/ext4/libext4_filesystem.c	(revision cfa1a8a78358769cc6887ad85112d4e22b218b83)
+++ uspace/lib/ext4/libext4_filesystem.c	(revision 3711e7ecc46c08bafffe8145e4284827e7a1deb0)
@@ -38,5 +38,5 @@
 #include <errno.h>
 #include <malloc.h>
-#include "libext4_filesystem.h"
+#include "libext4.h"
 
 /**
@@ -83,4 +83,13 @@
 
 	return EOK;
+}
+
+/**
+ * TODO doxy
+ */
+void ext4_filesystem_fini(ext4_filesystem_t *fs)
+{
+	free(fs->superblock);
+	block_fini(fs->device);
 }
 
@@ -132,10 +141,107 @@
  * TODO doxy
  */
-void ext4_filesystem_fini(ext4_filesystem_t *fs)
-{
-	free(fs->superblock);
-	block_fini(fs->device);
-}
-
+int ext4_filesystem_get_block_group_ref(ext4_filesystem_t *fs, uint32_t bgid,
+    ext4_block_group_ref_t **ref)
+{
+	int rc;
+	aoff64_t block_id;
+	uint32_t descriptors_per_block;
+	size_t offset;
+	ext4_block_group_ref_t *newref;
+
+	newref = malloc(sizeof(ext4_block_group_ref_t));
+	if (newref == NULL) {
+		return ENOMEM;
+	}
+
+	descriptors_per_block = ext4_superblock_get_block_size(fs->superblock)
+	    / EXT4_BLOCK_GROUP_DESCRIPTOR_SIZE;
+
+	/* Block group descriptor table starts at the next block after superblock */
+	block_id = ext4_superblock_get_first_block(fs->superblock) + 1;
+
+	/* Find the block containing the descriptor we are looking for */
+	block_id += bgid / descriptors_per_block;
+	offset = (bgid % descriptors_per_block) * EXT4_BLOCK_GROUP_DESCRIPTOR_SIZE;
+
+	rc = block_get(&newref->block, fs->device, block_id, 0);
+	if (rc != EOK) {
+		free(newref);
+		return rc;
+	}
+
+	newref->block_group = newref->block->data + offset;
+
+	*ref = newref;
+
+	return EOK;
+}
+
+/**
+ * TODO doxy
+ */
+int ext4_filesystem_get_inode_ref(ext4_filesystem_t *fs, uint32_t index,
+    ext4_inode_ref_t **ref)
+{
+	int rc;
+	aoff64_t block_id;
+	uint32_t block_group;
+	uint32_t offset_in_group;
+	uint32_t byte_offset_in_group;
+	size_t offset_in_block;
+	uint32_t inodes_per_group;
+	uint32_t inode_table_start;
+	uint16_t inode_size;
+	uint32_t block_size;
+	ext4_block_group_ref_t *bg_ref;
+	ext4_inode_ref_t *newref;
+
+	newref = malloc(sizeof(ext4_inode_ref_t));
+	if (newref == NULL) {
+		return ENOMEM;
+	}
+
+	inodes_per_group = ext4_superblock_get_inodes_per_group(fs->superblock);
+
+	/* inode numbers are 1-based, but it is simpler to work with 0-based
+	 * when computing indices
+	 */
+	index -= 1;
+	block_group = index / inodes_per_group;
+	offset_in_group = index % inodes_per_group;
+
+	rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
+	if (rc != EOK) {
+		free(newref);
+		return rc;
+	}
+
+	inode_table_start = ext4_block_group_get_inode_table_first_block(
+	    bg_ref->block_group);
+
+	inode_size = ext4_superblock_get_inode_size(fs->superblock);
+	block_size = ext4_superblock_get_block_size(fs->superblock);
+
+	byte_offset_in_group = offset_in_group * inode_size;
+
+	block_id = inode_table_start + (byte_offset_in_group / block_size);
+	offset_in_block = byte_offset_in_group % block_size;
+
+	rc = block_get(&newref->block, fs->device, block_id, 0);
+	if (rc != EOK) {
+		free(newref);
+		return rc;
+	}
+
+	newref->inode = newref->block->data + offset_in_block;
+	/* we decremented index above, but need to store the original value
+	 * in the reference
+	 */
+	newref->index = index+1;
+
+	*ref = newref;
+
+	return EOK;
+}
 
 /**
Index: uspace/lib/ext4/libext4_filesystem.h
===================================================================
--- uspace/lib/ext4/libext4_filesystem.h	(revision cfa1a8a78358769cc6887ad85112d4e22b218b83)
+++ uspace/lib/ext4/libext4_filesystem.h	(revision 3711e7ecc46c08bafffe8145e4284827e7a1deb0)
@@ -35,4 +35,6 @@
 
 #include <libblock.h>
+#include "libext4_block_group.h"
+#include "libext4_inode.h"
 #include "libext4_superblock.h"
 
@@ -42,6 +44,6 @@
 } ext4_filesystem_t;
 
-#define EXT4_MAX_BLOCK_SIZE 65536 //64 KiB
-
+#define EXT4_MAX_BLOCK_SIZE 	65536 //64 KiB
+#define EXT4_REV0_INODE_SIZE	128
 
 /* Compatible features */
@@ -99,7 +101,12 @@
 
 extern int ext4_filesystem_init(ext4_filesystem_t *, service_id_t);
+extern void ext4_filesystem_fini(ext4_filesystem_t *fs);
 extern int ext4_filesystem_check_sanity(ext4_filesystem_t *fs);
 extern int ext4_filesystem_check_features(ext4_filesystem_t *, bool *);
-extern void ext4_filesystem_fini(ext4_filesystem_t *fs);
+extern int ext4_filesystem_get_block_group_ref(ext4_filesystem_t *, uint32_t,
+    ext4_block_group_ref_t **);
+extern int ext4_filesystem_get_inode_ref(ext4_filesystem_t *, uint32_t,
+		ext4_inode_ref_t **);
+
 
 #endif
Index: uspace/lib/ext4/libext4_inode.c
===================================================================
--- uspace/lib/ext4/libext4_inode.c	(revision cfa1a8a78358769cc6887ad85112d4e22b218b83)
+++ uspace/lib/ext4/libext4_inode.c	(revision 3711e7ecc46c08bafffe8145e4284827e7a1deb0)
@@ -37,5 +37,5 @@
 
 #include <byteorder.h>
-#include "libext4_inode.h"
+#include "libext4.h"
 
 // TODO check return type
Index: uspace/lib/ext4/libext4_superblock.c
===================================================================
--- uspace/lib/ext4/libext4_superblock.c	(revision cfa1a8a78358769cc6887ad85112d4e22b218b83)
+++ uspace/lib/ext4/libext4_superblock.c	(revision 3711e7ecc46c08bafffe8145e4284827e7a1deb0)
@@ -40,5 +40,5 @@
 #include <libblock.h>
 #include <malloc.h>
-#include "libext4_superblock.h"
+#include "libext4.h"
 
 /**
@@ -80,4 +80,23 @@
 {
 	return uint32_t_le2host(sb->rev_level);
+}
+
+/**
+ * TODO doxy
+ */
+uint16_t ext4_superblock_get_inode_size(ext4_superblock_t *sb)
+{
+	if (ext4_superblock_get_rev_level(sb) == 0) {
+		return EXT4_REV0_INODE_SIZE;
+	}
+	return uint16_t_le2host(sb->inode_size);
+}
+
+/**
+ * TODO doxy
+ */
+uint32_t ext4_superblock_get_inodes_per_group(ext4_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->inodes_per_group);
 }
 
Index: uspace/lib/ext4/libext4_superblock.h
===================================================================
--- uspace/lib/ext4/libext4_superblock.h	(revision cfa1a8a78358769cc6887ad85112d4e22b218b83)
+++ uspace/lib/ext4/libext4_superblock.h	(revision 3711e7ecc46c08bafffe8145e4284827e7a1deb0)
@@ -51,5 +51,5 @@
 	uint32_t s_blocks_per_group; // Number of blocks per group
 	uint32_t s_obso_frags_per_group; // Obsoleted fragments per group
-	uint32_t s_inodes_per_group; // Number of inodes per group
+	uint32_t inodes_per_group; // Number of inodes per group
 	uint32_t s_mtime; // Mount time
 	uint32_t s_wtime; // Write time
@@ -69,5 +69,5 @@
 	// Fields for EXT4_DYNAMIC_REV superblocks only.
 	uint32_t s_first_ino; // First non-reserved inode
-	uint16_t s_inode_size; // Size of inode structure
+	uint16_t inode_size; // Size of inode structure
 	uint16_t s_block_group_nr; // Block group number of this superblock
 	uint32_t features_compatible; // Compatible feature set
@@ -147,4 +147,6 @@
 extern uint32_t ext4_superblock_get_block_size(ext4_superblock_t *);
 extern uint32_t	ext4_superblock_get_rev_level(ext4_superblock_t *);
+extern uint16_t	ext4_superblock_get_inode_size(ext4_superblock_t *);
+extern uint32_t	ext4_superblock_get_inodes_per_group(ext4_superblock_t *);
 extern uint32_t	ext4_superblock_get_features_compatible(ext4_superblock_t *);
 extern uint32_t	ext4_superblock_get_features_incompatible(ext4_superblock_t *);
