[RFC][PATCH 6/10] Move files from target block group to other block group

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

Signed-off-by: Takashi Sato <t-sato@xxxxxxxxxxxxx>
Signed-off-by: Akira Fujita <a-fujita@xxxxxxxxxxxxx>
---
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-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux