ext4: Add the EXT4_IOC_MOVE_VICTIM ioctl
Subsystems (2)
RFC PATCH 8/9 ext4: Add the EXT4_IOC_MOVE_VICTIM ioctl
ext4: online defrag -- Add the EXT4_IOC_MOVE_VICTIM ioctl.
From: Akira Fujita <[email protected]>
The EXT4_IOC_MOVE_VICTIM moves the victim extents into other block group. Therefore the contiguous free space is made in the target block group. This ioctl is used only in the force defrag (-f).
Signed-off-by Akira Fujita <[email protected]>
Signed-off-by Takashi Sato <[email protected]>
--- fs/ext4/balloc.c | 1 + fs/ext4/defrag.c | 264 ++++++++++++++++++++++++++++++++++++++++++----- fs/ext4/ext4.h | 20 ++++- fs/ext4/ext4_extents.h | 3 + fs/ext4/extents.c | 52 ++++++++-- fs/ext4/ioctl.c | 16 +++- fs/ext4/mballoc.c | 5 + fs/ext4/mballoc.h | 1 + 8 files changed, 322 insertions(+), 40 deletions(-)
fs/ext4/balloc.c +1 -0
@@ -705,6 +705,7 @@ static ext4_fsblk_t do_blk_alloc(handle_t *handle, struct inode *inode, ar.goal = goal; ar.len = *count; ar.logical = iblock; + ar.excepted_group =-1 ;if (S_ISREG (inode->i_mode) && !(flags &EXT4_META_BLOCK ))/* enable in-core preallocation for data block allocation */
fs/ext4/defrag.c +236 -28
517 lines not on this page · raw message
fs/ext4/ext4.h +19 -1
@@ -97,6 +97,11 @@ struct ext4_allocation_request {unsigned long len;/* flags. see above EXT4_MB_HINT_* */ unsigned long flags; +/* +* for ext4 online defrag: +* the block group which is excepted from allocation target +*/ +long long excepted_group; };/*
@@ -306,6 +311,7 @@ struct ext4_new_group_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)#define EXT4_IOC_FIEMAP_INO _IOWR('f', 18, struct fiemap_ino) +#define EXT4_IOC_MOVE_VICTIM _IOW('f', 19, struct ext4_extents_info)/* * ioctl commands in 32 bit emulation
@@ -328,8 +334,15 @@ struct ext4_new_group_data {* * DEFRAG_MAX_ENT: the maximum number of extents for exchanging between * kernel-space and user-space per an ioctl +* DEFRAG_FORCE_TRY: check whether we have free space fragmentation or not +* DEFRAG_FORCE_VICTIM: move victim extents to make sufficient space +* DEFRAG_FORCE_GATHER: move the target file into the free space made in the +* DEFRAG_FORCE_VICTIM phase */ #define DEFRAG_MAX_ENT 32 +#define DEFRAG_FORCE_TRY 1 +#define DEFRAG_FORCE_VICTIM 2 +#define DEFRAG_FORCE_GATHER 3struct ext4_extent_data {ext4_lblk_t block;/* start logical block number */
@@ -341,6 +354,8 @@ 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 */ +int flag;/* free space mode flag */ +struct ext4_extent_data ext; };struct ext4_extents_info {
@@ -1190,8 +1205,11 @@ extern void ext4_inode_table_set(struct super_block *sb,extern int ext4_ext_journal_restart (handle_t *handle,int needed);/* defrag.c */ extern int ext4_defrag (struct file *filp,ext4_lblk_t block_start, -ext4_lblk_t defrag_size,ext4_fsblk_t goal); +ext4_lblk_t defrag_size,ext4_fsblk_t goal, +int flag,struct ext4_extent_data *ext);extern int ext4_defrag_fiemap_ino (struct file *filp,unsigned long arg); +extern int ext4_defrag_move_victim (struct file *target_filp, +struct ext4_extents_info *ext_info);static inline ext4_fsblk_t ext4_blocks_count (struct ext4_super_block *es) {
fs/ext4/ext4_extents.h +3 -0
@@ -250,6 +250,9 @@ extern ext4_fsblk_t ext_pblock(struct ext4_extent *ex);extern ext4_fsblk_t ext4_ext_find_goal (struct inode *inode,struct ext4_ext_path *path,ext4_lblk_t block); +extern int ext4_ext_insert_extent_defrag (handle_t *handle,struct inode *inode, +struct ext4_ext_path *path, +struct ext4_extent *newext,int defrag);#endif /* _EXT4_EXTENTS */
fs/ext4/extents.c +42 -10
131 lines not on this page · raw message
fs/ext4/ioctl.c +15 -1
@@ -242,7 +242,8 @@ setversion_out: } err =ext4_defrag (filp, defrag.start_offset, - defrag.defrag_size, defrag.goal); + defrag.defrag_size, defrag.goal, defrag.flag, + &defrag.ext);return err; }
@@ -283,6 +284,19 @@ setversion_out:return err; } +case EXT4_IOC_MOVE_VICTIM : { +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 ; + + err =ext4_defrag_move_victim (filp, &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 +5 -0
@@ -1774,6 +1774,10 @@ repeat:if (group ==EXT4_SB (sb)->s_groups_count) group =0 ; +if (ac->ac_excepted_group !=-1 && + group == ac->ac_excepted_group) +continue ; +/* quick check to skip empty groups */ grp =ext4_get_group_info (ac->ac_sb, group);if (grp->bb_free ==0 )
@@ -4069,6 +4073,7 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac, ac->ac_bitmap_page =NULL ; ac->ac_buddy_page =NULL ; ac->ac_lg =NULL ; + ac->ac_excepted_group = ar->excepted_group;/* we have to define context: we'll we work with a file or * locality group. this is a policy, actually */
fs/ext4/mballoc.h +1 -0
@@ -219,6 +219,7 @@ struct ext4_allocation_context {struct page *ac_buddy_page;struct ext4_prealloc_space *ac_pa;struct ext4_locality_group *ac_lg; +long long ac_excepted_group; };#define AC_STATUS_CONTINUE 1