diff --git a/fs/ext4/defrag.c b/fs/ext4/defrag.c
index 941414b..f7c99de 100644
--- a/fs/ext4/defrag.c
+++ b/fs/ext4/defrag.c
@@ -20,6 +20,8 @@
 #include "ext4_extents.h"
 #include "group.h"

+#define FIEMAP_MAX_EXTENTS	(UINT_MAX / sizeof(struct fiemap_extent))
+
 /**
  * ext4_defrag_next_extent - Search for the next extent and set it to "extent"
  *
@@ -91,6 +93,106 @@ err:
 }

 /**
+ * ext4_defrag_fiemap_ino - Get extents information by inode number
+ *
+ * @filp:			pointer to file
+ * @arg:			pointer to fiemap_ino
+ *  @fiemap_ino->ino:		an inode number which is used to get
+ *				extent information
+ *  @fiemap_ino->fiemap:	request for fiemap ioctl
+ *
+ * This function returns 0 if succeed, otherwise returns error value.
+ */
+static int
+ext4_defrag_fiemap_ino(struct file *filp, unsigned long arg)
+{
+	struct fiemap_ino fiemap_ino;
+	struct fiemap_extent_info fieinfo = { 0, };
+	struct inode *inode;
+	struct super_block *sb = filp->f_dentry->d_inode->i_sb;
+	u64 len = 0;
+	int err = 0;
+
+	if (copy_from_user(&fiemap_ino, (struct fiemap_ino __user *)arg,
+			   sizeof(struct fiemap_ino)))
+		return -EFAULT;
+
+	/* Special inodes shouldn't be choiced */
+	if (fiemap_ino.ino < EXT4_GOOD_OLD_FIRST_INO)
+		return -ENOENT;
+
+	inode = ext4_iget(sb, fiemap_ino.ino);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+
+	/* Return -ENOENT if a file does not exist */
+	if (!inode->i_nlink || !S_ISREG(inode->i_mode)) {
+		err = -ENOENT;
+		goto out;
+	}
+
+	if (!inode->i_op->fiemap) {
+		err = -EOPNOTSUPP;
+		goto out;
+	}
+
+	if (fiemap_ino.fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (fiemap_ino.fiemap.fm_length == 0) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (fiemap_ino.fiemap.fm_start > sb->s_maxbytes) {
+		err = -EFBIG;
+		goto out;
+	}
+
+	/*
+	 * Check offset and length
+	 * If the specified range exceeds the max file size,
+	 * adjust the length.
+	 */
+	if ((fiemap_ino.fiemap.fm_length > sb->s_maxbytes) ||
+	    (sb->s_maxbytes - fiemap_ino.fiemap.fm_length)
+	     < fiemap_ino.fiemap.fm_start)
+		len = sb->s_maxbytes - fiemap_ino.fiemap.fm_start;
+	else
+		len = fiemap_ino.fiemap.fm_length;
+
+	fieinfo.fi_flags = fiemap_ino.fiemap.fm_flags;
+	fieinfo.fi_extents_max = fiemap_ino.fiemap.fm_extent_count;
+	fieinfo.fi_extents_start =
+		(struct fiemap_extent *)(arg + sizeof(fiemap_ino));
+
+	if (fiemap_ino.fiemap.fm_extent_count != 0 &&
+	    !access_ok(VERIFY_WRITE, fieinfo.fi_extents_start,
+		       fieinfo.fi_extents_max * sizeof(struct fiemap_extent))) {
+		err = -EFAULT;
+		goto out;
+	}
+
+	if (fieinfo.fi_flags & FIEMAP_FLAG_SYNC)
+		filemap_write_and_wait(inode->i_mapping);
+
+	err = inode->i_op->fiemap(inode, &fieinfo,
+				fiemap_ino.fiemap.fm_start, len);
+	if (!err) {
+		fiemap_ino.fiemap.fm_flags = fieinfo.fi_flags;
+		fiemap_ino.fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped;
+		if (copy_to_user((char *)arg, &fiemap_ino, sizeof(fiemap_ino)))
+			err = -EFAULT;
+	}
+
+out:
+	iput(inode);
+	return err;
+}
+
+/**
  * ext4_defrag_fblocks_distribution - Search free blocks distribution
  *
  * @org_inode:	original inode
@@ -237,6 +339,9 @@ int ext4_defrag_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 			err = copy_to_user(
 				(struct ext4_extents_info __user *)arg,
 				&ext_info, sizeof(ext_info));
+	} else if (cmd == EXT4_IOC_FIEMAP_INO) {
+
+		err = ext4_defrag_fiemap_ino(filp, arg);
 	} else if (cmd == EXT4_IOC_DEFRAG) {
 		struct ext4_ext_defrag_data defrag;
 		struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index ffe687b..8d008c8 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -306,6 +306,7 @@ struct ext4_new_group_data {
 #define EXT4_IOC_FIBMAP			_IOW('f', 16, ext4_fsblk_t)
 #define EXT4_IOC_GROUP_INFO		_IOW('f', 17, struct ext4_group_data_info)
 #define EXT4_IOC_FREE_BLOCKS_INFO	_IOW('f', 18, struct ext4_extents_info)
+#define EXT4_IOC_FIEMAP_INO		_IOW('f', 19, struct fiemap_ino)

 /*
  * ioctl commands in 32 bit emulation
@@ -358,6 +359,11 @@ struct ext4_extents_info {
 	struct ext4_extent_data ext[DEFRAG_MAX_ENT];
 };

+struct fiemap_ino {
+	__u64 ino;
+	struct fiemap fiemap;
+};
+
 #define EXT4_TRANS_META_BLOCKS 4 /* bitmap + group desc + sb + inode */

 /*
@@ -1321,6 +1327,7 @@ extern int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode,
 			sector_t block, unsigned long max_blocks,
 			struct buffer_head *bh, int create,
 			int extend_disksize, int flag);
+extern int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start);
 #endif	/* __KERNEL__ */

 #endif	/* _EXT4_H */
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 6e2ccb8..7fcf72d 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -2110,7 +2110,7 @@ ext4_ext_more_to_rm(struct ext4_ext_path *path)
 	return 1;
 }

-static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
+int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
 {
 	struct super_block *sb = inode->i_sb;
 	int depth = ext_depth(inode);
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 40bc2e1..a0e4915 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -259,7 +259,8 @@ setversion_out:
 	case EXT4_IOC_FIBMAP:
 	case EXT4_IOC_DEFRAG:
 	case EXT4_IOC_GROUP_INFO:
-	case EXT4_IOC_FREE_BLOCKS_INFO: {
+	case EXT4_IOC_FREE_BLOCKS_INFO:
+	case EXT4_IOC_FIEMAP_INO: {
 		return ext4_defrag_ioctl(inode, filp, cmd, arg);
 	}
 	case EXT4_IOC_GROUP_ADD: {
