Index: uspace/lib/ext4/libext4_filesystem.c
===================================================================
--- uspace/lib/ext4/libext4_filesystem.c	(revision fffb061c8a640cf507479b0db1f38dfff4482d99)
+++ uspace/lib/ext4/libext4_filesystem.c	(revision 1ac1ab45ddda2b390c1b5c8f669d639559500b3d)
@@ -169,4 +169,6 @@
 
 	newref->block_group = newref->block->data + offset;
+	newref->fs = fs;
+	newref->index = bgid;
 	newref->dirty = false;
 
@@ -176,4 +178,37 @@
 }
 
+static uint16_t ext4_filesystem_bg_checksum(ext4_superblock_t *sb, uint32_t bgid,
+                            ext4_block_group_t *bg)
+{
+	uint16_t crc = 0;
+
+	if (ext4_superblock_has_feature_read_only(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+
+		void *base = bg;
+		void *checksum = &bg->checksum;
+
+		uint32_t offset = (uint32_t)(checksum - base);
+
+		uint32_t le_group = host2uint32_t_le(bgid);
+
+		crc = crc16(~0, sb->uuid, sizeof(sb->uuid));
+		crc = crc16(crc, (uint8_t *)&le_group, sizeof(le_group));
+		crc = crc16(crc, (uint8_t *)bg, offset);
+
+		offset += sizeof(bg->checksum); /* skip checksum */
+
+		/* for checksum of struct ext4_group_desc do the rest...*/
+		if ((ext4_superblock_has_feature_incompatible(sb, EXT4_FEATURE_INCOMPAT_64BIT)) &&
+			offset < ext4_superblock_get_desc_size(sb)) {
+
+			crc = crc16(crc, ((uint8_t *)bg) + offset, ext4_superblock_get_desc_size(sb) - offset);
+		}
+	}
+
+	return crc;
+
+}
+
+
 int ext4_filesystem_put_block_group_ref(ext4_block_group_ref_t *ref)
 {
@@ -181,4 +216,9 @@
 
 	if (ref->dirty) {
+		 uint16_t checksum = ext4_filesystem_bg_checksum(
+				ref->fs->superblock, ref->index, ref->block_group);
+
+		 ext4_block_group_set_checksum(ref->block_group, checksum);
+
 		ref->block->dirty = true;
 	}
@@ -242,5 +282,6 @@
 	 * in the reference
 	 */
-	newref->index = index+1;
+	newref->index = index + 1;
+	newref->fs = fs;
 	newref->dirty = false;
 
@@ -321,5 +362,5 @@
 }
 
-int ext4_filesystem_free_inode(ext4_filesystem_t *fs, ext4_inode_ref_t *inode_ref)
+int ext4_filesystem_free_inode(ext4_inode_ref_t *inode_ref)
 {
 	int rc;
@@ -330,5 +371,5 @@
 	uint32_t fblock = ext4_inode_get_indirect_block(inode_ref->inode, 0);
 	if (fblock != 0) {
-		rc = ext4_balloc_free_block(fs, inode_ref, fblock);
+		rc = ext4_balloc_free_block(inode_ref, fblock);
 		if (rc != EOK) {
 			return rc;
@@ -337,4 +378,6 @@
 		ext4_inode_set_indirect_block(inode_ref->inode, 0, 0);
 	}
+
+	ext4_filesystem_t *fs = inode_ref->fs;
 
 	block_t *block;
@@ -355,5 +398,5 @@
 
 			if (ind_block != 0) {
-				rc = ext4_balloc_free_block(fs, inode_ref, ind_block);
+				rc = ext4_balloc_free_block(inode_ref, ind_block);
 				if (rc != EOK) {
 					block_put(block);
@@ -364,5 +407,5 @@
 
 		block_put(block);
-		rc = ext4_balloc_free_block(fs, inode_ref, fblock);
+		rc = ext4_balloc_free_block(inode_ref, fblock);
 		if (rc != EOK) {
 			return rc;
@@ -398,5 +441,5 @@
 
 					if (ind_subblock != 0) {
-						rc = ext4_balloc_free_block(fs, inode_ref, ind_subblock);
+						rc = ext4_balloc_free_block(inode_ref, ind_subblock);
 						if (rc != EOK) {
 							block_put(subblock);
@@ -411,5 +454,5 @@
 			}
 
-			rc = ext4_balloc_free_block(fs, inode_ref, ind_block);
+			rc = ext4_balloc_free_block(inode_ref, ind_block);
 			if (rc != EOK) {
 				block_put(block);
@@ -421,5 +464,5 @@
 
 		block_put(block);
-		rc = ext4_balloc_free_block(fs, inode_ref, fblock);
+		rc = ext4_balloc_free_block(inode_ref, fblock);
 		if (rc != EOK) {
 			return rc;
@@ -445,15 +488,17 @@
 }
 
-int ext4_filesystem_truncate_inode(ext4_filesystem_t *fs,
+int ext4_filesystem_truncate_inode(
 		ext4_inode_ref_t *inode_ref, aoff64_t new_size)
 {
 	int rc;
 
-	if (! ext4_inode_can_truncate(fs->superblock, inode_ref->inode)) {
+	ext4_superblock_t *sb = inode_ref->fs->superblock;
+
+	if (! ext4_inode_can_truncate(sb, inode_ref->inode)) {
 		// Unable to truncate
 		return EINVAL;
 	}
 
-	aoff64_t old_size = ext4_inode_get_size(fs->superblock, inode_ref->inode);
+	aoff64_t old_size = ext4_inode_get_size(sb, inode_ref->inode);
 	if (old_size == new_size) {
 		// Nothing to do
@@ -467,5 +512,5 @@
 
 	aoff64_t size_diff = old_size - new_size;
-	uint32_t block_size  = ext4_superblock_get_block_size(fs->superblock);
+	uint32_t block_size  = ext4_superblock_get_block_size(sb);
 	uint32_t diff_blocks_count = size_diff / block_size;
 	if (size_diff % block_size != 0) {
@@ -480,5 +525,5 @@
 	// starting from 1 because of logical blocks are numbered from 0
 	for (uint32_t i = 1; i <= diff_blocks_count; ++i) {
-		rc = ext4_filesystem_release_inode_block(fs, inode_ref, old_blocks_count - i);
+		rc = ext4_filesystem_release_inode_block(inode_ref, old_blocks_count - i);
 		if (rc != EOK) {
 			return rc;
@@ -493,9 +538,10 @@
 }
 
-int ext4_filesystem_get_inode_data_block_index(ext4_filesystem_t *fs,
-		ext4_inode_ref_t *inode_ref, aoff64_t iblock, uint32_t* fblock)
-{
-	int rc;
-
+int ext4_filesystem_get_inode_data_block_index(ext4_inode_ref_t *inode_ref,
+		aoff64_t iblock, uint32_t* fblock)
+{
+	int rc;
+
+	ext4_filesystem_t *fs = inode_ref->fs;
 
 	uint32_t current_block;
@@ -504,5 +550,5 @@
 	if (ext4_superblock_has_feature_incompatible(fs->superblock, EXT4_FEATURE_INCOMPAT_EXTENTS) &&
 			ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS)) {
-		rc = ext4_extent_find_block(fs, inode_ref, iblock, &current_block);
+		rc = ext4_extent_find_block(inode_ref, iblock, &current_block);
 
 		if (rc != EOK) {
@@ -591,9 +637,10 @@
 
 
-int ext4_filesystem_set_inode_data_block_index(ext4_filesystem_t *fs,
-		ext4_inode_ref_t *inode_ref, aoff64_t iblock, uint32_t fblock)
-{
-	int rc;
-
+int ext4_filesystem_set_inode_data_block_index(ext4_inode_ref_t *inode_ref,
+		aoff64_t iblock, uint32_t fblock)
+{
+	int rc;
+
+	ext4_filesystem_t *fs = inode_ref->fs;
 
 	/* Handle inode using extents */
@@ -635,5 +682,5 @@
 
 	if (current_block == 0) {
-		rc = ext4_balloc_alloc_block(fs, inode_ref, &new_block_addr);
+		rc = ext4_balloc_alloc_block(inode_ref, &new_block_addr);
 		if (rc != EOK) {
 			return rc;
@@ -646,5 +693,5 @@
 		rc = block_get(&new_block, fs->device, new_block_addr, BLOCK_FLAGS_NOREAD);
 		if (rc != EOK) {
-			ext4_balloc_free_block(fs, inode_ref, new_block_addr);
+			ext4_balloc_free_block(inode_ref, new_block_addr);
 			return rc;
 		}
@@ -674,5 +721,5 @@
 
 		if ((level > 1) && (current_block == 0)) {
-			rc = ext4_balloc_alloc_block(fs, inode_ref, &new_block_addr);
+			rc = ext4_balloc_alloc_block(inode_ref, &new_block_addr);
 			if (rc != EOK) {
 				block_put(block);
@@ -727,5 +774,5 @@
 }
 
-int ext4_filesystem_release_inode_block(ext4_filesystem_t *fs,
+int ext4_filesystem_release_inode_block(
 		ext4_inode_ref_t *inode_ref, uint32_t iblock)
 {
@@ -733,4 +780,6 @@
 
 	uint32_t fblock;
+
+	ext4_filesystem_t *fs = inode_ref->fs;
 
 	/* TODO Handle extents */
@@ -772,5 +821,5 @@
 
 		ext4_inode_set_direct_block(inode, iblock, 0);
-		return ext4_balloc_free_block(fs, inode_ref, fblock);
+		return ext4_balloc_free_block(inode_ref, fblock);
 	}
 
@@ -837,14 +886,15 @@
 	}
 
-	return ext4_balloc_free_block(fs, inode_ref, fblock);
-
-}
-
-int ext4_filesystem_add_orphan(ext4_filesystem_t *fs,
-		ext4_inode_ref_t *inode_ref)
-{
-	uint32_t next_orphan = ext4_superblock_get_last_orphan(fs->superblock);
+	return ext4_balloc_free_block(inode_ref, fblock);
+
+}
+
+int ext4_filesystem_add_orphan(ext4_inode_ref_t *inode_ref)
+{
+	uint32_t next_orphan = ext4_superblock_get_last_orphan(
+			inode_ref->fs->superblock);
 	ext4_inode_set_deletion_time(inode_ref->inode, next_orphan);
-	ext4_superblock_set_last_orphan(fs->superblock, inode_ref->index);
+	ext4_superblock_set_last_orphan(
+			inode_ref->fs->superblock, inode_ref->index);
 	inode_ref->dirty = true;
 
@@ -852,10 +902,10 @@
 }
 
-int ext4_filesystem_delete_orphan(ext4_filesystem_t *fs,
-		ext4_inode_ref_t *inode_ref)
-{
-	int rc;
-
-	uint32_t last_orphan = ext4_superblock_get_last_orphan(fs->superblock);
+int ext4_filesystem_delete_orphan(ext4_inode_ref_t *inode_ref)
+{
+	int rc;
+
+	uint32_t last_orphan = ext4_superblock_get_last_orphan(
+			inode_ref->fs->superblock);
 	assert(last_orphan > 0);
 
@@ -863,5 +913,5 @@
 
 	if (last_orphan == inode_ref->index) {
-		ext4_superblock_set_last_orphan(fs->superblock, next_orphan);
+		ext4_superblock_set_last_orphan(inode_ref->fs->superblock, next_orphan);
 		ext4_inode_set_deletion_time(inode_ref->inode, 0);
 		inode_ref->dirty = true;
@@ -870,5 +920,5 @@
 
 	ext4_inode_ref_t *current;
-	rc = ext4_filesystem_get_inode_ref(fs, last_orphan, &current);
+	rc = ext4_filesystem_get_inode_ref(inode_ref->fs, last_orphan, &current);
 	if (rc != EOK) {
 		return rc;
@@ -889,5 +939,5 @@
 		ext4_filesystem_put_inode_ref(current);
 
-		rc = ext4_filesystem_get_inode_ref(fs, next_orphan, &current);
+		rc = ext4_filesystem_get_inode_ref(inode_ref->fs, next_orphan, &current);
 		if (rc != EOK) {
 			return rc;
