Index: uspace/lib/ext2/Makefile
===================================================================
--- uspace/lib/ext2/Makefile	(revision 1d6f507f0b213da5fe9346663a8a45869e166812)
+++ uspace/lib/ext2/Makefile	(revision d241aae2bcae062a85266628d2e2c611d2dee48a)
@@ -36,5 +36,6 @@
 SOURCES = \
 	libext2_filesystem.c \
-	libext2_superblock.c
+	libext2_superblock.c \
+	libext2_block_group.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/ext2/libext2.h
===================================================================
--- uspace/lib/ext2/libext2.h	(revision 1d6f507f0b213da5fe9346663a8a45869e166812)
+++ uspace/lib/ext2/libext2.h	(revision d241aae2bcae062a85266628d2e2c611d2dee48a)
@@ -38,4 +38,5 @@
 
 #include "libext2_superblock.h"
+#include "libext2_block_group.h"
 #include "libext2_filesystem.h"
 
Index: uspace/lib/ext2/libext2_block_group.c
===================================================================
--- uspace/lib/ext2/libext2_block_group.c	(revision d241aae2bcae062a85266628d2e2c611d2dee48a)
+++ uspace/lib/ext2/libext2_block_group.c	(revision d241aae2bcae062a85266628d2e2c611d2dee48a)
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 libext2
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include "libext2.h"
+#include "libext2_block_group.h"
+#include <byteorder.h>
+
+/**
+ * Get block ID corresponding to the block bitmap of this block group
+ * 
+ * @param bg pointer to block group descriptor
+ */
+inline uint32_t	ext2_block_group_get_block_bitmap_block(ext2_block_group_t *bg)
+{
+	return uint32_t_le2host(bg->block_bitmap_block);
+}
+
+/**
+ * Get block ID corresponding to the inode bitmap of this block group
+ * 
+ * @param bg pointer to block group descriptor
+ */
+inline uint32_t	ext2_block_group_get_inode_bitmap_block(ext2_block_group_t *bg)
+{
+	return uint32_t_le2host(bg->inode_bitmap_block);
+}
+
+/**
+ * Get block ID of first block in inode table
+ * 
+ * @param bg pointer to block group descriptor
+ */
+inline uint32_t	ext2_block_group_get_inode_table_first_block(ext2_block_group_t *bg)
+{
+	return uint32_t_le2host(bg->inode_table_first_block);
+}
+
+/**
+ * Get amount of free blocks in this block group
+ * 
+ * @param bg pointer to block group descriptor
+ */
+inline uint16_t	ext2_block_group_get_free_block_count(ext2_block_group_t *bg)
+{
+	return uint16_t_le2host(bg->free_block_count);
+}
+
+/**
+ * Get amount of free inodes in this block group
+ * 
+ * @param bg pointer to block group descriptor
+ */
+inline uint16_t	ext2_block_group_get_free_inode_count(ext2_block_group_t *bg)
+{
+	return uint16_t_le2host(bg->free_inode_count);
+}
+
+/**
+ * Get amount of inodes allocated for directories
+ * 
+ * @param bg pointer to block group descriptor
+ */
+inline uint16_t	ext2_block_group_get_directory_inode_count(ext2_block_group_t *bg)
+{
+	return uint16_t_le2host(bg->directory_inode_count);
+}
+
+
+/** @}
+ */
Index: uspace/lib/ext2/libext2_block_group.h
===================================================================
--- uspace/lib/ext2/libext2_block_group.h	(revision d241aae2bcae062a85266628d2e2c611d2dee48a)
+++ uspace/lib/ext2/libext2_block_group.h	(revision d241aae2bcae062a85266628d2e2c611d2dee48a)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 libext2
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef LIBEXT2_LIBEXT2_BLOCK_GROUP_H_
+#define LIBEXT2_LIBEXT2_BLOCK_GROUP_H_
+
+#include <libblock.h>
+
+typedef struct ext2_block_group {
+	uint32_t block_bitmap_block; // Block ID for block bitmap
+	uint32_t inode_bitmap_block; // Block ID for inode bitmap
+	uint32_t inode_table_first_block; // Block ID of first block of inode table 
+	uint16_t free_block_count; // Count of free blocks
+	uint16_t free_inode_count; // Count of free inodes
+	uint16_t directory_inode_count; // Number of inodes allocated to directories
+} ext2_block_group_t;
+
+typedef struct ext2_block_group_ref {
+	block_t *block; // Reference to a block containing this block group descr
+	ext2_block_group_t *block_group;
+} ext2_block_group_ref_t;
+
+#define EXT2_BLOCK_GROUP_DESCRIPTOR_SIZE 32
+
+inline uint32_t	ext2_block_group_get_block_bitmap_block(ext2_block_group_t *);
+inline uint32_t	ext2_block_group_get_inode_bitmap_block(ext2_block_group_t *);
+inline uint32_t	ext2_block_group_get_inode_table_first_block(ext2_block_group_t *);
+inline uint16_t	ext2_block_group_get_free_block_count(ext2_block_group_t *);
+inline uint16_t	ext2_block_group_get_free_inode_count(ext2_block_group_t *);
+inline uint16_t	ext2_block_group_get_directory_inode_count(ext2_block_group_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/ext2/libext2_filesystem.c
===================================================================
--- uspace/lib/ext2/libext2_filesystem.c	(revision 1d6f507f0b213da5fe9346663a8a45869e166812)
+++ uspace/lib/ext2/libext2_filesystem.c	(revision d241aae2bcae062a85266628d2e2c611d2dee48a)
@@ -34,5 +34,7 @@
  */
 
-#include "libext2.h"
+#include "libext2_filesystem.h"
+#include "libext2_superblock.h"
+#include "libext2_block_group.h"
 #include <errno.h>
 #include <libblock.h>
@@ -105,4 +107,67 @@
 
 /**
+ * Get a reference to block descriptor
+ * 
+ * @param fs Pointer to filesystem information
+ * @param bgid Index of block group to find
+ * @param ref Pointer where to store pointer to block group reference
+ * 
+ * @return 		EOK on success or negative error code on failure
+ */
+int ext2_filesystem_get_block_group_ref(ext2_filesystem_t *fs, uint32_t bgid,
+    ext2_block_group_ref_t **ref)
+{
+	int rc;
+	aoff64_t block_id;
+	uint32_t descriptors_per_block;
+	size_t offset;
+	ext2_block_group_ref_t *newref;
+	
+	newref = malloc(sizeof(ext2_block_group_ref_t));
+	if (newref == NULL) {
+		return ENOMEM;
+	}
+	
+	descriptors_per_block = ext2_superblock_get_block_size(fs->superblock)
+	    / EXT2_BLOCK_GROUP_DESCRIPTOR_SIZE;
+	
+	// Block group descriptor table starts at the next block after superblock
+	block_id = ext2_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) * EXT2_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;
+}
+
+/**
+ * Free a reference to block group
+ * 
+ * @param ref Pointer to block group reference to free
+ * 
+ * @return 		EOK on success or negative error code on failure
+ */
+int ext2_filesystem_put_block_group_ref(ext2_block_group_ref_t *ref)
+{
+	int rc;
+	
+	rc = block_put(ref->block);
+	free(ref);
+	
+	return rc;
+}
+
+/**
  * Finalize an instance of filesystem
  * 
Index: uspace/lib/ext2/libext2_filesystem.h
===================================================================
--- uspace/lib/ext2/libext2_filesystem.h	(revision 1d6f507f0b213da5fe9346663a8a45869e166812)
+++ uspace/lib/ext2/libext2_filesystem.h	(revision d241aae2bcae062a85266628d2e2c611d2dee48a)
@@ -39,4 +39,5 @@
 #include <libblock.h>
 #include "libext2_superblock.h"
+#include "libext2_block_group.h"
 
 typedef struct ext2_filesystem {
@@ -52,4 +53,7 @@
 extern int ext2_filesystem_init(ext2_filesystem_t *, devmap_handle_t);
 extern int ext2_filesystem_check_sanity(ext2_filesystem_t *);
+extern int ext2_filesystem_get_block_group_ref(ext2_filesystem_t *, uint32_t, 
+    ext2_block_group_ref_t **);
+extern int ext2_filesystem_put_block_group_ref(ext2_block_group_ref_t *);
 extern void ext2_filesystem_fini(ext2_filesystem_t *);
 
Index: uspace/lib/ext2/libext2_superblock.c
===================================================================
--- uspace/lib/ext2/libext2_superblock.c	(revision 1d6f507f0b213da5fe9346663a8a45869e166812)
+++ uspace/lib/ext2/libext2_superblock.c	(revision d241aae2bcae062a85266628d2e2c611d2dee48a)
@@ -260,10 +260,31 @@
  * Compute count of block groups present in the filesystem
  * 
+ * Note: This function works only for correct filesystem,
+ *       i.e. it assumes that total block count > 0 and
+ *       blocks per group > 0
+ * 
+ * Example:
+ *   If there are 3 blocks per group, the result should be as follows:
+ *   Total blocks	Result
+ *   1				1
+ *   2				1
+ *   3				1
+ *   4				2
+ * 
+ * 
  * @param sb pointer to superblock
  */
 inline uint32_t ext2_superblock_get_block_group_count(ext2_superblock_t *sb)
 {
-	return ext2_superblock_get_total_block_count(sb) / 
-	    ext2_superblock_get_blocks_per_group(sb);
+	/* We add one to the result because e.g. 2/3 = 0, while to store
+	 *  2 blocks in 3-block group we need one (1) block group
+	 * 
+	 * We subtract one first because of special case that to store e.g.
+	 *  3 blocks in a 3-block group we need only one group
+	 *  (and 3/3 yields one - this is one more that we want as we
+	 *   already add one at the end)
+	 */ 
+	return ((ext2_superblock_get_total_block_count(sb)-1) / 
+	    ext2_superblock_get_blocks_per_group(sb))+1;
 }
 
