shithub: lwext4

Download patch

ref: 0c7f3604a3e2f26da99f8e126098ce8520139fbd
parent: f3e06a2a6d91b4502fb0e0f70a79fb6daaf601e1
author: ngkaho1234 <ngkaho1234@gmail.com>
date: Mon Dec 28 08:05:04 EST 2015

Introduce initial support of ext3/4 journalling.

To achieve this, a glue layer between block cache and lwext4 core routines
is added.

--- a/lwext4/ext4.c
+++ b/lwext4/ext4.c
@@ -251,7 +251,7 @@
 				return EIO;
 
 			ext4_dir_en_set_inode(res.dentry, parent->index);
-			ext4_bcache_set_dirty(res.block.buf);
+			ext4_trans_set_block_dirty(res.block.buf);
 			r = ext4_dir_destroy_result(ch, &res);
 			if (r != EOK)
 				return r;
@@ -414,6 +414,7 @@
 		}
 		return r;
 	}
+	bd->fs = &mp->fs;
 
 	return r;
 }
@@ -437,7 +438,7 @@
 
 	r = ext4_fs_fini(&mp->fs);
 	if (r != EOK)
-		return r;
+		goto Finish;
 
 	mp->mounted = 0;
 
@@ -446,8 +447,10 @@
 		ext4_bcache_fini_dynamic(mp->fs.bdev->bc);
 		free(mp->fs.bdev->bc);
 	}
-
-	return ext4_block_fini(mp->fs.bdev);
+	r = ext4_block_fini(mp->fs.bdev);
+Finish:
+	mp->fs.bdev->fs = NULL;
+	return r;
 }
 
 static struct ext4_mountpoint *ext4_get_mount(const char *path)
@@ -594,29 +597,6 @@
 	}
 }
 
-int ext4_trans_get_write_access(struct ext4_fs *fs,
-				struct ext4_block *block)
-{
-	int r = EOK;
-	if (fs->jbd_journal && fs->curr_trans) {
-		struct jbd_journal *journal = fs->jbd_journal;
-		struct jbd_trans *trans = fs->curr_trans;
-		r = jbd_trans_get_access(journal, trans, block);
-	}
-	return r;
-}
-
-int ext4_trans_set_block_dirty(struct ext4_fs *fs,
-			 struct ext4_block *block)
-{
-	int r = EOK;
-	if (fs->jbd_journal && fs->curr_trans) {
-		struct jbd_trans *trans = fs->curr_trans;
-		r = jbd_trans_set_block_dirty(trans, block);
-	}
-	return r;
-}
-
 int ext4_mount_point_stats(const char *mount_point,
 			   struct ext4_mount_stats *stats)
 {
@@ -2134,6 +2114,12 @@
 
 Finish:
 	ext4_block_cache_write_back(mp->fs.bdev, 0);
+
+	if (r != EOK)
+		ext4_trans_abort(mp);
+	else
+		ext4_trans_stop(mp);
+
 	EXT4_MP_UNLOCK(mp);
 	return r;
 }
@@ -2195,6 +2181,8 @@
 		return EINVAL;
 
 	EXT4_MP_LOCK(mp);
+	ext4_trans_start(mp);
+
 	r = ext4_generic_open2(&f, path, O_RDWR, EXT4_DE_UNKNOWN, NULL, NULL);
 	if (r != EOK)
 		goto Finish;
@@ -2217,6 +2205,11 @@
 	ext4_fs_put_xattr_ref(&xattr_ref);
 	ext4_fs_put_inode_ref(&inode_ref);
 Finish:
+	if (r != EOK)
+		ext4_trans_abort(mp);
+	else
+		ext4_trans_stop(mp);
+
 	EXT4_MP_UNLOCK(mp);
 	return r;
 }
@@ -2377,6 +2370,8 @@
 		return EINVAL;
 
 	EXT4_MP_LOCK(mp);
+	ext4_trans_start(mp);
+
 	r = ext4_generic_open2(&f, path, O_RDWR, EXT4_DE_UNKNOWN, NULL, NULL);
 	if (r != EOK)
 		goto Finish;
@@ -2399,6 +2394,11 @@
 	ext4_fs_put_xattr_ref(&xattr_ref);
 	ext4_fs_put_inode_ref(&inode_ref);
 Finish:
+	if (r != EOK)
+		ext4_trans_abort(mp);
+	else
+		ext4_trans_stop(mp);
+
 	EXT4_MP_UNLOCK(mp);
 	return r;
 
--- a/lwext4/ext4.h
+++ b/lwext4/ext4.h
@@ -182,6 +182,9 @@
  * @return  standard error code */
 int ext4_umount(const char *mount_point);
 
+int ext4_journal_start(const char *mount_point);
+
+int ext4_journal_stop(const char *mount_point);
 
 /**@brief   Journal recovery.
  * @param   mount_point mount point
--- a/lwext4/ext4_balloc.c
+++ b/lwext4/ext4_balloc.c
@@ -165,7 +165,7 @@
 
 	struct ext4_block bitmap_block;
 
-	rc = ext4_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);
+	rc = ext4_trans_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);
 	if (rc != EOK) {
 		ext4_fs_put_block_group_ref(&bg_ref);
 		return rc;
@@ -181,7 +181,7 @@
 	/* Modify bitmap */
 	ext4_bmap_bit_clr(bitmap_block.data, index_in_group);
 	ext4_balloc_set_bitmap_csum(sb, bg, bitmap_block.data);
-	ext4_bcache_set_dirty(bitmap_block.buf);
+	ext4_trans_set_block_dirty(bitmap_block.buf);
 
 	/* Release block with bitmap */
 	rc = ext4_block_set(fs->bdev, &bitmap_block);
@@ -211,6 +211,12 @@
 
 	bg_ref.dirty = true;
 
+	rc = ext4_trans_try_revoke_block(fs->bdev, baddr);
+	if (rc != EOK) {
+		bg_ref.dirty = false;
+		ext4_fs_put_block_group_ref(&bg_ref);
+		return rc;
+	}
 	ext4_bcache_invalidate_lba(fs->bdev->bc, baddr, 1);
 	/* Release block group reference */
 	return ext4_fs_put_block_group_ref(&bg_ref);
