Patchwork [U-Boot] Subject: [PATCH 2/2] ext4fs write support

login
register
mail settings
Submitter uma.shankar@samsung.com
Date Dec. 12, 2011, 10:47 a.m.
Message ID <067303F3A48847EE8B3D0BB4DCDF89F7@sisodomain.com>
Download mbox | patch
Permalink /patch/130695/
State Changes Requested
Headers show

Comments

uma.shankar@samsung.com - Dec. 12, 2011, 10:47 a.m.
From 5c06f2a289fa9e738fce23cdd4df48f53ef15cfc Mon Sep 17 00:00:00 2001
From: Uma Shankar <uma.shankar@samsung.com>
Date: Mon, 12 Dec 2011 12:01:23 +0530
Subject: [PATCH 2/2] ext4fs write support

Signed-off-by: Uma Shankar <uma.shankar@samsung.com>, Manjunatha C Achar 
<a.manjunatha@samsung.com>
Signed-off-by: Iqbal Shareef <iqbal.ams@samsung.com>
Signed-off-by: Hakgoo Lee <goodguy.lee@samsung.com>
---
 common/cmd_ext4.c      |  133 +++++
 fs/ext4/Makefile       |    2 +-
 fs/ext4/crc16.c        |   61 +++
 fs/ext4/crc16.h        |   17 +
 fs/ext4/ext4_common.c  | 1386 
+++++++++++++++++++++++++++++++++++++++++++++++-
 fs/ext4/ext4_common.h  |   17 +
 fs/ext4/ext4_journal.c |  657 +++++++++++++++++++++++
 fs/ext4/ext4_journal.h |  147 +++++
 fs/ext4/ext4fs.c       | 1039 ++++++++++++++++++++++++++++++++++++-
 include/ext4fs.h       |    8 +
 10 files changed, 3463 insertions(+), 4 deletions(-)
 create mode 100644 fs/ext4/crc16.c
 create mode 100644 fs/ext4/crc16.h
 create mode 100644 fs/ext4/ext4_journal.c
 create mode 100644 fs/ext4/ext4_journal.h

 int ext4fs_mount(unsigned part_length);

Patch

diff --git a/common/cmd_ext4.c b/common/cmd_ext4.c
index b223443..44cdc5d 100644
--- a/common/cmd_ext4.c
+++ b/common/cmd_ext4.c
@@ -55,6 +55,46 @@  static uint16_t cur_part = 1;
 #define DOS_FS_TYPE_OFFSET		0x36
 #define DOS_FS32_TYPE_OFFSET		0x52

