X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=misc%2Fe4defrag.c;h=9ec265f2e1b29a5c5bb704190f5e18b4cf4957e7;hb=6e4cc3d5eeb2dfaa055e652b5390beaa6c3d05da;hp=c2695e825d6b2211b079f44a9b91e68e02b0a5cb;hpb=9a3938918545b831b215b2befc2454f7b1a2dd84;p=tools%2Fe2fsprogs.git diff --git a/misc/e4defrag.c b/misc/e4defrag.c index c2695e8..9ec265f 100644 --- a/misc/e4defrag.c +++ b/misc/e4defrag.c @@ -39,9 +39,10 @@ #include #include #include -#include #include +#include "../version.h" + /* A relatively new ioctl interface ... */ #ifndef EXT4_IOC_MOVE_EXT #define EXT4_IOC_MOVE_EXT _IOWR('f', 15, struct move_extent) @@ -194,56 +195,9 @@ static struct frag_statistic_ino frag_rank[SHOW_FRAG_FILES]; #error posix_fadvise not available! #endif -/* - * Local definitions of some syscalls glibc may not yet have - */ -#ifndef HAVE_SYNC_FILE_RANGE -#warning Using locally defined sync_file_range interface. - -#ifndef __NR_sync_file_range -#ifndef __NR_sync_file_range2 /* ppc */ -#error Your kernel headers dont define __NR_sync_file_range -#endif -#endif - -/* - * sync_file_range() - Sync file region. - * - * @fd: defrag target file's descriptor. - * @offset: file offset. - * @length: area length. - * @flag: process flag. - */ -int sync_file_range(int fd, loff_t offset, loff_t length, unsigned int flag) -{ -#ifdef __NR_sync_file_range - return syscall(__NR_sync_file_range, fd, offset, length, flag); -#else - return syscall(__NR_sync_file_range2, fd, flag, offset, length); -#endif -} -#endif /* ! HAVE_SYNC_FILE_RANGE */ - #ifndef HAVE_FALLOCATE64 -#warning Using locally defined fallocate syscall interface. - -#ifndef __NR_fallocate -#error Your kernel headers dont define __NR_fallocate -#endif - -/* - * fallocate64() - Manipulate file space. - * - * @fd: defrag target file's descriptor. - * @mode: process flag. - * @offset: file offset. - * @len: file size. - */ -static int fallocate64(int fd, int mode, loff_t offset, loff_t len) -{ - return syscall(__NR_fallocate, fd, mode, offset, len); -} -#endif /* ! HAVE_FALLOCATE */ +#error fallocate64 not available! +#endif /* ! HAVE_FALLOCATE64 */ /* * get_mount_point() - Get device's mount point. @@ -408,7 +362,7 @@ static int page_in_core(int fd, struct move_extent defrag_data, { long pagesize; void *page = NULL; - loff_t offset, end_offset, length; + ext2_loff_t offset, end_offset, length; if (vec == NULL || *vec != NULL) return -1; @@ -417,8 +371,8 @@ static int page_in_core(int fd, struct move_extent defrag_data, if (pagesize < 0) return -1; /* In mmap, offset should be a multiple of the page size */ - offset = (loff_t)defrag_data.orig_start * block_size; - length = (loff_t)defrag_data.len * block_size; + offset = (ext2_loff_t)defrag_data.orig_start * block_size; + length = (ext2_loff_t)defrag_data.len * block_size; end_offset = offset + length; /* Round the offset down to the nearest multiple of pagesize */ offset = (offset / pagesize) * pagesize; @@ -431,8 +385,10 @@ static int page_in_core(int fd, struct move_extent defrag_data, *page_num = 0; *page_num = (length + pagesize - 1) / pagesize; *vec = (unsigned char *)calloc(*page_num, 1); - if (*vec == NULL) + if (*vec == NULL) { + munmap(page, length); return -1; + } /* Get information on whether pages are in core */ if (mincore(page, (size_t)length, *vec) == -1 || @@ -462,18 +418,20 @@ static int defrag_fadvise(int fd, struct move_extent defrag_data, SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER; unsigned int i; - loff_t offset; + ext2_loff_t offset; if (pagesize < 1) return -1; - offset = (loff_t)defrag_data.orig_start * block_size; + offset = (ext2_loff_t)defrag_data.orig_start * block_size; offset = (offset / pagesize) * pagesize; +#ifdef HAVE_SYNC_FILE_RANGE /* Sync file for fadvise process */ if (sync_file_range(fd, offset, - (loff_t)pagesize * page_num, sync_flag) < 0) + (ext2_loff_t)pagesize * page_num, sync_flag) < 0) return -1; +#endif /* Try to release buffer cache which this process used, * then other process can use the released buffer @@ -483,7 +441,8 @@ static int defrag_fadvise(int fd, struct move_extent defrag_data, offset += pagesize; continue; } - if (posix_fadvise(fd, offset, pagesize, fadvise_flag) < 0) { + if ((errno = posix_fadvise(fd, offset, + pagesize, fadvise_flag)) != 0) { if ((mode_flag & DETAIL) && flag) { perror("\tFailed to fadvise"); flag = 0; @@ -932,7 +891,9 @@ static int get_physical_count(struct fiemap_extent_list *physical_list_head) do { if ((ext_list_tmp->data.physical + ext_list_tmp->data.len) - != ext_list_tmp->next->data.physical) { + != ext_list_tmp->next->data.physical || + (ext_list_tmp->data.logical + ext_list_tmp->data.len) + != ext_list_tmp->next->data.logical) { /* This extent and next extent are not continuous. */ ret++; } @@ -1056,9 +1017,11 @@ static int get_best_count(ext4_fsblk_t block_count) int ret; unsigned int flex_bg_num; - /* Calcuate best extents count */ + if (blocks_per_group == 0) + return 1; + if (feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) { - flex_bg_num = 1 << log_groups_per_flex; + flex_bg_num = 1U << log_groups_per_flex; ret = ((block_count - 1) / ((ext4_fsblk_t)blocks_per_group * flex_bg_num)) + 1; @@ -1093,6 +1056,8 @@ static int file_statistic(const char *file, const struct stat64 *buf, struct fiemap_extent_list *logical_list_head = NULL; defraged_file_count++; + if (defraged_file_count > total_count) + total_count = defraged_file_count; if (mode_flag & DETAIL) { if (total_count == 1 && regular_count == 1) @@ -1214,10 +1179,13 @@ static int file_statistic(const char *file, const struct stat64 *buf, do { count++; printf("[ext %d]:\tstart %llu:\tlogical " - "%llu:\tlen %llu\n", count, - ext_list_tmp->data.physical, - ext_list_tmp->data.logical, - ext_list_tmp->data.len); + "%llu:\tlen %llu\n", count, + (unsigned long long) + ext_list_tmp->data.physical, + (unsigned long long) + ext_list_tmp->data.logical, + (unsigned long long) + ext_list_tmp->data.len); ext_list_tmp = ext_list_tmp->next; } while (ext_list_tmp != logical_list_head); @@ -1227,12 +1195,14 @@ static int file_statistic(const char *file, const struct stat64 *buf, if (current_uid == ROOT_UID) { if (strlen(file) > 40) printf("%s\n%50d/%-10d%6llu KB\n", - file, now_ext_count, - best_ext_count, size_per_ext); + file, now_ext_count, + best_ext_count, + (unsigned long long) size_per_ext); else printf("%-40s%10d/%-10d%6llu KB\n", - file, now_ext_count, - best_ext_count, size_per_ext); + file, now_ext_count, + best_ext_count, + (unsigned long long) size_per_ext); } else { if (strlen(file) > 40) printf("%s\n%50d/%-10s%7s\n", @@ -1255,14 +1225,16 @@ static int file_statistic(const char *file, const struct stat64 *buf, if (current_uid == ROOT_UID) { if (strlen(msg_buffer) > 40) printf("\033[79;0H\033[K%s\n" - "%50d/%-10d%6llu KB\n", - msg_buffer, now_ext_count, - best_ext_count, size_per_ext); + "%50d/%-10d%6llu KB\n", + msg_buffer, now_ext_count, + best_ext_count, + (unsigned long long) size_per_ext); else printf("\033[79;0H\033[K%-40s" - "%10d/%-10d%6llu KB\n", - msg_buffer, now_ext_count, - best_ext_count, size_per_ext); + "%10d/%-10d%6llu KB\n", + msg_buffer, now_ext_count, + best_ext_count, + (unsigned long long) size_per_ext); } else { if (strlen(msg_buffer) > 40) printf("\033[79;0H\033[K%s\n%50d/%-10s%7s\n", @@ -1321,7 +1293,8 @@ out: * @start: logical offset for defrag target file * @file_size: defrag target filesize */ -static void print_progress(const char *file, loff_t start, loff_t file_size) +static void print_progress(const char *file, ext2_loff_t start, + ext2_loff_t file_size) { int percent = (start * 100) / file_size; printf("\033[79;0H\033[K[%u/%u]%s:\t%3d%%", @@ -1343,7 +1316,7 @@ static void print_progress(const char *file, loff_t start, loff_t file_size) static int call_defrag(int fd, int donor_fd, const char *file, const struct stat64 *buf, struct fiemap_extent_list *ext_list_head) { - loff_t start = 0; + ext2_loff_t start = 0; unsigned int page_num; unsigned char *vec = NULL; int defraged_ret = 0; @@ -1459,6 +1432,8 @@ static int file_defrag(const char *file, const struct stat64 *buf, struct fiemap_extent_group *orig_group_tmp = NULL; defraged_file_count++; + if (defraged_file_count > total_count) + total_count = defraged_file_count; if (mode_flag & DETAIL) { printf("[%u/%u]", defraged_file_count, total_count); @@ -1548,10 +1523,7 @@ static int file_defrag(const char *file, const struct stat64 *buf, goto out; } - if (current_uid == ROOT_UID) - best = get_best_count(blk_count); - else - best = 1; + best = get_best_count(blk_count); if (file_frags_start <= best) goto check_improvement; @@ -1597,8 +1569,8 @@ static int file_defrag(const char *file, const struct stat64 *buf, orig_group_tmp = orig_group_head; do { ret = fallocate64(donor_fd, 0, - (loff_t)orig_group_tmp->start->data.logical * block_size, - (loff_t)orig_group_tmp->len * block_size); + (ext2_loff_t)orig_group_tmp->start->data.logical * block_size, + (ext2_loff_t)orig_group_tmp->len * block_size); if (ret < 0) { if (mode_flag & DETAIL) { PRINT_FILE_NAME(file); @@ -1620,7 +1592,7 @@ static int file_defrag(const char *file, const struct stat64 *buf, goto out; } - /* Calcuate donor inode's continuous physical region */ + /* Calculate donor inode's continuous physical region */ donor_physical_cnt = get_physical_count(donor_list_physical); /* Change donor extent list from physical to logical */ @@ -1715,12 +1687,15 @@ int main(int argc, char *argv[]) int i, j, ret = 0; int flags = FTW_PHYS | FTW_MOUNT; int arg_type = -1; + int mount_dir_len = 0; int success_flag = 0; char dir_name[PATH_MAX + 1]; char dev_name[PATH_MAX + 1]; struct stat64 buf; ext2_filsys fs = NULL; + printf("e4defrag %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE); + /* Parse arguments */ if (argc == 1) goto out; @@ -1838,25 +1813,23 @@ int main(int argc, char *argv[]) if (current_uid == ROOT_UID) { /* Get super block info */ - ret = ext2fs_open(dev_name, 0, 0, block_size, - unix_io_manager, &fs); + ret = ext2fs_open(dev_name, EXT2_FLAG_64BITS, 0, + block_size, unix_io_manager, &fs); if (ret) { - if (mode_flag & DETAIL) { - perror("Can't get super block info"); - PRINT_FILE_NAME(argv[i]); - } - continue; + if (mode_flag & DETAIL) + fprintf(stderr, + "Warning: couldn't get file " + "system details for %s: %s\n", + dev_name, error_message(ret)); + } else { + blocks_per_group = fs->super->s_blocks_per_group; + feature_incompat = fs->super->s_feature_incompat; + log_groups_per_flex = fs->super->s_log_groups_per_flex; + ext2fs_close_free(&fs); } - - blocks_per_group = fs->super->s_blocks_per_group; - feature_incompat = fs->super->s_feature_incompat; - log_groups_per_flex = fs->super->s_log_groups_per_flex; - - ext2fs_close(fs); } switch (arg_type) { - int mount_dir_len = 0; case DIRNAME: if (!(mode_flag & STATISTIC)) @@ -1868,11 +1841,11 @@ int main(int argc, char *argv[]) strncat(lost_found_dir, "/lost+found", PATH_MAX - strnlen(lost_found_dir, PATH_MAX)); - /* Not the case("e4defrag mount_piont_dir") */ + /* Not the case("e4defrag mount_point_dir") */ if (dir_name[mount_dir_len] != '\0') { /* - * "e4defrag mount_piont_dir/lost+found" - * or "e4defrag mount_piont_dir/lost+found/" + * "e4defrag mount_point_dir/lost+found" + * or "e4defrag mount_point_dir/lost+found/" */ if (strncmp(lost_found_dir, dir_name, strnlen(lost_found_dir, @@ -1886,9 +1859,10 @@ int main(int argc, char *argv[]) continue; } - /* "e4defrag mount_piont_dir/else_dir" */ + /* "e4defrag mount_point_dir/else_dir" */ memset(lost_found_dir, 0, PATH_MAX + 1); } + /* fall through */ case DEVNAME: if (arg_type == DEVNAME) { strncpy(lost_found_dir, dir_name, @@ -1931,6 +1905,7 @@ int main(int argc, char *argv[]) frag_rank[j].msg_buffer, frag_rank[j].now_count, frag_rank[j].best_count, + (unsigned long long) frag_rank[j]. size_per_ext); } else if (strlen(frag_rank[j]. @@ -1941,6 +1916,7 @@ int main(int argc, char *argv[]) frag_rank[j].msg_buffer, frag_rank[j].now_count, frag_rank[j].best_count, + (unsigned long long) frag_rank[j]. size_per_ext); } else @@ -2033,12 +2009,12 @@ int main(int argc, char *argv[]) 100 / files_block_count; score = CALC_SCORE(files_ratio); printf("\n Total/best extents\t\t\t\t%d/%d\n" - " Average size per extent" - "\t\t\t%llu KB\n" - " Fragmentation score\t\t\t\t%.0f\n", - extents_before_defrag, - extents_after_defrag, - size_per_ext, score); + " Average size per extent" + "\t\t\t%llu KB\n" + " Fragmentation score\t\t\t\t%.0f\n", + extents_before_defrag, + extents_after_defrag, + (unsigned long long) size_per_ext, score); printf(" [0-30 no problem:" " 31-55 a little bit fragmented:" " 56- needs defrag]\n");