Skip to contentSkip to conversation

ext4: Add the EXT4_IOC_FREE_BLOCKS_INFO ioctl

RFC PATCH In review Akira Fujita 1 participant 1 message Oct 24, 2008

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

RFC PATCH 6/9 ext4: Add the EXT4_IOC_FREE_BLOCKS_INFO ioctl

ext4: online defrag -- Add the EXT4_IOC_FREE_BLOCKS_INFO ioctl.

From: Akira Fujita <[email protected]>

The EXT4_IOC_FREE_BLOCKS_INFO ioctl gets free extents information of the target block group.
This ioctl is used only in the force defrag (-f).

Defragger calculates the victim extents (which will be moved
into other block group in order to make contiguous free space for the target file) based on used/unused extents information.

ext4_defrag_fblocks_distribution() was renamed as ext4_mb_search_free_extents() and moved into mballoc.c. Because it uses ext4_buddy structure.

---
 fs/ext4/ext4.h    |   27 +++++++++++++++++
 fs/ext4/ioctl.c   |   20 +++++++++++++
 fs/ext4/mballoc.c |   81 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 128 insertions(+), 0 deletions(-)
fs/ext4/ext4.h +27 -0
index 94c4186..f7b092d 100644
@@ -304,6 +304,7 @@ struct ext4_new_group_data {
  /* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
 #define EXT4_IOC_DEFRAG			_IOW('f', 15, struct ext4_ext_defrag_data)
 #define EXT4_IOC_SUPER_INFO		_IOR('f', 16, struct ext4_super_block)
+#define EXT4_IOC_FREE_BLOCKS_INFO	_IOWR('f', 17, struct ext4_extents_info)
 
 /*
  * ioctl commands in 32 bit emulation
@@ -321,12 +322,36 @@ struct ext4_new_group_data {
 #define EXT4_IOC32_GETVERSION_OLD	FS_IOC32_GETVERSION
 #define EXT4_IOC32_SETVERSION_OLD	FS_IOC32_SETVERSION
 
+/*
+ * The following four macros are used for the defrag force mode.
+ *
+ * DEFRAG_MAX_ENT:	the maximum number of extents for exchanging between
+ *			kernel-space and user-space per an ioctl
+ */
+#define DEFRAG_MAX_ENT		32
+
+struct ext4_extent_data {
+	ext4_lblk_t block;		/* start logical block number */
+	ext4_fsblk_t start;		/* start physical block number */
+	int len;			/* blocks count */
+};
+
 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 */
 };
 
+struct ext4_extents_info {
+	unsigned long long ino;		/* inode number */
+	int max_entries;		/* maximum extents count */
+	int entries;			/* extent number/count */
+	ext4_lblk_t f_offset;		/* file offset */
+	ext4_grpblk_t g_offset;		/* group offset */
+	ext4_fsblk_t goal;		/* block offset for allocation */
+	struct ext4_extent_data ext[DEFRAG_MAX_ENT];
+};
+
 #define EXT4_TRANS_META_BLOCKS 4 /* bitmap + group desc + sb + inode */
 
 /*
@@ -1069,6 +1094,8 @@ extern int ext4_mb_add_more_groupinfo(struct super_block *sb,
 		ext4_group_t i, struct ext4_group_desc *desc);
 extern void ext4_mb_update_group_info(struct ext4_group_info *grp,
 		ext4_grpblk_t add);
+extern int ext4_mb_search_free_extents(struct inode *inode,
+					struct ext4_extents_info *ext_info);
 
 
 /* inode.c */
fs/ext4/ioctl.c +20 -0
index f8ce89b..5709574 100644
@@ -256,6 +256,26 @@ setversion_out:
 			return 0;
 	}
 
+	case EXT4_IOC_FREE_BLOCKS_INFO: {
+		struct ext4_extents_info ext_info;
+		int err;
+
+		if (copy_from_user(&ext_info,
+			(struct ext4_extents_info __user *)arg,
+						sizeof(ext_info)))
+			return -EFAULT;
+
+		BUG_ON(ext_info.ino != inode->i_ino);
+
+		err = ext4_mb_search_free_extents(inode, &ext_info);
+
+		if (!err)
+			err = copy_to_user(
+			(struct ext4_extents_info __user *)arg,
+				&ext_info, sizeof(ext_info));
+		return err;
+	}
+
 	case EXT4_IOC_GROUP_ADD: {
 		struct ext4_new_group_data input;
 		struct super_block *sb = inode->i_sb;
fs/ext4/mballoc.c +81 -0

84 lines not on this page · raw message