+static int ext4_register_device(block_dev_desc_t *dev_desc, int part_no)
+{
+	unsigned char buffer[SECTOR_SIZE];
+	disk_partition_t info;
+
+	if (!dev_desc->block_read)
+		return -1;
+
+	/* check if we have a MBR (on floppies we have only a PBR) */
+	if (dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *) buffer) != 1) {
+		printf("** Can't read from device %d **\n", dev_desc->dev);
+		return -1;
+	}
+	if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 ||
+	    buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) {
+		/* no signature found */
+		return -1;
+	}
+
+	/* First we assume there is a MBR */
+	if (!get_partition_info(dev_desc, part_no, &info)) {
+		part_offset = info.start;
+		cur_part = part_no;
+		part_size = info.size;
+	} else if ((strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET],
+			    "FAT", 3) == 0) || (strncmp((char *)&buffer
+							[DOS_FS32_TYPE_OFFSET],
+							"FAT32", 5) == 0)) {
+		/* ok, we assume we are on a PBR only */
+		cur_part = 1;
+		part_offset = 0;
+	} else {
+		printf("** Partition %d not valid on device %d **\n",
+		       part_no, dev_desc->dev);
+		return -1;
+	}
+
+	return 0;
+}
+
 int do_ext4_load(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 {
 	char *filename = NULL;
@@ -243,6 +283,94 @@  int do_ext4_ls(cmd_tbl_t *cmdtp, int flag, int argc, 
char *const argv[])
 	return 0;
 }

+int do_ext4_write(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	char *filename = "/";
+	int part_length;
+	int part = 1;
+	int dev = 0;
+	char *ep;
+	unsigned long ram_address;
+	unsigned long file_size;
+	disk_partition_t info;
+	ExtFileSystem *fs;
+
+	if (argc < 6)
+		return cmd_usage(cmdtp);
+
+	dev = (int)strict_strtoul(argv[2], &ep, 16);
+	ext4_dev_desc = get_dev(argv[1], dev);
+	if (ext4_dev_desc == NULL) {
+		printf("Block device %s %d not \
+			supported\n", argv[1], dev);
+		return 1;
+	}
+	if (init_fs(ext4_dev_desc))
+		return 1;
+
+	fs = get_fs();
+	if (*ep) {
+		if (*ep != ':') {
+			puts("Invalid boot device, use `dev[:part]'\n");
+			goto fail;
+		}
+		part = (int)strict_strtoul(++ep, NULL, 16);
+	}
+
+	/*get the filename */
+	filename = argv[3];
+
+	/*get the address in hexadecimal format (string to int) */
+	ram_address = strict_strtoul(argv[4], NULL, 16);
+
+	/*get the filesize in base 10 format */
+	file_size = strict_strtoul(argv[5], NULL, 10);
+
+	/*set the device as block device */
+	part_length = ext2fs_set_blk_dev(fs->dev_desc, part);
+	if (part_length == 0) {
+		printf("Bad partition - %s %d:%d\n", argv[1], dev, part);
+		goto fail;
+	}
+
+	/*register the device and partition */
+	if (ext4_register_device(fs->dev_desc, part) != 0) {
+		printf("Unable to use %s %d:%d for fattable\n",
+		       argv[1], dev, part);
+		goto fail;
+	}
+
+	/*get the partition information */
+	if (!get_partition_info(fs->dev_desc, part, &info)) {
+		total_sector = (info.size * info.blksz) / SECTOR_SIZE;
+		fs->total_sect = total_sector;
+	} else {
+		printf("error : get partition info\n");
+		goto fail;
+	}
+
+	/*mount the filesystem */
+	if (!ext4fs_mount(part_length)) {
+		printf("Bad ext4 partition %s %d:%d\n", argv[1], dev, part);
+		goto fail;
+	}
+
+	/*start write */
+	if (ext4fs_write(filename, (unsigned char *)ram_address, file_size)) {
+		printf("** Error ext4fs_write() **\n");
+		goto fail;
+	}
+
+	ext4fs_close();
+	deinit_fs(fs->dev_desc);
+	return 0;
+
+fail:
+	ext4fs_close();
+	deinit_fs(fs->dev_desc);
+	return 1;
+}
+
 U_BOOT_CMD(ext4ls, 4, 1, do_ext4_ls,
 	   "list files in a directory (default /)",
 	   "<interface> <dev[:part]> [directory]\n"
@@ -253,3 +381,8 @@  U_BOOT_CMD(ext4load, 6, 0, do_ext4_load,
 	   "<interface> <dev[:part]> [addr] [filename] [bytes]\n"
 	   "	  - load binary file 'filename' from 'dev' on 'interface'\n"
 	   "		 to address 'addr' from ext2 filesystem");
+U_BOOT_CMD
+		(ext4write, 6, 1, do_ext4_write,
+		"create a file in the root directory",
+		"<interface> <dev[:part]> [Absolute filename path] [Address] 
[sizebytes]\n"
+		"	  - create a file in / directory");
diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index 850f821..1e7e7a8 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -30,7 +30,7 @@  include $(TOPDIR)/config.mk
 LIB	= $(obj)libext4fs.o

 AOBJS	=
-COBJS-$(CONFIG_CMD_EXT4) := ext4fs.o ext4_common.o
+COBJS-$(CONFIG_CMD_EXT4) := ext4fs.o ext4_common.o ext4_journal.o crc16.o

 SRCS	:= $(AOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(AOBJS) $(COBJS-y))
diff --git a/fs/ext4/crc16.c b/fs/ext4/crc16.c
new file mode 100644
index 0000000..9648ac2
--- /dev/null
+++ b/fs/ext4/crc16.c
@@ -0,0 +1,61 @@ 
+/*
+ *      crc16.c
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <common.h>
+#include <asm/byteorder.h>
+#include <linux/stat.h>
+#include "crc16.h"
+
+/** CRC table for the CRC-16. The poly is 0x8005 (x16 + x15 + x2 + 1) */
+static __u16 const crc16_table[256] = {
+	0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
+	0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
+	0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
+	0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
+	0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
+	0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
+	0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
+	0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
+	0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
+	0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
+	0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
+	0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
+	0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
+	0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
+	0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
+	0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
+	0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
+	0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
+	0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
+	0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
+	0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
+	0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
+	0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
+	0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
+	0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
+	0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
+	0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
+	0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
+	0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
+	0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
+	0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
+	0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
+};
+
+/**
+ * Compute the CRC-16 for the data buffer
+*/
+
+crc16_t ext2fs_crc16(crc16_t crc, const void *buffer, unsigned int len)
+{
+	const unsigned char *cp = buffer;
+
+	while (len--)
+		crc = (((crc >> 8) & 0xffU) ^
+		       crc16_table[(crc ^ *cp++) & 0xffU]) & 0x0000ffffU;
+	return crc;
+}
diff --git a/fs/ext4/crc16.h b/fs/ext4/crc16.h
new file mode 100644
index 0000000..738768a
--- /dev/null
+++ b/fs/ext4/crc16.h
@@ -0,0 +1,17 @@ 
+/*
+ * crc16.h - CRC-16 routine
+ * Implements the standard CRC-16:
+ *  Width 16
+ *  Poly  0x8005 (x16 + x15 + x2 + 1)
+ *  Init  0
+ *
+ * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+#ifndef __CRC16_H
+#define __CRC16_H
+
+typedef unsigned int crc16_t;
+extern crc16_t ext2fs_crc16(crc16_t crc, const void *buffer, unsigned int 
len);
+#endif
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 39321f6..1d835c0 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -22,7 +22,13 @@ 

 /*
  *  ext4load - based on code from GRUB2  fs/ext2.c
-*/
+ *
+ * ext4write - based on existing ext2 support in UBOOT and ext4
+ *				implementation in Linux Kernel
+ * Journaling feature of ext4 has been referred from JBD2
+ * (Journaling Block device 2) implementation in Linux Kernel
+ */
+
 #include <common.h>
 #include <ext2fs.h>
 #include <ext4fs.h>
@@ -30,7 +36,8 @@ 
 #include <asm/byteorder.h>
 #include <linux/stat.h>
 #include <linux/time.h>
-#include "ext4_common.h"
+#include "crc16.h"
+#include "ext4_journal.h"

 struct ext2_data *ext4fs_root;
 ext2fs_node_t ext4fs_file;
@@ -65,6 +72,834 @@  void *xzalloc(size_t size)
 	return ptr;
 }

+uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n)
+{
+	uint32_t res = size / n;
+	if (res * n != size)
+		res++;
+	return res;
+}
+
+/* To convert big endian journal superblock entries to little endian */
+unsigned int be_le(unsigned int num)
+{
+	unsigned int swapped;
+	swapped = (((num >> 24) & 0xff) |
+		   ((num << 8) & 0xff0000) |
+		   ((num >> 8) & 0xff00) | ((num << 24) & 0xff000000));
+	return swapped;
+}
+
+/* 4-byte number*/
+unsigned int le_be(unsigned int num)
+{
+	return ((num & 0xff) << 24) + ((num & 0xff00) << 8)
+	    + ((num & 0xff0000) >> 8) + ((num >> 24) & 0xff);
+}
+
+void put_ext4(uint64_t off, void *buf, uint32_t size)
+{
+	uint64_t startblock, remainder;
+	short sector_size = 512;
+	unsigned char *temp_ptr = NULL;
+	char sec_buf[SECTOR_SIZE];
+	ExtFileSystem *fs = get_fs();
+
+	startblock = off / (uint64_t) sector_size;
+	startblock += part_offset;
+	remainder = off % (uint64_t) sector_size;
+	remainder &= SECTOR_SIZE - 1;
+
+	if (fs->dev_desc == NULL)
+		return;
+
+	if ((startblock + (size / SECTOR_SIZE)) >
+	    (part_offset + fs->total_sect)) {
+		printf("part_offset is %lu\n", part_offset);
+		printf("total_sector is %llu\n", fs->total_sect);
+		printf("error: overflow occurs\n");
+		return;
+	}
+
+	if (remainder) {
+		if (fs->dev_desc->block_read) {
+			fs->dev_desc->block_read(fs->dev_desc->dev,
+						 startblock, 1,
+						 (unsigned char *)sec_buf);
+			temp_ptr = (unsigned char *)sec_buf;
+			memcpy((temp_ptr + remainder),
+			       (unsigned char *)buf, size);
+			fs->dev_desc->block_write(fs->dev_desc->dev,
+						  startblock, 1,
+						  (unsigned char *)sec_buf);
+		}
+	} else {
+		if (size / SECTOR_SIZE != 0) {
+			fs->dev_desc->block_write(fs->dev_desc->dev,
+						  startblock,
+						  size / SECTOR_SIZE,
+						  (unsigned long *)buf);
+		} else {
+			fs->dev_desc->block_read(fs->dev_desc->dev,
+						 startblock, 1,
+						 (unsigned char *)sec_buf);
+			temp_ptr = (unsigned char *)sec_buf;
+			memcpy(temp_ptr, buf, size);
+			fs->dev_desc->block_write(fs->dev_desc->dev,
+						  startblock, 1,
+						  (unsigned long *)sec_buf);
+		}
+	}
+	return;
+}
+
+static int _get_new_inode_no(unsigned char *buffer)
+{
+	ExtFileSystem *fs = get_fs();
+	unsigned char input;
+	int operand, status, count = 1, j = 0;
+
+	/*get the blocksize of the filesystem */
+	unsigned char *ptr = buffer;
+	while (*ptr == 255) {
+		ptr++;
+		count += 8;
+		if (count > (uint32_t) ext4fs_root->sblock.inodes_per_group)
+			return -1;
+	}
+
+	for (j = 0; j < fs->blksz; j++) {
+		input = *ptr;
+		int i = 0;
+		while (i <= 7) {
+			operand = 1 << i;
+			status = input & operand;
+			if (status) {
+				i++;
+				count++;
+			} else {
+				*ptr |= operand;
+				return count;
+			}
+		}
+		ptr = ptr + 1;
+	}
+	return -1;
+}
+
+static int _get_new_blk_no(unsigned char *buffer)
+{
+	unsigned char input;
+	int operand, status, count = 0, j = 0;
+	unsigned char *ptr = buffer;
+	ExtFileSystem *fs = get_fs();
+
+	if (fs->blksz != 1024)
+		count = 0;
+	else
+		count = 1;
+
+	while (*ptr == 255) {
+		ptr++;
+		count += 8;
+		if (count == (fs->blksz * 8))
+			return -1;
+	}
+
+	for (j = 0; j < fs->blksz; j++) {
+		input = *ptr;
+		int i = 0;
+		while (i <= 7) {
+			operand = 1 << i;
+			status = input & operand;
+			if (status) {
+				i++;
+				count++;
+			} else {
+				*ptr |= operand;
+				return count;
+			}
+		}
+		ptr = ptr + 1;
+	}
+	return -1;
+}
+
+int set_block_bmap(long int blockno, unsigned char *buffer, int index)
+{
+	int i, remainder, status;
+	unsigned char *ptr = buffer;
+	unsigned char operand;
+	i = blockno / 8;
+	remainder = blockno % 8;
+	int blocksize = EXT2_BLOCK_SIZE(ext4fs_root);
+
+	i = i - (index * blocksize);
+	if (blocksize != 1024) {
+		ptr = ptr + i;
+		operand = 1 << remainder;
+		status = *ptr & operand;
+		if (status)
+			return -1;
+		else {
+			*ptr = *ptr | operand;
+			return 0;
+		}
+	} else {
+		if (remainder == 0) {
+			ptr = ptr + i - 1;
+			operand = (1 << 7);
+		} else {
+			ptr = ptr + i;
+			operand = (1 << (remainder - 1));
+		}
+		status = *ptr & operand;
+		if (status)
+			return -1;
+		else {
+			*ptr = *ptr | operand;
+			return 0;
+		}
+	}
+}
+
+void reset_block_bmap(long int blockno, unsigned char *buffer, int index)
+{
+	int i, remainder, status;
+	unsigned char *ptr = buffer;
+	unsigned char operand;
+	i = blockno / 8;
+	remainder = blockno % 8;
+	int blocksize = EXT2_BLOCK_SIZE(ext4fs_root);
+
+	i = i - (index * blocksize);
+	if (blocksize != 1024) {
+		ptr = ptr + i;
+		operand = (1 << remainder);
+		status = *ptr & operand;
+		if (status)
+			*ptr = *ptr & ~(operand);
+	} else {
+		if (remainder == 0) {
+			ptr = ptr + i - 1;
+			operand = (1 << 7);
+		} else {
+			ptr = ptr + i;
+			operand = (1 << (remainder - 1));
+		}
+		status = *ptr & operand;
+		if (status)
+			*ptr = *ptr & ~(operand);
+	}
+	return;
+}
+
+int set_inode_bmap(int inode_no, unsigned char *buffer, int index)
+{
+	int i, remainder, status;
+	unsigned char *ptr = buffer;
+	unsigned char operand;
+
+	inode_no -= (index * (uint32_t) ext4fs_root->sblock.inodes_per_group);
+	i = inode_no / 8;
+	remainder = inode_no % 8;
+	if (remainder == 0) {
+		ptr = ptr + i - 1;
+		operand = (1 << 7);
+	} else {
+		ptr = ptr + i;
+		operand = (1 << (remainder - 1));
+	}
+	status = *ptr & operand;
+	if (status)
+		return -1;
+	else {
+		*ptr = *ptr | operand;
+		return 0;
+	}
+}
+
+void reset_inode_bmap(int inode_no, unsigned char *buffer, int index)
+{
+	int i, remainder, status;
+	unsigned char *ptr = buffer;
+	unsigned char operand;
+
+	inode_no -= (index * (uint32_t) ext4fs_root->sblock.inodes_per_group);
+	i = inode_no / 8;
+	remainder = inode_no % 8;
+	if (remainder == 0) {
+		ptr = ptr + i - 1;
+		operand = (1 << 7);
+	} else {
+		ptr = ptr + i;
+		operand = (1 << (remainder - 1));
+	}
+	status = *ptr & operand;
+	if (status)
+		*ptr = *ptr & ~(operand);
+	return;
+}
+
+int ext4fs_checksum_update(unsigned int i)
+{
+	struct ext2_block_group *desc;
+	ExtFileSystem *fs = get_fs();
+	__u16 crc = 0;
+
+	desc = (struct ext2_block_group *)&fs->gd[i];
+	if (fs->sb->feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
+		int offset = offsetof(struct ext2_block_group, bg_checksum);
+
+		crc = ext2fs_crc16(~0, fs->sb->unique_id,
+				   sizeof(fs->sb->unique_id));
+		crc = ext2fs_crc16(crc, &i, sizeof(i));
+		crc = ext2fs_crc16(crc, desc, offset);
+		offset += sizeof(desc->bg_checksum);	/* skip checksum */
+		assert(offset == sizeof(*desc));
+	}
+	return crc;
+}
+
+static int check_void_in_dentry(struct ext2_dirent *dir, char *filename)
+{
+	int dentry_length = 0;
+	short padding_factor = 0;
+	int sizeof_void_space = 0;
+	int new_entry_byte_reqd = 0;
+
+	if (dir->namelen % 4 != 0)
+		padding_factor = 4 - (dir->namelen % 4);
+
+	dentry_length = sizeof(struct ext2_dirent) +
+	    dir->namelen + padding_factor;
+	sizeof_void_space = dir->direntlen - dentry_length;
+	if (sizeof_void_space == 0) {
+		return 0;
+	} else {
+		padding_factor = 0;
+		if (strlen(filename) % 4 != 0)
+			padding_factor = 4 - (strlen(filename) % 4);
+
+		new_entry_byte_reqd = strlen(filename) +
+		    sizeof(struct ext2_dirent) + padding_factor;
+		if (sizeof_void_space >= new_entry_byte_reqd) {
+			dir->direntlen = dentry_length;
+			return sizeof_void_space;
+		} else
+			return 0;
+	}
+}
+
+void update_parent_dentry(char *filename, int *p_ino, int file_type)
+{
+	unsigned int *zero_buffer = NULL;
+	char *root_first_block_buffer = NULL;
+	ExtFileSystem *fs = get_fs();
+	int direct_blk_idx;
+	long int root_blknr;
+	long int first_block_no_of_root = 0;
+	long int previous_blknr = -1;
+	int totalbytes = 0;
+	short int padding_factor = 0;
+	unsigned int new_entry_byte_reqd;
+	unsigned int last_entry_dirlen;
+	int sizeof_void_space = 0;
+	int templength = 0, inodeno, status;
+	/*directory entry */
+	struct ext2_dirent *dir;
+	char *ptr = NULL;
+	char *temp_dir = NULL;
+
+	/*##START: Update the root directory entry block of root inode ### */
+	/*since we are populating this file under  root
+	 *directory take the root inode and its first block
+	 *currently we are looking only in first block of root
+	 *inode*/
+
+	zero_buffer = xzalloc(fs->blksz);
+	if (!zero_buffer)
+		return;
+	root_first_block_buffer = (char *)xzalloc(fs->blksz);
+	if (!root_first_block_buffer)
+		return;
+RESTART:
+
+	/*read the block no allocated to a file */
+	for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS;
+	     direct_blk_idx++) {
+		root_blknr = read_allocated_block(g_parent_inode,
+						  direct_blk_idx);
+		if (root_blknr == 0) {
+			first_block_no_of_root = previous_blknr;
+			break;
+		}
+		previous_blknr = root_blknr;
+	}
+
+	status = ext2fs_devread(first_block_no_of_root
+				* fs->sect_perblk,
+				0, fs->blksz, root_first_block_buffer);
+	if (status == 0)
+		goto fail;
+	else {
+		if (log_journal(root_first_block_buffer,
+				first_block_no_of_root))
+			goto fail;
+		dir = (struct ext2_dirent *)root_first_block_buffer;
+		ptr = (char *)dir;
+		totalbytes = 0;
+		while (dir->direntlen > 0) {
+			/* blocksize-totalbytes because last directory length
+			 * i.e. dir->direntlen is free availble space in the
+			 * block that means  it is a last entry of directory
+			 * entry
+			 */
+
+			/* traversing the each directory entry */
+			if (fs->blksz - totalbytes == dir->direntlen) {
+				if (strlen(filename) % 4 != 0)
+					padding_factor = 4 -
+					    (strlen(filename) % 4);
+
+				new_entry_byte_reqd = strlen(filename) +
+				    sizeof(struct ext2_dirent) + padding_factor;
+				padding_factor = 0;
+				/* update last directory entry length to its
+				 *  length because we are creating new directory
+				 *  entry */
+				if (dir->namelen % 4 != 0)
+					padding_factor = 4 - (dir->namelen % 4);
+
+				last_entry_dirlen = dir->namelen +
+				    sizeof(struct ext2_dirent) + padding_factor;
+				if ((fs->blksz - totalbytes - last_entry_dirlen)
+				    < new_entry_byte_reqd) {
+					printf("1st Block Full:\
+					allocating new block\n");
+
+					if (direct_blk_idx ==
+					    INDIRECT_BLOCKS - 1) {
+						printf("Directory capacity \
+						exceeds the limit\n");
+						goto fail;
+					}
+					g_parent_inode->b.blocks.dir_blocks
+					    [direct_blk_idx] = get_new_blk_no();
+					if (g_parent_inode->b.blocks.dir_blocks
+					    [direct_blk_idx] == -1) {
+						printf("no block\
+							left to assign\n");
+						goto fail;
+					}
+					put_ext4(((uint64_t)
+						  (g_parent_inode->b.blocks.
+						   dir_blocks[direct_blk_idx] *
+						   fs->blksz)), zero_buffer,
+						 fs->blksz);
+					g_parent_inode->size =
+					    g_parent_inode->size + fs->blksz;
+					g_parent_inode->blockcnt =
+					    g_parent_inode->blockcnt +
+					    fs->sect_perblk;
+					if (put_metadata
+					    (root_first_block_buffer,
+					     first_block_no_of_root))
+						goto fail;
+					goto RESTART;
+				}
+				dir->direntlen = last_entry_dirlen;
+				break;
+			}
+
+			templength = dir->direntlen;
+			totalbytes = totalbytes + templength;
+			sizeof_void_space = check_void_in_dentry(dir, filename);
+			if (sizeof_void_space)
+				break;
+
+			dir = (struct ext2_dirent *)((char *)dir + templength);
+			ptr = (char *)dir;
+		}
+
+		/*make a pointer ready for creating next directory entry */
+		templength = dir->direntlen;
+		totalbytes = totalbytes + templength;
+		dir = (struct ext2_dirent *)((char *)dir + templength);
+		ptr = (char *)dir;
+
+		/*get the next available inode number */
+		inodeno = get_new_inode_no();
+		if (inodeno == -1) {
+			printf("no inode left to assign\n");
+			goto fail;
+		}
+		dir->inode = inodeno;
+		if (sizeof_void_space)
+			dir->direntlen = sizeof_void_space;
+		else
+			dir->direntlen = fs->blksz - totalbytes;
+		dir->namelen = strlen(filename);
+		dir->filetype = FILETYPE_REG;	/*regular file */
+		temp_dir = (char *)dir;
+		temp_dir = temp_dir + sizeof(struct ext2_dirent);
+		memcpy(temp_dir, filename, strlen(filename));
+	}
+	*p_ino = inodeno;
+
+	/*update or write  the 1st block of root inode */
+	if (put_metadata(root_first_block_buffer, first_block_no_of_root))
+		goto fail;
+
+fail:
+	if (zero_buffer)
+		free(zero_buffer);
+	if (root_first_block_buffer)
+		free(root_first_block_buffer);
+
+	/*END: Update the root directory entry block of root inode */
+}
+
+static int search_dir(struct ext4_inode *parent_inode, char *dirname)
+{
+	unsigned char *block_buffer;
+	ExtFileSystem *fs = get_fs();
+	struct ext2_dirent *dir = NULL;
+	struct ext2_dirent *previous_dir = NULL;
+	int status, inodeno, totalbytes, templength, direct_blk_idx;
+	int found = 0;
+	char *ptr;
+	long int blknr;
+
+	/*get the first block of root */
+	/*read the block no allocated to a file */
+	for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS;
+	     direct_blk_idx++) {
+		blknr = read_allocated_block(parent_inode, direct_blk_idx);
+		if (blknr == 0)
+			goto fail;
+
+		/*read the blocks of parenet inode */
+		block_buffer = xzalloc(fs->blksz);
+		if (!block_buffer)
+			goto fail;
+
+		status = ext2fs_devread(blknr * fs->sect_perblk,
+					0, fs->blksz, (char *)block_buffer);
+		if (status == 0)
+			goto fail;
+		else {
+			dir = (struct ext2_dirent *)block_buffer;
+			ptr = (char *)dir;
+			totalbytes = 0;
+			while (dir->direntlen >= 0) {
+				/*blocksize-totalbytes because last directory
+				 *length i.e.,*dir->direntlen is free availble
+				 *space in the block that means
+				 *it is a last entry of directory entry
+				 */
+				if (strlen(dirname) == dir->namelen) {
+					if (strncmp(dirname, ptr +
+						    sizeof(struct ext2_dirent),
+						    dir->namelen) == 0) {
+						previous_dir->direntlen +=
+						    dir->direntlen;
+						inodeno = dir->inode;
+						dir->inode = 0;
+						found = 1;
+						break;
+					}
+				}
+
+				if (fs->blksz - totalbytes == dir->direntlen)
+					break;
+
+				/*traversing the each directory entry */
+				templength = dir->direntlen;
+				totalbytes = totalbytes + templength;
+				previous_dir = dir;
+				dir = (struct ext2_dirent *)((char *)dir
+							     + templength);
+				ptr = (char *)dir;
+			}
+		}
+
+		if (found == 1) {
+			if (block_buffer) {
+				free(block_buffer);
+				block_buffer = NULL;
+			}
+			return inodeno;
+		}
+
+		if (block_buffer) {
+			free(block_buffer);
+			block_buffer = NULL;
+		}
+	}
+
+fail:
+	if (block_buffer) {
+		free(block_buffer);
+		block_buffer = NULL;
+	}
+	return -1;
+}
+
+static int find_dir_depth(char *dirname)
+{
+	char *token = strtok(dirname, "/");
+	int count = 0;
+	while (token != NULL) {
+		token = strtok(NULL, "/");
+		count++;
+	}
+	return count + 1 + 1;
+	/*
+	 *for example  for string /home/temp
+	 *depth=home(1)+temp(1)+1 extra for NULL;
+	 *so count is 4;
+	 */
+}
+
+static int parse_path(char **arr, char *dirname)
+{
+	char *token = strtok(dirname, "/");
+	int i = 0;
+
+	/*add root */
+	arr[i] = xzalloc(strlen("/") + 1);
+	if (!arr[i])
+		return -1;
+
+	arr[i++] = "/";
+
+	/*add each path entry after root */
+	while (token != NULL) {
+		arr[i] = xzalloc(strlen(token) + 1);
+		if (!arr[i])
+			return -1;
+		memcpy(arr[i++], token, strlen(token));
+		token = strtok(NULL, "/");
+	}
+
+	arr[i] = NULL;
+	/*success */
+	return 0;
+}
+
+int iget(int inode_no, struct ext4_inode *inode)
+{
+	if (ext4fs_read_inode(ext4fs_root, inode_no, inode) == 0)
+		return -1;
+	else
+		return 0;
+}
+
+/*
+* Function:get_parent_inode_num
+* Return Value: inode Number of the parent directory of  file/Directory to 
be
+* created
+* dirname : Input parmater, input path name of the file/directory to be 
created
+* dname : Output parameter, to be filled with the name of the directory
+* extracted from dirname
+*/
+int get_parent_inode_num(char *dirname, char *dname, int flags)
+{
+	char **ptr = NULL;
+	int i, depth = 0;
+	char *depth_dirname = NULL;
+	char *parse_dirname = NULL;
+	struct ext4_inode *parent_inode = NULL;
+	struct ext4_inode *first_inode = NULL;
+	struct ext4_inode temp_inode;
+	int matched_inode_no;
+	int result_inode_no = -1;
+
+	if (*dirname != '/') {
+		printf("Please supply Absolute path\n");
+		return -1;
+	}
+
+	depth_dirname = (char *)xzalloc(strlen(dirname) + 1);
+	if (!depth_dirname)
+		return -1;
+
+	memcpy(depth_dirname, dirname, strlen(dirname));
+	depth = find_dir_depth(depth_dirname);
+	parse_dirname = (char *)xzalloc(strlen(dirname) + 1);
+	if (!parse_dirname)
+		goto fail;
+	memcpy(parse_dirname, dirname, strlen(dirname));
+
+	ptr = (char **)xzalloc((depth) * sizeof(char *));
+	if (!ptr)
+		goto fail;
+	if (parse_path(ptr, parse_dirname))
+		goto fail;
+	parent_inode = (struct ext4_inode *)
+	    xzalloc(sizeof(struct ext4_inode));
+	if (!parent_inode)
+		goto fail;
+	first_inode = (struct ext4_inode *)
+	    xzalloc(sizeof(struct ext4_inode));
+	if (!first_inode)
+		goto fail;
+	memcpy(parent_inode, ext4fs_root->inode, sizeof(struct ext4_inode));
+	memcpy(first_inode, parent_inode, sizeof(struct ext4_inode));
+	if (flags & F_FILE)
+		result_inode_no = EXT2_ROOT_INO;
+	for (i = 1; i < depth; i++) {
+		matched_inode_no = search_dir(parent_inode, ptr[i]);
+		if (matched_inode_no == -1) {
+			if (ptr[i + 1] == NULL && i == 1) {
+				result_inode_no = EXT2_ROOT_INO;
+				goto END;
+			} else {
+				if (ptr[i + 1] == NULL)
+					break;
+				printf("Invalid path\n");
+				result_inode_no = -1;
+				goto fail;
+			}
+		} else {
+			if (ptr[i + 1] != NULL) {
+				memset(parent_inode, '\0',
+				       sizeof(struct ext4_inode));
+				if (iget(matched_inode_no, parent_inode)) {
+					result_inode_no = -1;
+					goto fail;
+				}
+				result_inode_no = matched_inode_no;
+			} else
+				break;
+		}
+	}
+
+END:
+	if (i == 1)
+		matched_inode_no = search_dir(first_inode, ptr[i]);
+	else
+		matched_inode_no = search_dir(parent_inode, ptr[i]);
+
+	if (matched_inode_no != -1) {
+		iget(matched_inode_no, &temp_inode);
+		if (temp_inode.mode & S_IFDIR) {
+			printf("It is a Directory\n");
+			result_inode_no = -1;
+			goto fail;
+		}
+	}
+
+	if (strlen(ptr[i]) > 256) {
+		result_inode_no = -1;
+		goto fail;
+	}
+	memcpy(dname, ptr[i], strlen(ptr[i]));
+
+fail:
+	if (depth_dirname)
+		free(depth_dirname);
+	if (parse_dirname)
+		free(parse_dirname);
+	if (ptr)
+		free(ptr);
+	if (parent_inode)
+		free(parent_inode);
+	if (first_inode)
+		free(first_inode);
+
+	return result_inode_no;
+}
+
+static int check_filename(char *filename, unsigned int blknr)
+{
+	char *root_first_block_buffer, *root_first_block_addr;
+	unsigned int first_block_no_of_root;
+	ExtFileSystem *fs = get_fs();
+	struct ext2_dirent *dir;
+	struct ext2_dirent *previous_dir = NULL;
+	int totalbytes = 0;
+	int templength = 0;
+	int status, inodeno;
+	int found = 0;
+	char *ptr;
+
+	first_block_no_of_root = blknr;
+	root_first_block_buffer = (char *)xzalloc(fs->blksz);
+	if (!root_first_block_buffer)
+		return -1;
+	root_first_block_addr = root_first_block_buffer;
+	status = ext2fs_devread(first_block_no_of_root *
+				fs->sect_perblk, 0,
+				fs->blksz, root_first_block_buffer);
+	if (status == 0) {
+		goto fail;
+	} else {
+		if (log_journal(root_first_block_buffer,
+				first_block_no_of_root))
+			goto fail;
+		dir = (struct ext2_dirent *)root_first_block_buffer;
+		ptr = (char *)dir;
+		totalbytes = 0;
+		while (dir->direntlen >= 0) {
+			if (strlen(filename) == dir->namelen) {
+				if (strncmp(filename,
+					    ptr + sizeof(struct ext2_dirent),
+					    dir->namelen) == 0) {
+					printf("file found deleting\n");
+					previous_dir->direntlen +=
+					    dir->direntlen;
+					inodeno = dir->inode;
+					dir->inode = 0;
+					found = 1;
+					break;
+				}
+			}
+
+			if (fs->blksz - totalbytes == dir->direntlen)
+				break;
+
+			/*traversing the each directory entry */
+			templength = dir->direntlen;
+			totalbytes = totalbytes + templength;
+			previous_dir = dir;
+			dir = (struct ext2_dirent *)((char *)dir + templength);
+			ptr = (char *)dir;
+		}
+	}
+
+	if (found == 1) {
+		if (put_metadata(root_first_block_addr, first_block_no_of_root))
+			goto fail;
+		return inodeno;
+	}
+
+fail:
+	if (root_first_block_buffer)
+		free(root_first_block_buffer);
+	return -1;
+}
+
+int ext4fs_filename_check(char *filename)
+{
+	short direct_blk_idx = 0;
+	long int blknr = -1;
+	int inodeno = -1;
+
+	/*read the block no allocated to a file */
+	for (direct_blk_idx = 0; direct_blk_idx < INDIRECT_BLOCKS;
+	     direct_blk_idx++) {
+		blknr = read_allocated_block(g_parent_inode, direct_blk_idx);
+		if (blknr == 0)
+			break;
+		inodeno = check_filename(filename, blknr);
+		if (inodeno != -1)
+			return inodeno;
+	}
+	return -1;
+}
+
 static struct ext4_extent_header *ext4fs_find_leaf(struct ext2_data *data,
 	char *buf, struct ext4_extent_header *ext_block, uint32_t fileblock)
 {
@@ -152,6 +987,553 @@  int ext4fs_read_inode(struct ext2_data *data, int ino, 
struct ext4_inode *inode)
 	return 1;
 }

