mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
ext4: online defrag -- Add EXT4_IOC_MOVE_EXT ioctl
The EXT4_IOC_MOVE_EXT exchanges the blocks between orig_fd and donor_fd, and then write the file data of orig_fd to donor_fd. ext4_mext_move_extent() is the main fucntion of ext4 online defrag, and this patch includes all functions related to ext4 online defrag. Signed-off-by: Akira Fujita <a-fujita@rs.jp.nec.com> Signed-off-by: Takashi Sato <t-sato@yk.jp.nec.com> Signed-off-by: Kazuya Mio <k-mio@sx.jp.nec.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
This commit is contained in:
parent
8b0f9e8f78
commit
748de6736c
6 changed files with 1378 additions and 3 deletions
|
@ -6,7 +6,7 @@ obj-$(CONFIG_EXT4_FS) += ext4.o
|
||||||
|
|
||||||
ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
|
ext4-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 \
|
ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
|
||||||
ext4_jbd2.o migrate.o mballoc.o block_validity.o
|
ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o
|
||||||
|
|
||||||
ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
|
ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
|
||||||
ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
|
ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
|
||||||
|
|
|
@ -352,6 +352,7 @@ struct ext4_new_group_data {
|
||||||
/* note ioctl 10 reserved for an early version of the FIEMAP ioctl */
|
/* note ioctl 10 reserved for an early version of the FIEMAP ioctl */
|
||||||
/* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
|
/* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
|
||||||
#define EXT4_IOC_ALLOC_DA_BLKS _IO('f', 12)
|
#define EXT4_IOC_ALLOC_DA_BLKS _IO('f', 12)
|
||||||
|
#define EXT4_IOC_MOVE_EXT _IOWR('f', 15, struct move_extent)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ioctl commands in 32 bit emulation
|
* ioctl commands in 32 bit emulation
|
||||||
|
@ -447,6 +448,15 @@ struct ext4_inode {
|
||||||
__le32 i_version_hi; /* high 32 bits for 64-bit version */
|
__le32 i_version_hi; /* high 32 bits for 64-bit version */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct move_extent {
|
||||||
|
__u32 reserved; /* should be zero */
|
||||||
|
__u32 donor_fd; /* donor file descriptor */
|
||||||
|
__u64 orig_start; /* logical start offset in block for orig */
|
||||||
|
__u64 donor_start; /* logical start offset in block for donor */
|
||||||
|
__u64 len; /* block length to be moved */
|
||||||
|
__u64 moved_len; /* moved block length */
|
||||||
|
};
|
||||||
|
#define MAX_DEFRAG_SIZE ((1UL<<31) - 1)
|
||||||
|
|
||||||
#define EXT4_EPOCH_BITS 2
|
#define EXT4_EPOCH_BITS 2
|
||||||
#define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
|
#define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
|
||||||
|
@ -1647,6 +1657,11 @@ extern int ext4_get_blocks(handle_t *handle, struct inode *inode,
|
||||||
struct buffer_head *bh, int flags);
|
struct buffer_head *bh, int flags);
|
||||||
extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
||||||
__u64 start, __u64 len);
|
__u64 start, __u64 len);
|
||||||
|
/* move_extent.c */
|
||||||
|
extern int ext4_move_extents(struct file *o_filp, struct file *d_filp,
|
||||||
|
__u64 start_orig, __u64 start_donor,
|
||||||
|
__u64 len, __u64 *moved_len);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add new method to test wether block and inode bitmaps are properly
|
* Add new method to test wether block and inode bitmaps are properly
|
||||||
|
|
|
@ -221,12 +221,16 @@ static inline int ext4_ext_get_actual_len(struct ext4_extent *ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks);
|
extern int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks);
|
||||||
|
extern ext4_fsblk_t ext_pblock(struct ext4_extent *ex);
|
||||||
extern ext4_fsblk_t idx_pblock(struct ext4_extent_idx *);
|
extern ext4_fsblk_t idx_pblock(struct ext4_extent_idx *);
|
||||||
extern void ext4_ext_store_pblock(struct ext4_extent *, ext4_fsblk_t);
|
extern void ext4_ext_store_pblock(struct ext4_extent *, ext4_fsblk_t);
|
||||||
extern int ext4_extent_tree_init(handle_t *, struct inode *);
|
extern int ext4_extent_tree_init(handle_t *, struct inode *);
|
||||||
extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode,
|
extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode,
|
||||||
int num,
|
int num,
|
||||||
struct ext4_ext_path *path);
|
struct ext4_ext_path *path);
|
||||||
|
extern int ext4_can_extents_be_merged(struct inode *inode,
|
||||||
|
struct ext4_extent *ex1,
|
||||||
|
struct ext4_extent *ex2);
|
||||||
extern int ext4_ext_try_to_merge(struct inode *inode,
|
extern int ext4_ext_try_to_merge(struct inode *inode,
|
||||||
struct ext4_ext_path *path,
|
struct ext4_ext_path *path,
|
||||||
struct ext4_extent *);
|
struct ext4_extent *);
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
* ext_pblock:
|
* ext_pblock:
|
||||||
* combine low and high parts of physical block number into ext4_fsblk_t
|
* 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;
|
ext4_fsblk_t block;
|
||||||
|
|
||||||
|
@ -1417,7 +1417,7 @@ static int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
|
ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
|
||||||
struct ext4_extent *ex2)
|
struct ext4_extent *ex2)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
#include <linux/smp_lock.h>
|
#include <linux/smp_lock.h>
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
|
#include <linux/file.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include "ext4_jbd2.h"
|
#include "ext4_jbd2.h"
|
||||||
#include "ext4.h"
|
#include "ext4.h"
|
||||||
|
@ -213,6 +214,41 @@ setversion_out:
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case EXT4_IOC_MOVE_EXT: {
|
||||||
|
struct move_extent me;
|
||||||
|
struct file *donor_filp;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (copy_from_user(&me,
|
||||||
|
(struct move_extent __user *)arg, sizeof(me)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
donor_filp = fget(me.donor_fd);
|
||||||
|
if (!donor_filp)
|
||||||
|
return -EBADF;
|
||||||
|
|
||||||
|
if (!capable(CAP_DAC_OVERRIDE)) {
|
||||||
|
if ((current->real_cred->fsuid != inode->i_uid) ||
|
||||||
|
!(inode->i_mode & S_IRUSR) ||
|
||||||
|
!(donor_filp->f_dentry->d_inode->i_mode &
|
||||||
|
S_IRUSR)) {
|
||||||
|
fput(donor_filp);
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ext4_move_extents(filp, donor_filp, me.orig_start,
|
||||||
|
me.donor_start, me.len, &me.moved_len);
|
||||||
|
fput(donor_filp);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
if (copy_to_user((struct move_extent *)arg,
|
||||||
|
&me, sizeof(me)))
|
||||||
|
return -EFAULT;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
case EXT4_IOC_GROUP_ADD: {
|
case EXT4_IOC_GROUP_ADD: {
|
||||||
struct ext4_new_group_data input;
|
struct ext4_new_group_data input;
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
|
|
1320
fs/ext4/move_extent.c
Normal file
1320
fs/ext4/move_extent.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue