From patchwork Fri Apr 8 07:52:22 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kazuya Mio X-Patchwork-Id: 90288 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id B1E33B6F83 for ; Fri, 8 Apr 2011 18:07:35 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932178Ab1DHIHd (ORCPT ); Fri, 8 Apr 2011 04:07:33 -0400 Received: from TYO202.gate.nec.co.jp ([202.32.8.206]:56439 "EHLO tyo202.gate.nec.co.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932099Ab1DHIHc (ORCPT ); Fri, 8 Apr 2011 04:07:32 -0400 Received: from mailgate3.nec.co.jp ([10.7.69.192]) by tyo202.gate.nec.co.jp (8.13.8/8.13.4) with ESMTP id p3887TxF020123; Fri, 8 Apr 2011 17:07:29 +0900 (JST) Received: (from root@localhost) by mailgate3.nec.co.jp (8.11.7/3.7W-MAILGATE-NEC) id p3887RE28969; Fri, 8 Apr 2011 17:07:27 +0900 (JST) Received: from mail02.kamome.nec.co.jp (mail02.kamome.nec.co.jp [10.25.43.5]) by mailsv4.nec.co.jp (8.13.8/8.13.4) with ESMTP id p3887QS9002508; Fri, 8 Apr 2011 17:07:26 +0900 (JST) Received: from togyo.jp.nec.com ([10.26.220.4] [10.26.220.4]) by mail01b.kamome.nec.co.jp with ESMTP id BT-MMP-583922; Fri, 8 Apr 2011 16:52:29 +0900 Received: from [10.64.168.30] ([10.64.168.30] [10.64.168.30]) by mail.jp.nec.com with ESMTP; Fri, 8 Apr 2011 16:52:29 +0900 Message-ID: <4D9EBEB6.3050803@sx.jp.nec.com> Date: Fri, 08 Apr 2011 16:52:22 +0900 From: Kazuya Mio User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; ja; rv:1.9.2.15) Gecko/20110303 Thunderbird/3.1.9 MIME-Version: 1.0 To: ext4 , Theodore Tso Subject: [PATCH 05/11] e4defrag: Use get_fragment_score() for decision of whether to defrag Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org This makes e4defrag use get_fragment_score() to calculate fragmentation score. If fragmentation score of the target file is zero or less than the destination file's one, e4defrag stops defragmentation. The threshold that shows whether a fragment is good or not comes from "blocksize * 8 - 2048". It's the same value as filefrag. Signed-off-by: Kazuya Mio --- misc/Makefile.in | 4 +-- misc/e4defrag.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 60 insertions(+), 8 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/misc/Makefile.in b/misc/Makefile.in index 19eaa43..681475b 100644 --- a/misc/Makefile.in +++ b/misc/Makefile.in @@ -196,9 +196,9 @@ e2undo.profiled: $(PROFILED_E2UNDO_OBJS) $(PROFILED_DEPLIBS) $(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o e2undo.profiled \ $(PROFILED_E2UNDO_OBJS) $(PROFILED_LIBS) $(LIBINTL) -e4defrag: $(E4DEFRAG_OBJS) $(DEPLIBS) +e4defrag: $(E4DEFRAG_OBJS) $(DEPLIBS) $(DEPLIBS_E2P) $(E) " LD $@" - $(Q) $(CC) $(ALL_LDFLAGS) -o e4defrag $(E4DEFRAG_OBJS) $(LIBS) + $(Q) $(CC) $(ALL_LDFLAGS) -o e4defrag $(E4DEFRAG_OBJS) $(LIBS) $(LIBE2P) e4defrag.profiled: $(PROFILED_E4DEFRAG_OBJS) $(PROFILED_DEPLIBS) $(E) " LD $@" diff --git a/misc/e4defrag.c b/misc/e4defrag.c index b168700..891bad4 100644 --- a/misc/e4defrag.c +++ b/misc/e4defrag.c @@ -31,16 +31,18 @@ #include #include #include -#include #include #include -#include #include #include #include #include #include +#include "e2p/e2p.h" +#include "ext2fs/ext2_types.h" +#include "ext2fs/fiemap.h" + /* A relatively new ioctl interface ... */ #ifndef EXT4_IOC_MOVE_EXT #define EXT4_IOC_MOVE_EXT _IOWR('f', 15, struct move_extent) @@ -107,6 +109,7 @@ #define NGMSG_FILE_OPEN "Failed to open" #define NGMSG_FILE_UNREG "File is not regular file" #define NGMSG_LOST_FOUND "Can not process \"lost+found\"" +#define NGMSG_EXT_FORMAT "File is not extent format" /* Data type for filesystem-wide blocks number */ typedef unsigned long long ext4_fsblk_t; @@ -961,9 +964,11 @@ static int file_defrag(const char *file, const struct stat64 *buf, { int fd; int donor_fd = -1; + int orig_score = 0, donor_score = 0; int ret; int file_frags_start, file_frags_end; char tmp_inode_name[PATH_MAX + 8]; + size_t threshold; ext4_fsblk_t blk_count = 0; struct fiemap_extent_list *orig_list = NULL; struct fiemap_extent_list *donor_list = NULL; @@ -1046,16 +1051,26 @@ static int file_defrag(const char *file, const struct stat64 *buf, goto out; } - /* Combine extents to group */ - ret = join_extents(orig_list, &orig_group_head); - if (ret < 0) { + /* + * Calculate the threshold of perfection. + * NOTE: 2048 means the maximum block region of mballoc. + */ + threshold = (block_size * 8 - 2048) * block_size; + orig_score = get_fragment_score(fd, threshold); + if (orig_score < 0) { if (mode_flag & DETAIL) { PRINT_FILE_NAME(file); - PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); + if (errno == EOPNOTSUPP) + PRINT_ERR_MSG_WITH_ERRNO(NGMSG_EXT_FORMAT); + else + PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); } goto out; } + if (!orig_score) + goto check_improvement; + /* Create donor inode */ memset(tmp_inode_name, 0, PATH_MAX + 8); sprintf(tmp_inode_name, "%.*s.defrag", @@ -1083,6 +1098,16 @@ static int file_defrag(const char *file, const struct stat64 *buf, goto out; } + /* Combine extents to group */ + ret = join_extents(orig_list, &orig_group_head); + if (ret < 0) { + if (mode_flag & DETAIL) { + PRINT_FILE_NAME(file); + PRINT_ERR_MSG_WITH_ERRNO("Failed to allocate memory"); + } + goto out; + } + /* Allocate space for donor inode */ orig_group_tmp = orig_group_head; do { @@ -1110,6 +1135,16 @@ static int file_defrag(const char *file, const struct stat64 *buf, goto out; } + donor_score = get_fragment_score(donor_fd, threshold); + if (donor_score < 0) { + if (mode_flag & DETAIL) { + PRINT_FILE_NAME(file); + PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); + } + goto out; + } + +check_improvement: if (mode_flag & DETAIL) { if (file_frags_start != 1) frag_files_before_defrag++; @@ -1117,6 +1152,23 @@ static int file_defrag(const char *file, const struct stat64 *buf, extents_before_defrag += file_frags_start; } + if (!orig_score || orig_score <= donor_score) { + printf("\033[79;0H\033[K[%u/%u]%s:\t%3d%%", + defraged_file_count, total_count, file, 100); + if (mode_flag & DETAIL) + printf(" extents: %d -> %d", + file_frags_start, file_frags_start); + + printf("\t[ OK ]\n"); + succeed_cnt++; + + if (file_frags_start != 1) + frag_files_after_defrag++; + + extents_after_defrag += file_frags_start; + goto out; + } + /* Defrag the file */ ret = call_defrag(fd, donor_fd, file, buf, donor_list);