+long int get_new_blk_no(void)
+{
+	short i, status;
+	int remainder;
+	unsigned int bg_idx;
+	static int prev_bg_bitmap_index = -1;
+	ExtFileSystem *fs = get_fs();
+	char *journal_buffer = (char *)xzalloc(fs->blksz);
+	char *zero_buffer = (char *)xzalloc(fs->blksz);
+	if (!journal_buffer || !zero_buffer)
+		goto fail;
+	struct ext2_block_group *gd = (struct ext2_block_group *)fs->gdtable;
+
+	if (fs->first_pass_bbmap == 0) {
+		for (i = 0; i < fs->no_blkgrp; i++) {
+			if (gd[i].free_blocks) {
+				if (gd[i].bg_flags & EXT4_BG_BLOCK_UNINIT) {
+					put_ext4(((uint64_t) (gd[i].block_id *
+							      fs->blksz)),
+						 zero_buffer, fs->blksz);
+					gd[i].bg_flags =
+					    gd[i].
+					    bg_flags & ~EXT4_BG_BLOCK_UNINIT;
+					memcpy(fs->blk_bmaps[i], zero_buffer,
+					       fs->blksz);
+				}
+				fs->curr_blkno =
+				    _get_new_blk_no(fs->blk_bmaps[i]);
+				if (fs->curr_blkno == -1) {
+					/*if block bitmap is completely fill */
+					continue;
+				}
+				fs->curr_blkno = fs->curr_blkno +
+				    (i * fs->blksz * 8);
+				fs->first_pass_bbmap++;
+				gd[i].free_blocks--;
+				fs->sb->free_blocks--;
+				status = ext2fs_devread(gd[i].block_id *
+							fs->sect_perblk, 0,
+							fs->blksz,
+							journal_buffer);
+				if (status == 0)
+					goto fail;
+				if (log_journal(journal_buffer, gd[i].block_id))
+					goto fail;
+				goto success;
+			} else {
+				debug("no space left on block group %d\n", i);
+			}
+		}
+		goto fail;
+	} else {
+restart:
+		fs->curr_blkno++;
+		/*get the blockbitmap index respective to blockno */
+		if (fs->blksz != 1024) {
+			bg_idx = fs->curr_blkno /
+			    (uint32_t) ext4fs_root->sblock.blocks_per_group;
+		} else {
+			bg_idx = fs->curr_blkno /
+			    (uint32_t) ext4fs_root->sblock.blocks_per_group;
+			remainder = fs->curr_blkno %
+			    (uint32_t) ext4fs_root->sblock.blocks_per_group;
+			if (!remainder)
+				bg_idx--;
+		}
+
+		if (bg_idx >= fs->no_blkgrp)
+			goto fail;
+
+		if (gd[bg_idx].free_blocks == 0) {
+			debug("block group %u is full. Skipping\n", bg_idx);
+			fs->curr_blkno = fs->curr_blkno +
+			    ext4fs_root->sblock.blocks_per_group;
+			fs->curr_blkno--;
+			goto restart;
+		}
+
+		if (gd[bg_idx].bg_flags & EXT4_BG_BLOCK_UNINIT) {
+			memset(zero_buffer, '\0', fs->blksz);
+			put_ext4(((uint64_t) (gd[bg_idx].block_id * fs->blksz)),
+				 zero_buffer, fs->blksz);
+			memcpy(fs->blk_bmaps[bg_idx], zero_buffer, fs->blksz);
+			gd[bg_idx].bg_flags = gd[bg_idx].bg_flags &
+			    ~EXT4_BG_BLOCK_UNINIT;
+		}
+
+		if (set_block_bmap(fs->curr_blkno, fs->blk_bmaps[bg_idx],
+				   bg_idx) != 0) {
+			debug("going for restart for the block no %ld %u\n",
+			      fs->curr_blkno, bg_idx);
+			goto restart;
+		}
+
+		/*journal backup */
+		if (prev_bg_bitmap_index != bg_idx) {
+			memset(journal_buffer, '\0', fs->blksz);
+			status = ext2fs_devread(gd[bg_idx].block_id
+						* fs->sect_perblk,
+						0, fs->blksz, journal_buffer);
+			if (status == 0)
+				goto fail;
+			if (log_journal(journal_buffer, gd[bg_idx].block_id))
+				goto fail;
+
+			prev_bg_bitmap_index = bg_idx;
+		}
+		gd[bg_idx].free_blocks--;
+		fs->sb->free_blocks--;
+		goto success;
+	}
+success:
+	if (journal_buffer)
+		free(journal_buffer);
+	if (zero_buffer)
+		free(zero_buffer);
+	return fs->curr_blkno;
+fail:
+	if (journal_buffer)
+		free(journal_buffer);
+	if (zero_buffer)
+		free(zero_buffer);
+	return -1;
+}
+
+int get_new_inode_no(void)
+{
+	short i, status;
+	unsigned int ibmap_idx;
+	static int prev_inode_bitmap_index = -1;
+	ExtFileSystem *fs = get_fs();
+	char *journal_buffer = (char *)xzalloc(fs->blksz);
+	char *zero_buffer = (char *)xzalloc(fs->blksz);
+	if (!journal_buffer || !zero_buffer)
+		goto fail;
+	struct ext2_block_group *gd = (struct ext2_block_group *)fs->gdtable;
+
+	if (fs->first_pass_ibmap == 0) {
+		for (i = 0; i < fs->no_blkgrp; i++) {
+			if (gd[i].free_inodes) {
+				if (gd[i].bg_flags & EXT4_BG_INODE_UNINIT) {
+					put_ext4(((uint64_t)
+						  (gd[i].inode_id * fs->blksz)),
+						 zero_buffer, fs->blksz);
+					gd[i].bg_flags = gd[i].bg_flags &
+					    ~EXT4_BG_INODE_UNINIT;
+					memcpy(fs->inode_bmaps[i],
+					       zero_buffer, fs->blksz);
+				}
+				fs->curr_inode_no =
+				    _get_new_inode_no(fs->inode_bmaps[i]);
+				if (fs->curr_inode_no == -1) {
+					/*if block bitmap is completely fill */
+					continue;
+				}
+				fs->curr_inode_no = fs->curr_inode_no +
+				    (i * ext4fs_root->sblock.inodes_per_group);
+				fs->first_pass_ibmap++;
+				gd[i].free_inodes--;
+				gd[i].bg_itable_unused--;
+				fs->sb->free_inodes--;
+				status = ext2fs_devread(gd[i].inode_id *
+							fs->sect_perblk, 0,
+							fs->blksz,
+							journal_buffer);
+				if (status == 0)
+					goto fail;
+				if (log_journal(journal_buffer, gd[i].inode_id))
+					goto fail;
+				goto success;
+			} else
+				debug("no inode left on block group %d\n", i);
+		}
+		goto fail;
+	} else {
+restart:
+		fs->curr_inode_no++;
+		/*get the blockbitmap index respective to blockno */
+		ibmap_idx = fs->curr_inode_no /
+		    (uint32_t) ext4fs_root->sblock.inodes_per_group;
+		if (gd[ibmap_idx].bg_flags & EXT4_BG_INODE_UNINIT) {
+			memset(zero_buffer, '\0', fs->blksz);
+			put_ext4(((uint64_t) (gd[ibmap_idx].inode_id *
+					      fs->blksz)), zero_buffer,
+				 fs->blksz);
+			gd[ibmap_idx].bg_flags =
+			    gd[ibmap_idx].bg_flags & ~EXT4_BG_INODE_UNINIT;
+			memcpy(fs->inode_bmaps[ibmap_idx], zero_buffer,
+			       fs->blksz);
+		}
+
+		if (set_inode_bmap(fs->curr_inode_no,
+				   fs->inode_bmaps[ibmap_idx],
+				   ibmap_idx) != 0) {
+			debug("going for restart for the block no %d %u\n",
+			      fs->curr_inode_no, ibmap_idx);
+			goto restart;
+		}
+
+		/*journal backup */
+		if (prev_inode_bitmap_index != ibmap_idx) {
+			memset(journal_buffer, '\0', fs->blksz);
+			status = ext2fs_devread(gd[ibmap_idx].inode_id
+						* fs->sect_perblk,
+						0, fs->blksz, journal_buffer);
+			if (status == 0)
+				goto fail;
+			if (log_journal(journal_buffer, gd[ibmap_idx].inode_id))
+				goto fail;
+			prev_inode_bitmap_index = ibmap_idx;
+		}
+
+		gd[ibmap_idx].free_inodes--;
+		gd[ibmap_idx].bg_itable_unused--;
+		fs->sb->free_inodes--;
+		goto success;
+	}
+
+success:
+	if (journal_buffer)
+		free(journal_buffer);
+	if (zero_buffer)
+		free(zero_buffer);
+	return fs->curr_inode_no;
+
+fail:
+	if (journal_buffer)
+		free(journal_buffer);
+	if (zero_buffer)
+		free(zero_buffer);
+	return -1;
+
+}
+
+/*allocation of single indirect blocks*/
+static void alloc_single_indirect_block(struct ext4_inode *file_inode,
+					unsigned int *total_remaining_blocks,
+					unsigned int *no_blks_reqd)
+{
+	short i, status;
+	long int actual_block_no;
+	/*single indirect */
+	unsigned int *SI_buffer = NULL;
+	long int SI_blockno;
+	unsigned int *SI_start_addr = NULL;
+	ExtFileSystem *fs = get_fs();
+
+	if (*total_remaining_blocks != 0) {
+		SI_buffer = xzalloc(fs->blksz);
+		if (!SI_buffer)
+			return;
+		SI_start_addr = SI_buffer;
+		SI_blockno = get_new_blk_no();
+		if (SI_blockno == -1) {
+			printf("no block left to assign\n");
+			goto fail;
+		}
+		(*no_blks_reqd)++;
+		debug("SIPB %ld: %u\n", SI_blockno, *total_remaining_blocks);
+
+		status = ext2fs_devread(SI_blockno * fs->sect_perblk,
+					0, fs->blksz, (char *)SI_buffer);
+		memset(SI_buffer, '\0', fs->blksz);
+		if (status == 0)
+			goto fail;
+
+		for (i = 0; i < (fs->blksz / sizeof(int)); i++) {
+			actual_block_no = get_new_blk_no();
+			if (actual_block_no == -1) {
+				printf("no block left to assign\n");
+				goto fail;
+			}
+			*SI_buffer = actual_block_no;
+			debug("SIAB %ld: %u\n", *SI_buffer,
+			      *total_remaining_blocks);
+
+			SI_buffer++;
+			(*total_remaining_blocks)--;
+			if (*total_remaining_blocks == 0)
+				break;
+		}
+
+		/*write the block to disk */
+		put_ext4(((uint64_t) (SI_blockno * fs->blksz)),
+			 SI_start_addr, fs->blksz);
+		file_inode->b.blocks.indir_block = SI_blockno;
+	}
+fail:
+	if (SI_start_addr)
+		free(SI_start_addr);
+	return;
+}
+
+/*allocation of double indirect blocks*/
+static void alloc_double_indirect_block(struct ext4_inode *file_inode,
+					unsigned int *total_remaining_blocks,
+					unsigned int *no_blks_reqd)
+{
+	short i, j, status;
+	long int actual_block_no;
+	/*double indirect */
+	long int DI_blockno_parent, DI_blockno_child;
+	unsigned int *DI_parent_buffer = NULL;
+	unsigned int *DI_child_buff = NULL;
+	unsigned int *DI_block_start_addr = NULL;
+	unsigned int *DI_child_buff_start = NULL;
+	ExtFileSystem *fs = get_fs();
+
+	if (*total_remaining_blocks != 0) {
+		/*double indirect parent block connecting to inode */
+		DI_blockno_parent = get_new_blk_no();
+		if (DI_blockno_parent == -1) {
+			printf("no block left to assign\n");
+			goto fail;
+		}
+		DI_parent_buffer = xzalloc(fs->blksz);
+		if (!DI_parent_buffer)
+			goto fail;
+
+		DI_block_start_addr = DI_parent_buffer;
+		(*no_blks_reqd)++;
+		debug("DIPB %ld: %u\n", DI_blockno_parent,
+		      *total_remaining_blocks);
+
+		status = ext2fs_devread(DI_blockno_parent *
+					fs->sect_perblk, 0,
+					fs->blksz, (char *)DI_parent_buffer);
+		memset(DI_parent_buffer, '\0', fs->blksz);
+
+		/*START: for each double indirect parent
+		 *block create one more block*/
+		for (i = 0; i < (fs->blksz / sizeof(int)); i++) {
+			DI_blockno_child = get_new_blk_no();
+			if (DI_blockno_child == -1) {
+				printf("no block left to assign\n");
+				goto fail;
+			}
+			DI_child_buff = xzalloc(fs->blksz);
+			if (!DI_child_buff)
+				goto fail;
+
+			DI_child_buff_start = DI_child_buff;
+			*DI_parent_buffer = DI_blockno_child;
+			DI_parent_buffer++;
+			(*no_blks_reqd)++;
+			debug("DICB %ld: %u\n", DI_blockno_child,
+			      *total_remaining_blocks);
+
+			status = ext2fs_devread(DI_blockno_child *
+						fs->sect_perblk, 0,
+						fs->blksz,
+						(char *)DI_child_buff);
+			memset(DI_child_buff, '\0', fs->blksz);
+			/*END: for each double indirect parent block block */
+			/*filling of actual datablocks for each child */
+			for (j = 0; j < (fs->blksz / sizeof(int)); j++) {
+				actual_block_no = get_new_blk_no();
+				if (actual_block_no == -1) {
+					printf("no block left to assign\n");
+					goto fail;
+				}
+				*DI_child_buff = actual_block_no;
+				debug("DIAB %ld: %u\n", actual_block_no,
+				      *total_remaining_blocks);
+
+				DI_child_buff++;
+				(*total_remaining_blocks)--;
+				if (*total_remaining_blocks == 0)
+					break;
+			}
+			/*write the block  table */
+			put_ext4(((uint64_t) (DI_blockno_child * fs->blksz)),
+				 DI_child_buff_start, fs->blksz);
+			if (DI_child_buff_start)
+				free(DI_child_buff_start);
+
+			if (*total_remaining_blocks == 0)
+				break;
+		}
+		put_ext4(((uint64_t) (DI_blockno_parent * fs->blksz)),
+			 DI_block_start_addr, fs->blksz);
+		file_inode->b.blocks.double_indir_block = DI_blockno_parent;
+	}
+fail:
+	if (DI_block_start_addr)
+		free(DI_block_start_addr);
+	return;
+}
+
+/*allocation of triple indirect blocks*/
+static void alloc_triple_indirect_block(struct ext4_inode *file_inode,
+					unsigned int *total_remaining_blocks,
+					unsigned int *no_blks_reqd)
+{
+	short i, j, k;
+	long int actual_block_no;
+	/*Triple Indirect */
+	long int TI_gp_blockno, TI_parent_blockno, TI_child_blockno;
+	unsigned int *TI_gp_buff = NULL;
+	unsigned int *TI_parent_buff = NULL;
+	unsigned int *TI_child_buff = NULL;
+	unsigned int *TI_gp_buff_start_addr = NULL;
+	unsigned int *TI_pbuff_start_addr = NULL;
+	unsigned int *TI_cbuff_start_addr = NULL;
+	ExtFileSystem *fs = get_fs();
+	if (*total_remaining_blocks != 0) {
+		/*triple indirect grand parent block connecting to inode */
+		TI_gp_blockno = get_new_blk_no();
+		if (TI_gp_blockno == -1) {
+			printf("no block left to assign\n");
+			goto fail;
+		}
+		TI_gp_buff = xzalloc(fs->blksz);
+		if (!TI_gp_buff)
+			goto fail;
+
+		TI_gp_buff_start_addr = TI_gp_buff;
+		(*no_blks_reqd)++;
+		debug("TIGPB %ld: %u\n", TI_gp_blockno,
+		      *total_remaining_blocks);
+
+		/* for each 4 byte grand parent entry create one more block */
+		for (i = 0; i < (fs->blksz / sizeof(int)); i++) {
+			TI_parent_blockno = get_new_blk_no();
+			if (TI_parent_blockno == -1) {
+				printf("no block left to assign\n");
+				goto fail;
+			}
+			TI_parent_buff = xzalloc(fs->blksz);
+			if (!TI_parent_buff)
+				goto fail;
+
+			TI_pbuff_start_addr = TI_parent_buff;
+			*TI_gp_buff = TI_parent_blockno;
+			TI_gp_buff++;
+			(*no_blks_reqd)++;
+			debug("TIPB %ld: %u\n", TI_parent_blockno,
+			      *total_remaining_blocks);
+
+			/*for each 4 byte entry parent create one more block */
+			for (j = 0; j < (fs->blksz / sizeof(int)); j++) {
+				TI_child_blockno = get_new_blk_no();
+				if (TI_child_blockno == -1) {
+					printf("no block \
+						left assign\n");
+					goto fail;
+				}
+				TI_child_buff = xzalloc(fs->blksz);
+				if (!TI_child_buff)
+					goto fail;
+
+				TI_cbuff_start_addr = TI_child_buff;
+				*TI_parent_buff = TI_child_blockno;
+				TI_parent_buff++;
+				(*no_blks_reqd)++;
+				debug("TICB %ld: %u\n", TI_parent_blockno,
+				      *total_remaining_blocks);
+
+				/*filling of actual datablocks for each child */
+				for (k = 0; k < (fs->blksz / sizeof(int));
+					k++) {
+					actual_block_no = get_new_blk_no();
+					if (actual_block_no == -1) {
+						printf("no block \
+						left to assign\n");
+						goto fail;
+					}
+					*TI_child_buff = actual_block_no;
+					debug("TIAB %ld: %u\n", actual_block_no,
+					      *total_remaining_blocks);
+
+					TI_child_buff++;
+					(*total_remaining_blocks)--;
+					if (*total_remaining_blocks == 0)
+						break;
+				}
+				/*write the child block */
+				put_ext4(((uint64_t) (TI_child_blockno *
+						      fs->blksz)),
+					 TI_cbuff_start_addr, fs->blksz);
+				if (TI_cbuff_start_addr)
+					free(TI_cbuff_start_addr);
+
+				if (*total_remaining_blocks == 0)
+					break;
+			}
+			/*write the parent block */
+			put_ext4(((uint64_t) (TI_parent_blockno * fs->blksz)),
+				 TI_pbuff_start_addr, fs->blksz);
+			if (TI_pbuff_start_addr)
+				free(TI_pbuff_start_addr);
+
+			if (*total_remaining_blocks == 0)
+				break;
+		}
+		/*write the grand parent block */
+		put_ext4(((uint64_t) (TI_gp_blockno * fs->blksz)),
+			 TI_gp_buff_start_addr, fs->blksz);
+		file_inode->b.blocks.tripple_indir_block = TI_gp_blockno;
+	}
+fail:
+	if (TI_gp_buff_start_addr)
+		free(TI_gp_buff_start_addr);
+	return;
+}
+
+void allocate_blocks(struct ext4_inode *file_inode,
+		     unsigned int total_remaining_blocks,
+		     unsigned int *total_no_of_block)
+{
+	short i;
+	long int direct_blockno;
+	unsigned int no_blks_reqd = 0;
+
+	/*-------------START:Allocation of Blocks to Inode-------------*/
+	/*allocation of direct blocks */
+	for (i = 0; i < INDIRECT_BLOCKS; i++) {
+		direct_blockno = get_new_blk_no();
+		if (direct_blockno == -1) {
+			printf("no block left to assign\n");
+			return;
+		}
+		file_inode->b.blocks.dir_blocks[i] = direct_blockno;
+		debug("DB %ld: %u\n", direct_blockno, total_remaining_blocks);
+
+		total_remaining_blocks--;
+		if (total_remaining_blocks == 0)
+			break;
+	}
+
+	/*allocation of single indirect blocks */
+	alloc_single_indirect_block(file_inode, &total_remaining_blocks,
+				    &no_blks_reqd);
+
+	/*allocation of double indirect blocks */
+	alloc_double_indirect_block(file_inode, &total_remaining_blocks,
+				    &no_blks_reqd);
+
+	/*allocation of triple indirect blocks */
+	alloc_triple_indirect_block(file_inode, &total_remaining_blocks,
+				    &no_blks_reqd);
+
+	/*-----------------END:Allocation of Blocks to Inode-------------- */
+	*total_no_of_block += no_blks_reqd;
+	return;
+}
+
 long int read_allocated_block(struct ext4_inode *inode, int fileblock)
 {
 	long int blknr;
diff --git a/fs/ext4/ext4_common.h b/fs/ext4/ext4_common.h
index 2014298..acd14ee 100644
--- a/fs/ext4/ext4_common.h
+++ b/fs/ext4/ext4_common.h
@@ -41,4 +41,21 @@ 
 extern unsigned long part_offset;
 int ext4fs_read_inode(struct ext2_data *data, int ino,
 		      struct ext4_inode *inode);
+uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n);
+int ext4fs_checksum_update(unsigned int i);
+int get_parent_inode_num(char *dirname, char *dname, int flags);
+void update_parent_dentry(char *filename, int *p_ino, int file_type);
+long int get_new_blk_no(void);
+int get_new_inode_no(void);
+void reset_block_bmap(long int blockno, unsigned char *buffer, int index);
+int set_block_bmap(long int blockno, unsigned char *buffer, int index);
+int set_inode_bmap(int inode_no, unsigned char *buffer, int index);
+void reset_inode_bmap(int inode_no, unsigned char *buffer, int index);
+int iget(int inode_no, struct ext4_inode *inode);
+void allocate_blocks(struct ext4_inode *file_inode,
+		     unsigned int total_remaining_blocks,
+		     unsigned int *total_no_of_block);
+void put_ext4(uint64_t off, void *buf, uint32_t size);
+unsigned int be_le(unsigned int num);
+unsigned int le_be(unsigned int num);
 #endif