@@ -256,7 +262,7 @@
 		ext4_fsblk_t bitmap_blk = ext4_bg_get_block_bitmap(bg, sb);
 
 		struct ext4_block blk;
-		rc = ext4_block_get(fs->bdev, &blk, bitmap_blk);
+		rc = ext4_trans_block_get(fs->bdev, &blk, bitmap_blk);
 		if (rc != EOK) {
 			ext4_fs_put_block_group_ref(&bg_ref);
 			return rc;
@@ -277,7 +283,7 @@
 		/* Modify bitmap */
 		ext4_bmap_bits_free(blk.data, idx_in_bg_first, free_cnt);
 		ext4_balloc_set_bitmap_csum(sb, bg, blk.data);
-		ext4_bcache_set_dirty(blk.buf);
+		ext4_trans_set_block_dirty(blk.buf);
 
 		count -= free_cnt;
 		first += free_cnt;
@@ -318,6 +324,14 @@
 		bg_first++;
 	}
 
+	uint32_t i;
+	for (i = 0;i < count;i++) {
+		rc = ext4_trans_try_revoke_block(fs->bdev, first + i);
+		if (rc != EOK)
+			return rc;
+
+	}
+
 	ext4_bcache_invalidate_lba(fs->bdev->bc, first, count);
 	/*All blocks should be released*/
 	ext4_assert(count == 0);
@@ -368,7 +382,7 @@
 	/* Load block with bitmap */
 	bmp_blk_adr = ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
 
-	r = ext4_block_get(inode_ref->fs->bdev, &b, bmp_blk_adr);
+	r = ext4_trans_block_get(inode_ref->fs->bdev, &b, bmp_blk_adr);
 	if (r != EOK) {
 		ext4_fs_put_block_group_ref(&bg_ref);
 		return r;
@@ -386,7 +400,7 @@
 		ext4_bmap_bit_set(b.data, idx_in_bg);
 		ext4_balloc_set_bitmap_csum(sb, bg_ref.block_group,
 					    b.data);
-		ext4_bcache_set_dirty(b.buf);
+		ext4_trans_set_block_dirty(b.buf);
 		r = ext4_block_set(inode_ref->fs->bdev, &b);
 		if (r != EOK) {
 			ext4_fs_put_block_group_ref(&bg_ref);
@@ -410,7 +424,7 @@
 			ext4_bmap_bit_set(b.data, tmp_idx);
 
 			ext4_balloc_set_bitmap_csum(sb, bg, b.data);
-			ext4_bcache_set_dirty(b.buf);
+			ext4_trans_set_block_dirty(b.buf);
 			r = ext4_block_set(inode_ref->fs->bdev, &b);
 			if (r != EOK)
 				return r;
@@ -425,7 +439,7 @@
 	if (r == EOK) {
 		ext4_bmap_bit_set(b.data, rel_blk_idx);
 		ext4_balloc_set_bitmap_csum(sb, bg_ref.block_group, b.data);
-		ext4_bcache_set_dirty(b.buf);
+		ext4_trans_set_block_dirty(b.buf);
 		r = ext4_block_set(inode_ref->fs->bdev, &b);
 		if (r != EOK)
 			return r;
@@ -466,7 +480,7 @@
 
 		/* Load block with bitmap */
 		bmp_blk_adr = ext4_bg_get_block_bitmap(bg, sb);
-		r = ext4_block_get(inode_ref->fs->bdev, &b, bmp_blk_adr);
+		r = ext4_trans_block_get(inode_ref->fs->bdev, &b, bmp_blk_adr);
 		if (r != EOK) {
 			ext4_fs_put_block_group_ref(&bg_ref);
 			return r;
@@ -493,7 +507,7 @@
 		if (r == EOK) {
 			ext4_bmap_bit_set(b.data, rel_blk_idx);
 			ext4_balloc_set_bitmap_csum(sb, bg, b.data);
-			ext4_bcache_set_dirty(b.buf);
+			ext4_trans_set_block_dirty(b.buf);
 			r = ext4_block_set(inode_ref->fs->bdev, &b);
 			if (r != EOK) {
 				ext4_fs_put_block_group_ref(&bg_ref);
@@ -576,7 +590,7 @@
 	bmp_blk_addr = ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
 
 	struct ext4_block b;
-	rc = ext4_block_get(fs->bdev, &b, bmp_blk_addr);
+	rc = ext4_trans_block_get(fs->bdev, &b, bmp_blk_addr);
 	if (rc != EOK) {
 		ext4_fs_put_block_group_ref(&bg_ref);
 		return rc;
@@ -596,7 +610,7 @@
 	if (*free) {
 		ext4_bmap_bit_set(b.data, index_in_group);
 		ext4_balloc_set_bitmap_csum(sb, bg_ref.block_group, b.data);
-		ext4_bcache_set_dirty(b.buf);
+		ext4_trans_set_block_dirty(b.buf);
 	}
 
 	/* Release block with bitmap */
--- a/lwext4/ext4_bcache.c
+++ b/lwext4/ext4_bcache.c
@@ -132,6 +132,7 @@
 
 	buf->lba = lba;
 	buf->data = data;
+	buf->bc = bc;
 	return buf;
 }
 
--- a/lwext4/ext4_bcache.h
+++ b/lwext4/ext4_bcache.h
@@ -85,6 +85,9 @@
 	/**@brief   Reference count table*/
 	uint32_t refctr;
 
+	/**@brief   The block cache this buffer belongs to. */
+	struct ext4_bcache *bc;
+
 	/**@brief   Whether or not buffer is on dirty list.*/
 	bool on_dirty_list;
 
--- a/lwext4/ext4_blockdev.h
+++ b/lwext4/ext4_blockdev.h
@@ -42,6 +42,7 @@
 
 #include "ext4_config.h"
 #include "ext4_bcache.h"
+#include "ext4_trans.h"
 #include "ext4_debug.h"
 
 #include <stdbool.h>
@@ -122,6 +123,9 @@
 
 	/**@brief   Cache write back mode reference counter*/
 	uint32_t cache_write_back;
+
+	/**@brief   The filesystem this block device belongs to. */
+	struct ext4_fs *fs;
 };
 
 /**@brief   Static initialization of the block device.*/
--- a/lwext4/ext4_dir.c
+++ b/lwext4/ext4_dir.c
@@ -239,7 +239,7 @@
 		if (r != EOK)
 			return r;
 
-		r = ext4_block_get(bdev, &it->curr_blk, next_blk);
+		r = ext4_trans_block_get(bdev, &it->curr_blk, next_blk);
 		if (r != EOK) {
 			it->curr_blk.lb_id = 0;
 			return r;
@@ -364,7 +364,7 @@
 			return r;
 
 		struct ext4_block block;
-		r = ext4_block_get(fs->bdev, &block, fblock);
+		r = ext4_trans_block_get(fs->bdev, &block, fblock);
 		if (r != EOK)
 			return r;
 
@@ -402,7 +402,7 @@
 	/* Load new block */
 	struct ext4_block b;
 
-	r = ext4_block_get_noread(fs->bdev, &b, fblock);
+	r = ext4_trans_block_get_noread(fs->bdev, &b, fblock);
 	if (r != EOK)
 		return r;
 
@@ -421,7 +421,7 @@
 	}
 
 	ext4_dir_set_csum(parent, (void *)b.data);
-	ext4_bcache_set_dirty(b.buf);
+	ext4_trans_set_block_dirty(b.buf);
 	r = ext4_block_set(fs->bdev, &b);
 
 	return r;
@@ -474,7 +474,7 @@
 
 		/* Load data block */
 		struct ext4_block b;
-		r = ext4_block_get(parent->fs->bdev, &b, fblock);
+		r = ext4_trans_block_get(parent->fs->bdev, &b, fblock);
 		if (r != EOK)
 			return r;
 
@@ -554,7 +554,7 @@
 
 	ext4_dir_set_csum(parent,
 			(struct ext4_dir_en *)result.block.data);
-	ext4_bcache_set_dirty(result.block.buf);
+	ext4_trans_set_block_dirty(result.block.buf);
 
 	return ext4_dir_destroy_result(parent, &result);
 }
@@ -591,7 +591,7 @@
 			ext4_dir_write_entry(sb, start, rec_len, child, name,
 					     name_len);
 			ext4_dir_set_csum(inode_ref, (void *)dst_blk->data);
-			ext4_bcache_set_dirty(dst_blk->buf);
+			ext4_trans_set_block_dirty(dst_blk->buf);
 
 			return EOK;
 		}
@@ -620,7 +620,7 @@
 
 				ext4_dir_set_csum(inode_ref,
 						  (void *)dst_blk->data);
-				ext4_bcache_set_dirty(dst_blk->buf);
+				ext4_trans_set_block_dirty(dst_blk->buf);
 				return EOK;
 			}
 		}
--- a/lwext4/ext4_dir_idx.c
+++ b/lwext4/ext4_dir_idx.c
@@ -353,7 +353,7 @@
 		return rc;
 
 	struct ext4_block block;
-	rc = ext4_block_get_noread(dir->fs->bdev, &block, fblock);
+	rc = ext4_trans_block_get_noread(dir->fs->bdev, &block, fblock);
 	if (rc != EOK)
 		return rc;
 
@@ -403,7 +403,7 @@
 	}
 
 	struct ext4_block new_block;
