- To make contiguous free blocks, move files from the target block group
  to other block group. 

Signed-off-by: Takashi Sato <[EMAIL PROTECTED]>
Signed-off-by: Akira Fujita <[EMAIL PROTECTED]>
---
diff -X Online-Defrag_linux-2.6.19-rc6-git/Documentation/dontdiff -upNr 
Online-Defrag_linux-2.6.19-rc6-git-MOVE_VICTIM/fs/ext4/extents.c 
Online-Defrag_linux-2.6.19-rc6-git-RESERVE_BLOCK/fs/ext4/extents.c
--- Online-Defrag_linux-2.6.19-rc6-git-MOVE_VICTIM/fs/ext4/extents.c    
2007-06-20 08:27:44.000000000 +0900
+++ Online-Defrag_linux-2.6.19-rc6-git-RESERVE_BLOCK/fs/ext4/extents.c  
2007-06-19 21:40:55.000000000 +0900
@@ -1279,20 +1279,20 @@ ext4_can_extents_be_merged(struct inode 
 }
 
 /*
- * ext4_ext_insert_extent:
- * tries to merge requsted extent into the existing extent or
- * inserts requested extent as new one into the tree,
- * creating new leaf in the no-space case.
+ * ext4_ext_insert_extent_defrag:
+ * The difference from ext4_ext_insert_extent is to use the first block
+ * in newext as the goal of the new index block.
  */
-int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+int ext4_ext_insert_extent_defrag(handle_t *handle, struct inode *inode,
                                struct ext4_ext_path *path,
-                               struct ext4_extent *newext)
+                               struct ext4_extent *newext, int defrag)
 {
        struct ext4_extent_header * eh;
        struct ext4_extent *ex, *fex;
        struct ext4_extent *nearex; /* nearest extent */
        struct ext4_ext_path *npath = NULL;
        int depth, len, err, next;
+       ext4_fsblk_t defrag_goal;
 
        BUG_ON(newext->ee_len == 0);
        depth = ext_depth(inode);
@@ -1342,11 +1342,17 @@ repeat:
                          le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max));
        }
 
+       if (defrag) {
+               defrag_goal = ext_pblock(newext);
+       } else {
+               defrag_goal = 0;
+       }
        /*
         * There is no free space in the found leaf.
         * We're gonna add a new leaf in the tree.
         */
-       err = ext4_ext_create_new_leaf(handle, inode, path, newext);
+       err = ext4_ext_create_new_leaf(handle, inode, path,
+                                               newext, defrag_goal);
        if (err)
                goto cleanup;
        depth = ext_depth(inode);
@@ -1438,6 +1444,19 @@ cleanup:
        return err;
 }
 
+/*
+ * ext4_ext_insert_extent:
+ * tries to merge requsted extent into the existing extent or
+ * inserts requested extent as new one into the tree,
+ * creating new leaf in the no-space case.
+ */
+int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
+                               struct ext4_ext_path *path,
+                               struct ext4_extent *newext)
+{
+       return ext4_ext_insert_extent_defrag(handle, inode, path, newext, 0);
+}
+
 int ext4_ext_walk_space(struct inode *inode, unsigned long block,
                        unsigned long num, ext_prepare_callback func,
                        void *cbdata)
@@ -2600,6 +2619,70 @@ out:
 }
 
 /**
+ * ext4_ext_defrag_victim - Create free space for defrag
+ * @filp      target file
+ * @ex_info   target extents array to move
+ *
+ * This function returns 0 if succeeded, otherwise
+ * returns error value
+ */
+static int ext4_ext_defrag_victim(struct file *target_filp,
+                       struct ext4_extents_info *ex_info)
+{
+       struct inode *target_inode = target_filp->f_dentry->d_inode;
+       struct super_block *sb = target_inode->i_sb;
+       struct file victim_file;
+       struct dentry victim_dent;
+       struct inode *victim_inode;
+       ext4_fsblk_t goal = ex_info->goal;
+       int ret = 0;
+       int i = 0;
+       int flag = DEFRAG_RESERVE_BLOCKS_SECOND;
+       struct ext4_extent_data ext;
+       unsigned long group;
+       ext4_grpblk_t grp_off;
+
+       /* Setup dummy entent data */
+       ext.len = 0;
+
+       /* Get the inode of the victim file */
+       victim_inode = iget(sb, ex_info->ino);
+       if (!victim_inode)
+               return -EACCES;
+
+       /* Setup file for the victim file */
+       victim_dent.d_inode = victim_inode;
+       victim_file.f_dentry = &victim_dent;
+
+       /* Set the goal appropriate offset */
+       if (goal == -1) {
+               ext4_get_group_no_and_offset(victim_inode->i_sb,
+                               ex_info->ext[0].start, &group, &grp_off);
+               goal = ext4_group_first_block_no(sb, group + 1);
+       }
+
+       for (i = 0; i < ex_info->entries; i++ ) {
+               /* Move original blocks to another block group */
+               if ((ret = ext4_ext_defrag(&victim_file, ex_info->ext[i].block,
+                       ex_info->ext[i].len, goal, flag, &ext)) < 0)
+                       goto ERR;
+
+               /* Sync journal blocks before reservation */
+               if (do_fsync(target_filp, 0))
+                       goto ERR;
+       }
+
+       iput(victim_inode);
+       return 0;
+ERR:
+       mutex_lock(&EXT4_I(target_inode)->truncate_mutex);
+       ext4_discard_reservation(target_inode);
+       mutex_unlock(&EXT4_I(target_inode)->truncate_mutex);
+       iput(victim_inode);
+       return ret;
+}
+
+/**
  * ext4_ext_fblocks_distribution - Search free block distribution
  * @filp      target file
  * @ex_info   ext4_extents_info
@@ -2788,6 +2871,16 @@ int ext4_ext_ioctl(struct inode *inode, 
                                &ext_info, sizeof(ext_info)))
                                return -EFAULT;
                }
+       } else if (cmd == EXT4_IOC_MOVE_VICTIM) {
+               struct ext4_extents_info ext_info;
+
+               if (copy_from_user(&ext_info,
+                       (struct ext4_extents_info __user *)arg,
+                       sizeof(ext_info)))
+                       return -EFAULT;
+
+               err = ext4_ext_defrag_victim(filp, &ext_info);
+
        } else if (cmd == EXT4_IOC_DEFRAG) {
                struct ext4_ext_defrag_data defrag;
 


-
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to