diff --git a/fs/ext4/ext4_journal.c b/fs/ext4/ext4_journal.c
new file mode 100644
index 0000000..844ff39
--- /dev/null
+++ b/fs/ext4/ext4_journal.c
@@ -0,0 +1,657 @@ 
+/*
+ * (C) Copyright 2011 Samsung Electronics
+ * EXT4 filesystem implementation in Uboot by
+ * Uma Shankar <uma.shankar@samsung.com>
+ * Manjunatha C Achar <a.manjunatha@samsung.com>
+ *
+ *  Copyright (C) 2003, 2004  Free Software Foundation, Inc.
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+  * Journaling feature of ext4 has been referred from JBD2
+  * (Journaling Block device 2) implementation in Linux Kernel
+ */
+#include <common.h>
+#include "ext4_journal.h"
+#include <ext2fs.h>
+#include <ext4fs.h>
+#include <malloc.h>
+
+static revoke_blk_list *revk_blk_list;
+static revoke_blk_list *prev_node;
+static int first_node = TRUE;
+
+int gindex;
+int gd_index;
+int jrnl_blk_idx;
+struct journal_log *journal_ptr[MAX_JOURNAL_ENTRIES];
+struct dirty_blocks *dirty_block_ptr[MAX_JOURNAL_ENTRIES];
+
+int init_journal(void)
+{
+	int i;
+	char *temp = NULL;
+	ExtFileSystem *fs = get_fs();
+
+	/*init globals */
+	revk_blk_list = NULL;
+	prev_node = NULL;
+	gindex = 0;
+	gd_index = 0;
+	jrnl_blk_idx = 1;
+
+	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
+		journal_ptr[i] = (struct journal_log *)xzalloc
+		    (sizeof(struct journal_log));
+		if (!journal_ptr[i])
+			goto fail;
+		dirty_block_ptr[i] = (struct dirty_blocks *)
+		    xzalloc(sizeof(struct dirty_blocks));
+		if (!dirty_block_ptr[i])
+			goto fail;
+		journal_ptr[i]->buf = NULL;
+		journal_ptr[i]->blknr = -1;
+
+		dirty_block_ptr[i]->buf = NULL;
+		dirty_block_ptr[i]->blknr = -1;
+	}
+
+	if (fs->blksz == 4096) {
+		temp = (char *)xzalloc(fs->blksz);
+		if (!temp)
+			goto fail;
+		journal_ptr[gindex]->buf = (char *)xzalloc(fs->blksz);
+		if (!journal_ptr[gindex]->buf)
+			goto fail;
+		ext2fs_devread(0, 0, fs->blksz, temp);
+		memcpy(temp + SUPERBLOCK_SIZE, fs->sb, SUPERBLOCK_SIZE);
+		memcpy(journal_ptr[gindex]->buf, temp, fs->blksz);
+		journal_ptr[gindex++]->blknr = 0;
+		free(temp);
+	} else {
+		journal_ptr[gindex]->buf = (char *)xzalloc(fs->blksz);
+		if (!journal_ptr[gindex]->buf)
+			goto fail;
+		memcpy(journal_ptr[gindex]->buf, fs->sb, SUPERBLOCK_SIZE);
+		journal_ptr[gindex++]->blknr = 1;
+	}
+
+	/* Check the file system state using journal super block */
+	if (check_journal_state(SCAN))
+		goto fail;
+	if (check_journal_state(RECOVER))
+		goto fail;
+	return 0;
+fail:
+	return -1;
+}
+
+void dump_metadata(void)
+{
+	ExtFileSystem *fs = get_fs();
+	int i;
+	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
+		if (dirty_block_ptr[i]->blknr == -1)
+			break;
+		put_ext4((uint64_t) (dirty_block_ptr[i]->blknr * fs->blksz),
+			 dirty_block_ptr[i]->buf, (uint32_t) fs->blksz);
+	}
+	return;
+}
+
+void free_journal(void)
+{
+	int i;
+	jrnl_blk_idx = 1;
+	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
+		if (dirty_block_ptr[i]->blknr == -1)
+			break;
+		if (dirty_block_ptr[i]->buf)
+			free(dirty_block_ptr[i]->buf);
+	}
+
+	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
+		if (journal_ptr[i]->blknr == -1)
+			break;
+		if (journal_ptr[i]->buf)
+			free(journal_ptr[i]->buf);
+	}
+
+	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
+		if (journal_ptr[i])
+			free(journal_ptr[i]);
+		if (dirty_block_ptr[i])
+			free(dirty_block_ptr[i]);
+	}
+	gindex = 0;
+	gd_index = 0;
+	return;
+}
+
+int log_gdt(char *gd_table)
+{
+	ExtFileSystem *fs = get_fs();
+	short i;
+	long int var = fs->gdtable_blkno;
+	for (i = 0; i < fs->no_blk_pergdt; i++) {
+		journal_ptr[gindex]->buf = (char *)xzalloc(fs->blksz);
+		if (!journal_ptr[gindex]->buf)
+			return -1;
+		memcpy(journal_ptr[gindex]->buf, gd_table, fs->blksz);
+		gd_table += fs->blksz;
+		journal_ptr[gindex++]->blknr = var++;
+	}
+	return 0;
+}
+
+/* This function stores the backup copy of meta data in RAM
+*  journal_buffer -- Buffer containing meta data
+*  blknr -- Block number on disk of the meta data buffer
+*/
+int log_journal(char *journal_buffer, long int blknr)
+{
+	ExtFileSystem *fs = get_fs();
+	short i;
+
+	if (!journal_buffer) {
+		printf("Invalid input arguments %s\n", __func__);
+		return -1;
+	}
+
+	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
+		if (journal_ptr[i]->blknr == -1)
+			break;
+		if (journal_ptr[i]->blknr == blknr)
+			return 0;
+	}
+
+	journal_ptr[gindex]->buf = (char *)xzalloc(fs->blksz);
+	if (!journal_ptr[gindex]->buf)
+		return -1;
+
+	memcpy(journal_ptr[gindex]->buf, journal_buffer, fs->blksz);
+	journal_ptr[gindex++]->blknr = blknr;
+	return 0;
+}
+
+/* This function stores the modified meta data in RAM
+*  metadata_buffer -- Buffer containing meta data
+*  blknr -- Block number on disk of the meta data buffer
+*/
+int put_metadata(char *metadata_buffer, long int blknr)
+{
+	ExtFileSystem *fs = get_fs();
+	if (!metadata_buffer) {
+		printf("Invalid input arguments %s\n", __func__);
+		return -1;
+	}
+	dirty_block_ptr[gd_index]->buf = (char *)xzalloc(fs->blksz);
+	if (!dirty_block_ptr[gd_index]->buf)
+		return -1;
+	memcpy(dirty_block_ptr[gd_index]->buf, metadata_buffer, fs->blksz);
+	dirty_block_ptr[gd_index++]->blknr = blknr;
+	return 0;
+}
+
+/*------------------------------------*/
+/*Revoke block handling functions*/
+void print_revoke_blks(char *revk_blk)
+{
+	journal_revoke_header_t *header;
+	int offset, max;
+	long int blocknr;
+
+	if (revk_blk == NULL)
+		return;
+
+	header = (journal_revoke_header_t *) revk_blk;
+	offset = sizeof(journal_revoke_header_t);
+	max = be_le(header->r_count);
+	printf("total bytes %d\n", max);
+
+	while (offset < max) {
+		blocknr = be_le(*((long int *)(revk_blk + offset)));
+		printf("revoke blknr is %ld\n", blocknr);
+		offset += 4;
+	}
+	return;
+}
+
+static revoke_blk_list *_get_node(void)
+{
+	revoke_blk_list *tmp_node;
+	tmp_node = (revoke_blk_list *) malloc(sizeof(revoke_blk_list));
+	if (tmp_node == NULL)
+		return NULL;
+	tmp_node->content = NULL;
+	tmp_node->next = NULL;
+	return tmp_node;
+}
+
+void push_revoke_blk(char *buffer)
+{
+	revoke_blk_list *node;
+	ExtFileSystem *fs = get_fs();
+	if (buffer == NULL) {
+		printf("buffer ptr is NULL\n");
+		return;
+	}
+	node = _get_node();
+	if (!node) {
+		printf("_get_node: malloc failed\n");
+		return;
+	}
+
+	node->content = (char *)malloc(fs->blksz);
+	memcpy(node->content, buffer, fs->blksz);
+
+	if (first_node == TRUE) {
+		revk_blk_list = node;
+		prev_node = node;
+		first_node = FALSE;
+	} else {
+		prev_node->next = node;
+		prev_node = node;
+	}
+	return;
+}
+
+void free_revoke_blks()
+{
+	revoke_blk_list *tmp_node = revk_blk_list;
+	revoke_blk_list *next_node = NULL;
+
+	while (tmp_node != NULL) {
+		if (tmp_node->content)
+			free(tmp_node->content);
+		tmp_node = tmp_node->next;
+	}
+
+	tmp_node = revk_blk_list;
+	while (tmp_node != NULL) {
+		next_node = tmp_node->next;
+		free(tmp_node);
+		tmp_node = next_node;
+	}
+
+	revk_blk_list = NULL;
+	prev_node = NULL;
+	first_node = TRUE;
+	return;
+}
+
+int check_blknr_for_revoke(long int blknr, int sequence_no)
+{
+	journal_revoke_header_t *header;
+	int offset, max;
+	long int blocknr;
+	char *revk_blk;
+	revoke_blk_list *tmp_revk_node = revk_blk_list;
+	while (tmp_revk_node != NULL) {
+		revk_blk = tmp_revk_node->content;
+
+		header = (journal_revoke_header_t *) revk_blk;
+		if (sequence_no <= be_le(header->r_header.h_sequence)) {
+			offset = sizeof(journal_revoke_header_t);
+			max = be_le(header->r_count);
+
+			while (offset < max) {
+				blocknr = be_le(*((long int *)
+						  (revk_blk + offset)));
+				if (blocknr == blknr)
+					goto found;
+				offset += 4;
+			}
+		}
+		tmp_revk_node = tmp_revk_node->next;
+	}
+	return -1;
+
+found:
+	return 0;
+}
+
+/*
+* This function parses the journal blocks and replays the
+* suceessful transactions. A transaction is successfull
+* if commit block is found for a descriptor block
+* The tags in descriptor block contain the disk block
+* numbers of the metadata  to be replayed
+*/
+void recover_transaction(int prev_desc_logical_no)
+{
+	struct ext4_inode inode_journal;
+	ExtFileSystem *fs = get_fs();
+	journal_header_t *jdb;
+	long int blknr;
+	char *p_jdb;
+	int ofs, flags;
+	int i;
+	struct ext3_journal_block_tag *tag;
+	char *temp_buff = (char *)xzalloc(fs->blksz);
+	char *metadata_buff = (char *)xzalloc(fs->blksz);
+	if (!temp_buff || !metadata_buff)
+		goto fail;
+	i = prev_desc_logical_no;
+	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
+			  (struct ext4_inode *)&inode_journal);
+	blknr = read_allocated_block((struct ext4_inode *)
+				     &inode_journal, i);
+	ext2fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, temp_buff);
+	p_jdb = (char *)temp_buff;
+	jdb = (journal_header_t *) temp_buff;
+	ofs = sizeof(journal_header_t);
+
+	do {
+		tag = (struct ext3_journal_block_tag *)&p_jdb[ofs];
+		ofs += sizeof(struct ext3_journal_block_tag);
+
+		if (ofs > fs->blksz)
+			break;
+
+		flags = be_le(tag->flags);
+		if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
+			ofs += 16;
+
+		i++;
+		debug("\t\ttag %u\n", be_le(tag->block));
+		if (revk_blk_list != NULL) {
+			if (check_blknr_for_revoke(be_le(tag->block),
+						   be_le(jdb->h_sequence)) ==
+			    0) {
+				continue;
+			}
+		}
+		blknr = read_allocated_block((struct ext4_inode *)
+					     &inode_journal, i);
+		ext2fs_devread(blknr * fs->sect_perblk, 0,
+			       fs->blksz, metadata_buff);
+		put_ext4((uint64_t) (be_le(tag->block) * fs->blksz),
+			 metadata_buff, (uint32_t) fs->blksz);
+	} while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
+fail:
+	if (temp_buff)
+		free(temp_buff);
+	if (metadata_buff)
+		free(metadata_buff);
+}
+
+void print_jrnl_status(int recovery_flag)
+{
+	if (recovery_flag == RECOVER)
+		printf("Journal Recovery Completed\n");
+	else
+		printf("Journal Scan Completed\n");
+	return;
+}
+
+int check_journal_state(int recovery_flag)
+{
+	struct ext4_inode inode_journal;
+	ExtFileSystem *fs = get_fs();
+	journal_superblock_t *jsb;
+	journal_header_t *jdb;
+	char *p_jdb;
+	int i;
+	int DB_FOUND = NO;
+	long int blknr;
+	int transaction_state = TRANSACTION_COMPLETE;
+	int prev_desc_logical_no = 0;
+	int curr_desc_logical_no = 0;
+	int ofs, flags, block;
+	struct ext3_journal_block_tag *tag;
+	char *temp_buff, *temp_buff1;
+
+	temp_buff = (char *)xzalloc(fs->blksz);
+	if (!temp_buff)
+		return -1;
+	temp_buff1 = (char *)xzalloc(fs->blksz);
+	if (!temp_buff1) {
+		free(temp_buff);
+		return -1;
+	}
+
+	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
+	blknr = read_allocated_block((struct ext4_inode *)&inode_journal,
+				     EXT2_JOURNAL_SUPERBLOCK);
+	ext2fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, temp_buff);
+	jsb = (journal_superblock_t *) temp_buff;
+
+	if (fs->sb->feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
+		if (recovery_flag == RECOVER)
+			printf("Recovery required\n");
+	} else {
+		if (recovery_flag == RECOVER)
+			printf("File System is consistent\n");
+		goto END;
+	}
+
+	if (be_le(jsb->s_start) == 0)
+		goto END;
+
+	if (!(jsb->s_feature_compat & le_be(JBD2_FEATURE_COMPAT_CHECKSUM)))
+		jsb->s_feature_compat |= le_be(JBD2_FEATURE_COMPAT_CHECKSUM);
+
+	i = be_le(jsb->s_first);
+	while (1) {
+		block = be_le(jsb->s_first);
+		blknr = read_allocated_block((struct ext4_inode *)
+					     &inode_journal, i);
+		memset(temp_buff1, '\0', fs->blksz);
+		ext2fs_devread(blknr * fs->sect_perblk,
+			       0, fs->blksz, temp_buff1);
+		jdb = (journal_header_t *) temp_buff1;
+
+		if (be_le(jdb->h_blocktype) == EXT3_JOURNAL_DESCRIPTOR_BLOCK) {
+			if (be_le(jdb->h_sequence) != be_le(jsb->s_sequence)) {
+				print_jrnl_status(recovery_flag);
+				break;
+			}
+
+			curr_desc_logical_no = i;
+			if (transaction_state == TRANSACTION_COMPLETE)
+				transaction_state = TRANSACTION_RUNNING;
+			else
+				return -1;
+			p_jdb = (char *)temp_buff1;
+			ofs = sizeof(journal_header_t);
+			do {
+				tag = (struct ext3_journal_block_tag *)
+				    &p_jdb[ofs];
+				ofs += sizeof(struct ext3_journal_block_tag);
+				if (ofs > fs->blksz)
+					break;
+				flags = be_le(tag->flags);
+				if (!(flags & EXT3_JOURNAL_FLAG_SAME_UUID))
+					ofs += 16;
+				i++;
+				debug("\t\ttag %u\n", be_le(tag->block));
+			} while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
+			i++;
+			DB_FOUND = YES;
+		} else if (be_le(jdb->h_blocktype) ==
+				EXT3_JOURNAL_COMMIT_BLOCK) {
+			if ((be_le(jdb->h_sequence) != be_le(jsb->s_sequence))
+			    || (DB_FOUND == NO)) {
+				print_jrnl_status(recovery_flag);
+				break;
+			}
+
+			if (transaction_state == TRANSACTION_RUNNING) {
+				transaction_state = TRANSACTION_COMPLETE;
+				i++;
+				jsb->s_sequence =
+				    le_be(be_le(jsb->s_sequence) + 1);
+			}
+			prev_desc_logical_no = curr_desc_logical_no;
+			recover_transaction(prev_desc_logical_no);
+			DB_FOUND = NO;
+		} else if (be_le(jdb->h_blocktype) ==
+				EXT3_JOURNAL_REVOKE_BLOCK) {
+			if (be_le(jdb->h_sequence) != be_le(jsb->s_sequence)) {
+				print_jrnl_status(recovery_flag);
+				break;
+			}
+			if (recovery_flag == SCAN)
+				push_revoke_blk((char *)jdb);
+			i++;
+		} else {
+			debug("Else Case\n");
+			if (be_le(jdb->h_sequence) != be_le(jsb->s_sequence)) {
+				print_jrnl_status(recovery_flag);
+				break;
+			}
+		}
+	}
+
+END:
+	if (recovery_flag == RECOVER) {
+		jsb->s_start = le_be(1);
+		jsb->s_sequence = le_be(be_le(jsb->s_sequence) + 1);
+		ext2fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE,
+			       (char *)fs->sb);
+		fs->sb->feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER;
+
+		put_ext4((uint64_t) (SUPERBLOCK_SIZE),
+			 (struct ext2_sblock *)fs->sb,
+			 (uint32_t) SUPERBLOCK_SIZE);
+		ext2fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE,
+			       (char *)fs->sb);
+
+		blknr =
+		    read_allocated_block((struct ext4_inode *)&inode_journal,
+					 EXT2_JOURNAL_SUPERBLOCK);
+		put_ext4((uint64_t) (blknr * fs->blksz),
+			 (struct journal_superblock_t *)temp_buff,
+			 (uint32_t) fs->blksz);
+		free_revoke_blks();
+	}
+	free(temp_buff);
+	free(temp_buff1);
+
+	return 0;
+}
+
+static void update_descriptor_block(long int blknr)
+{
+	journal_header_t jdb;
+	struct ext3_journal_block_tag tag;
+	struct ext4_inode inode_journal;
+	journal_superblock_t *jsb;
+	long int jsb_blknr;
+	ExtFileSystem *fs = get_fs();
+	char *buf = NULL, *temp = NULL;
+	int i;
+	char *temp_buff = (char *)xzalloc(fs->blksz);
+	if (!temp_buff)
+		return;
+
+	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
+	jsb_blknr = read_allocated_block((struct ext4_inode *)
+					 &inode_journal,
+					 EXT2_JOURNAL_SUPERBLOCK);
+	ext2fs_devread(jsb_blknr * fs->sect_perblk, 0, fs->blksz, temp_buff);
+	jsb = (journal_superblock_t *) temp_buff;
+
+	jdb.h_blocktype = le_be(EXT3_JOURNAL_DESCRIPTOR_BLOCK);
+	jdb.h_magic = le_be(EXT3_JOURNAL_MAGIC_NUMBER);
+	jdb.h_sequence = jsb->s_sequence;
+	buf = (char *)xzalloc(fs->blksz);
+	if (!buf) {
+		free(temp_buff);
+		return;
+	}
+	temp = buf;
+	memcpy(buf, &jdb, sizeof(journal_header_t));
+	temp += sizeof(journal_header_t);
+
+	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
+		if (journal_ptr[i]->blknr == -1)
+			break;
+
+		tag.block = le_be(journal_ptr[i]->blknr);
+		tag.flags = le_be(EXT3_JOURNAL_FLAG_SAME_UUID);
+		memcpy(temp, &tag, sizeof(struct ext3_journal_block_tag));
+		temp = temp + sizeof(struct ext3_journal_block_tag);
+	}
+
+	tag.block = le_be(journal_ptr[--i]->blknr);
+	tag.flags = le_be(EXT3_JOURNAL_FLAG_LAST_TAG);
+	memcpy(temp - sizeof(struct ext3_journal_block_tag), &tag,
+	       sizeof(struct ext3_journal_block_tag));
+	put_ext4((uint64_t) (blknr * fs->blksz), buf, (uint32_t) fs->blksz);
+
+	free(temp_buff);
+	free(buf);
+}
+
+static void update_commit_block(long int blknr)
+{
+	journal_header_t jdb;
+	ExtFileSystem *fs = get_fs();
+	char *buf = NULL;
+	struct ext4_inode inode_journal;
+	journal_superblock_t *jsb;
+	long int jsb_blknr;
+	char *temp_buff = (char *)xzalloc(fs->blksz);
+	if (!temp_buff)
+		return;
+
+	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
+	jsb_blknr = read_allocated_block((struct ext4_inode *)
+					 &inode_journal,
+					 EXT2_JOURNAL_SUPERBLOCK);
+	ext2fs_devread(jsb_blknr * fs->sect_perblk, 0, fs->blksz, temp_buff);
+	jsb = (journal_superblock_t *) temp_buff;
+
+	jdb.h_blocktype = le_be(EXT3_JOURNAL_COMMIT_BLOCK);
+	jdb.h_magic = le_be(EXT3_JOURNAL_MAGIC_NUMBER);
+	jdb.h_sequence = jsb->s_sequence;
+	buf = (char *)xzalloc(fs->blksz);
+	if (!buf) {
+		free(temp_buff);
+		return;
+	}
+	memcpy(buf, &jdb, sizeof(journal_header_t));
+	put_ext4((uint64_t) (blknr * fs->blksz), buf, (uint32_t) fs->blksz);
+
+	free(temp_buff);
+	free(buf);
+}
+
+void update_journal(void)
+{
+	struct ext4_inode inode_journal;
+	ExtFileSystem *fs = get_fs();
+	long int blknr;
+	int i;
+	ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, &inode_journal);
+	blknr = read_allocated_block((struct ext4_inode *)&inode_journal,
+				     jrnl_blk_idx++);
+	update_descriptor_block(blknr);
+	for (i = 0; i < MAX_JOURNAL_ENTRIES; i++) {
+		if (journal_ptr[i]->blknr == -1)
+			break;
+		blknr = read_allocated_block((struct ext4_inode *)
+					     &inode_journal, jrnl_blk_idx++);
+		put_ext4((uint64_t) (blknr * fs->blksz),
+			 journal_ptr[i]->buf, (uint32_t) fs->blksz);
+	}
+	blknr = read_allocated_block((struct ext4_inode *)
+				     &inode_journal, jrnl_blk_idx++);
+	update_commit_block(blknr);
+	printf("update journal finished\n");
+}
diff --git a/fs/ext4/ext4_journal.h b/fs/ext4/ext4_journal.h
new file mode 100644
index 0000000..191a9ea
--- /dev/null
+++ b/fs/ext4/ext4_journal.h
@@ -0,0 +1,147 @@ 
+/*
+ * (C) Copyright 2011 Samsung Electronics
+ * EXT4 filesystem implementation in Uboot by
+ * Uma Shankar <uma.shankar@samsung.com>
+ * Manjunatha C Achar <a.manjunatha@samsung.com>
+ *
+ *  Copyright (C) 2003, 2004  Free Software Foundation, Inc.
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Journaling feature of ext4 has been referred from JBD2
+ * (Journaling Block device 2) implementation in Linux Kernel
+ */
+
+#ifndef __EXT4_JRNL__
+#define __EXT4_JRNL__
+
+#include "ext4_common.h"
+
+#define EXT2_JOURNAL_INO		8 /* Journal inode */
+#define EXT2_JOURNAL_SUPERBLOCK		0 /* Journal  Superblock number */
+
+#define JBD2_FEATURE_COMPAT_CHECKSUM	0x00000001
+#define EXT3_JOURNAL_MAGIC_NUMBER	0xc03b3998U
+#define TRANSACTION_RUNNING		1
+#define TRANSACTION_COMPLETE		0
+#define EXT3_FEATURE_INCOMPAT_RECOVER	0x0004	/* Needs recovery */
+#define EXT3_JOURNAL_DESCRIPTOR_BLOCK	1
+#define EXT3_JOURNAL_COMMIT_BLOCK	2
+#define EXT3_JOURNAL_SUPERBLOCK_V1	3
+#define EXT3_JOURNAL_SUPERBLOCK_V2	4
+#define EXT3_JOURNAL_REVOKE_BLOCK	5
+#define EXT3_JOURNAL_FLAG_ESCAPE	1
+#define EXT3_JOURNAL_FLAG_SAME_UUID	2
+#define EXT3_JOURNAL_FLAG_DELETED	4
+#define EXT3_JOURNAL_FLAG_LAST_TAG	8
+
+/* Maximum entries in 1 journal transaction */
+#define MAX_JOURNAL_ENTRIES		100
+struct journal_log {
+	char *buf;
+	int blknr;
+};
+
+struct dirty_blocks {
+	char *buf;
+	int blknr;
+};
+
+/*
+ * Standard header for all descriptor blocks:
+ */
+typedef struct journal_header_s {
+	__u32 h_magic;
+	__u32 h_blocktype;
+	__u32 h_sequence;
+} journal_header_t;
+
+/*
+ * The journal superblock.  All fields are in big-endian byte order.
+ */
+typedef struct journal_superblock_s {
+	/* 0x0000 */
+	journal_header_t s_header;
+
+	/* 0x000C */
+	/* Static information describing the journal */
+	__u32 s_blocksize;	/* journal device blocksize */
+	__u32 s_maxlen;		/* total blocks in journal file */
+	__u32 s_first;		/* first block of log information */
+
+	/* 0x0018 */
+	/* Dynamic information describing the current state of the log */
+	__u32 s_sequence;	/* first commit ID expected in log */
+	__u32 s_start;		/* blocknr of start of log */
+
+	/* 0x0020 */
+	/* Error value, as set by journal_abort(). */
+	__s32 s_errno;
+
+	/* 0x0024 */
+	/* Remaining fields are only valid in a version-2 superblock */
+	__u32 s_feature_compat;	/* compatible feature set */
+	__u32 s_feature_incompat;	/* incompatible feature set */
+	__u32 s_feature_ro_compat;	/* readonly-compatible feature set */
+	/* 0x0030 */
+	__u8 s_uuid[16];	/* 128-bit uuid for journal */
+
+	/* 0x0040 */
+	__u32 s_nr_users;	/* Nr of filesystems sharing log */
+
+	__u32 s_dynsuper;	/* Blocknr of dynamic superblock copy */
+
+	/* 0x0048 */
+	__u32 s_max_transaction;	/* Limit of journal blocks per trans. */
+	__u32 s_max_trans_data;	/* Limit of data blocks per trans. */
+
+	/* 0x0050 */
+	__u32 s_padding[44];
+
+	/* 0x0100 */
+	__u8 s_users[16 * 48];	/* ids of all fs'es sharing the log */
+	/* 0x0400 */
+} journal_superblock_t;
+
+struct ext3_journal_block_tag {
+	uint32_t block;
+	uint32_t flags;
+};
+
+typedef struct journal_revoke_header_s {
+	journal_header_t r_header;
+	int r_count;		/* Count of bytes used in the block */
+} journal_revoke_header_t;
+
+typedef struct _revoke_blk_list {
+	char *content;		/*revoke block itself */
+	struct _revoke_blk_list *next;
+} revoke_blk_list;
+
+extern struct ext2_data *ext4fs_root;
+
+int init_journal(void);
+void deinit_journal(void);
+int log_gdt(char *gd_table);
+void update_journal(void);
+int check_journal_state(int recovery_flag);
+int log_journal(char *journal_buffer, long int blknr);
+int put_metadata(char *metadata_buffer, long int blknr);
+void dump_metadata(void);
+void free_journal(void);
+void free_revoke_blks(void);
+void push_revoke_blk(char *buffer);
+#endif
diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
index 890aaf3..bb5bfb9 100644
--- a/fs/ext4/ext4fs.c
+++ b/fs/ext4/ext4fs.c
@@ -22,7 +22,13 @@ 

 /*
  *  ext4load - based on code from GRUB2  fs/ext2.c
-*/
+ *
+ * ext4write - based on existing ext2 support in UBOOT and ext4
+ * implementation in Linux Kernel.
+ * Journaling feature of ext4 has been referred from JBD2
+ * (Journaling Block device 2) implementation in Linux Kernel
+ */
+
 #include <common.h>
 #include <malloc.h>
 #include <asm/byteorder.h>