-	rc = ext4_block_get_noread(dir->fs->bdev, &new_block, fblock);
+	rc = ext4_trans_block_get_noread(dir->fs->bdev, &new_block, fblock);
 	if (rc != EOK) {
 		ext4_block_set(dir->fs->bdev, &block);
 		return rc;
@@ -425,7 +425,7 @@
 
 	ext4_dir_en_set_inode(be, 0);
 
-	ext4_bcache_set_dirty(new_block.buf);
+	ext4_trans_set_block_dirty(new_block.buf);
 	rc = ext4_block_set(dir->fs->bdev, &new_block);
 	if (rc != EOK) {
 		ext4_block_set(dir->fs->bdev, &block);
@@ -437,7 +437,7 @@
 	ext4_dir_dx_entry_set_block(entry, iblock);
 
 	ext4_dir_set_dx_csum(dir, (struct ext4_dir_en *)block.data);
-	ext4_bcache_set_dirty(block.buf);
+	ext4_trans_set_block_dirty(block.buf);
 
 	return ext4_block_set(dir->fs->bdev, &block);
 }
@@ -580,7 +580,7 @@
 		if (r != EOK)
 			return r;
 
-		r = ext4_block_get(inode_ref->fs->bdev, tmp_blk, fblk);
+		r = ext4_trans_block_get(inode_ref->fs->bdev, tmp_blk, fblk);
 		if (r != EOK)
 			return r;
 
@@ -662,7 +662,7 @@
 			return r;
 
 		struct ext4_block b;
-		r = ext4_block_get(inode_ref->fs->bdev, &b, blk_adr);
+		r = ext4_trans_block_get(inode_ref->fs->bdev, &b, blk_adr);
 		if (r != EOK)
 			return r;
 
@@ -705,7 +705,7 @@
 	struct ext4_fs *fs = inode_ref->fs;
 
 	struct ext4_block root_block;
-	rc = ext4_block_get(fs->bdev, &root_block, root_block_addr);
+	rc = ext4_trans_block_get(fs->bdev, &root_block, root_block_addr);
 	if (rc != EOK)
 		return rc;
 
@@ -753,7 +753,7 @@
 		if (rc != EOK)
 			goto cleanup;
 
-		rc = ext4_block_get(fs->bdev, &b, leaf_block_addr);
+		rc = ext4_trans_block_get(fs->bdev, &b, leaf_block_addr);
 		if (rc != EOK)
 			goto cleanup;
 
@@ -897,7 +897,7 @@
 	ext4_dir_dx_entry_set_hash(new_index_entry, hash);
 	ext4_dir_dx_climit_set_count(climit, count + 1);
 	ext4_dir_set_dx_csum(inode_ref, (void *)index_block->b.data);
-	ext4_bcache_set_dirty(index_block->b.buf);
+	ext4_trans_set_block_dirty(index_block->b.buf);
 }
 
 /**@brief Split directory entries to two parts preventing node overflow.
@@ -994,7 +994,7 @@
 
 	/* Load new block */
 	struct ext4_block new_data_block_tmp;
-	rc = ext4_block_get_noread(inode_ref->fs->bdev, &new_data_block_tmp,
+	rc = ext4_trans_block_get_noread(inode_ref->fs->bdev, &new_data_block_tmp,
 				   new_fblock);
 	if (rc != EOK) {
 		free(sort);
@@ -1073,8 +1073,8 @@
 	}
 	ext4_dir_set_csum(inode_ref, (void *)old_data_block->data);
 	ext4_dir_set_csum(inode_ref, (void *)new_data_block_tmp.data);
-	ext4_bcache_set_dirty(old_data_block->buf);
-	ext4_bcache_set_dirty(new_data_block_tmp.buf);
+	ext4_trans_set_block_dirty(old_data_block->buf);
+	ext4_trans_set_block_dirty(new_data_block_tmp.buf);
 
 	free(sort);
 	free(entry_buffer);
@@ -1142,7 +1142,7 @@
 
 		/* load new block */
 		struct ext4_block b;
-		r = ext4_block_get_noread(ino_ref->fs->bdev, &b, new_fblk);
+		r = ext4_trans_block_get_noread(ino_ref->fs->bdev, &b, new_fblk);
 		if (r != EOK)
 			return r;
 
@@ -1187,7 +1187,7 @@
 						ino_ref,
 						(struct ext4_dir_en *)
 						dxb->b.data);
-				ext4_bcache_set_dirty(dxb->b.buf);
+				ext4_trans_set_block_dirty(dxb->b.buf);
 
 				struct ext4_block block_tmp = dxb->b;
 
@@ -1205,11 +1205,11 @@
 						 new_iblk);
 			ext4_dir_set_dx_csum(ino_ref, (void*)dx_blks[0].b.data);
 			ext4_dir_set_dx_csum(ino_ref, (void*)dx_blks[1].b.data);
-			ext4_bcache_set_dirty(dx_blks[0].b.buf);
-			ext4_bcache_set_dirty(dx_blks[1].b.buf);
+			ext4_trans_set_block_dirty(dx_blks[0].b.buf);
+			ext4_trans_set_block_dirty(dx_blks[1].b.buf);
 
 			ext4_dir_set_dx_csum(ino_ref, (void *)b.data);
-			ext4_bcache_set_dirty(b.buf);
+			ext4_trans_set_block_dirty(b.buf);
 			return ext4_block_set(ino_ref->fs->bdev, &b);
 		} else {
 			size_t sz;
@@ -1241,8 +1241,8 @@
 
 			ext4_dir_set_dx_csum(ino_ref, (void*)dx_blks[0].b.data);
 			ext4_dir_set_dx_csum(ino_ref, (void*)dx_blks[1].b.data);
-			ext4_bcache_set_dirty(dx_blks[0].b.buf);
-			ext4_bcache_set_dirty(dx_blks[1].b.buf);
+			ext4_trans_set_block_dirty(dx_blks[0].b.buf);
+			ext4_trans_set_block_dirty(dx_blks[1].b.buf);
 		}
 	}
 
@@ -1263,7 +1263,7 @@
 	struct ext4_fs *fs = parent->fs;
 	struct ext4_block root_blk;
 
-	r = ext4_block_get(fs->bdev, &root_blk, rblock_addr);
+	r = ext4_trans_block_get(fs->bdev, &root_blk, rblock_addr);
 	if (r != EOK)
 		return r;
 
@@ -1316,7 +1316,7 @@
 		goto release_target_index;
 
 	struct ext4_block target_block;
-	r = ext4_block_get(fs->bdev, &target_block, leaf_block_addr);
+	r = ext4_trans_block_get(fs->bdev, &target_block, leaf_block_addr);
 	if (r != EOK)
 		goto release_index;
 
@@ -1394,7 +1394,7 @@
 		return rc;
 
 	struct ext4_block block;
-	rc = ext4_block_get(dir->fs->bdev, &block, fblock);
+	rc = ext4_trans_block_get(dir->fs->bdev, &block, fblock);
 	if (rc != EOK)
 		return rc;
 
@@ -1414,7 +1414,7 @@
 	ext4_dx_dot_en_set_inode(&root->dots[1], parent_inode);
 
 	ext4_dir_set_dx_csum(dir, (void *)block.data);
-	ext4_bcache_set_dirty(block.buf);
+	ext4_trans_set_block_dirty(block.buf);
 
 	return ext4_block_set(dir->fs->bdev, &block);
 }
--- a/lwext4/ext4_extent.c
+++ b/lwext4/ext4_extent.c
@@ -257,7 +257,7 @@
 				return rc;
 		}
 
