1e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 2e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * e4defrag.c - ext4 filesystem defragmenter 3e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 4e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Copyright (C) 2009 NEC Software Tohoku, Ltd. 5e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 6e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Author: Akira Fujita <a-fujita@rs.jp.nec.com> 7e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Takashi Sato <t-sato@yk.jp.nec.com> 8e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 9e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 10e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef _LARGEFILE_SOURCE 11e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define _LARGEFILE_SOURCE 12e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 13e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 14e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef _LARGEFILE64_SOURCE 15e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define _LARGEFILE64_SOURCE 16e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 17e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 18e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef _GNU_SOURCE 19e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define _GNU_SOURCE 20e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 21e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 22e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <ctype.h> 23e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <dirent.h> 24e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <endian.h> 25e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <errno.h> 26e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <fcntl.h> 27e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <ftw.h> 28e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <limits.h> 29e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <mntent.h> 30e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <stdio.h> 31e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <stdlib.h> 32e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <string.h> 33e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <unistd.h> 34e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <ext2fs/ext2_types.h> 35e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <ext2fs/ext2fs.h> 36e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <linux/fs.h> 37e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/ioctl.h> 38e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <ext2fs/fiemap.h> 39e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/mman.h> 40e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/stat.h> 41e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/statfs.h> 42e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/syscall.h> 43e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/vfs.h> 44e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 45e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* A relatively new ioctl interface ... */ 46e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef EXT4_IOC_MOVE_EXT 47e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define EXT4_IOC_MOVE_EXT _IOWR('f', 15, struct move_extent) 48e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 49e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 50e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Macro functions */ 51e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define PRINT_ERR_MSG(msg) fprintf(stderr, "%s\n", (msg)) 52e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define IN_FTW_PRINT_ERR_MSG(msg) \ 53e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, "\t%s\t\t[ NG ]\n", (msg)) 54e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define PRINT_FILE_NAME(file) fprintf(stderr, " \"%s\"\n", (file)) 55e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define PRINT_ERR_MSG_WITH_ERRNO(msg) \ 56e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, "\t%s:%s\t[ NG ]\n", (msg), strerror(errno)) 57e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define STATISTIC_ERR_MSG(msg) \ 58e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, "\t%s\n", (msg)) 59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define STATISTIC_ERR_MSG_WITH_ERRNO(msg) \ 60e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, "\t%s:%s\n", (msg), strerror(errno)) 61e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define min(x, y) (((x) > (y)) ? (y) : (x)) 62e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define CALC_SCORE(ratio) \ 63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ((ratio) > 10 ? (80 + 20 * (ratio) / 100) : (8 * (ratio))) 64e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Wrap up the free function */ 65e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define FREE(tmp) \ 66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall do { \ 67e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((tmp) != NULL) \ 68e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free(tmp); \ 69e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } while (0) \ 70e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Insert list2 after list1 */ 71e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define insert(list1, list2) \ 72e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall do { \ 73e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall list2->next = list1->next; \ 74e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall list1->next->prev = list2; \ 75e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall list2->prev = list1; \ 76e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall list1->next = list2; \ 77e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } while (0) 78e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 79e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* To delete unused warning */ 80e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef __GNUC__ 81e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define EXT2FS_ATTR(x) __attribute__(x) 82e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#else 83e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define EXT2FS_ATTR(x) 84e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 85e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 86e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* The mode of defrag */ 87e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define DETAIL 0x01 88e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define STATISTIC 0x02 89e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 90e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define DEVNAME 0 91e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define DIRNAME 1 92e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define FILENAME 2 93e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 94e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define FTW_OPEN_FD 2000 95e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 96e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define FS_EXT4 "ext4" 97e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define ROOT_UID 0 98e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 99e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define BOUND_SCORE 55 100e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define SHOW_FRAG_FILES 5 101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 102e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Magic number for ext4 */ 103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define EXT4_SUPER_MAGIC 0xEF53 104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Definition of flex_bg */ 106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* The following macro is used for ioctl FS_IOC_FIEMAP 109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * EXTENT_MAX_COUNT: the maximum number of extents for exchanging between 110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * kernel-space and user-space per ioctl 111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define EXTENT_MAX_COUNT 512 113e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 114e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* The following macros are error message */ 115e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define MSG_USAGE \ 116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall"Usage : e4defrag [-v] file...| directory...| device...\n\ 117e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall : e4defrag -c file...| directory...| device...\n" 118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 119e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define NGMSG_EXT4 "Filesystem is not ext4 filesystem" 120e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define NGMSG_FILE_EXTENT "Failed to get file extents" 121e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define NGMSG_FILE_INFO "Failed to get file information" 122e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define NGMSG_FILE_OPEN "Failed to open" 123e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define NGMSG_FILE_UNREG "File is not regular file" 124e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define NGMSG_LOST_FOUND "Can not process \"lost+found\"" 125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 126e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Data type for filesystem-wide blocks number */ 127e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgralltypedef unsigned long long ext4_fsblk_t; 128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 129e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstruct fiemap_extent_data { 130e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 len; /* blocks count */ 131e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 logical; /* start logical block number */ 132e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext4_fsblk_t physical; /* start physical block number */ 133e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}; 134e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 135e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstruct fiemap_extent_list { 136e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *prev; 137e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *next; 138e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_data data; /* extent belong to file */ 139e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}; 140e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 141e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstruct fiemap_extent_group { 142e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_group *prev; 143e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_group *next; 144e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 len; /* length of this continuous region */ 145e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *start; /* start ext */ 146e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *end; /* end ext */ 147e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}; 148e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 149e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstruct move_extent { 150e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __s32 reserved; /* original file descriptor */ 151e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u32 donor_fd; /* donor file descriptor */ 152e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 orig_start; /* logical start offset in block for orig */ 153e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 donor_start; /* logical start offset in block for donor */ 154e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 len; /* block length to be moved */ 155e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 moved_len; /* moved block length */ 156e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}; 157e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 158e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstruct frag_statistic_ino { 159e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int now_count; /* the file's extents count of before defrag */ 160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int best_count; /* the best file's extents count */ 161e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 size_per_ext; /* size(KB) per extent */ 162e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall float ratio; /* the ratio of fragmentation */ 163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char msg_buffer[PATH_MAX + 1]; /* pathname of the file */ 164e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}; 165e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 166e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic char lost_found_dir[PATH_MAX + 1]; 167e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int block_size; 168e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int extents_before_defrag; 169e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int extents_after_defrag; 170e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int mode_flag; 171e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic unsigned int current_uid; 172e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic unsigned int defraged_file_count; 173e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic unsigned int frag_files_before_defrag; 174e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic unsigned int frag_files_after_defrag; 175e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic unsigned int regular_count; 176e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic unsigned int succeed_cnt; 177e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic unsigned int total_count; 178e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic __u8 log_groups_per_flex; 179e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic __u32 blocks_per_group; 180e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic __u32 feature_incompat; 181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic ext4_fsblk_t files_block_count; 182e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic struct frag_statistic_ino frag_rank[SHOW_FRAG_FILES]; 183e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 184e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 185e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Local definitions of some syscalls glibc may not yet have */ 186e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 187e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef HAVE_POSIX_FADVISE 188e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#warning Using locally defined posix_fadvise interface. 189e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 190e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef __NR_fadvise64_64 191e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#error Your kernel headers dont define __NR_fadvise64_64 192e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 193e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 194e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 195e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * fadvise() - Give advice about file access. 196e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 197e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @fd: defrag target file's descriptor. 198e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @offset: file offset. 199e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @len: area length. 200e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @advise: process flag. 201e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int posix_fadvise(int fd, loff_t offset, size_t len, int advise) 203e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 204e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return syscall(__NR_fadvise64_64, fd, offset, len, advise); 205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 206e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif /* ! HAVE_FADVISE64_64 */ 207e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 208e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef HAVE_SYNC_FILE_RANGE 209e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#warning Using locally defined sync_file_range interface. 210e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 211e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef __NR_sync_file_range 212e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef __NR_sync_file_range2 /* ppc */ 213e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#error Your kernel headers dont define __NR_sync_file_range 214e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 215e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 216e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 218e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * sync_file_range() - Sync file region. 219e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 220e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @fd: defrag target file's descriptor. 221e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @offset: file offset. 222e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @length: area length. 223e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @flag: process flag. 224e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 225e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallint sync_file_range(int fd, loff_t offset, loff_t length, unsigned int flag) 226e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 227e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef __NR_sync_file_range 228e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return syscall(__NR_sync_file_range, fd, offset, length, flag); 229e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#else 230e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return syscall(__NR_sync_file_range2, fd, flag, offset, length); 231e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 232e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 233e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif /* ! HAVE_SYNC_FILE_RANGE */ 234e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 235e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef HAVE_FALLOCATE64 236e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#warning Using locally defined fallocate syscall interface. 237e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 238e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef __NR_fallocate 239e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#error Your kernel headers dont define __NR_fallocate 240e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 241e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 242e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 243e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * fallocate64() - Manipulate file space. 244e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 245e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @fd: defrag target file's descriptor. 246e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @mode: process flag. 247e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @offset: file offset. 248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @len: file size. 249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 250e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int fallocate64(int fd, int mode, loff_t offset, loff_t len) 251e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 252e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return syscall(__NR_fallocate, fd, mode, offset, len); 253e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 254e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif /* ! HAVE_FALLOCATE */ 255e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 256e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 257e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * get_mount_point() - Get device's mount point. 258e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 259e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @devname: the device's name. 260e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @mount_point: the mount point. 261e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @dir_path_len: the length of directory. 262e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 263e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int get_mount_point(const char *devname, char *mount_point, 264e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int dir_path_len) 265e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 266e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Refer to /etc/mtab */ 267e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const char *mtab = MOUNTED; 268e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall FILE *fp = NULL; 269e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct mntent *mnt = NULL; 270e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct stat64 sb; 271e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 272e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (stat64(devname, &sb) < 0) { 273e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror(NGMSG_FILE_INFO); 274e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(devname); 275e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 276e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 277e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 278e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fp = setmntent(mtab, "r"); 279e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fp == NULL) { 280e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror("Couldn't access /etc/mtab"); 281e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 282e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 283e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 284e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while ((mnt = getmntent(fp)) != NULL) { 285e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct stat64 ms; 286e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 287e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 288e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * To handle device symlinks, we see if the 289e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * device number matches, not the name 290e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 291e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (stat64(mnt->mnt_fsname, &ms) < 0) 292e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 293e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (sb.st_rdev != ms.st_rdev) 294e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 295e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 296e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall endmntent(fp); 297e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (strcmp(mnt->mnt_type, FS_EXT4) == 0) { 298e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncpy(mount_point, mnt->mnt_dir, 299e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dir_path_len); 300e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 301e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 302e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG(NGMSG_EXT4); 303e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 304e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 305e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall endmntent(fp); 306e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG("Filesystem is not mounted"); 307e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 308e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 309e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 310e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 311e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * is_ext4() - Whether on an ext4 filesystem. 312e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 313e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @file: the file's name. 314e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 315e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int is_ext4(const char *file, char *devname) 316e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 317e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int maxlen = 0; 318e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int len, ret; 319e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall FILE *fp = NULL; 320e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *mnt_type = NULL; 321e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Refer to /etc/mtab */ 322e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const char *mtab = MOUNTED; 323e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char file_path[PATH_MAX + 1]; 324e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct mntent *mnt = NULL; 325e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct statfs64 fsbuf; 326e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 327e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Get full path */ 328e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (realpath(file, file_path) == NULL) { 329e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror("Couldn't get full path"); 330e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 331e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 332e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 333e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 334e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (statfs64(file_path, &fsbuf) < 0) { 335e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror("Failed to get filesystem information"); 336e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 337e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 338e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 339e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 340e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fsbuf.f_type != EXT4_SUPER_MAGIC) { 341e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG(NGMSG_EXT4); 342e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 343e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 344e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 345e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fp = setmntent(mtab, "r"); 346e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fp == NULL) { 347e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror("Couldn't access /etc/mtab"); 348e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 349e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 350e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 351e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while ((mnt = getmntent(fp)) != NULL) { 352e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mnt->mnt_fsname[0] != '/') 353e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 354e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall len = strlen(mnt->mnt_dir); 355e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = memcmp(file_path, mnt->mnt_dir, len); 356e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret != 0) 357e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 358e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 359e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (maxlen >= len) 360e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 361e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 362e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall maxlen = len; 363e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 364e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall mnt_type = realloc(mnt_type, strlen(mnt->mnt_type) + 1); 365e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mnt_type == NULL) { 366e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall endmntent(fp); 367e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 368e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 369e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(mnt_type, 0, strlen(mnt->mnt_type) + 1); 370e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncpy(mnt_type, mnt->mnt_type, strlen(mnt->mnt_type)); 371e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncpy(lost_found_dir, mnt->mnt_dir, PATH_MAX); 372e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncpy(devname, mnt->mnt_fsname, strlen(mnt->mnt_fsname) + 1); 373e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 374e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 375e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall endmntent(fp); 376e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mnt_type && strcmp(mnt_type, FS_EXT4) == 0) { 377e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall FREE(mnt_type); 378e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 379e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 380e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall FREE(mnt_type); 381e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG(NGMSG_EXT4); 382e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 383e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 384e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 385e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 386e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 387e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * calc_entry_counts() - Calculate file counts. 388e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 389e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @file: file name. 390e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @buf: file info. 391e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @flag: file type. 392e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ftwbuf: the pointer of a struct FTW. 393e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 394e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int calc_entry_counts(const char *file EXT2FS_ATTR((unused)), 395e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const struct stat64 *buf, int flag EXT2FS_ATTR((unused)), 396e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct FTW *ftwbuf EXT2FS_ATTR((unused))) 397e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 398e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (S_ISREG(buf->st_mode)) 399e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall regular_count++; 400e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 401e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall total_count++; 402e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 403e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 404e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 405e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 406e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 407e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * page_in_core() - Get information on whether pages are in core. 408e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 409e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @fd: defrag target file's descriptor. 410e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @defrag_data: data used for defrag. 411e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @vec: page state array. 412e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @page_num: page number. 413e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 414e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int page_in_core(int fd, struct move_extent defrag_data, 415e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned char **vec, unsigned int *page_num) 416e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 417e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall long pagesize; 418e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *page = NULL; 419e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall loff_t offset, end_offset, length; 420e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 421e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (vec == NULL || *vec != NULL) 422e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 423e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 424e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall pagesize = sysconf(_SC_PAGESIZE); 425e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (pagesize < 0) 426e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 427e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* In mmap, offset should be a multiple of the page size */ 428e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall offset = (loff_t)defrag_data.orig_start * block_size; 429e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall length = (loff_t)defrag_data.len * block_size; 430e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall end_offset = offset + length; 431e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Round the offset down to the nearest multiple of pagesize */ 432e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall offset = (offset / pagesize) * pagesize; 433e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall length = end_offset - offset; 434e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 435e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall page = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, offset); 436e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (page == MAP_FAILED) 437e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 438e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 439e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *page_num = 0; 440e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *page_num = (length + pagesize - 1) / pagesize; 441e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *vec = (unsigned char *)calloc(*page_num, 1); 442e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*vec == NULL) 443e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 444e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 445e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Get information on whether pages are in core */ 446e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mincore(page, (size_t)length, *vec) == -1 || 447e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall munmap(page, length) == -1) { 448e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall FREE(*vec); 449e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 450e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 451e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 452e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 453e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 454e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 455e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 456e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * defrag_fadvise() - Predeclare an access pattern for file data. 457e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 458e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @fd: defrag target file's descriptor. 459e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @defrag_data: data used for defrag. 460e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @vec: page state array. 461e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @page_num: page number. 462e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 463e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int defrag_fadvise(int fd, struct move_extent defrag_data, 464e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned char *vec, unsigned int page_num) 465e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 466e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int flag = 1; 467e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall long pagesize = sysconf(_SC_PAGESIZE); 468e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int fadvise_flag = POSIX_FADV_DONTNEED; 469e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int sync_flag = SYNC_FILE_RANGE_WAIT_BEFORE | 470e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall SYNC_FILE_RANGE_WRITE | 471e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall SYNC_FILE_RANGE_WAIT_AFTER; 472e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int i; 473e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall loff_t offset; 474e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 475e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (pagesize < 1) 476e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 477e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 478e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall offset = (loff_t)defrag_data.orig_start * block_size; 479e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall offset = (offset / pagesize) * pagesize; 480e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 481e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Sync file for fadvise process */ 482e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (sync_file_range(fd, offset, 483e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (loff_t)pagesize * page_num, sync_flag) < 0) 484e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 485e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 486e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Try to release buffer cache which this process used, 487e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * then other process can use the released buffer 488e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 489e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < page_num; i++) { 490e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((vec[i] & 0x1) == 0) { 491e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall offset += pagesize; 492e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 493e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 494e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (posix_fadvise(fd, offset, pagesize, fadvise_flag) < 0) { 495e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((mode_flag & DETAIL) && flag) { 496e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror("\tFailed to fadvise"); 497e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall flag = 0; 498e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 499e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 500e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall offset += pagesize; 501e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 502e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 503e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 504e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 505e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 506e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 507e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * check_free_size() - Check if there's enough disk space. 508e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 509e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @fd: defrag target file's descriptor. 510e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @file: file name. 511e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @blk_count: file blocks. 512e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 513e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int check_free_size(int fd, const char *file, ext4_fsblk_t blk_count) 514e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 515e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext4_fsblk_t free_blk_count; 516e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct statfs64 fsbuf; 517e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 518e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fstatfs64(fd, &fsbuf) < 0) { 519e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 520e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 521e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO( 522e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "Failed to get filesystem information"); 523e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 524e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 525e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 526e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 527e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Compute free space for root and normal user separately */ 528e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (current_uid == ROOT_UID) 529e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free_blk_count = fsbuf.f_bfree; 530e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 531e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free_blk_count = fsbuf.f_bavail; 532e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 533e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (free_blk_count >= blk_count) 534e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 535e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 536e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -ENOSPC; 537e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 538e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 539e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 540e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * file_frag_count() - Get file fragment count. 541e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 542e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @fd: defrag target file's descriptor. 543e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 544e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int file_frag_count(int fd) 545e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 546e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int ret; 547e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap fiemap_buf; 548e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 549e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* When fm_extent_count is 0, 550e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * ioctl just get file fragment count. 551e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 552e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(&fiemap_buf, 0, sizeof(struct fiemap)); 553e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fiemap_buf.fm_start = 0; 554e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fiemap_buf.fm_length = FIEMAP_MAX_OFFSET; 555e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fiemap_buf.fm_flags |= FIEMAP_FLAG_SYNC; 556e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 557e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = ioctl(fd, FS_IOC_FIEMAP, &fiemap_buf); 558e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) 559e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ret; 560e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 561e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return fiemap_buf.fm_mapped_extents; 562e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 563e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 564e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 565e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * file_check() - Check file's attributes. 566e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 567e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @fd: defrag target file's descriptor. 568e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @buf: a pointer of the struct stat64. 569e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @file: file name. 570e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @extents: file extents. 571e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @blk_count: file blocks. 572e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 573e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int file_check(int fd, const struct stat64 *buf, const char *file, 574e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int extents, ext4_fsblk_t blk_count) 575e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 576e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int ret; 577e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct flock lock; 578e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 579e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Write-lock check is more reliable */ 580e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall lock.l_type = F_WRLCK; 581e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall lock.l_start = 0; 582e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall lock.l_whence = SEEK_SET; 583e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall lock.l_len = 0; 584e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 585e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Free space */ 586e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = check_free_size(fd, file, blk_count); 587e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) { 588e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((mode_flag & DETAIL) && ret == -ENOSPC) { 589e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\033[79;0H\033[K[%u/%u] \"%s\"\t\t" 590e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall " extents: %d -> %d\n", defraged_file_count, 591e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall total_count, file, extents, extents); 592e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall IN_FTW_PRINT_ERR_MSG( 593e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "Defrag size is larger than filesystem's free space"); 594e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 595e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 596e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 597e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 598e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Access authority */ 599e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (current_uid != ROOT_UID && 600e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall buf->st_uid != current_uid) { 601e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 602e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\033[79;0H\033[K[%u/%u] \"%s\"\t\t" 603e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall " extents: %d -> %d\n", defraged_file_count, 604e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall total_count, file, extents, extents); 605e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall IN_FTW_PRINT_ERR_MSG( 606e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "File is not current user's file" 607e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall " or current user is not root"); 608e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 609e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 610e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 611e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 612e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Lock status */ 613e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fcntl(fd, F_GETLK, &lock) < 0) { 614e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 615e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 616e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO( 617e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "Failed to get lock information"); 618e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 619e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 620e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else if (lock.l_type != F_UNLCK) { 621e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 622e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 623e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall IN_FTW_PRINT_ERR_MSG("File has been locked"); 624e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 625e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 626e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 627e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 628e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 629e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 630e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 631e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 632e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * insert_extent_by_logical() - Sequentially insert extent by logical. 633e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 634e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ext_list_head: the head of logical extent list. 635e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ext: the extent element which will be inserted. 636e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 637e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int insert_extent_by_logical(struct fiemap_extent_list **ext_list_head, 638e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *ext) 639e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 640e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *ext_list_tmp = *ext_list_head; 641e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 642e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext == NULL) 643e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 644e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 645e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* First element */ 646e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*ext_list_head == NULL) { 647e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (*ext_list_head) = ext; 648e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (*ext_list_head)->prev = *ext_list_head; 649e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (*ext_list_head)->next = *ext_list_head; 650e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 651e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 652e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 653e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext->data.logical <= ext_list_tmp->data.logical) { 654e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Insert before head */ 655e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext_list_tmp->data.logical < 656e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext->data.logical + ext->data.len) 657e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Overlap */ 658e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 659e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Adjust head */ 660e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *ext_list_head = ext; 661e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 662e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Insert into the middle or last of the list */ 663e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall do { 664e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext->data.logical < ext_list_tmp->data.logical) 665e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 666e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp = ext_list_tmp->next; 667e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } while (ext_list_tmp != (*ext_list_head)); 668e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext->data.logical < 669e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp->prev->data.logical + 670e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp->prev->data.len) 671e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Overlap */ 672e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 673e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 674e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext_list_tmp != *ext_list_head && 675e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp->data.logical < 676e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext->data.logical + ext->data.len) 677e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Overlap */ 678e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 679e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 680e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp = ext_list_tmp->prev; 681e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Insert "ext" after "ext_list_tmp" */ 682e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall insert(ext_list_tmp, ext); 683e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 684e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallout: 685e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errno = EINVAL; 686e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 687e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 688e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 689e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 690e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * insert_extent_by_physical() - Sequentially insert extent by physical. 691e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 692e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ext_list_head: the head of physical extent list. 693e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ext: the extent element which will be inserted. 694e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 695e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int insert_extent_by_physical(struct fiemap_extent_list **ext_list_head, 696e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *ext) 697e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 698e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *ext_list_tmp = *ext_list_head; 699e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 700e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext == NULL) 701e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 702e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 703e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* First element */ 704e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*ext_list_head == NULL) { 705e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (*ext_list_head) = ext; 706e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (*ext_list_head)->prev = *ext_list_head; 707e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (*ext_list_head)->next = *ext_list_head; 708e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 709e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 710e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 711e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext->data.physical <= ext_list_tmp->data.physical) { 712e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Insert before head */ 713e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext_list_tmp->data.physical < 714e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext->data.physical + ext->data.len) 715e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Overlap */ 716e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 717e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Adjust head */ 718e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *ext_list_head = ext; 719e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 720e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Insert into the middle or last of the list */ 721e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall do { 722e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext->data.physical < ext_list_tmp->data.physical) 723e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 724e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp = ext_list_tmp->next; 725e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } while (ext_list_tmp != (*ext_list_head)); 726e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext->data.physical < 727e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp->prev->data.physical + 728e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp->prev->data.len) 729e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Overlap */ 730e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 731e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 732e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext_list_tmp != *ext_list_head && 733e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp->data.physical < 734e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext->data.physical + ext->data.len) 735e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Overlap */ 736e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 737e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 738e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp = ext_list_tmp->prev; 739e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Insert "ext" after "ext_list_tmp" */ 740e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall insert(ext_list_tmp, ext); 741e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 742e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallout: 743e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errno = EINVAL; 744e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 745e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 746e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 747e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 748e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * insert_exts_group() - Insert a exts_group. 749e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 750e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ext_group_head: the head of a exts_group list. 751e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @exts_group: the exts_group element which will be inserted. 752e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 753e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int insert_exts_group(struct fiemap_extent_group **ext_group_head, 754e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_group *exts_group) 755e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 756e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_group *ext_group_tmp = NULL; 757e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 758e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (exts_group == NULL) { 759e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errno = EINVAL; 760e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 761e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 762e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 763e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Initialize list */ 764e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*ext_group_head == NULL) { 765e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (*ext_group_head) = exts_group; 766e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (*ext_group_head)->prev = *ext_group_head; 767e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (*ext_group_head)->next = *ext_group_head; 768e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 769e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 770e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 771e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_group_tmp = (*ext_group_head)->prev; 772e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall insert(ext_group_tmp, exts_group); 773e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 774e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 775e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 776e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 777e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 778e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * join_extents() - Find continuous region(exts_group). 779e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 780e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ext_list_head: the head of the extent list. 781e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ext_group_head: the head of the target exts_group list. 782e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 783e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int join_extents(struct fiemap_extent_list *ext_list_head, 784e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_group **ext_group_head) 785e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 786e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 len = ext_list_head->data.len; 787e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *ext_list_start = ext_list_head; 788e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *ext_list_tmp = ext_list_head->next; 789e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 790e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall do { 791e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_group *ext_group_tmp = NULL; 792e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 793e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* This extent and previous extent are not continuous, 794e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * so, all previous extents are treated as an extent group. 795e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 796e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((ext_list_tmp->prev->data.logical + 797e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp->prev->data.len) 798e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall != ext_list_tmp->data.logical) { 799e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_group_tmp = 800e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall malloc(sizeof(struct fiemap_extent_group)); 801e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext_group_tmp == NULL) 802e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 803e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 804e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(ext_group_tmp, 0, 805e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sizeof(struct fiemap_extent_group)); 806e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_group_tmp->len = len; 807e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_group_tmp->start = ext_list_start; 808e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_group_tmp->end = ext_list_tmp->prev; 809e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 810e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (insert_exts_group(ext_group_head, 811e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_group_tmp) < 0) { 812e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall FREE(ext_group_tmp); 813e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 814e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 815e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_start = ext_list_tmp; 816e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall len = ext_list_tmp->data.len; 817e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp = ext_list_tmp->next; 818e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 819e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 820e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 821e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* This extent and previous extent are continuous, 822e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * so, they belong to the same extent group, and we check 823e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * if the next extent belongs to the same extent group. 824e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 825e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall len += ext_list_tmp->data.len; 826e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp = ext_list_tmp->next; 827e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } while (ext_list_tmp != ext_list_head->next); 828e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 829e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 830e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 831e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 832e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 833e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * get_file_extents() - Get file's extent list. 834e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 835e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @fd: defrag target file's descriptor. 836e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ext_list_head: the head of the extent list. 837e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 838e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int get_file_extents(int fd, struct fiemap_extent_list **ext_list_head) 839e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 840e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u32 i; 841e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int ret; 842e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int ext_buf_size, fie_buf_size; 843e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 pos = 0; 844e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap *fiemap_buf = NULL; 845e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent *ext_buf = NULL; 846e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *ext_list = NULL; 847e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 848e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Convert units, in bytes. 849e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Be careful : now, physical block number in extent is 48bit, 850e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * and the maximum blocksize for ext4 is 4K(12bit), 851e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * so there is no overflow, but in future it may be changed. 852e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 853e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 854e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Alloc space for fiemap */ 855e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_buf_size = EXTENT_MAX_COUNT * sizeof(struct fiemap_extent); 856e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fie_buf_size = sizeof(struct fiemap) + ext_buf_size; 857e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 858e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fiemap_buf = malloc(fie_buf_size); 859e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fiemap_buf == NULL) 860e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 861e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 862e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_buf = fiemap_buf->fm_extents; 863e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(fiemap_buf, 0, fie_buf_size); 864e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fiemap_buf->fm_length = FIEMAP_MAX_OFFSET; 865e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fiemap_buf->fm_flags |= FIEMAP_FLAG_SYNC; 866e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fiemap_buf->fm_extent_count = EXTENT_MAX_COUNT; 867e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 868e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall do { 869e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fiemap_buf->fm_start = pos; 870e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(ext_buf, 0, ext_buf_size); 871e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = ioctl(fd, FS_IOC_FIEMAP, fiemap_buf); 872e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0 || fiemap_buf->fm_mapped_extents == 0) 873e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 874e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < fiemap_buf->fm_mapped_extents; i++) { 875e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list = NULL; 876e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list = malloc(sizeof(struct fiemap_extent_list)); 877e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext_list == NULL) 878e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 879e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 880e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list->data.physical = ext_buf[i].fe_physical 881e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall / block_size; 882e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list->data.logical = ext_buf[i].fe_logical 883e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall / block_size; 884e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list->data.len = ext_buf[i].fe_length 885e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall / block_size; 886e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 887e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = insert_extent_by_physical( 888e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_head, ext_list); 889e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) { 890e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall FREE(ext_list); 891e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 892e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 893e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 894e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Record file's logical offset this time */ 895e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall pos = ext_buf[EXTENT_MAX_COUNT-1].fe_logical + 896e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_buf[EXTENT_MAX_COUNT-1].fe_length; 897e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 898e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * If fm_extents array has been filled and 899e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * there are extents left, continue to cycle. 900e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 901e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } while (fiemap_buf->fm_mapped_extents 902e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall == EXTENT_MAX_COUNT && 903e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !(ext_buf[EXTENT_MAX_COUNT-1].fe_flags 904e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall & FIEMAP_EXTENT_LAST)); 905e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 906e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall FREE(fiemap_buf); 907e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 908e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallout: 909e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall FREE(fiemap_buf); 910e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 911e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 912e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 913e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 914e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * get_logical_count() - Get the file logical extents count. 915e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 916e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @logical_list_head: the head of the logical extent list. 917e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 918e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int get_logical_count(struct fiemap_extent_list *logical_list_head) 919e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 920e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int ret = 0; 921e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *ext_list_tmp = logical_list_head; 922e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 923e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall do { 924e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret++; 925e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp = ext_list_tmp->next; 926e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } while (ext_list_tmp != logical_list_head); 927e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 928e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ret; 929e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 930e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 931e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 932e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * get_physical_count() - Get the file physical extents count. 933e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 934e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @physical_list_head: the head of the physical extent list. 935e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 936e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int get_physical_count(struct fiemap_extent_list *physical_list_head) 937e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 938e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int ret = 0; 939e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *ext_list_tmp = physical_list_head; 940e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 941e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall do { 942e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((ext_list_tmp->data.physical + ext_list_tmp->data.len) 943e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall != ext_list_tmp->next->data.physical) { 944e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* This extent and next extent are not continuous. */ 945e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret++; 946e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 947e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 948e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp = ext_list_tmp->next; 949e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } while (ext_list_tmp != physical_list_head); 950e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 951e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ret; 952e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 953e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 954e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 955e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * change_physical_to_logical() - Change list from physical to logical. 956e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 957e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @physical_list_head: the head of physical extent list. 958e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @logical_list_head: the head of logical extent list. 959e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 960e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int change_physical_to_logical( 961e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list **physical_list_head, 962e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list **logical_list_head) 963e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 964e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int ret; 965e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *ext_list_tmp = *physical_list_head; 966e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *ext_list_next = ext_list_tmp->next; 967e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 968e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (1) { 969e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext_list_tmp == ext_list_next) { 970e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = insert_extent_by_logical( 971e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall logical_list_head, ext_list_tmp); 972e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) 973e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 974e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 975e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *physical_list_head = NULL; 976e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 977e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 978e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 979e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp->prev->next = ext_list_tmp->next; 980e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp->next->prev = ext_list_tmp->prev; 981e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *physical_list_head = ext_list_next; 982e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 983e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = insert_extent_by_logical( 984e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall logical_list_head, ext_list_tmp); 985e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) { 986e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall FREE(ext_list_tmp); 987e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 988e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 989e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp = ext_list_next; 990e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_next = ext_list_next->next; 991e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 992e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 993e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 994e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 995e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 996e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* get_file_blocks() - Get total file blocks. 997e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 998e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ext_list_head: the extent list head of the target file 999e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 1000e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic ext4_fsblk_t get_file_blocks(struct fiemap_extent_list *ext_list_head) 1001e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 1002e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext4_fsblk_t blk_count = 0; 1003e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *ext_list_tmp = ext_list_head; 1004e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1005e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall do { 1006e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk_count += ext_list_tmp->data.len; 1007e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp = ext_list_tmp->next; 1008e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } while (ext_list_tmp != ext_list_head); 1009e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1010e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return blk_count; 1011e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 1012e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1013e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 1014e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * free_ext() - Free the extent list. 1015e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 1016e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ext_list_head: the extent list head of which will be free. 1017e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 1018e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void free_ext(struct fiemap_extent_list *ext_list_head) 1019e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 1020e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *ext_list_tmp = NULL; 1021e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1022e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext_list_head == NULL) 1023e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 1024e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1025e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (ext_list_head->next != ext_list_head) { 1026e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp = ext_list_head; 1027e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_head->prev->next = ext_list_head->next; 1028e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_head->next->prev = ext_list_head->prev; 1029e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_head = ext_list_head->next; 1030e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free(ext_list_tmp); 1031e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1032e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free(ext_list_head); 1033e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 1034e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1035e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 1036e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * free_exts_group() - Free the exts_group. 1037e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 1038e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @*ext_group_head: the exts_group list head which will be free. 1039e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 1040e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void free_exts_group(struct fiemap_extent_group *ext_group_head) 1041e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 1042e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_group *ext_group_tmp = NULL; 1043e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1044e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext_group_head == NULL) 1045e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 1046e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1047e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (ext_group_head->next != ext_group_head) { 1048e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_group_tmp = ext_group_head; 1049e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_group_head->prev->next = ext_group_head->next; 1050e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_group_head->next->prev = ext_group_head->prev; 1051e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_group_head = ext_group_head->next; 1052e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free(ext_group_tmp); 1053e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1054e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free(ext_group_head); 1055e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 1056e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1057e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 1058e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * get_best_count() - Get the file best extents count. 1059e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 1060e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @block_count: the file's physical block count. 1061e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 1062e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int get_best_count(ext4_fsblk_t block_count) 1063e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 1064e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int ret; 1065e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int flex_bg_num; 1066e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1067e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Calcuate best extents count */ 1068e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) { 1069e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall flex_bg_num = 1 << log_groups_per_flex; 1070e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = ((block_count - 1) / 1071e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ((ext4_fsblk_t)blocks_per_group * 1072e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall flex_bg_num)) + 1; 1073e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else 1074e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = ((block_count - 1) / blocks_per_group) + 1; 1075e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1076e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ret; 1077e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 1078e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1079e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1080e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 1081e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * file_statistic() - Get statistic info of the file's fragments. 1082e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 1083e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @file: the file's name. 1084e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @buf: the pointer of the struct stat64. 1085e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @flag: file type. 1086e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ftwbuf: the pointer of a struct FTW. 1087e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 1088e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int file_statistic(const char *file, const struct stat64 *buf, 1089e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int flag EXT2FS_ATTR((unused)), 1090e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct FTW *ftwbuf EXT2FS_ATTR((unused))) 1091e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 1092e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int fd; 1093e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int ret; 1094e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int now_ext_count, best_ext_count = 0, physical_ext_count; 1095e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int i, j; 1096e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 size_per_ext = 0; 1097e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall float ratio = 0.0; 1098e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext4_fsblk_t blk_count = 0; 1099e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char msg_buffer[PATH_MAX + 24]; 1100e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *physical_list_head = NULL; 1101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *logical_list_head = NULL; 1102e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall defraged_file_count++; 1104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (total_count == 1 && regular_count == 1) 1107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("<File>\n"); 1108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else { 1109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("[%u/%u]", defraged_file_count, total_count); 1110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fflush(stdout); 1111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1113e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (lost_found_dir[0] != '\0' && 1114e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !memcmp(file, lost_found_dir, strnlen(lost_found_dir, PATH_MAX))) { 1115e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1117e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall STATISTIC_ERR_MSG(NGMSG_LOST_FOUND); 1118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1119e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 1120e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1121e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1122e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!S_ISREG(buf->st_mode)) { 1123e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1124e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall STATISTIC_ERR_MSG(NGMSG_FILE_UNREG); 1126e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1127e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 1128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1129e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1130e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Access authority */ 1131e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (current_uid != ROOT_UID && 1132e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall buf->st_uid != current_uid) { 1133e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1134e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1135e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall STATISTIC_ERR_MSG( 1136e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "File is not current user's file" 1137e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall " or current user is not root"); 1138e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1139e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 1140e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1141e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1142e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Empty file */ 1143e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (buf->st_size == 0) { 1144e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1145e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1146e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall STATISTIC_ERR_MSG("File size is 0"); 1147e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1148e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 1149e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1150e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1151e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Has no blocks */ 1152e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (buf->st_blocks == 0) { 1153e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1154e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1155e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall STATISTIC_ERR_MSG("File has no blocks"); 1156e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1157e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 1158e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1159e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fd = open64(file, O_RDONLY); 1161e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fd < 0) { 1162e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1164e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall STATISTIC_ERR_MSG_WITH_ERRNO(NGMSG_FILE_OPEN); 1165e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1166e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 1167e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1168e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1169e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Get file's physical extents */ 1170e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = get_file_extents(fd, &physical_list_head); 1171e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) { 1172e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1173e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1174e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall STATISTIC_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); 1175e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1176e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1177e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1178e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1179e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Get the count of file's continuous physical region */ 1180e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall physical_ext_count = get_physical_count(physical_list_head); 1181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1182e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Change list from physical to logical */ 1183e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = change_physical_to_logical(&physical_list_head, 1184e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall &logical_list_head); 1185e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) { 1186e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1187e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1188e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall STATISTIC_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); 1189e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1190e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1191e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1192e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1193e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Count file fragments before defrag */ 1194e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall now_ext_count = get_logical_count(logical_list_head); 1195e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1196e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (current_uid == ROOT_UID) { 1197e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Calculate the size per extent */ 1198e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk_count = get_file_blocks(logical_list_head); 1199e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1200e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall best_ext_count = get_best_count(blk_count); 1201e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* e4defrag rounds size_per_ext up to a block size boundary */ 1203e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall size_per_ext = blk_count * (buf->st_blksize / 1024) / 1204e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall now_ext_count; 1205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1206e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ratio = (float)(physical_ext_count - best_ext_count) * 100 / 1207e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk_count; 1208e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1209e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extents_before_defrag += now_ext_count; 1210e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extents_after_defrag += best_ext_count; 1211e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall files_block_count += blk_count; 1212e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1213e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1214e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (total_count == 1 && regular_count == 1) { 1215e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* File only */ 1216e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int count = 0; 1218e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *ext_list_tmp = 1219e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall logical_list_head; 1220e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1221e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Print extents info */ 1222e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall do { 1223e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall count++; 1224e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("[ext %d]:\tstart %llu:\tlogical " 1225e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "%llu:\tlen %llu\n", count, 1226e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp->data.physical, 1227e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp->data.logical, 1228e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp->data.len); 1229e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp = ext_list_tmp->next; 1230e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } while (ext_list_tmp != logical_list_head); 1231e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1232e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 1233e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("%-40s%10s/%-10s%9s\n", 1234e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "<File>", "now", "best", "size/ext"); 1235e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (current_uid == ROOT_UID) { 1236e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (strlen(file) > 40) 1237e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("%s\n%50d/%-10d%6llu KB\n", 1238e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall file, now_ext_count, 1239e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall best_ext_count, size_per_ext); 1240e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 1241e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("%-40s%10d/%-10d%6llu KB\n", 1242e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall file, now_ext_count, 1243e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall best_ext_count, size_per_ext); 1244e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 1245e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (strlen(file) > 40) 1246e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("%s\n%50d/%-10s%7s\n", 1247e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall file, now_ext_count, 1248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "-", "-"); 1249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 1250e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("%-40s%10d/%-10s%7s\n", 1251e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall file, now_ext_count, 1252e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "-", "-"); 1253e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1254e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1255e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall succeed_cnt++; 1256e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1257e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1258e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1259e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1260e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Print statistic info */ 1261e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sprintf(msg_buffer, "[%u/%u]%s", 1262e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall defraged_file_count, total_count, file); 1263e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (current_uid == ROOT_UID) { 1264e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (strlen(msg_buffer) > 40) 1265e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\033[79;0H\033[K%s\n" 1266e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "%50d/%-10d%6llu KB\n", 1267e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall msg_buffer, now_ext_count, 1268e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall best_ext_count, size_per_ext); 1269e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 1270e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\033[79;0H\033[K%-40s" 1271e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "%10d/%-10d%6llu KB\n", 1272e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall msg_buffer, now_ext_count, 1273e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall best_ext_count, size_per_ext); 1274e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 1275e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (strlen(msg_buffer) > 40) 1276e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\033[79;0H\033[K%s\n%50d/%-10s%7s\n", 1277e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall msg_buffer, now_ext_count, 1278e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "-", "-"); 1279e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 1280e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\033[79;0H\033[K%-40s%10d/%-10s%7s\n", 1281e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall msg_buffer, now_ext_count, 1282e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "-", "-"); 1283e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1284e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1285e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1286e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < SHOW_FRAG_FILES; i++) { 1287e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ratio >= frag_rank[i].ratio) { 1288e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (j = SHOW_FRAG_FILES - 1; j > i; j--) { 1289e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(&frag_rank[j], 0, 1290e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sizeof(struct frag_statistic_ino)); 1291e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncpy(frag_rank[j].msg_buffer, 1292e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j - 1].msg_buffer, 1293e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strnlen(frag_rank[j - 1].msg_buffer, 1294e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PATH_MAX)); 1295e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j].now_count = 1296e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j - 1].now_count; 1297e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j].best_count = 1298e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j - 1].best_count; 1299e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j].size_per_ext = 1300e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j - 1].size_per_ext; 1301e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j].ratio = 1302e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j - 1].ratio; 1303e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1304e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(&frag_rank[i], 0, 1305e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sizeof(struct frag_statistic_ino)); 1306e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncpy(frag_rank[i].msg_buffer, file, 1307e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strnlen(file, PATH_MAX)); 1308e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[i].now_count = now_ext_count; 1309e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[i].best_count = best_ext_count; 1310e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[i].size_per_ext = size_per_ext; 1311e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[i].ratio = ratio; 1312e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 1313e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1314e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1315e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1316e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall succeed_cnt++; 1317e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1318e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallout: 1319e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall close(fd); 1320e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free_ext(physical_list_head); 1321e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free_ext(logical_list_head); 1322e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 1323e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 1324e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1325e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 1326e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * print_progress - Print defrag progress 1327e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 1328e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @file: file name. 1329e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @start: logical offset for defrag target file 1330e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @file_size: defrag target filesize 1331e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 1332e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void print_progress(const char *file, loff_t start, loff_t file_size) 1333e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 1334e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int percent = (start * 100) / file_size; 1335e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\033[79;0H\033[K[%u/%u]%s:\t%3d%%", 1336e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall defraged_file_count, total_count, file, min(percent, 100)); 1337e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fflush(stdout); 1338e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1339e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 1340e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 1341e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1342e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 1343e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * call_defrag() - Execute the defrag program. 1344e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 1345e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @fd: target file descriptor. 1346e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @donor_fd: donor file descriptor. 1347e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @file: target file name. 1348e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @buf: pointer of the struct stat64. 1349e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ext_list_head: head of the extent list. 1350e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 1351e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int call_defrag(int fd, int donor_fd, const char *file, 1352e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const struct stat64 *buf, struct fiemap_extent_list *ext_list_head) 1353e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 1354e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall loff_t start = 0; 1355e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int page_num; 1356e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned char *vec = NULL; 1357e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int defraged_ret = 0; 1358e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int ret; 1359e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct move_extent move_data; 1360e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *ext_list_tmp = NULL; 1361e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1362e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(&move_data, 0, sizeof(struct move_extent)); 1363e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall move_data.donor_fd = donor_fd; 1364e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1365e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Print defrag progress */ 1366e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_progress(file, start, buf->st_size); 1367e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1368e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp = ext_list_head; 1369e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall do { 1370e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall move_data.orig_start = ext_list_tmp->data.logical; 1371e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Logical offset of orig and donor should be same */ 1372e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall move_data.donor_start = move_data.orig_start; 1373e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall move_data.len = ext_list_tmp->data.len; 1374e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall move_data.moved_len = 0; 1375e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1376e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = page_in_core(fd, move_data, &vec, &page_num); 1377e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) { 1378e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1379e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\n"); 1380e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO( 1381e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "Failed to get file map"); 1382e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 1383e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\t[ NG ]\n"); 1384e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1385e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 1386e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1387e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1388e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* EXT4_IOC_MOVE_EXT */ 1389e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall defraged_ret = 1390e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ioctl(fd, EXT4_IOC_MOVE_EXT, &move_data); 1391e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1392e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Free pages */ 1393e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = defrag_fadvise(fd, move_data, vec, page_num); 1394e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (vec) { 1395e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free(vec); 1396e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall vec = NULL; 1397e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1398e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) { 1399e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1400e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\n"); 1401e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO( 1402e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "Failed to free page"); 1403e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 1404e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\t[ NG ]\n"); 1405e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1406e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 1407e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1408e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1409e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (defraged_ret < 0) { 1410e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1411e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\n"); 1412e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO( 1413e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "Failed to defrag with " 1414e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "EXT4_IOC_MOVE_EXT ioctl"); 1415e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (errno == ENOTTY) 1416e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\tAt least 2.6.31-rc1 of " 1417e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "vanilla kernel is required\n"); 1418e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 1419e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\t[ NG ]\n"); 1420e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1421e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 1422e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1423e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Adjust logical offset for next ioctl */ 1424e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall move_data.orig_start += move_data.moved_len; 1425e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall move_data.donor_start = move_data.orig_start; 1426e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1427e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall start = move_data.orig_start * buf->st_blksize; 1428e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1429e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Print defrag progress */ 1430e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_progress(file, start, buf->st_size); 1431e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1432e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* End of file */ 1433e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (start >= buf->st_size) 1434e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 1435e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1436e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext_list_tmp = ext_list_tmp->next; 1437e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } while (ext_list_tmp != ext_list_head); 1438e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1439e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 1440e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 1441e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1442e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 1443e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * file_defrag() - Check file attributes and call ioctl to defrag. 1444e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 1445e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @file: the file's name. 1446e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @buf: the pointer of the struct stat64. 1447e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @flag: file type. 1448e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @ftwbuf: the pointer of a struct FTW. 1449e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 1450e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int file_defrag(const char *file, const struct stat64 *buf, 1451e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int flag EXT2FS_ATTR((unused)), 1452e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct FTW *ftwbuf EXT2FS_ATTR((unused))) 1453e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 1454e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int fd; 1455e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int donor_fd = -1; 1456e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int ret; 1457e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int best; 1458e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int file_frags_start, file_frags_end; 1459e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int orig_physical_cnt, donor_physical_cnt = 0; 1460e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char tmp_inode_name[PATH_MAX + 8]; 1461e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext4_fsblk_t blk_count = 0; 1462e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *orig_list_physical = NULL; 1463e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *orig_list_logical = NULL; 1464e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *donor_list_physical = NULL; 1465e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_list *donor_list_logical = NULL; 1466e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_group *orig_group_head = NULL; 1467e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct fiemap_extent_group *orig_group_tmp = NULL; 1468e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1469e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall defraged_file_count++; 1470e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1471e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1472e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("[%u/%u]", defraged_file_count, total_count); 1473e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fflush(stdout); 1474e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1475e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1476e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (lost_found_dir[0] != '\0' && 1477e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !memcmp(file, lost_found_dir, strnlen(lost_found_dir, PATH_MAX))) { 1478e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1479e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1480e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall IN_FTW_PRINT_ERR_MSG(NGMSG_LOST_FOUND); 1481e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1482e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 1483e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1484e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1485e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!S_ISREG(buf->st_mode)) { 1486e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1487e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1488e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall IN_FTW_PRINT_ERR_MSG(NGMSG_FILE_UNREG); 1489e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1490e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 1491e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1492e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1493e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Empty file */ 1494e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (buf->st_size == 0) { 1495e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1496e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1497e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall IN_FTW_PRINT_ERR_MSG("File size is 0"); 1498e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1499e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 1500e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1501e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1502e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Has no blocks */ 1503e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (buf->st_blocks == 0) { 1504e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1505e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1506e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall STATISTIC_ERR_MSG("File has no blocks"); 1507e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1508e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 1509e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1510e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1511e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fd = open64(file, O_RDWR); 1512e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fd < 0) { 1513e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1514e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1515e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_OPEN); 1516e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1517e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 1518e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1519e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1520e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Get file's extents */ 1521e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = get_file_extents(fd, &orig_list_physical); 1522e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) { 1523e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1524e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1525e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); 1526e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1527e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1528e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1529e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1530e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Get the count of file's continuous physical region */ 1531e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall orig_physical_cnt = get_physical_count(orig_list_physical); 1532e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1533e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Change list from physical to logical */ 1534e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = change_physical_to_logical(&orig_list_physical, 1535e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall &orig_list_logical); 1536e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) { 1537e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1538e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1539e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); 1540e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1541e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1542e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1543e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1544e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Count file fragments before defrag */ 1545e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall file_frags_start = get_logical_count(orig_list_logical); 1546e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1547e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk_count = get_file_blocks(orig_list_logical); 1548e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (file_check(fd, buf, file, file_frags_start, blk_count) < 0) 1549e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1550e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1551e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fsync(fd) < 0) { 1552e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1553e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1554e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO("Failed to sync(fsync)"); 1555e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1556e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1557e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1558e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1559e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (current_uid == ROOT_UID) 1560e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall best = get_best_count(blk_count); 1561e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 1562e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall best = 1; 1563e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1564e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (file_frags_start <= best) 1565e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto check_improvement; 1566e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1567e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Combine extents to group */ 1568e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = join_extents(orig_list_logical, &orig_group_head); 1569e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) { 1570e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1571e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1572e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); 1573e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1574e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1575e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1576e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1577e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Create donor inode */ 1578e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(tmp_inode_name, 0, PATH_MAX + 8); 1579e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sprintf(tmp_inode_name, "%.*s.defrag", 1580e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (int)strnlen(file, PATH_MAX), file); 1581e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall donor_fd = open64(tmp_inode_name, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR); 1582e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (donor_fd < 0) { 1583e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1584e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1585e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (errno == EEXIST) 1586e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO( 1587e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "File is being defraged by other program"); 1588e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 1589e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_OPEN); 1590e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1591e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1592e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1593e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1594e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Unlink donor inode */ 1595e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = unlink(tmp_inode_name); 1596e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) { 1597e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1598e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1599e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO("Failed to unlink"); 1600e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1601e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1602e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1603e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1604e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Allocate space for donor inode */ 1605e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall orig_group_tmp = orig_group_head; 1606e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall do { 1607e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = fallocate64(donor_fd, 0, 1608e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (loff_t)orig_group_tmp->start->data.logical * block_size, 1609e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (loff_t)orig_group_tmp->len * block_size); 1610e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) { 1611e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1612e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1613e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO("Failed to fallocate"); 1614e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1615e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1616e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1617e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1618e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall orig_group_tmp = orig_group_tmp->next; 1619e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } while (orig_group_tmp != orig_group_head); 1620e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1621e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Get donor inode's extents */ 1622e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = get_file_extents(donor_fd, &donor_list_physical); 1623e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) { 1624e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1625e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1626e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); 1627e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1628e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1629e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1630e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1631e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Calcuate donor inode's continuous physical region */ 1632e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall donor_physical_cnt = get_physical_count(donor_list_physical); 1633e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1634e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Change donor extent list from physical to logical */ 1635e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = change_physical_to_logical(&donor_list_physical, 1636e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall &donor_list_logical); 1637e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) { 1638e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1639e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(file); 1640e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); 1641e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1642e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1643e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1644e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1645e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallcheck_improvement: 1646e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1647e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (file_frags_start != 1) 1648e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_files_before_defrag++; 1649e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1650e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extents_before_defrag += file_frags_start; 1651e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1652e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1653e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (file_frags_start <= best || 1654e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall orig_physical_cnt <= donor_physical_cnt) { 1655e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\033[79;0H\033[K[%u/%u]%s:\t%3d%%", 1656e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall defraged_file_count, total_count, file, 100); 1657e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) 1658e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf(" extents: %d -> %d", 1659e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall file_frags_start, file_frags_start); 1660e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1661e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\t[ OK ]\n"); 1662e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall succeed_cnt++; 1663e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1664e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (file_frags_start != 1) 1665e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_files_after_defrag++; 1666e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1667e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extents_after_defrag += file_frags_start; 1668e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1669e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1670e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1671e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Defrag the file */ 1672e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = call_defrag(fd, donor_fd, file, buf, donor_list_logical); 1673e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1674e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Count file fragments after defrag and print extents info */ 1675e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1676e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall file_frags_end = file_frag_count(fd); 1677e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (file_frags_end < 0) { 1678e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\n"); 1679e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_INFO); 1680e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1681e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1682e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1683e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (file_frags_end != 1) 1684e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_files_after_defrag++; 1685e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1686e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extents_after_defrag += file_frags_end; 1687e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1688e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) 1689e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1690e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1691e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf(" extents: %d -> %d", 1692e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall file_frags_start, file_frags_end); 1693e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fflush(stdout); 1694e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1695e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1696e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret < 0) 1697e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1698e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1699e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\t[ OK ]\n"); 1700e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fflush(stdout); 1701e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall succeed_cnt++; 1702e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1703e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallout: 1704e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall close(fd); 1705e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (donor_fd != -1) 1706e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall close(donor_fd); 1707e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free_ext(orig_list_physical); 1708e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free_ext(orig_list_logical); 1709e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free_ext(donor_list_physical); 1710e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free_exts_group(orig_group_head); 1711e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 1712e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 1713e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1714e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 1715e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * main() - Ext4 online defrag. 1716e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 1717e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @argc: the number of parameter. 1718e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * @argv[]: the pointer array of parameter. 1719e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 1720e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallint main(int argc, char *argv[]) 1721e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 1722e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int opt; 1723e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int i, j, ret = 0; 1724e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int flags = FTW_PHYS | FTW_MOUNT; 1725e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int arg_type = -1; 1726e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int success_flag = 0; 1727e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char dir_name[PATH_MAX + 1]; 1728e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char dev_name[PATH_MAX + 1]; 1729e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct stat64 buf; 1730e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_filsys fs = NULL; 1731e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1732e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Parse arguments */ 1733e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (argc == 1) 1734e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1735e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1736e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while ((opt = getopt(argc, argv, "vc")) != EOF) { 1737e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall switch (opt) { 1738e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall case 'v': 1739e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall mode_flag |= DETAIL; 1740e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 1741e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall case 'c': 1742e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall mode_flag |= STATISTIC; 1743e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 1744e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall default: 1745e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1746e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1747e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1748e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1749e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (argc == optind) 1750e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out; 1751e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1752e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall current_uid = getuid(); 1753e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1754e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Main process */ 1755e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = optind; i < argc; i++) { 1756e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall succeed_cnt = 0; 1757e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall regular_count = 0; 1758e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall total_count = 0; 1759e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_files_before_defrag = 0; 1760e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_files_after_defrag = 0; 1761e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extents_before_defrag = 0; 1762e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extents_after_defrag = 0; 1763e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall defraged_file_count = 0; 1764e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall files_block_count = 0; 1765e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blocks_per_group = 0; 1766e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall feature_incompat = 0; 1767e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_groups_per_flex = 0; 1768e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1769e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(dir_name, 0, PATH_MAX + 1); 1770e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(dev_name, 0, PATH_MAX + 1); 1771e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(lost_found_dir, 0, PATH_MAX + 1); 1772e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(frag_rank, 0, 1773e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sizeof(struct frag_statistic_ino) * SHOW_FRAG_FILES); 1774e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1775e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((mode_flag & STATISTIC) && i > optind) 1776e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\n"); 1777e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1778e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#if BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN 1779e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG("Endian's type is not big/little endian"); 1780e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(argv[i]); 1781e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 1782e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 1783e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1784e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (lstat64(argv[i], &buf) < 0) { 1785e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror(NGMSG_FILE_INFO); 1786e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(argv[i]); 1787e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 1788e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1789e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1790e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Handle i.e. lvm device symlinks */ 1791e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (S_ISLNK(buf.st_mode)) { 1792e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct stat64 buf2; 1793e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1794e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (stat64(argv[i], &buf2) == 0 && 1795e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall S_ISBLK(buf2.st_mode)) 1796e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall buf = buf2; 1797e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1798e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1799e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (S_ISBLK(buf.st_mode)) { 1800e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Block device */ 1801e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncpy(dev_name, argv[i], strnlen(argv[i], PATH_MAX)); 1802e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (get_mount_point(argv[i], dir_name, PATH_MAX) < 0) 1803e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 1804e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (lstat64(dir_name, &buf) < 0) { 1805e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror(NGMSG_FILE_INFO); 1806e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(argv[i]); 1807e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 1808e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1809e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall arg_type = DEVNAME; 1810e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!(mode_flag & STATISTIC)) 1811e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("ext4 defragmentation for device(%s)\n", 1812e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall argv[i]); 1813e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else if (S_ISDIR(buf.st_mode)) { 1814e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Directory */ 1815e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (access(argv[i], R_OK) < 0) { 1816e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror(argv[i]); 1817e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 1818e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1819e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall arg_type = DIRNAME; 1820e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncpy(dir_name, argv[i], strnlen(argv[i], PATH_MAX)); 1821e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else if (S_ISREG(buf.st_mode)) { 1822e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Regular file */ 1823e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall arg_type = FILENAME; 1824e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 1825e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Irregular file */ 1826e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG(NGMSG_FILE_UNREG); 1827e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(argv[i]); 1828e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 1829e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1830e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1831e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Set blocksize */ 1832e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall block_size = buf.st_blksize; 1833e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1834e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* For device case, 1835e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * filesystem type checked in get_mount_point() 1836e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 1837e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (arg_type == FILENAME || arg_type == DIRNAME) { 1838e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (is_ext4(argv[i], dev_name) < 0) 1839e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 1840e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (realpath(argv[i], dir_name) == NULL) { 1841e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror("Couldn't get full path"); 1842e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(argv[i]); 1843e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 1844e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1845e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1846e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1847e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (current_uid == ROOT_UID) { 1848e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Get super block info */ 1849e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret = ext2fs_open(dev_name, 0, 0, block_size, 1850e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unix_io_manager, &fs); 1851e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ret) { 1852e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1853e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror("Can't get super block info"); 1854e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(argv[i]); 1855e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1856e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 1857e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1858e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1859e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blocks_per_group = fs->super->s_blocks_per_group; 1860e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall feature_incompat = fs->super->s_feature_incompat; 1861e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_groups_per_flex = fs->super->s_log_groups_per_flex; 1862e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1863e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_close(fs); 1864e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1865e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1866e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall switch (arg_type) { 1867e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int mount_dir_len = 0; 1868e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1869e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall case DIRNAME: 1870e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!(mode_flag & STATISTIC)) 1871e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("ext4 defragmentation " 1872e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "for directory(%s)\n", argv[i]); 1873e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1874e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall mount_dir_len = strnlen(lost_found_dir, PATH_MAX); 1875e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1876e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncat(lost_found_dir, "/lost+found", 1877e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PATH_MAX - strnlen(lost_found_dir, PATH_MAX)); 1878e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1879e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Not the case("e4defrag mount_piont_dir") */ 1880e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (dir_name[mount_dir_len] != '\0') { 1881e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 1882e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * "e4defrag mount_piont_dir/lost+found" 1883e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * or "e4defrag mount_piont_dir/lost+found/" 1884e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 1885e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (strncmp(lost_found_dir, dir_name, 1886e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strnlen(lost_found_dir, 1887e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PATH_MAX)) == 0 && 1888e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (dir_name[strnlen(lost_found_dir, 1889e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PATH_MAX)] == '\0' || 1890e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dir_name[strnlen(lost_found_dir, 1891e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PATH_MAX)] == '/')) { 1892e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG(NGMSG_LOST_FOUND); 1893e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(argv[i]); 1894e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 1895e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1896e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1897e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* "e4defrag mount_piont_dir/else_dir" */ 1898e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(lost_found_dir, 0, PATH_MAX + 1); 1899e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1900e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall case DEVNAME: 1901e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (arg_type == DEVNAME) { 1902e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncpy(lost_found_dir, dir_name, 1903e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strnlen(dir_name, PATH_MAX)); 1904e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncat(lost_found_dir, "/lost+found/", 1905e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PATH_MAX - strnlen(lost_found_dir, 1906e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PATH_MAX)); 1907e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1908e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1909e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall nftw64(dir_name, calc_entry_counts, FTW_OPEN_FD, flags); 1910e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1911e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & STATISTIC) { 1912e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) 1913e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("%-40s%10s/%-10s%9s\n", 1914e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "<File>", "now", "best", "size/ext"); 1915e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1916e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!(mode_flag & DETAIL) && 1917e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall current_uid != ROOT_UID) { 1918e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf(" Done.\n"); 1919e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall success_flag = 1; 1920e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 1921e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1922e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1923e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall nftw64(dir_name, file_statistic, 1924e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall FTW_OPEN_FD, flags); 1925e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1926e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (succeed_cnt != 0 && 1927e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall current_uid == ROOT_UID) { 1928e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) 1929e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\n"); 1930e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("%-40s%10s/%-10s%9s\n", 1931e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "<Fragmented files>", "now", 1932e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "best", "size/ext"); 1933e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (j = 0; j < SHOW_FRAG_FILES; j++) { 1934e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (strlen(frag_rank[j]. 1935e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall msg_buffer) > 37) { 1936e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("%d. %s\n%50d/" 1937e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "%-10d%6llu KB\n", 1938e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall j + 1, 1939e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j].msg_buffer, 1940e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j].now_count, 1941e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j].best_count, 1942e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j]. 1943e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall size_per_ext); 1944e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else if (strlen(frag_rank[j]. 1945e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall msg_buffer) > 0) { 1946e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("%d. %-37s%10d/" 1947e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "%-10d%6llu KB\n", 1948e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall j + 1, 1949e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j].msg_buffer, 1950e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j].now_count, 1951e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j].best_count, 1952e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_rank[j]. 1953e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall size_per_ext); 1954e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else 1955e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 1956e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1957e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1958e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 1959e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1960e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* File tree walk */ 1961e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall nftw64(dir_name, file_defrag, FTW_OPEN_FD, flags); 1962e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\n\tSuccess:\t\t\t[ %u/%u ]\n", succeed_cnt, 1963e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall total_count); 1964e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\tFailure:\t\t\t[ %u/%u ]\n", 1965e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall total_count - succeed_cnt, total_count); 1966e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) { 1967e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\tTotal extents:\t\t\t%4d->%d\n", 1968e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extents_before_defrag, 1969e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extents_after_defrag); 1970e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\tFragmented percentage:\t\t" 1971e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "%3llu%%->%llu%%\n", 1972e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !regular_count ? 0 : 1973e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ((unsigned long long) 1974e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_files_before_defrag * 100) / 1975e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall regular_count, 1976e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !regular_count ? 0 : 1977e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ((unsigned long long) 1978e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall frag_files_after_defrag * 100) / 1979e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall regular_count); 1980e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1981e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 1982e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall case FILENAME: 1983e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall total_count = 1; 1984e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall regular_count = 1; 1985e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncat(lost_found_dir, "/lost+found/", 1986e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PATH_MAX - strnlen(lost_found_dir, 1987e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PATH_MAX)); 1988e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (strncmp(lost_found_dir, dir_name, 1989e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strnlen(lost_found_dir, 1990e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PATH_MAX)) == 0) { 1991e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_ERR_MSG(NGMSG_LOST_FOUND); 1992e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall PRINT_FILE_NAME(argv[i]); 1993e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 1994e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1995e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1996e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & STATISTIC) { 1997e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall file_statistic(argv[i], &buf, FTW_F, NULL); 1998e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 1999e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else 2000e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("ext4 defragmentation for %s\n", 2001e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall argv[i]); 2002e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Defrag single file process */ 2003e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall file_defrag(argv[i], &buf, FTW_F, NULL); 2004e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (succeed_cnt != 0) 2005e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf(" Success:\t\t\t[1/1]\n"); 2006e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 2007e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf(" Success:\t\t\t[0/1]\n"); 2008e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2009e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 2010e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 2011e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2012e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (succeed_cnt != 0) 2013e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall success_flag = 1; 2014e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & STATISTIC) { 2015e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (current_uid != ROOT_UID) { 2016e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf(" Done.\n"); 2017e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 2018e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 2019e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2020e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!succeed_cnt) { 2021e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (mode_flag & DETAIL) 2022e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\n"); 2023e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2024e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (arg_type == DEVNAME) 2025e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf(" In this device(%s), " 2026e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "none can be defragmented.\n", argv[i]); 2027e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (arg_type == DIRNAME) 2028e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf(" In this directory(%s), " 2029e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "none can be defragmented.\n", argv[i]); 2030e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 2031e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf(" This file(%s) " 2032e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "can't be defragmented.\n", argv[i]); 2033e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 2034e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall float files_ratio = 0.0; 2035e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall float score = 0.0; 2036e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 size_per_ext = files_block_count * 2037e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (buf.st_blksize / 1024) / 2038e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extents_before_defrag; 2039e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall files_ratio = (float)(extents_before_defrag - 2040e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extents_after_defrag) * 2041e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 100 / files_block_count; 2042e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall score = CALC_SCORE(files_ratio); 2043e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("\n Total/best extents\t\t\t\t%d/%d\n" 2044e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall " Average size per extent" 2045e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "\t\t\t%llu KB\n" 2046e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall " Fragmentation score\t\t\t\t%.0f\n", 2047e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extents_before_defrag, 2048e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extents_after_defrag, 2049e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall size_per_ext, score); 2050e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf(" [0-30 no problem:" 2051e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall " 31-55 a little bit fragmented:" 2052e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall " 56- needs defrag]\n"); 2053e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2054e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (arg_type == DEVNAME) 2055e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf(" This device (%s) ", argv[i]); 2056e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (arg_type == DIRNAME) 2057e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf(" This directory (%s) ", 2058e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall argv[i]); 2059e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 2060e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf(" This file (%s) ", argv[i]); 2061e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2062e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (score > BOUND_SCORE) 2063e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("needs defragmentation.\n"); 2064e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 2065e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("does not need " 2066e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "defragmentation.\n"); 2067e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 2068e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf(" Done.\n"); 2069e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 2070e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2071e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 2072e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2073e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (success_flag) 2074e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 2075e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2076e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall exit(1); 2077e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2078e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallout: 2079e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf(MSG_USAGE); 2080e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall exit(1); 2081e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 2082e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2083