@@ -31,6 +37,7 @@ 
 #include <ext2fs.h>
 #include <ext4fs.h>
 #include "ext4_common.h"
+#include "ext4_journal.h"

 int ext4fs_symlinknest;
 block_dev_desc_t *ext4_dev_desc;
@@ -213,3 +220,1033 @@  int ext4fs_read(char *buf, unsigned len)
 		return 0;
 	return  ext4fs_read_file(ext4fs_file, 0, len, buf);
 }
+
+static void ext4fs_update(void)
+{
+	short i;
+	update_journal();
+	ExtFileSystem *fs = get_fs();
+
+	/*Update the super block */
+	put_ext4((uint64_t) (SUPERBLOCK_SIZE),
+		 (struct ext2_sblock *)fs->sb, (uint32_t) SUPERBLOCK_SIZE);
+
+	/*update the block group */
+	for (i = 0; i < fs->no_blkgrp; i++) {
+		fs->gd[i].bg_checksum = ext4fs_checksum_update(i);
+		put_ext4((uint64_t) (fs->gd[i].block_id * fs->blksz),
+			 fs->blk_bmaps[i], (uint32_t) fs->blksz);
+	}
+
+	/*update the inode table group */
+	for (i = 0; i < fs->no_blkgrp; i++) {
+		put_ext4((uint64_t) (fs->gd[i].inode_id * fs->blksz),
+			 fs->inode_bmaps[i], (uint32_t) fs->blksz);
+	}
+
+	/*update the block group descriptor table */
+	put_ext4((uint64_t) (fs->gdtable_blkno * fs->blksz),
+		 (struct ext2_block_group *)fs->gdtable, (uint32_t)
+		 (fs->blksz * fs->no_blk_pergdt));
+
+	dump_metadata();
+
+	gindex = 0;
+	gd_index = 0;
+}
+
+int ext4fs_get_bgdtable(void)
+{
+	int status;
+	int grp_desc_size;
+	ExtFileSystem *fs = get_fs();
+	grp_desc_size = sizeof(struct ext2_block_group);
+	fs->no_blk_pergdt = (fs->no_blkgrp * grp_desc_size) / fs->blksz;
+	if ((fs->no_blkgrp * grp_desc_size) % fs->blksz)
+		fs->no_blk_pergdt++;
+
+	/*allocate mem for gdtable */
+	fs->gdtable = (char *)xzalloc(fs->blksz * fs->no_blk_pergdt);
+	if (!fs->gdtable)
+		return -1;
+	/*Read the first group descriptor table */
+	status = ext2fs_devread(fs->gdtable_blkno * fs->sect_perblk, 0,
+				fs->blksz * fs->no_blk_pergdt, fs->gdtable);
+	if (status == 0)
+		goto fail;
+
+	if (log_gdt(fs->gdtable)) {
+		printf("Error in log_gdt\n");
+		return -1;
+	}
+
+	return 0;
+fail:
+	if (fs->gdtable) {
+		free(fs->gdtable);
+		fs->gdtable = NULL;
+	}
+	return -1;
+}
+
+static void delete_single_indirect_block(struct ext4_inode *inode)
+{
+	struct ext2_block_group *gd;
+	static int prev_bg_bitmap_index = -1;
+	long int blknr;
+	int remainder;
+	int bg_idx;
+	int status;
+	ExtFileSystem *fs = get_fs();
+	char *journal_buffer = (char *)xzalloc(fs->blksz);
+	if (!journal_buffer)
+		return;
+	/*get the block group descriptor table */
+	gd = (struct ext2_block_group *)fs->gdtable;
+
+	/*deleting the single indirect block associated with inode */
+	if (inode->b.blocks.indir_block != 0) {
+		debug("SIPB releasing %u\n", inode->b.blocks.indir_block);
+		blknr = inode->b.blocks.indir_block;
+		if (fs->blksz != 1024) {
+			bg_idx = blknr / (uint32_t)
+			    ext4fs_root->sblock.blocks_per_group;
+		} else {
+			bg_idx = blknr /
+			    (uint32_t) ext4fs_root->sblock.blocks_per_group;
+			remainder = blknr % (uint32_t)
+			    ext4fs_root->sblock.blocks_per_group;
+			if (!remainder)
+				bg_idx--;
+		}
+		reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
+		gd[bg_idx].free_blocks++;
+		fs->sb->free_blocks++;
+		/*journal backup */
+		if (prev_bg_bitmap_index != bg_idx) {
+			status =
+			    ext2fs_devread(gd[bg_idx].block_id *
+					   fs->sect_perblk, 0, fs->blksz,
+					   journal_buffer);
+			if (status == 0)
+				goto fail;
+			if (log_journal(journal_buffer, gd[bg_idx].block_id))
+				goto fail;
+			prev_bg_bitmap_index = bg_idx;
+		}
+	}
+fail:
+	if (journal_buffer)
+		free(journal_buffer);
+	return;
+
+}
+
+/*deleting the double indirect blocks */
+static void delete_double_indirect_block(struct ext4_inode *inode)
+{
+	int i;
+	short status;
+	static int prev_bg_bitmap_index = -1;
+	long int blknr;
+	int remainder;
+	int bg_idx;
+	unsigned int *double_indirect_buffer;
+	unsigned int *DIB_start_addr = NULL;
+	struct ext2_block_group *gd;
+	ExtFileSystem *fs = get_fs();
+	char *journal_buffer = (char *)xzalloc(fs->blksz);
+	if (!journal_buffer)
+		return;
+	/*get the block group descriptor table */
+	gd = (struct ext2_block_group *)fs->gdtable;
+
+	if (inode->b.blocks.double_indir_block != 0) {
+		double_indirect_buffer = (unsigned int *)xzalloc(fs->blksz);
+		if (!double_indirect_buffer)
+			return;
+		DIB_start_addr = (unsigned int *)double_indirect_buffer;
+		blknr = inode->b.blocks.double_indir_block;
+		status = ext2fs_devread(blknr * fs->sect_perblk, 0, fs->blksz,
+					(char *)double_indirect_buffer);
+		for (i = 0; i < fs->blksz / sizeof(int); i++) {
+			if (*double_indirect_buffer == 0)
+				break;
+
+			debug("DICB releasing %ld\n", *double_indirect_buffer);
+			if (fs->blksz != 1024) {
+				bg_idx = (*double_indirect_buffer) /
+				    (uint32_t) ext4fs_root->sblock.
+				    blocks_per_group;
+			} else {
+				bg_idx = (*double_indirect_buffer) /
+				    (uint32_t) ext4fs_root->sblock.
+				    blocks_per_group;
+				remainder =
+				    (*double_indirect_buffer) %
+				    (uint32_t) ext4fs_root->sblock.
+				    blocks_per_group;
+				if (!remainder)
+					bg_idx--;
+			}
+			reset_block_bmap(*double_indirect_buffer,
+					 fs->blk_bmaps[bg_idx], bg_idx);
+			double_indirect_buffer++;
+			gd[bg_idx].free_blocks++;
+			fs->sb->free_blocks++;
+			/*journal backup */
+			if (prev_bg_bitmap_index != bg_idx) {
+				status = ext2fs_devread(gd[bg_idx].block_id
+							* fs->sect_perblk, 0,
+							fs->blksz,
+							journal_buffer);
+				if (status == 0)
+					goto fail;
+
+				if (log_journal(journal_buffer,
+						gd[bg_idx].block_id))
+					goto fail;
+				prev_bg_bitmap_index = bg_idx;
+			}
+		}
+
+		/*removing the parent double indirect block */
+		/*find the bitmap index */
+		blknr = inode->b.blocks.double_indir_block;
+		if (fs->blksz != 1024) {
+			bg_idx = blknr / (uint32_t)
+			    ext4fs_root->sblock.blocks_per_group;
+		} else {
+			bg_idx = blknr /
+			    (uint32_t) ext4fs_root->sblock.blocks_per_group;
+			remainder =
+			    blknr %
+			    (uint32_t) ext4fs_root->sblock.blocks_per_group;
+			if (!remainder)
+				bg_idx--;
+		}
+		reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
+		gd[bg_idx].free_blocks++;
+		fs->sb->free_blocks++;
+		/*journal backup */
+		if (prev_bg_bitmap_index != bg_idx) {
+			memset(journal_buffer, '\0', fs->blksz);
+			status = ext2fs_devread(gd[bg_idx].block_id *
+						fs->sect_perblk, 0, fs->blksz,
+						journal_buffer);
+			if (status == 0)
+				goto fail;
+
+			if (log_journal(journal_buffer, gd[bg_idx].block_id))
+				goto fail;
+			prev_bg_bitmap_index = bg_idx;
+		}
+		debug("DIPB releasing %ld\n", blknr);
+	}
+fail:
+	if (DIB_start_addr)
+		free(DIB_start_addr);
+	if (journal_buffer)
+		free(journal_buffer);
+	return;
+}
+
+/*deleting the triple indirect blocks */
+static void delete_triple_indirect_block(struct ext4_inode *inode)
+{
+	int i, j;
+	short status;
+	static int prev_bg_bitmap_index = -1;
+	long int blknr;
+	int remainder;
+	int bg_idx;
+	unsigned int *TIGP_buffer = NULL;
+	unsigned int *TIB_start_addr = NULL;
+	unsigned int *TIP_buffer = NULL;
+	unsigned int *TIPB_start_addr = NULL;
+	struct ext2_block_group *gd;
+	ExtFileSystem *fs = get_fs();
+	char *journal_buffer = (char *)xzalloc(fs->blksz);
+	if (!journal_buffer)
+		return;
+	/*get the block group descriptor table */
+	gd = (struct ext2_block_group *)fs->gdtable;
+
+	if (inode->b.blocks.tripple_indir_block != 0) {
+		TIGP_buffer = (unsigned int *)xzalloc(fs->blksz);
+		if (!TIGP_buffer)
+			return;
+		TIB_start_addr = (unsigned int *)TIGP_buffer;
+		blknr = inode->b.blocks.tripple_indir_block;
+		status = ext2fs_devread(blknr * fs->sect_perblk, 0, fs->blksz,
+					(char *)TIGP_buffer);
+		for (i = 0; i < fs->blksz / sizeof(int); i++) {
+			if (*TIGP_buffer == 0)
+				break;
+			debug("TIGPB releasing %ld\n", *TIGP_buffer);
+
+			TIP_buffer = (unsigned int *)xzalloc(fs->blksz);
+			if (!TIP_buffer)
+				goto fail;
+			TIPB_start_addr = (unsigned int *)TIP_buffer;
+			status = ext2fs_devread((*TIGP_buffer) *
+						fs->sect_perblk, 0, fs->blksz,
+						(char *)TIP_buffer);
+			for (j = 0; j < fs->blksz / sizeof(int); j++) {
+				if (*TIP_buffer == 0)
+					break;
+				if (fs->blksz != 1024) {
+					bg_idx = (*TIP_buffer) / (uint32_t)
+					    ext4fs_root->sblock.
+					    blocks_per_group;
+				} else {
+					bg_idx = (*TIP_buffer) / (uint32_t)
+					    ext4fs_root->sblock.
+					    blocks_per_group;
+
+					remainder = (*TIP_buffer) % (uint32_t)
+					    ext4fs_root->sblock.
+					    blocks_per_group;
+					if (!remainder)
+						bg_idx--;
+				}
+
+				reset_block_bmap(*TIP_buffer,
+						 fs->blk_bmaps[bg_idx], bg_idx);
+
+				TIP_buffer++;
+				gd[bg_idx].free_blocks++;
+				fs->sb->free_blocks++;
+				/*journal backup */
+				if (prev_bg_bitmap_index != bg_idx) {
+					status =
+					    ext2fs_devread(gd[bg_idx].block_id *
+							   fs->sect_perblk, 0,
+							   fs->blksz,
+							   journal_buffer);
+					if (status == 0)
+						goto fail;
+
+					if (log_journal(journal_buffer,
+							gd[bg_idx].block_id))
+						goto fail;
+					prev_bg_bitmap_index = bg_idx;
+				}
+			}
+			if (TIPB_start_addr) {
+				free(TIPB_start_addr);
+				TIPB_start_addr = NULL;
+			}
+
+			/*removing the grand parent blocks
+			 *which is connected to inode
+			 */
+			if (fs->blksz != 1024) {
+				bg_idx = (*TIGP_buffer) / (uint32_t)
+				    ext4fs_root->sblock.blocks_per_group;
+			} else {
+				bg_idx = (*TIGP_buffer) / (uint32_t)
+				    ext4fs_root->sblock.blocks_per_group;
+
+				remainder = (*TIGP_buffer) % (uint32_t)
+				    ext4fs_root->sblock.blocks_per_group;
+				if (!remainder)
+					bg_idx--;
+			}
+			reset_block_bmap(*TIGP_buffer,
+					 fs->blk_bmaps[bg_idx], bg_idx);
+
+			TIGP_buffer++;
+			gd[bg_idx].free_blocks++;
+			fs->sb->free_blocks++;
+			/*journal backup */
+			if (prev_bg_bitmap_index != bg_idx) {
+				memset(journal_buffer, '\0', fs->blksz);
+				status =
+				    ext2fs_devread(gd[bg_idx].block_id *
+						   fs->sect_perblk, 0,
+						   fs->blksz, journal_buffer);
+				if (status == 0)
+					goto fail;
+
+				if (log_journal(journal_buffer,
+						gd[bg_idx].block_id))
+					goto fail;
+				prev_bg_bitmap_index = bg_idx;
+			}
+		}
+
+		/*removing the grand parent triple indirect block */
+		/*find the bitmap index */
+		blknr = inode->b.blocks.tripple_indir_block;
+		if (fs->blksz != 1024) {
+			bg_idx = blknr / (uint32_t)
+			    ext4fs_root->sblock.blocks_per_group;
+		} else {
+			bg_idx = blknr / (uint32_t)
+			    ext4fs_root->sblock.blocks_per_group;
+			remainder = blknr % (uint32_t)
+			    ext4fs_root->sblock.blocks_per_group;
+			if (!remainder)
+				bg_idx--;
+		}
+		reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
+		gd[bg_idx].free_blocks++;
+		fs->sb->free_blocks++;
+		/*journal backup */
+		if (prev_bg_bitmap_index != bg_idx) {
+			memset(journal_buffer, '\0', fs->blksz);
+			status = ext2fs_devread(gd[bg_idx].block_id
+						* fs->sect_perblk, 0, fs->blksz,
+						journal_buffer);
+			if (status == 0)
+				goto fail;
+
+			if (log_journal(journal_buffer, gd[bg_idx].block_id))
+				goto fail;
+			prev_bg_bitmap_index = bg_idx;
+		}
+		debug("TIGPB iteself releasing %ld\n", blknr);
+	}
+fail:
+	if (TIB_start_addr)
+		free(TIB_start_addr);
+	if (TIPB_start_addr)
+		free(TIPB_start_addr);
+	if (journal_buffer)
+		free(journal_buffer);
+	return;
+}
+
+static int ext4fs_delete_file(int inodeno)
+{
+	struct ext4_inode inode;
+	short status;
+	int i;
+	int remainder;
+	long int blknr;
+	int bg_idx;
+	int inode_bitmap_index;
+	char *read_buffer;
+	char *start_block_address = NULL;
+	unsigned int no_blocks;
+
+	static int prev_bg_bitmap_index = -1;
+	unsigned int inodes_per_block;
+	long int blkno;
+	unsigned int blkoff;
+	struct ext4_inode *inode_buffer;
+	struct ext2_block_group *gd;
+	ExtFileSystem *fs = get_fs();
+	char *journal_buffer = (char *)xzalloc(fs->blksz);
+	if (!journal_buffer)
+		return -1;
+	/*get the block group descriptor table */
+	gd = (struct ext2_block_group *)fs->gdtable;
+	status = ext4fs_read_inode(ext4fs_root, inodeno, &inode);
+	if (status == 0)
+		goto fail;
+
+	/*read the block no allocated to a file */
+	no_blocks = inode.size / fs->blksz;
+	if (inode.size % fs->blksz)
+		no_blocks++;
+
+	if (le32_to_cpu(inode.flags) & EXT4_EXTENTS_FLAG) {
+		ext2fs_node_t node_inode =
+		    (ext2fs_node_t) xzalloc(sizeof(struct ext2fs_node));
+		if (!node_inode)
+			goto fail;
+		node_inode->data = ext4fs_root;
+		node_inode->ino = inodeno;
+		node_inode->inode_read = 0;
+		memcpy(&(node_inode->inode), &inode, sizeof(struct ext4_inode));
+
+		for (i = 0; i < no_blocks; i++) {
+			blknr = read_allocated_block((struct ext4_inode *)
+						     &(node_inode->inode), i);
+			if (fs->blksz != 1024) {
+				bg_idx = blknr / (uint32_t)
+				    ext4fs_root->sblock.blocks_per_group;
+			} else {
+				bg_idx = blknr / (uint32_t)
+				    ext4fs_root->sblock.blocks_per_group;
+				remainder = blknr % (uint32_t)
+				    ext4fs_root->sblock.blocks_per_group;
+				if (!remainder)
+					bg_idx--;
+			}
+			reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
+			debug("EXT4_EXTENTS Block releasing %ld: %d\n",
+			      blknr, bg_idx);
+
+			gd[bg_idx].free_blocks++;
+			fs->sb->free_blocks++;
+
+			/*journal backup */
+			if (prev_bg_bitmap_index != bg_idx) {
+				status =
+				    ext2fs_devread(gd[bg_idx].block_id *
+						   fs->sect_perblk, 0,
+						   fs->blksz, journal_buffer);
+				if (status == 0)
+					goto fail;
+				if (log_journal(journal_buffer,
+						gd[bg_idx].block_id))
+					goto fail;
+				prev_bg_bitmap_index = bg_idx;
+			}
+		}
+		if (node_inode) {
+			free(node_inode);
+			node_inode = NULL;
+		}
+	} else {
+		/*deleting the single indirect block associated with inode */
+		delete_single_indirect_block(&inode);
+
+		/*deleting the double indirect blocks */
+		delete_double_indirect_block(&inode);
+
+		/*deleting the triple indirect blocks */
+		delete_triple_indirect_block(&inode);
+
+		/*read the block no allocated to a file */
+		no_blocks = inode.size / fs->blksz;
+		if (inode.size % fs->blksz)
+			no_blocks++;
+		for (i = 0; i < no_blocks; i++) {
+			blknr = read_allocated_block(&inode, i);
+			if (fs->blksz != 1024) {
+				bg_idx = blknr /
+				    (uint32_t) ext4fs_root->sblock.
+				    blocks_per_group;
+			} else {
+				bg_idx =
+				    blknr /
+				    (uint32_t) ext4fs_root->sblock.
+				    blocks_per_group;
+				remainder = blknr % (uint32_t)
+				    ext4fs_root->sblock.blocks_per_group;
+				if (!remainder)
+					bg_idx--;
+			}
+			reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx);
+			debug("ActualB releasing %ld: %d\n", blknr, bg_idx);
+
+			gd[bg_idx].free_blocks++;
+			fs->sb->free_blocks++;
+			/*journal backup */
+			if (prev_bg_bitmap_index != bg_idx) {
+				memset(journal_buffer, '\0', fs->blksz);
+				status = ext2fs_devread(gd[bg_idx].block_id
+							* fs->sect_perblk,
+							0, fs->blksz,
+							journal_buffer);
+				if (status == 0) {
+					free(journal_buffer);
+					goto fail;
+				}
+				if (log_journal(journal_buffer,
+						gd[bg_idx].block_id))
+					goto fail;
+				prev_bg_bitmap_index = bg_idx;
+			}
+		}
+	}
+
+	/*from the inode no to blockno */
+	inodes_per_block = EXT2_BLOCK_SIZE(ext4fs_root) / fs->inodesz;
+	inode_bitmap_index = inodeno /
+	    (uint32_t) ext4fs_root->sblock.inodes_per_group;
+
+	/*get the block no */
+	inodeno--;
+	blkno = __le32_to_cpu(gd[inode_bitmap_index].inode_table_id) +
+	    (inodeno % __le32_to_cpu(ext4fs_root->sblock.inodes_per_group))
+	    / inodes_per_block;
+
+	/*get the offset of the inode */
+	blkoff = ((inodeno) % inodes_per_block) * fs->inodesz;
+
+	/*read the block no containing the inode */
+	read_buffer = (char *)xzalloc(fs->blksz);
+	if (!read_buffer)
+		goto fail;
+	start_block_address = read_buffer;
+	status = ext2fs_devread(blkno * fs->sect_perblk,
+				0, fs->blksz, read_buffer);
+	if (status == 0)
+		goto fail;
+
+	if (log_journal(read_buffer, blkno))
+		goto fail;
+
+	read_buffer = read_buffer + blkoff;
+	inode_buffer = (struct ext4_inode *)read_buffer;
+	memset(inode_buffer, '\0', sizeof(struct ext4_inode));
+
+	/*write the inode to original position in inode table */
+	if (put_metadata(start_block_address, blkno))
+		goto fail;
+
+	/*update the respective inode bitmaps */
+	inodeno++;
+	reset_inode_bmap(inodeno, fs->inode_bmaps
+			 [inode_bitmap_index], inode_bitmap_index);
+	gd[inode_bitmap_index].free_inodes++;
+	fs->sb->free_inodes++;
+	/*journal backup */
+	memset(journal_buffer, '\0', fs->blksz);
+	status = ext2fs_devread(gd[inode_bitmap_index].inode_id *
+				fs->sect_perblk, 0, fs->blksz, journal_buffer);
+	if (status == 0)
+		goto fail;
+	if (log_journal(journal_buffer, gd[inode_bitmap_index].inode_id))
+		goto fail;
+
+	ext4fs_update();
+	ext4fs_deinit();
+
+	if (ext4fs_init() != 0) {
+		printf("error in File System init\n");
+		goto fail;
+	}
+
+	/*free */
+	if (start_block_address)
+		free(start_block_address);
+	if (journal_buffer)
+		free(journal_buffer);
+	return 0;
+
+fail:
+	if (start_block_address)
+		free(start_block_address);
+	if (journal_buffer)
+		free(journal_buffer);
+	return -1;
+}
+
+int ext4fs_init(void)
+{
+	short status;
+	int i;
+	int sector_per_block;
+	unsigned int real_free_blocks = 0;
+	ExtFileSystem *fs = get_fs();
+
+	/*populate fs */
+	fs->blksz = EXT2_BLOCK_SIZE(ext4fs_root);
+	fs->inodesz = INODE_SIZE_FILESYSTEM(ext4fs_root);
+	fs->sect_perblk = fs->blksz / SECTOR_SIZE;
+
+	sector_per_block = fs->sect_perblk;
+	/*get the superblock */
+	fs->sb = (struct ext2_sblock *)xzalloc(SUPERBLOCK_SIZE);
+	if (!fs->sb)
+		return -1;
+	status = ext2fs_devread(SUPERBLOCK_SECTOR, 0,
+				SUPERBLOCK_SIZE, (char *)fs->sb);
+	if (status == 0)
+		goto fail;
+
+	/*init journal */
+	if (init_journal())
+		goto fail;
+
+	/*get the no of blockgroups */
+
+	fs->no_blkgrp = (uint32_t) ext4fs_div_roundup
+	    ((uint32_t) (ext4fs_root->sblock.total_blocks
+			 - ext4fs_root->sblock.first_data_block),
+	     (uint32_t) ext4fs_root->sblock.blocks_per_group);
+
+	/*get the block group descriptor table */
+	fs->gdtable_blkno = ((EXT2_MIN_BLOCK_SIZE == fs->blksz) + 1);
+	if (ext4fs_get_bgdtable() == -1) {
+		printf("*Eror in getting the block group descriptor table\n");
+		goto fail;
+	} else {
+		fs->gd = (struct ext2_block_group *)fs->gdtable;
+	}
+
+	/*load all the available bitmap block of the partition */
+	fs->blk_bmaps = (unsigned char **)xzalloc
+	    (fs->no_blkgrp * sizeof(unsigned char *));
+	if (!fs->blk_bmaps)
+		goto fail;
+	for (i = 0; i < fs->no_blkgrp; i++) {
+		fs->blk_bmaps[i] = (unsigned char *)xzalloc(fs->blksz);
+		if (!fs->blk_bmaps[i])
+			goto fail;
+	}
+
+	for (i = 0; i < fs->no_blkgrp; i++) {
+		status =
+		    ext2fs_devread(fs->gd[i].block_id * sector_per_block, 0,
+				   fs->blksz, (char *)fs->blk_bmaps[i]);
+		if (status == 0)
+			goto fail;
+	}
+
+	/*load all the available inode bitmap of the partition */
+	fs->inode_bmaps = (unsigned char **)xzalloc
+	    (fs->no_blkgrp * sizeof(unsigned char *));
+	if (!fs->inode_bmaps)
+		goto fail;
+	for (i = 0; i < fs->no_blkgrp; i++) {
+		fs->inode_bmaps[i] = (unsigned char *)xzalloc(fs->blksz);
+		if (!fs->inode_bmaps[i])
+			goto fail;
+	}
+
+	for (i = 0; i < fs->no_blkgrp; i++) {
+		status = ext2fs_devread(fs->gd[i].inode_id * sector_per_block,
+					0, fs->blksz,
+					(char *)fs->inode_bmaps[i]);
+		if (status == 0)
+			goto fail;
+	}
+
+	/*
+	 *check filesystem consistency with free blocks of file system
+	 *some time we observed that superblock freeblocks does not match
+	 *with the  blockgroups freeblocks when improper
+	 *reboot of a linux kernel
+	 */
+	for (i = 0; i < fs->no_blkgrp; i++)
+		real_free_blocks = real_free_blocks + fs->gd[i].free_blocks;
+	if (real_free_blocks != fs->sb->free_blocks)
+		fs->sb->free_blocks = real_free_blocks;
+	return 0;
+
+fail:
+	ext4fs_deinit();
+	return -1;
+}
+
+void ext4fs_deinit(void)
+{
+	int i;
+	struct ext4_inode inode_journal;
+	journal_superblock_t *jsb;
+	long int blknr;
+	ExtFileSystem *fs = get_fs();
+	/*free journal */
+	char *temp_buff = (char *)xzalloc(fs->blksz);
+	if (temp_buff) {
+		ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,
+				  &inode_journal);
+		blknr =
+		    read_allocated_block(&inode_journal,
+					 EXT2_JOURNAL_SUPERBLOCK);
+		ext2fs_devread(blknr * fs->sect_perblk, 0, fs->blksz,
+			       temp_buff);
+		jsb = (journal_superblock_t *) temp_buff;
+		jsb->s_start = le_be(0);
+		put_ext4((uint64_t) (blknr * fs->blksz),
+			 (struct journal_superblock_t *)temp_buff,
+			 (uint32_t) fs->blksz);
+		free(temp_buff);
+	}
+	free_journal();
+	/*get the superblock */
+	ext2fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, (char *)fs->sb);
+	fs->sb->feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
+	put_ext4((uint64_t) (SUPERBLOCK_SIZE),
+		 (struct ext2_sblock *)fs->sb, (uint32_t) SUPERBLOCK_SIZE);
+	if (fs->sb) {
+		free(fs->sb);
+		fs->sb = NULL;
+	}
+
+	if (fs->blk_bmaps) {
+		for (i = 0; i < fs->no_blkgrp; i++) {
+			if (fs->blk_bmaps[i]) {
+				free(fs->blk_bmaps[i]);
+				fs->blk_bmaps[i] = NULL;
+			}
+		}
+		free(fs->blk_bmaps);
+		fs->blk_bmaps = NULL;
+	}
+
+	if (fs->inode_bmaps) {
+		for (i = 0; i < fs->no_blkgrp; i++) {
+			if (fs->inode_bmaps[i]) {
+				free(fs->inode_bmaps[i]);
+				fs->inode_bmaps[i] = NULL;
+			}
+		}
+		free(fs->inode_bmaps);
+		fs->inode_bmaps = NULL;
+	}
+
+	if (fs->gdtable) {
+		free(fs->gdtable);
+		fs->gdtable = NULL;
+	}
+	fs->gd = NULL;
+	/*
+	 *Reinitiliazed the global inode and
+	 *block bitmap first execution check variables
+	 */
+	fs->first_pass_ibmap = 0;
+	fs->first_pass_bbmap = 0;
+	fs->curr_inode_no = 0;
+	fs->curr_blkno = 0;
+
+	return;
+}
+
+static int ext4fs_write_file(struct ext4_inode *file_inode,
+			     int pos, unsigned int len, char *buf)
+{
+	int i;
+	int blockcnt;
+	int log2blocksize = LOG2_EXT2_BLOCK_SIZE(ext4fs_root);
+	unsigned int filesize = __le32_to_cpu(file_inode->size);
+	ExtFileSystem *fs = get_fs();
+	int previous_block_number = -1;
+	int delayed_start = 0;
+	int delayed_extent = 0;
+	int delayed_skipfirst = 0;
+	int delayed_next = 0;
+	char *delayed_buf = NULL;
+
+	/* Adjust len so it we can't read past the end of the file. */
+	if (len > filesize)
+		len = filesize;
+
+	blockcnt = ((len + pos) + fs->blksz - 1) / fs->blksz;
+
+	for (i = pos / fs->blksz; i < blockcnt; i++) {
+		long int blknr;
+		int blockend = fs->blksz;
+		int skipfirst = 0;
+		blknr = read_allocated_block(file_inode, i);
+		if (blknr < 0)
+			return -1;
+
+		blknr = blknr << log2blocksize;
+
+		if (blknr) {
+			if (previous_block_number != -1) {
+				if (delayed_next == blknr) {
+					delayed_extent += blockend;
+					delayed_next += blockend >> SECTOR_BITS;
+				} else {	/* spill */
+					put_ext4((uint64_t) (delayed_start *
+							     SECTOR_SIZE),
+						 delayed_buf,
+						 (uint32_t) delayed_extent);
+					previous_block_number = blknr;
+					delayed_start = blknr;
+					delayed_extent = blockend;
+					delayed_skipfirst = skipfirst;
+					delayed_buf = buf;
+					delayed_next = blknr +
+					    (blockend >> SECTOR_BITS);
+				}
+			} else {
+				previous_block_number = blknr;
+				delayed_start = blknr;
+				delayed_extent = blockend;
+				delayed_skipfirst = skipfirst;
+				delayed_buf = buf;
+				delayed_next = blknr +
+				    (blockend >> SECTOR_BITS);
+			}
+		} else {
+			if (previous_block_number != -1) {
+				/* spill */
+				put_ext4((uint64_t) (delayed_start *
+						     SECTOR_SIZE), delayed_buf,
+					 (uint32_t) delayed_extent);
+				previous_block_number = -1;
+			}
+			memset(buf, 0, fs->blksz - skipfirst);
+		}
+		buf += fs->blksz - skipfirst;
+	}
+	if (previous_block_number != -1) {
+		/* spill */
+		put_ext4((uint64_t) (delayed_start * SECTOR_SIZE),
+			 delayed_buf, (uint32_t) delayed_extent);
+		previous_block_number = -1;
+	}
+	return len;
+}
+
+int ext4fs_write(char *fname, unsigned char *buffer, unsigned long 
sizebytes)
+{
+	int ret = 0;
+	/*inode */
+	struct ext4_inode *file_inode = NULL;
+	unsigned char *inode_buffer = NULL;
+	int parent_inodeno;
+	int inodeno;
+	time_t timestamp = 0;
+
+	/*filesize */
+	uint64_t total_no_of_bytes_for_file;
+	unsigned int total_no_of_block_for_file;
+	unsigned int total_remaining_blocks;
+	int existing_file_inodeno;
+	char filename[256];
+
+	char *temp_ptr = NULL;
+	long int itable_blkno, parent_itable_blkno, blkoff;
+	struct ext2_sblock *sblock = &(ext4fs_root->sblock);
+	unsigned int inodes_per_block;
+	unsigned int inode_bitmap_index;
+	ExtFileSystem *fs = get_fs();
+
+	g_parent_inode = (struct ext4_inode *)
+	    xzalloc(sizeof(struct ext4_inode));
+	if (!g_parent_inode)
+		goto fail;
+
+	if (ext4fs_init() != 0) {
+		printf("error in File System init\n");
+		return -1;
+	}
+	inodes_per_block = fs->blksz / fs->inodesz;
+	parent_inodeno = get_parent_inode_num(fname, filename, F_FILE);
+	if (parent_inodeno == -1)
+		goto fail;
+	if (iget(parent_inodeno, g_parent_inode))
+		goto fail;
+	/*check if the filename is already present in root */
+	existing_file_inodeno = ext4fs_filename_check(filename);
+	if (existing_file_inodeno != -1) {
+		ret = ext4fs_delete_file(existing_file_inodeno);
+		fs->first_pass_bbmap = 0;
+		fs->curr_blkno = 0;
+
+		fs->first_pass_ibmap = 0;
+		fs->curr_inode_no = 0;
+		if (ret)
+			goto fail;
+	}
+	/*calucalate how many blocks required */
+	total_no_of_bytes_for_file = sizebytes;
+	total_no_of_block_for_file = total_no_of_bytes_for_file / fs->blksz;
+	if (total_no_of_bytes_for_file % fs->blksz != 0) {
+		total_no_of_block_for_file++;
+		debug("total bytes for a file %u\n",
+		      total_no_of_block_for_file);
+	}
+	total_remaining_blocks = total_no_of_block_for_file;
+	/*Test for available space in partition */
+	if (fs->sb->free_blocks < total_no_of_block_for_file) {
+		printf("Not enough space on partition !!!\n");
+		goto fail;
+	}
+
+	update_parent_dentry(filename, &inodeno, FILETYPE_REG);
+	/*prepare file inode */
+	inode_buffer = xmalloc(fs->inodesz);
+	memset(inode_buffer, '\0', fs->inodesz);
+	file_inode = (struct ext4_inode *)inode_buffer;
+	file_inode->mode = S_IFREG | S_IRWXU |
+	    S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH;
+	/* ToDo: Update correct time */
+	file_inode->mtime = timestamp;
+	file_inode->atime = timestamp;
+	file_inode->ctime = timestamp;
+	file_inode->nlinks = 1;
+	file_inode->size = sizebytes;
+
+	/* Allocate data blocks */
+	allocate_blocks(file_inode, total_remaining_blocks,
+			&total_no_of_block_for_file);
+	/*
+	 *write the inode to inode table after last filled inode in inode table
+	 *we are using hardcoded  gd[0].inode_table_id becuase 0th blockgroup
+	 *is suffcient to create more than 1000 file.TODO exapnd the logic to
+	 *all blockgroup
+	 */
+	file_inode->blockcnt = (total_no_of_block_for_file * fs->blksz)
+	    / SECTOR_SIZE;
+
+	temp_ptr = (char *)xzalloc(fs->blksz);
+	if (!temp_ptr)
+		goto fail;
+	inode_bitmap_index = inodeno /
+	    (uint32_t) ext4fs_root->sblock.inodes_per_group;
+	inodeno--;
+	itable_blkno =
+	    __le32_to_cpu(fs->gd[inode_bitmap_index].inode_table_id) +
+	    (inodeno % __le32_to_cpu(sblock->inodes_per_group))
+	    / inodes_per_block;
+	blkoff = (inodeno % inodes_per_block) * fs->inodesz;
+	ext2fs_devread(itable_blkno * fs->sect_perblk, 0, fs->blksz, temp_ptr);
+	if (log_journal(temp_ptr, itable_blkno))
+		goto fail;
+
+	memcpy(temp_ptr + blkoff, inode_buffer, fs->inodesz);
+	if (put_metadata(temp_ptr, itable_blkno))
+		goto fail;
+	/*Copy the file content into data blocks */
+	if (ext4fs_write_file(file_inode, 0, sizebytes, (char *)buffer) == -1) {
+		printf("Error in copying content\n");
+		goto fail;
+	}
+	inode_bitmap_index = parent_inodeno /
+	    (uint32_t) ext4fs_root->sblock.inodes_per_group;
+	parent_inodeno--;
+	parent_itable_blkno =
+	    __le32_to_cpu(fs->gd[inode_bitmap_index].inode_table_id) +
+	    (parent_inodeno % __le32_to_cpu(sblock->inodes_per_group)) /
+	    inodes_per_block;
+	blkoff = (parent_inodeno % inodes_per_block) * fs->inodesz;
+	if (parent_itable_blkno != itable_blkno) {
+		memset(temp_ptr, '\0', fs->blksz);
+		ext2fs_devread(parent_itable_blkno * fs->sect_perblk,
+			       0, fs->blksz, temp_ptr);
+		if (log_journal(temp_ptr, parent_itable_blkno))
+			goto fail;
+
+		memcpy(temp_ptr + blkoff, g_parent_inode,
+		       sizeof(struct ext4_inode));
+		if (put_metadata(temp_ptr, parent_itable_blkno))
+			goto fail;
+		free(temp_ptr);
+	} else {
+		/* If parent and child fall in same inode table block
+		 * both should be kept in 1 buffer
+		 */
+		memcpy(temp_ptr + blkoff, g_parent_inode,
+		       sizeof(struct ext4_inode));
+		gd_index--;
+		if (put_metadata(temp_ptr, itable_blkno))
+			goto fail;
+		free(temp_ptr);
+	}
+	ext4fs_update();
+	ext4fs_deinit();
+
+	fs->first_pass_bbmap = 0;
+	fs->curr_blkno = 0;
+	fs->first_pass_ibmap = 0;
+	fs->curr_inode_no = 0;
+	if (inode_buffer)
+		free(inode_buffer);
+	if (g_parent_inode) {
+		free(g_parent_inode);
+		g_parent_inode = NULL;
+	}
+	return 0;
+
+fail:
+	ext4fs_deinit();
+	if (inode_buffer)
+		free(inode_buffer);
+	if (g_parent_inode) {
+		free(g_parent_inode);
+		g_parent_inode = NULL;
+	}
+	return -1;
+}
diff --git a/include/ext4fs.h b/include/ext4fs.h
index 168acba..ab1fee3 100644
--- a/include/ext4fs.h
+++ b/include/ext4fs.h
@@ -149,9 +149,17 @@  extern block_dev_desc_t *ext4_dev_desc;

 extern struct ext2_data *ext4fs_root;
 extern ext2fs_node_t ext4fs_file;
+extern struct ext4_inode *g_parent_inode;
+extern int gd_index;
+extern int gindex;
+
 ExtFileSystem *get_fs(void);
 int init_fs(block_dev_desc_t *);
 void deinit_fs(block_dev_desc_t *);
+int ext4fs_init(void);
+void ext4fs_deinit(void);
+int ext4fs_write(char *fname, unsigned char *buffer, unsigned long 
sizebytes);
+int ext4fs_filename_check(char *filename);
 int ext4fs_open(const char *filename);
 int ext4fs_read(char *buf, unsigned len);