-		int rc = ext4_block_get(inode_ref->fs->bdev, &block, child);
+		int rc = ext4_trans_block_get(inode_ref->fs->bdev, &block, child);
 		if (rc != EOK)
 			return rc;
 		if (!ext4_extent_verify_block_csum(inode_ref,
@@ -342,7 +342,7 @@
 		    ext4_extent_index_get_leaf(tmp_path[pos].index);
 
 		struct ext4_block block;
-		rc = ext4_block_get(inode_ref->fs->bdev, &block, fblock);
+		rc = ext4_trans_block_get(inode_ref->fs->bdev, &block, fblock);
 		if (rc != EOK)
 			goto cleanup;
 
@@ -419,7 +419,7 @@
 	ext4_fsblk_t fblock = ext4_extent_index_get_leaf(index);
 	uint32_t i;
 	struct ext4_block block;
-	int rc = ext4_block_get(inode_ref->fs->bdev, &block, fblock);
+	int rc = ext4_trans_block_get(inode_ref->fs->bdev, &block, fblock);
 	if (rc != EOK)
 		return rc;
 
@@ -534,7 +534,7 @@
 
 	ext4_extent_header_set_entries_count(path_ptr->header, entries);
 	ext4_extent_block_csum_set(inode_ref, path_ptr->header);
-	ext4_bcache_set_dirty(path_ptr->block.buf);
+	ext4_trans_set_block_dirty(path_ptr->block.buf);
 
 	/* If leaf node is empty, parent entry must be modified */
 	bool remove_parent_record = false;
@@ -576,7 +576,7 @@
 
 		ext4_extent_header_set_entries_count(path_ptr->header, entries);
 		ext4_extent_block_csum_set(inode_ref, path_ptr->header);
-		ext4_bcache_set_dirty(path_ptr->block.buf);
+		ext4_trans_set_block_dirty(path_ptr->block.buf);
 
 		/* Free the node if it is empty */
 		if ((entries == 0) && (path_ptr != path)) {
@@ -651,7 +651,7 @@
 
 			struct ext4_block block;
 			rc =
-			    ext4_block_get_noread(inode_ref->fs->bdev, &block, fblock);
+			    ext4_trans_block_get_noread(inode_ref->fs->bdev, &block, fblock);
 			if (rc != EOK) {
 				ext4_balloc_free_block(inode_ref, fblock);
 				return rc;
@@ -704,7 +704,7 @@
 			ext4_extent_header_set_generation(path_ptr->header, 0);
 
 			ext4_extent_block_csum_set(inode_ref, path_ptr->header);
-			ext4_bcache_set_dirty(path_ptr->block.buf);
+			ext4_trans_set_block_dirty(path_ptr->block.buf);
 
 			/* Jump to the preceding item */
 			path_ptr--;
@@ -730,7 +730,7 @@
 			ext4_extent_header_set_entries_count(path_ptr->header,
 							     entries + 1);
 			ext4_extent_block_csum_set(inode_ref, path_ptr->header);
-			ext4_bcache_set_dirty(path_ptr->block.buf);
+			ext4_trans_set_block_dirty(path_ptr->block.buf);
 
 			/* No more splitting needed */
 			return EOK;
@@ -755,7 +755,7 @@
 			return rc;
 
 		struct ext4_block block;
-		rc = ext4_block_get_noread(inode_ref->fs->bdev, &block, new_fblock);
+		rc = ext4_trans_block_get_noread(inode_ref->fs->bdev, &block, new_fblock);
 		if (rc != EOK)
 			return rc;
 
@@ -813,7 +813,7 @@
 							 limit);
 
 		ext4_extent_block_csum_set(inode_ref, old_root->header);
-		ext4_bcache_set_dirty(old_root->block.buf);
+		ext4_trans_set_block_dirty(old_root->block.buf);
 
 		/* Re-initialize new root metadata */
 		new_root->depth = root_depth + 1;
@@ -831,7 +831,7 @@
 
 		/* Since new_root belongs to on-disk inode,
 		 * we don't do checksum here */
-		ext4_bcache_set_dirty(new_root->block.buf);
+		ext4_trans_set_block_dirty(new_root->block.buf);
 	} else {
 		if (path->depth) {
 			path->index =
@@ -848,7 +848,7 @@
 		ext4_extent_header_set_entries_count(path->header, entries + 1);
 		/* Since new_root belongs to on-disk inode,
 		 * we don't do checksum here */
-		ext4_bcache_set_dirty(path->block.buf);
+		ext4_trans_set_block_dirty(path->block.buf);
 	}
 
 	return EOK;
@@ -928,7 +928,7 @@
 			}
 
 			ext4_extent_block_csum_set(inode_ref, path_ptr->header);
-			ext4_bcache_set_dirty(path_ptr->block.buf);
+			ext4_trans_set_block_dirty(path_ptr->block.buf);
 
 			goto finish;
 		} else {
@@ -970,7 +970,7 @@
 			}
 
 			ext4_extent_block_csum_set(inode_ref, path_ptr->header);
-			ext4_bcache_set_dirty(path_ptr->block.buf);
+			ext4_trans_set_block_dirty(path_ptr->block.buf);
 
 			goto finish;
 		}
@@ -1011,7 +1011,7 @@
 	}
 
 	ext4_extent_block_csum_set(inode_ref, path_ptr->header);
-	ext4_bcache_set_dirty(path_ptr->block.buf);
+	ext4_trans_set_block_dirty(path_ptr->block.buf);
 
 finish:
 	/* Set return values */
