Skip to contentSkip to conversation

ext4: Add the EXT4_IOC_DEFRAG ioctl and defrag main function

RFC PATCH In review Akira Fujita 1 participant 1 message Sep 27, 2008

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/12 ext4: Add the EXT4_IOC_DEFRAG ioctl and defrag main function

ext4: online defrag -- Add the EXT4_IOC_DEFRAG ioctl and defrag main function.

From: Akira Fujita <[email protected]>

The EXT4_IOC_DEFRAG ioctl is the main ioctl of ext4 online defrag. Create the temporary inode in memory and allocate contiguous blocks to it. After that exchange data blocks between original inode and temporary inode. Lastly, remove the temporary inode which has fragmented data blocks. This method would be done between user space and kernel space per 64MB data size.

This patch is equivalent to creating/removing a temporary inode and common defrag functions.

---
 fs/ext4/Makefile       |    2 +-
 fs/ext4/defrag.c       |  467 ++++++++++++++++++++++++++++++++++++++++++++++++
 fs/ext4/ext4.h         |   14 ++
 fs/ext4/ext4_extents.h |    2 +
 fs/ext4/extents.c      |    2 +-
 fs/ext4/inode.c        |    2 +-
 fs/ext4/ioctl.c        |    3 +
 7 files changed, 489 insertions(+), 3 deletions(-)
fs/ext4/Makefile +1 -1
index ac6fa8c..8028102 100644
@@ -6,7 +6,7 @@ obj-$(CONFIG_EXT4DEV_FS) += ext4dev.o
 
 ext4dev-y	:= balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
 		   ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
-		   ext4_jbd2.o migrate.o mballoc.o
+		   ext4_jbd2.o migrate.o mballoc.o defrag.o
 
 ext4dev-$(CONFIG_EXT4DEV_FS_XATTR)	+= xattr.o xattr_user.o xattr_trusted.o
 ext4dev-$(CONFIG_EXT4DEV_FS_POSIX_ACL)	+= acl.o
fs/ext4/defrag.c new file +467 -0

467 lines not on this page · raw message

fs/ext4/ext4.h +14 -0
index c8ab668..64c61ae 100644
@@ -302,6 +302,7 @@ struct ext4_new_group_data {
 #define EXT4_IOC_GROUP_ADD		_IOW('f', 8, struct ext4_new_group_input)
 #define EXT4_IOC_MIGRATE		_IO('f', 9)
  /* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
+#define EXT4_IOC_DEFRAG			_IOW('f', 15, struct ext4_ext_defrag_data)
 
 /*
  * ioctl commands in 32 bit emulation
@@ -319,6 +320,12 @@ struct ext4_new_group_data {
 #define EXT4_IOC32_GETVERSION_OLD	FS_IOC32_GETVERSION
 #define EXT4_IOC32_SETVERSION_OLD	FS_IOC32_SETVERSION
 
+struct ext4_ext_defrag_data {
+	ext4_lblk_t start_offset;	/* start offset to defrag in blocks */
+	ext4_lblk_t defrag_size;	/* size of defrag in blocks */
+	ext4_fsblk_t goal;		/* block offset for allocation */
+};
+
 
 /*
  *  Mount options
@@ -1081,6 +1088,8 @@ extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks);
 extern int ext4_block_truncate_page(handle_t *handle,
 		struct address_space *mapping, loff_t from);
 extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page);
+extern int ext4_get_block(struct inode *inode, sector_t iblock,
+		struct buffer_head *bh_result, int create);
 
 /* ioctl.c */
 extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
@@ -1128,6 +1137,11 @@ extern void ext4_inode_bitmap_set(struct super_block *sb,
 				  struct ext4_group_desc *bg, ext4_fsblk_t blk);
 extern void ext4_inode_table_set(struct super_block *sb,
 				 struct ext4_group_desc *bg, ext4_fsblk_t blk);
+/* defrag.c */
+extern int ext4_defrag(struct file *filp, ext4_lblk_t block_start,
+			ext4_lblk_t defrag_size);
+extern int ext4_defrag_ioctl(struct inode *, struct file *, unsigned int,
+				unsigned long);
 
 static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
 {
fs/ext4/ext4_extents.h +2 -0
index bec7ce5..0325158 100644
@@ -246,5 +246,7 @@ extern int ext4_ext_search_left(struct inode *, struct ext4_ext_path *,
 extern int ext4_ext_search_right(struct inode *, struct ext4_ext_path *,
 						ext4_lblk_t *, ext4_fsblk_t *);
 extern void ext4_ext_drop_refs(struct ext4_ext_path *);
+extern ext4_fsblk_t ext_pblock(struct ext4_extent *ex);
+extern void ext4_ext_drop_refs(struct ext4_ext_path *path);
 #endif /* _EXT4_EXTENTS */
 
fs/ext4/extents.c +1 -1
index 3094ed3..d05dfb7 100644
@@ -49,7 +49,7 @@
  * ext_pblock:
  * combine low and high parts of physical block number into ext4_fsblk_t
  */
-static ext4_fsblk_t ext_pblock(struct ext4_extent *ex)
+ext4_fsblk_t ext_pblock(struct ext4_extent *ex)
 {
 	ext4_fsblk_t block;
 
fs/ext4/inode.c +1 -1
index 9764b79..9b0117c 100644
@@ -1161,7 +1161,7 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block,
 /* Maximum number of blocks we map for direct IO at once. */
 #define DIO_MAX_BLOCKS 4096
 
-static int ext4_get_block(struct inode *inode, sector_t iblock,
+int ext4_get_block(struct inode *inode, sector_t iblock,
 			struct buffer_head *bh_result, int create)
 {
 	handle_t *handle = ext4_journal_current_handle();
fs/ext4/ioctl.c +3 -0
index 3e14060..1c25e8e 100644
@@ -256,6 +256,9 @@ setversion_out:
 
 		return err;
 	}
+	case EXT4_IOC_DEFRAG: {
+		return ext4_defrag_ioctl(inode, filp, cmd, arg);
+	}
 	case EXT4_IOC_GROUP_ADD: {
 		struct ext4_new_group_data input;
 		struct super_block *sb = inode->i_sb;