--- a/lwext4/ext4_extent_full.c
+++ b/lwext4/ext4_extent_full.c
@@ -353,7 +353,7 @@
 			  struct ext4_extent_path *path)
 {
 	if (path->block.lb_id)
-		ext4_bcache_set_dirty(path->block.buf);
+		ext4_trans_set_block_dirty(path->block.buf);
 	else
 		inode_ref->dirty = true;
 
@@ -440,7 +440,7 @@
 {
 	int err;
 
-	err = ext4_block_get(inode_ref->fs->bdev, bh, pblk);
+	err = ext4_trans_block_get(inode_ref->fs->bdev, bh, pblk);
 	if (err != EOK)
 		goto errout;
 
@@ -627,7 +627,7 @@
 		goto cleanup;
 
 	/*  For write access.# */
-	ret = ext4_block_get_noread(inode_ref->fs->bdev, &bh, newblock);
+	ret = ext4_trans_block_get_noread(inode_ref->fs->bdev, &bh, newblock);
 	if (ret != EOK)
 		goto cleanup;
 
@@ -798,7 +798,7 @@
 	} else if (bh.lb_id) {
 		/* If we got a sibling leaf. */
 		ext4_extent_block_csum_set(inode_ref, ext_block_hdr(&bh));
-		ext4_bcache_set_dirty(bh.buf);
+		ext4_trans_set_block_dirty(bh.buf);
 
 		spt->path.p_block = ext4_idx_pblock(ix);
 		spt->path.depth = to_le16(eh->depth);
@@ -1070,7 +1070,7 @@
 	} else if (bh.lb_id) {
 		/* If we got a sibling leaf. */
 		ext4_extent_block_csum_set(inode_ref, ext_block_hdr(&bh));
-		ext4_bcache_set_dirty(bh.buf);
+		ext4_trans_set_block_dirty(bh.buf);
 
 		spt->path.p_block = ext4_ext_pblock(ex);
 		spt->path.depth = to_le16(eh->depth);
@@ -1129,7 +1129,7 @@
 		return err;
 
 	/* # */
-	err = ext4_block_get_noread(inode_ref->fs->bdev, &bh, newblock);
+	err = ext4_trans_block_get_noread(inode_ref->fs->bdev, &bh, newblock);
 	if (err != EOK) {
 		ext4_ext_free_blocks(inode_ref, newblock, 1, 0);
 		return err;
@@ -1166,7 +1166,7 @@
 	}
 	neh->depth = to_le16(to_le16(neh->depth) + 1);
 
-	ext4_bcache_set_dirty(bh.buf);
+	ext4_trans_set_block_dirty(bh.buf);
 	inode_ref->dirty = true;
 	ext4_block_set(inode_ref->fs->bdev, &bh);
 
@@ -1723,12 +1723,12 @@
 	uint32_t block_size = ext4_sb_get_block_size(&inode_ref->fs->sb);
 	for (i = 0; i < blocks_count; i++) {
 		struct ext4_block bh = EXT4_BLOCK_ZERO();
-		err = ext4_block_get_noread(inode_ref->fs->bdev, &bh, block + i);
+		err = ext4_trans_block_get_noread(inode_ref->fs->bdev, &bh, block + i);
 		if (err != EOK)
 			break;
 
 		memset(bh.data, 0, block_size);
-		ext4_bcache_set_dirty(bh.buf);
+		ext4_trans_set_block_dirty(bh.buf);
 		err = ext4_block_set(inode_ref->fs->bdev, &bh);
 		if (err != EOK)
 			break;
--- a/lwext4/ext4_fs.c
+++ b/lwext4/ext4_fs.c
@@ -302,7 +302,7 @@
 	uint32_t inode_table_bcnt = inodes_per_group * inode_size / block_size;
 
 	struct ext4_block block_bitmap;
-	rc = ext4_block_get_noread(bg_ref->fs->bdev, &block_bitmap, bmp_blk);
+	rc = ext4_trans_block_get_noread(bg_ref->fs->bdev, &block_bitmap, bmp_blk);
 	if (rc != EOK)
 		return rc;
 
@@ -356,7 +356,7 @@
          * of bitmap ), set rest of the block bitmap to 1
          */
         ext4_fs_mark_bitmap_end(group_blocks, block_size * 8, block_bitmap.data);
-	ext4_bcache_set_dirty(block_bitmap.buf);
+	ext4_trans_set_block_dirty(block_bitmap.buf);
 
 	ext4_balloc_set_bitmap_csum(sb, bg_ref->block_group, block_bitmap.data);
 	bg_ref->dirty = true;
@@ -379,7 +379,7 @@
 	ext4_fsblk_t bitmap_block_addr = ext4_bg_get_inode_bitmap(bg, sb);
 
 	struct ext4_block b;
-	rc = ext4_block_get_noread(bg_ref->fs->bdev, &b, bitmap_block_addr);
+	rc = ext4_trans_block_get_noread(bg_ref->fs->bdev, &b, bitmap_block_addr);
 	if (rc != EOK)
 		return rc;
 
@@ -399,7 +399,7 @@
 	if (i < end_bit)
 		memset(b.data + (i >> 3), 0xff, (end_bit - i) >> 3);
 
-	ext4_bcache_set_dirty(b.buf);
+	ext4_trans_set_block_dirty(b.buf);
 
 	ext4_ialloc_set_bitmap_csum(sb, bg, b.data);
 	bg_ref->dirty = true;
@@ -435,12 +435,12 @@
 	/* Initialization of all itable blocks */
 	for (fblock = first_block; fblock <= last_block; ++fblock) {
 		struct ext4_block b;
-		int rc = ext4_block_get_noread(bg_ref->fs->bdev, &b, fblock);
+		int rc = ext4_trans_block_get_noread(bg_ref->fs->bdev, &b, fblock);
 		if (rc != EOK)
 			return rc;
 
 		memset(b.data, 0, block_size);
-		ext4_bcache_set_dirty(b.buf);
+		ext4_trans_set_block_dirty(b.buf);
 
 		ext4_block_set(bg_ref->fs->bdev, &b);
 		if (rc != EOK)
@@ -566,7 +566,7 @@
 
 	uint32_t offset = (bgid % dsc_cnt) * ext4_sb_get_desc_size(&fs->sb);
 
-	int rc = ext4_block_get(fs->bdev, &ref->block, block_id);
+	int rc = ext4_trans_block_get(fs->bdev, &ref->block, block_id);
 	if (rc != EOK)
 		return rc;
 
@@ -629,7 +629,7 @@
 		ref->block_group->checksum = to_le16(cs);
 
 		/* Mark block dirty for writing changes to physical device */
-		ext4_bcache_set_dirty(ref->block.buf);
+		ext4_trans_set_block_dirty(ref->block.buf);
 	}
 
 	/* Put back block, that contains block group descriptor */
@@ -745,7 +745,7 @@
 	ext4_fsblk_t block_id =
 	    inode_table_start + (byte_offset_in_group / block_size);
 
-	rc = ext4_block_get(fs->bdev, &ref->block, block_id);
+	rc = ext4_trans_block_get(fs->bdev, &ref->block, block_id);
 	if (rc != EOK) {
 		return rc;
 	}
@@ -781,7 +781,7 @@
 	if (ref->dirty) {
 		/* Mark block dirty for writing changes to physical device */
 		ext4_fs_set_inode_checksum(ref);
-		ext4_bcache_set_dirty(ref->block.buf);
+		ext4_trans_set_block_dirty(ref->block.buf);
 	}
 
 	/* Put back block, that contains i-node */
@@ -937,7 +937,7 @@
 	/* 2) Double indirect */
 	fblock = ext4_inode_get_indirect_block(inode_ref->inode, 1);
 	if (fblock != 0) {
-		int rc = ext4_block_get(fs->bdev, &block, fblock);
+		int rc = ext4_trans_block_get(fs->bdev, &block, fblock);
 		if (rc != EOK)
 			return rc;
 
@@ -968,7 +968,7 @@
 	fblock = ext4_inode_get_indirect_block(inode_ref->inode, 2);
 	if (fblock == 0)
 		goto finish;
-	rc = ext4_block_get(fs->bdev, &block, fblock);
+	rc = ext4_trans_block_get(fs->bdev, &block, fblock);
 	if (rc != EOK)
 		return rc;
 
@@ -978,7 +978,7 @@
 
 		if (ind_block == 0)
 			continue;
-		rc = ext4_block_get(fs->bdev, &subblock,
+		rc = ext4_trans_block_get(fs->bdev, &subblock,
 				ind_block);
 		if (rc != EOK) {
 			ext4_block_set(fs->bdev, &block);
@@ -1108,7 +1108,7 @@
 		if (current_block == 0)
 			return EOK;
 
-		int rc = ext4_block_get(fs->bdev, &block, current_block);
+		int rc = ext4_trans_block_get(fs->bdev, &block, current_block);
 		if (rc != EOK)
 			return rc;
 
@@ -1118,7 +1118,7 @@
 		/* Set zero if physical data block address found */
 		if (level == 1) {
 			((uint32_t *)block.data)[offset_in_block] = to_le32(0);
-			ext4_bcache_set_dirty(block.buf);
+			ext4_trans_set_block_dirty(block.buf);
 		}
 
 		rc = ext4_block_set(fs->bdev, &block);
@@ -1380,7 +1380,7 @@
 	 */
 	while (l > 0) {
 		/* Load indirect block */
-		int rc = ext4_block_get(fs->bdev, &block, current_block);
+		int rc = ext4_trans_block_get(fs->bdev, &block, current_block);
 		if (rc != EOK)
 			return rc;
 
@@ -1499,7 +1499,7 @@
 		inode_ref->dirty = true;
 
 		/* Load newly allocated block */
-		rc = ext4_block_get_noread(fs->bdev, &new_block, new_blk);
+		rc = ext4_trans_block_get_noread(fs->bdev, &new_block, new_blk);
 		if (rc != EOK) {
 			ext4_balloc_free_block(inode_ref, new_blk);
 			return rc;
@@ -1507,7 +1507,7 @@
 
 		/* Initialize new block */
 		memset(new_block.data, 0, block_size);
-		ext4_bcache_set_dirty(new_block.buf);
+		ext4_trans_set_block_dirty(new_block.buf);
 
 		/* Put back the allocated block */
 		rc = ext4_block_set(fs->bdev, &new_block);
@@ -1522,7 +1522,7 @@
 	 * or find null reference meaning we are dealing with sparse file
 	 */
 	while (l > 0) {
-		int rc = ext4_block_get(fs->bdev, &block, current_block);
+		int rc = ext4_trans_block_get(fs->bdev, &block, current_block);
 		if (rc != EOK)
 			return rc;
 
@@ -1544,7 +1544,7 @@
 			}
 
 			/* Load newly allocated block */
-			rc = ext4_block_get_noread(fs->bdev, &new_block,
+			rc = ext4_trans_block_get_noread(fs->bdev, &new_block,
 					    new_blk);
 
 			if (rc != EOK) {
@@ -1554,7 +1554,7 @@
 
 			/* Initialize allocated block */
 			memset(new_block.data, 0, block_size);
-			ext4_bcache_set_dirty(new_block.buf);
+			ext4_trans_set_block_dirty(new_block.buf);
 
 			rc = ext4_block_set(fs->bdev, &new_block);
 			if (rc != EOK) {
@@ -1565,7 +1565,7 @@
 			/* Write block address to the parent */
 			uint32_t * p = (uint32_t * )block.data;
 			p[off_in_blk] = to_le32((uint32_t)new_blk);
-			ext4_bcache_set_dirty(block.buf);
+			ext4_trans_set_block_dirty(block.buf);
 			current_block = new_blk;
 		}
 
@@ -1573,7 +1573,7 @@
 		if (l == 1) {
 			uint32_t * p = (uint32_t * )block.data;
 			p[off_in_blk] = to_le32((uint32_t)fblock);
-			ext4_bcache_set_dirty(block.buf);
+			ext4_trans_set_block_dirty(block.buf);
 		}
 
 		rc = ext4_block_set(fs->bdev, &block);
--- a/lwext4/ext4_ialloc.c
+++ b/lwext4/ext4_ialloc.c
@@ -169,7 +169,7 @@
 	    ext4_bg_get_inode_bitmap(bg, sb);
 
 	struct ext4_block b;
-	rc = ext4_block_get(fs->bdev, &b, bitmap_block_addr);
+	rc = ext4_trans_block_get(fs->bdev, &b, bitmap_block_addr);
 	if (rc != EOK)
 		return rc;
 
@@ -184,7 +184,7 @@
 	uint32_t index_in_group = ext4_ialloc_inode_to_bgidx(sb, index);
 	ext4_bmap_bit_clr(b.data, index_in_group);
 	ext4_ialloc_set_bitmap_csum(sb, bg, b.data);
-	ext4_bcache_set_dirty(b.buf);
+	ext4_trans_set_block_dirty(b.buf);
 
 	/* Put back the block with bitmap */
 	rc = ext4_block_set(fs->bdev, &b);
@@ -260,7 +260,7 @@
 			uint32_t bmp_blk_add = ext4_bg_get_inode_bitmap(bg, sb);
 
 			struct ext4_block b;
-			rc = ext4_block_get(fs->bdev, &b, bmp_blk_add);
+			rc = ext4_trans_block_get(fs->bdev, &b, bmp_blk_add);
 			if (rc != EOK) {
 				ext4_fs_put_block_group_ref(&bg_ref);
 				return rc;
@@ -300,7 +300,7 @@
 			/* Free i-node found, save the bitmap */
 			ext4_ialloc_set_bitmap_csum(sb,bg,
 						    b.data);
-			ext4_bcache_set_dirty(b.buf);
+			ext4_trans_set_block_dirty(b.buf);
 
 			ext4_block_set(fs->bdev, &b);
 			if (rc != EOK) {
--- /dev/null
+++ b/lwext4/ext4_trans.c
@@ -1,0 +1,115 @@
+/*
+ * Copyright (c) 2015 Grzegorz Kostka (kostka.grzegorz@gmail.com)
+ * Copyright (c) 2015 Kaho Ng (ngkaho1234@gmail.com)
+ * 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 lwext4
+ * @{
+ */
+/**
+ * @file  ext4.h
+ * @brief Ext4 transaction buffer operations.
+ */
+
+#include "ext4_config.h"
+#include "ext4_types.h"
+#include "ext4_journal.h"
+
+static int ext4_trans_get_write_access(struct ext4_fs *fs,
+				struct ext4_block *block)
+{
+	int r = EOK;
+	if (fs->jbd_journal && fs->curr_trans) {
+		struct jbd_journal *journal = fs->jbd_journal;
+		struct jbd_trans *trans = fs->curr_trans;
+		r = jbd_trans_get_access(journal, trans, block);
+	}
+	return r;
+}
+
+int ext4_trans_set_block_dirty(struct ext4_buf *buf)
+{
+	int r = EOK;
+	struct ext4_fs *fs = buf->bc->bdev->fs;
+	struct ext4_block block = {
+		.lb_id = buf->lba,
+		.data = buf->data,
+		.buf = buf
+	};
+
+	if (fs->jbd_journal && fs->curr_trans) {
+		struct jbd_trans *trans = fs->curr_trans;
+		r = jbd_trans_set_block_dirty(trans, &block);
+	} else
+		ext4_bcache_set_dirty(buf);
+
+	return r;
+}
+
+int ext4_trans_block_get_noread(struct ext4_blockdev *bdev,
+			  struct ext4_block *b,
+			  uint64_t lba)
+{
+	int r = ext4_block_get_noread(bdev, b, lba);
+	if (r != EOK)
+		return r;
+
+	if((r = ext4_trans_get_write_access(bdev->fs, b)) != EOK)
+		ext4_block_set(bdev, b);
+
+	return r;
+}
+
+int ext4_trans_block_get(struct ext4_blockdev *bdev,
+		   struct ext4_block *b,
+		   uint64_t lba)
+{
+	int r = ext4_block_get(bdev, b, lba);
+	if (r != EOK)
+		return r;
+
+	if((r = ext4_trans_get_write_access(bdev->fs, b)) != EOK)
+		ext4_block_set(bdev, b);
+
+	return r;
+}
+
+int ext4_trans_try_revoke_block(struct ext4_blockdev *bdev,
+			       uint64_t lba)
+{
+	int r = EOK;
+	struct ext4_fs *fs = bdev->fs;
+	if (fs->jbd_journal && fs->curr_trans) {
+		struct jbd_trans *trans = fs->curr_trans;
+		jbd_trans_try_revoke_block(trans, lba);
+	}
+	return r;
+}
+
+/**
+ * @}
+ */
--- /dev/null
+++ b/lwext4/ext4_trans.h
@@ -1,0 +1,90 @@
+/*
+ * Copyright (c) 2015 Grzegorz Kostka (kostka.grzegorz@gmail.com)
+ * Copyright (c) 2015 Kaho Ng (ngkaho1234@gmail.com)
+ *
+ * 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 lwext4
+ * @{
+ */
+/**
+ * @file  ext4_trans.h
+ * @brief Transaction handle functions
+ */
+
+#ifndef EXT4_TRANS_H
+#define EXT4_TRANS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ext4_config.h"
+#include "ext4_types.h"
+
+
+/**@brief   Mark a buffer dirty and add it to the current transaction.
+ * @param   buf buffer
+ * @return  standard error code*/
+int ext4_trans_set_block_dirty(struct ext4_buf *buf);
+
+/**@brief   Block get function (through cache, don't read).
+ *          jbd_trans_get_access would be called in order to
+ *          get write access to the buffer.
+ * @param   bdev block device descriptor
+ * @param   b block descriptor
+ * @param   lba logical block address
+ * @return  standard error code*/
+int ext4_trans_block_get_noread(struct ext4_blockdev *bdev,
+			  struct ext4_block *b,
+			  uint64_t lba);
+
+/**@brief   Block get function (through cache).
+ *          jbd_trans_get_access would be called in order to
+ *          get write access to the buffer.
+ * @param   bdev block device descriptor
+ * @param   b block descriptor
+ * @param   lba logical block address
+ * @return  standard error code*/
+int ext4_trans_block_get(struct ext4_blockdev *bdev,
+		   struct ext4_block *b,
+		   uint64_t lba);
+
+/**@brief  Try to add block to be revoked to the current transaction.
+ * @param  bdev block device descriptor
+ * @param  lba logical block address
+ * @return standard error code*/
+int ext4_trans_try_revoke_block(struct ext4_blockdev *bdev,
+			       uint64_t lba);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EXT4_TRANS_H */
+
+/**
+ * @}
+ */
--- a/lwext4/ext4_xattr.c
+++ b/lwext4/ext4_xattr.c
@@ -543,7 +543,7 @@
 		if (ret != EOK)
 			goto Finish;
 
-		ret = ext4_block_get(xattr_ref->fs->bdev, &xattr_ref->block,
+		ret = ext4_trans_block_get(xattr_ref->fs->bdev, &xattr_ref->block,
 				     xattr_block);
 		if (ret != EOK) {
 			ext4_balloc_free_block(xattr_ref->inode_ref,
@@ -655,7 +655,7 @@
 		block_data = (char *)block_header + block_size_rem;
 		block_size_rem -= sizeof(struct ext4_xattr_header);
 
-		ext4_bcache_set_dirty(xattr_ref->block.buf);
+		ext4_trans_set_block_dirty(xattr_ref->block.buf);
 	} else {
 		/* We don't need an extra block.*/
 		if (xattr_ref->block_loaded) {
@@ -677,7 +677,7 @@
 				    &xattr_ref->fs->sb, 0);
 
 				xattr_ref->inode_ref->dirty = true;
-				ext4_bcache_set_dirty(xattr_ref->block.buf);
+				ext4_trans_set_block_dirty(xattr_ref->block.buf);
 			}
 		}
 	}
@@ -726,7 +726,7 @@
 		ext4_xattr_set_block_checksum(xattr_ref->inode_ref,
 					      xattr_ref->block.lb_id,
 					      block_header);
-		ext4_bcache_set_dirty(xattr_ref->block.buf);
+		ext4_trans_set_block_dirty(xattr_ref->block.buf);
 	}
 
 Finish:
@@ -837,7 +837,7 @@
 	ref->ea_size = 0;
 	ref->iter_from = NULL;
 	if (xattr_block) {
-		rc = ext4_block_get(fs->bdev, &ref->block, xattr_block);
+		rc = ext4_trans_block_get(fs->bdev, &ref->block, xattr_block);
 		if (rc != EOK)
 			return EIO;