e4defrag.c revision f404167dda29a59d2be2882328aeb074b9899669
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * e4defrag.c - ext4 filesystem defragmenter 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 2009 NEC Software Tohoku, Ltd. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Author: Akira Fujita <a-fujita@rs.jp.nec.com> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Takashi Sato <t-sato@yk.jp.nec.com> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef _LARGEFILE_SOURCE 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _LARGEFILE_SOURCE 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#ifndef _LARGEFILE64_SOURCE 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#define _LARGEFILE64_SOURCE 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#ifndef _GNU_SOURCE 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _GNU_SOURCE 207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "config.h" 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <ctype.h> 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <dirent.h> 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <endian.h> 266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <errno.h> 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h> 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <ftw.h> 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <limits.h> 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mntent.h> 31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include <stdio.h> 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <unistd.h> 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <ext2fs/ext2_types.h> 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <ext2fs/ext2fs.h> 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <linux/fs.h> 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <sys/ioctl.h> 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ext2fs/fiemap.h> 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <sys/mman.h> 416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <sys/stat.h> 42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include <sys/statfs.h> 436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <sys/syscall.h> 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <sys/vfs.h> 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)/* A relatively new ioctl interface ... */ 476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#ifndef EXT4_IOC_MOVE_EXT 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define EXT4_IOC_MOVE_EXT _IOWR('f', 15, struct move_extent) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Macro functions */ 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PRINT_ERR_MSG(msg) fprintf(stderr, "%s\n", (msg)) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IN_FTW_PRINT_ERR_MSG(msg) \ 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "\t%s\t\t[ NG ]\n", (msg)) 5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define PRINT_FILE_NAME(file) fprintf(stderr, " \"%s\"\n", (file)) 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#define PRINT_ERR_MSG_WITH_ERRNO(msg) \ 57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch fprintf(stderr, "\t%s:%s\t[ NG ]\n", (msg), strerror(errno)) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define STATISTIC_ERR_MSG(msg) \ 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "\t%s\n", (msg)) 6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#define STATISTIC_ERR_MSG_WITH_ERRNO(msg) \ 6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) fprintf(stderr, "\t%s:%s\n", (msg), strerror(errno)) 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#define min(x, y) (((x) > (y)) ? (y) : (x)) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CALC_SCORE(ratio) \ 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((ratio) > 10 ? (80 + 20 * (ratio) / 100) : (8 * (ratio))) 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* Wrap up the free function */ 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#define FREE(tmp) \ 6723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) do { \ 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if ((tmp) != NULL) \ 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) free(tmp); \ 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } while (0) \ 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/* Insert list2 after list1 */ 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define insert(list1, list2) \ 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) do { \ 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) list2->next = list1->next; \ 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) list1->next->prev = list2; \ 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci list2->prev = list1; \ 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) list1->next = list2; \ 78a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } while (0) 79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/* To delete unused warning */ 81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#ifdef __GNUC__ 828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#define EXT2FS_ATTR(x) __attribute__(x) 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#else 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define EXT2FS_ATTR(x) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/* The mode of defrag */ 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define DETAIL 0x01 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define STATISTIC 0x02 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DEVNAME 0 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DIRNAME 1 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FILENAME 2 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FTW_OPEN_FD 2000 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FS_EXT4 "ext4" 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define ROOT_UID 0 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BOUND_SCORE 55 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#define SHOW_FRAG_FILES 5 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* Magic number for ext4 */ 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define EXT4_SUPER_MAGIC 0xEF53 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Definition of flex_bg */ 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 108c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* The following macro is used for ioctl FS_IOC_FIEMAP 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * EXTENT_MAX_COUNT: the maximum number of extents for exchanging between 111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * kernel-space and user-space per ioctl 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define EXTENT_MAX_COUNT 512 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* The following macros are error message */ 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#define MSG_USAGE \ 1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)"Usage : e4defrag [-v] file...| directory...| device...\n\ 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : e4defrag -c file...| directory...| device...\n" 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NGMSG_EXT4 "Filesystem is not ext4 filesystem" 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NGMSG_FILE_EXTENT "Failed to get file extents" 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NGMSG_FILE_INFO "Failed to get file information" 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NGMSG_FILE_OPEN "Failed to open" 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NGMSG_FILE_UNREG "File is not regular file" 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NGMSG_LOST_FOUND "Can not process \"lost+found\"" 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Data type for filesystem-wide blocks number */ 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef unsigned long long ext4_fsblk_t; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct fiemap_extent_data { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __u64 len; /* blocks count */ 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __u64 logical; /* start logical block number */ 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext4_fsblk_t physical; /* start physical block number */ 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct fiemap_extent_list { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *prev; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *next; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_data data; /* extent belong to file */ 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct fiemap_extent_group { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_group *prev; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_group *next; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __u64 len; /* length of this continuous region */ 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) struct fiemap_extent_list *start; /* start ext */ 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) struct fiemap_extent_list *end; /* end ext */ 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct move_extent { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __s32 reserved; /* original file descriptor */ 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) __u32 donor_fd; /* donor file descriptor */ 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci __u64 orig_start; /* logical start offset in block for orig */ 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) __u64 donor_start; /* logical start offset in block for donor */ 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) __u64 len; /* block length to be moved */ 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) __u64 moved_len; /* moved block length */ 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct frag_statistic_ino { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int now_count; /* the file's extents count of before defrag */ 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int best_count; /* the best file's extents count */ 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __u64 size_per_ext; /* size(KB) per extent */ 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float ratio; /* the ratio of fragmentation */ 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char msg_buffer[PATH_MAX + 1]; /* pathname of the file */ 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static char lost_found_dir[PATH_MAX + 1]; 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int block_size; 1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int extents_before_defrag; 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int extents_after_defrag; 1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int mode_flag; 1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static unsigned int current_uid; 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static unsigned int defraged_file_count; 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static unsigned int frag_files_before_defrag; 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static unsigned int frag_files_after_defrag; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned int regular_count; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned int succeed_cnt; 178effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic unsigned int total_count; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static __u8 log_groups_per_flex; 1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static __u32 blocks_per_group; 1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static __u32 feature_incompat; 1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static ext4_fsblk_t files_block_count; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct frag_statistic_ino frag_rank[SHOW_FRAG_FILES]; 18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/* Local definitions of some syscalls glibc may not yet have */ 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef HAVE_POSIX_FADVISE 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#warning Using locally defined posix_fadvise interface. 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef __NR_fadvise64_64 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error Your kernel headers dont define __NR_fadvise64_64 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * fadvise() - Give advice about file access. 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @fd: defrag target file's descriptor. 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @offset: file offset. 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @len: area length. 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @advise: process flag. 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int posix_fadvise(int fd, loff_t offset, size_t len, int advise) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return syscall(__NR_fadvise64_64, fd, offset, len, advise); 206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif /* ! HAVE_FADVISE64_64 */ 208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#ifndef HAVE_SYNC_FILE_RANGE 210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#warning Using locally defined sync_file_range interface. 211effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef __NR_sync_file_range 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef __NR_sync_file_range2 /* ppc */ 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error Your kernel headers dont define __NR_sync_file_range 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * sync_file_range() - Sync file region. 220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @fd: defrag target file's descriptor. 222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @offset: file offset. 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @length: area length. 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @flag: process flag. 225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int sync_file_range(int fd, loff_t offset, loff_t length, unsigned int flag) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __NR_sync_file_range 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return syscall(__NR_sync_file_range, fd, offset, length, flag); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return syscall(__NR_sync_file_range2, fd, flag, offset, length); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* ! HAVE_SYNC_FILE_RANGE */ 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#ifndef HAVE_FALLOCATE64 2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#warning Using locally defined fallocate syscall interface. 2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef __NR_fallocate 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error Your kernel headers dont define __NR_fallocate 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * fallocate64() - Manipulate file space. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @fd: defrag target file's descriptor. 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @mode: process flag. 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @offset: file offset. 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @len: file size. 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int fallocate64(int fd, int mode, loff_t offset, loff_t len) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return syscall(__NR_fallocate, fd, mode, offset, len); 25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif /* ! HAVE_FALLOCATE */ 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * get_mount_point() - Get device's mount point. 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 2601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * @devname: the device's name. 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @mount_point: the mount point. 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @dir_path_len: the length of directory. 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int get_mount_point(const char *devname, char *mount_point, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dir_path_len) 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) /* Refer to /etc/mtab */ 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *mtab = MOUNTED; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE *fp = NULL; 270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch struct mntent *mnt = NULL; 271e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch struct stat64 sb; 272c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stat64(devname, &sb) < 0) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) perror(NGMSG_FILE_INFO); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_FILE_NAME(devname); 276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return -1; 277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fp = setmntent(mtab, "r"); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fp == NULL) { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) perror("Couldn't access /etc/mtab"); 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return -1; 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((mnt = getmntent(fp)) != NULL) { 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct stat64 ms; 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * To handle device symlinks, we see if the 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * device number matches, not the name 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (stat64(mnt->mnt_fsname, &ms) < 0) 2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci continue; 2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (sb.st_rdev != ms.st_rdev) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) endmntent(fp); 29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (strcmp(mnt->mnt_type, FS_EXT4) == 0) { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strncpy(mount_point, mnt->mnt_dir, 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dir_path_len); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_ERR_MSG(NGMSG_EXT4); 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return -1; 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) endmntent(fp); 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PRINT_ERR_MSG("Filesystem is not mounted"); 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return -1; 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/* 3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * is_ext4() - Whether on an ext4 filesystem. 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @file: the file's name. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int is_ext4(const char *file, char *devname) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int maxlen = 0; 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int len, ret; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE *fp = NULL; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *mnt_type = NULL; 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* Refer to /etc/mtab */ 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char *mtab = MOUNTED; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char file_path[PATH_MAX + 1]; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct mntent *mnt = NULL; 326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) struct statfs64 fsbuf; 327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /* Get full path */ 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (realpath(file, file_path) == NULL) { 330c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch perror("Couldn't get full path"); 331c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch PRINT_FILE_NAME(file); 332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return -1; 333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 334c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (statfs64(file_path, &fsbuf) < 0) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) perror("Failed to get filesystem information"); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_FILE_NAME(file); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fsbuf.f_type != EXT4_SUPER_MAGIC) { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_ERR_MSG(NGMSG_EXT4); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fp = setmntent(mtab, "r"); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fp == NULL) { 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) perror("Couldn't access /etc/mtab"); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((mnt = getmntent(fp)) != NULL) { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mnt->mnt_fsname[0] != '/') 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = strlen(mnt->mnt_dir); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = memcmp(file_path, mnt->mnt_dir, len); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret != 0) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (maxlen >= len) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maxlen = len; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mnt_type = realloc(mnt_type, strlen(mnt->mnt_type) + 1); 3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (mnt_type == NULL) { 3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci endmntent(fp); 3683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return -1; 3693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(mnt_type, 0, strlen(mnt->mnt_type) + 1); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strncpy(mnt_type, mnt->mnt_type, strlen(mnt->mnt_type)); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strncpy(lost_found_dir, mnt->mnt_dir, PATH_MAX); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strncpy(devname, mnt->mnt_fsname, strlen(mnt->mnt_fsname) + 1); 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) endmntent(fp); 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mnt_type && strcmp(mnt_type, FS_EXT4) == 0) { 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FREE(mnt_type); 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return 0; 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FREE(mnt_type); 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PRINT_ERR_MSG(NGMSG_EXT4); 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * calc_entry_counts() - Calculate file counts. 389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 39090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * @file: file name. 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @buf: file info. 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @flag: file type. 393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @ftwbuf: the pointer of a struct FTW. 39434680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) */ 395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int calc_entry_counts(const char *file EXT2FS_ATTR((unused)), 396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const struct stat64 *buf, int flag EXT2FS_ATTR((unused)), 397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) struct FTW *ftwbuf EXT2FS_ATTR((unused))) 398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){ 399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (S_ISREG(buf->st_mode)) 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) regular_count++; 401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch total_count++; 403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return 0; 4053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 4063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/* 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * page_in_core() - Get information on whether pages are in core. 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * 4103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @fd: defrag target file's descriptor. 4113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @defrag_data: data used for defrag. 4123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @vec: page state array. 4133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) * @page_num: page number. 4143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) */ 4153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)static int page_in_core(int fd, struct move_extent defrag_data, 4163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) unsigned char **vec, unsigned int *page_num) 4173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles){ 4183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) long pagesize; 4193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) void *page = NULL; 4203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) loff_t offset, end_offset, length; 421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (vec == NULL || *vec != NULL) 423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return -1; 424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pagesize = sysconf(_SC_PAGESIZE); 426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (pagesize < 0) 427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return -1; 428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch /* In mmap, offset should be a multiple of the page size */ 429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch offset = (loff_t)defrag_data.orig_start * block_size; 430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch length = (loff_t)defrag_data.len * block_size; 431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch end_offset = offset + length; 432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch /* Round the offset down to the nearest multiple of pagesize */ 433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch offset = (offset / pagesize) * pagesize; 434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch length = end_offset - offset; 435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch page = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, offset); 437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (page == MAP_FAILED) 438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return -1; 439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *page_num = 0; 441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *page_num = (length + pagesize - 1) / pagesize; 442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *vec = (unsigned char *)calloc(*page_num, 1); 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (*vec == NULL) 444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return -1; 445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch /* Get information on whether pages are in core */ 447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (mincore(page, (size_t)length, *vec) == -1 || 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) munmap(page, length) == -1) { 449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FREE(*vec); 450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return -1; 451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return 0; 454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 457f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * defrag_fadvise() - Predeclare an access pattern for file data. 458f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 459f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * @fd: defrag target file's descriptor. 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @defrag_data: data used for defrag. 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @vec: page state array. 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @page_num: page number. 46323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) */ 46423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)static int defrag_fadvise(int fd, struct move_extent defrag_data, 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) unsigned char *vec, unsigned int page_num) 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles){ 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int flag = 1; 4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) long pagesize = sysconf(_SC_PAGESIZE); 4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int fadvise_flag = POSIX_FADV_DONTNEED; 4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int sync_flag = SYNC_FILE_RANGE_WAIT_BEFORE | 4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SYNC_FILE_RANGE_WRITE | 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SYNC_FILE_RANGE_WAIT_AFTER; 4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) unsigned int i; 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) loff_t offset; 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (pagesize < 1) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) offset = (loff_t)defrag_data.orig_start * block_size; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset = (offset / pagesize) * pagesize; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Sync file for fadvise process */ 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sync_file_range(fd, offset, 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (loff_t)pagesize * page_num, sync_flag) < 0) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Try to release buffer cache which this process used, 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * then other process can use the released buffer 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < page_num; i++) { 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((vec[i] & 0x1) == 0) { 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset += pagesize; 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (posix_fadvise(fd, offset, pagesize, fadvise_flag) < 0) { 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((mode_flag & DETAIL) && flag) { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) perror("\tFailed to fadvise"); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flag = 0; 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset += pagesize; 502a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * check_free_size() - Check if there's enough disk space. 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 510ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch * @fd: defrag target file's descriptor. 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @file: file name. 512ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch * @blk_count: file blocks. 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 514ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstatic int check_free_size(int fd, const char *file, ext4_fsblk_t blk_count) 515ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch{ 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext4_fsblk_t free_blk_count; 5174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) struct statfs64 fsbuf; 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fstatfs64(fd, &fsbuf) < 0) { 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_FILE_NAME(file); 522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO( 523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "Failed to get filesystem information"); 5244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 5254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return -1; 526116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Compute free space for root and normal user separately */ 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_uid == ROOT_UID) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free_blk_count = fsbuf.f_bfree; 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free_blk_count = fsbuf.f_bavail; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (free_blk_count >= blk_count) 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -ENOSPC; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * file_frag_count() - Get file fragment count. 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @fd: defrag target file's descriptor. 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int file_frag_count(int fd) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap fiemap_buf; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* When fm_extent_count is 0, 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ioctl just get file fragment count. 55223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) */ 55323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) memset(&fiemap_buf, 0, sizeof(struct fiemap)); 55423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) fiemap_buf.fm_start = 0; 555116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch fiemap_buf.fm_length = FIEMAP_MAX_OFFSET; 556116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch fiemap_buf.fm_flags |= FIEMAP_FLAG_SYNC; 557116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 558f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ret = ioctl(fd, FS_IOC_FIEMAP, &fiemap_buf); 559cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (ret < 0) 5606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return ret; 561f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return fiemap_buf.fm_mapped_extents; 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/* 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * file_check() - Check file's attributes. 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @fd: defrag target file's descriptor. 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @buf: a pointer of the struct stat64. 570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * @file: file name. 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @extents: file extents. 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @blk_count: file blocks. 5736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) */ 5746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static int file_check(int fd, const struct stat64 *buf, const char *file, 575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int extents, ext4_fsblk_t blk_count) 576cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles){ 577cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int ret; 578116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch struct flock lock; 579116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write-lock check is more reliable */ 5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lock.l_type = F_WRLCK; 5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lock.l_start = 0; 583cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) lock.l_whence = SEEK_SET; 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lock.l_len = 0; 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* Free space */ 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = check_free_size(fd, file, blk_count); 588cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (ret < 0) { 589cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if ((mode_flag & DETAIL) && ret == -ENOSPC) { 590cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) printf("\033[79;0H\033[K[%u/%u] \"%s\"\t\t" 591cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) " extents: %d -> %d\n", defraged_file_count, 592cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) total_count, file, extents, extents); 593cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IN_FTW_PRINT_ERR_MSG( 594cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "Defrag size is larger than filesystem's free space"); 5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 596cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return -1; 597cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 598cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 599cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /* Access authority */ 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_uid != ROOT_UID && 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf->st_uid != current_uid) { 602cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (mode_flag & DETAIL) { 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("\033[79;0H\033[K[%u/%u] \"%s\"\t\t" 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " extents: %d -> %d\n", defraged_file_count, 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_count, file, extents, extents); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IN_FTW_PRINT_ERR_MSG( 607f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "File is not current user's file" 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " or current user is not root"); 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return -1; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 6136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) /* Lock status */ 6146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (fcntl(fd, F_GETLK, &lock) < 0) { 6157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (mode_flag & DETAIL) { 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_FILE_NAME(file); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO( 618cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) "Failed to get lock information"); 619ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 620cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return -1; 621cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (lock.l_type != F_UNLCK) { 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PRINT_FILE_NAME(file); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IN_FTW_PRINT_ERR_MSG("File has been locked"); 625f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 626f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return -1; 627f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 628f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 629f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return 0; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 633cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * insert_extent_by_logical() - Sequentially insert extent by logical. 634cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * 635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * @ext_list_head: the head of logical extent list. 6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @ext: the extent element which will be inserted. 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int insert_extent_by_logical(struct fiemap_extent_list **ext_list_head, 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *ext) 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *ext_list_tmp = *ext_list_head; 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ext == NULL) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* First element */ 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*ext_list_head == NULL) { 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*ext_list_head) = ext; 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*ext_list_head)->prev = *ext_list_head; 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*ext_list_head)->next = *ext_list_head; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ext->data.logical <= ext_list_tmp->data.logical) { 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Insert before head */ 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ext_list_tmp->data.logical < 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext->data.logical + ext->data.len) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Overlap */ 659116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch goto out; 660116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /* Adjust head */ 661116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *ext_list_head = ext; 662116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Insert into the middle or last of the list */ 664116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch do { 665116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (ext->data.logical < ext_list_tmp->data.logical) 666116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 667116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ext_list_tmp = ext_list_tmp->next; 668116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } while (ext_list_tmp != (*ext_list_head)); 669116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (ext->data.logical < 670116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ext_list_tmp->prev->data.logical + 671116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ext_list_tmp->prev->data.len) 672116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /* Overlap */ 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (ext_list_tmp != *ext_list_head && 676cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ext_list_tmp->data.logical < 677cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ext->data.logical + ext->data.len) 678cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /* Overlap */ 6795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) goto out; 6805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 681cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ext_list_tmp = ext_list_tmp->prev; 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Insert "ext" after "ext_list_tmp" */ 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) insert(ext_list_tmp, ext); 684cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 685cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)out: 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = EINVAL; 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * insert_extent_by_physical() - Sequentially insert extent by physical. 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 693c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * @ext_list_head: the head of physical extent list. 694c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch * @ext: the extent element which will be inserted. 695c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch */ 696c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic int insert_extent_by_physical(struct fiemap_extent_list **ext_list_head, 697c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch struct fiemap_extent_list *ext) 698c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch{ 699116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch struct fiemap_extent_list *ext_list_tmp = *ext_list_head; 7005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (ext == NULL) 7025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) goto out; 7035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /* First element */ 7055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (*ext_list_head == NULL) { 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*ext_list_head) = ext; 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*ext_list_head)->prev = *ext_list_head; 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*ext_list_head)->next = *ext_list_head; 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 7105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 712868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (ext->data.physical <= ext_list_tmp->data.physical) { 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Insert before head */ 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ext_list_tmp->data.physical < 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext->data.physical + ext->data.len) 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Overlap */ 7171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci goto out; 7181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci /* Adjust head */ 7191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *ext_list_head = ext; 7201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 7211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) /* Insert into the middle or last of the list */ 7221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) do { 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ext->data.physical < ext_list_tmp->data.physical) 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 725a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ext_list_tmp = ext_list_tmp->next; 726f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } while (ext_list_tmp != (*ext_list_head)); 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ext->data.physical < 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list_tmp->prev->data.physical + 729868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ext_list_tmp->prev->data.len) 73046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) /* Overlap */ 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ext_list_tmp != *ext_list_head && 734cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ext_list_tmp->data.physical < 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext->data.physical + ext->data.len) 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Overlap */ 7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) goto out; 7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ext_list_tmp = ext_list_tmp->prev; 740cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /* Insert "ext" after "ext_list_tmp" */ 741cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) insert(ext_list_tmp, ext); 742cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 743a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochout: 744cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) errno = EINVAL; 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/* 7495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * insert_exts_group() - Insert a exts_group. 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 751cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @ext_group_head: the head of a exts_group list. 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @exts_group: the exts_group element which will be inserted. 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int insert_exts_group(struct fiemap_extent_group **ext_group_head, 7555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) struct fiemap_extent_group *exts_group) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 757868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) struct fiemap_extent_group *ext_group_tmp = NULL; 7585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (exts_group == NULL) { 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = EINVAL; 7611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return -1; 762cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 7631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Initialize list */ 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*ext_group_head == NULL) { 766cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (*ext_group_head) = exts_group; 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*ext_group_head)->prev = *ext_group_head; 768cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (*ext_group_head)->next = *ext_group_head; 769cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 770d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_group_tmp = (*ext_group_head)->prev; 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) insert(ext_group_tmp, exts_group); 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 777cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 778cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)/* 779cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * join_extents() - Find continuous region(exts_group). 780cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * 781cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @ext_list_head: the head of the extent list. 782cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @ext_group_head: the head of the target exts_group list. 783cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 784cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static int join_extents(struct fiemap_extent_list *ext_list_head, 785cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) struct fiemap_extent_group **ext_group_head) 786cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles){ 787cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) __u64 len = ext_list_head->data.len; 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *ext_list_start = ext_list_head; 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *ext_list_tmp = ext_list_head->next; 7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) do { 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_group *ext_group_tmp = NULL; 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* This extent and previous extent are not continuous, 7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * so, all previous extents are treated as an extent group. 7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((ext_list_tmp->prev->data.logical + 7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ext_list_tmp->prev->data.len) 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) != ext_list_tmp->data.logical) { 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_group_tmp = 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) malloc(sizeof(struct fiemap_extent_group)); 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ext_group_tmp == NULL) 803cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return -1; 8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(ext_group_tmp, 0, 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(struct fiemap_extent_group)); 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_group_tmp->len = len; 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_group_tmp->start = ext_list_start; 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_group_tmp->end = ext_list_tmp->prev; 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (insert_exts_group(ext_group_head, 8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ext_group_tmp) < 0) { 8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FREE(ext_group_tmp); 814f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return -1; 815f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 816f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ext_list_start = ext_list_tmp; 817f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) len = ext_list_tmp->data.len; 818f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ext_list_tmp = ext_list_tmp->next; 819f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) continue; 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* This extent and previous extent are continuous, 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * so, they belong to the same extent group, and we check 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * if the next extent belongs to the same extent group. 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len += ext_list_tmp->data.len; 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list_tmp = ext_list_tmp->next; 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (ext_list_tmp != ext_list_head->next); 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return 0; 8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * get_file_extents() - Get file's extent list. 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @fd: defrag target file's descriptor. 8375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @ext_list_head: the head of the extent list. 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int get_file_extents(int fd, struct fiemap_extent_list **ext_list_head) 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 8411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) __u32 i; 8421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int ret; 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ext_buf_size, fie_buf_size; 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __u64 pos = 0; 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap *fiemap_buf = NULL; 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent *ext_buf = NULL; 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *ext_list = NULL; 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Convert units, in bytes. 8505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Be careful : now, physical block number in extent is 48bit, 8515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * and the maximum blocksize for ext4 is 4K(12bit), 8525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * so there is no overflow, but in future it may be changed. 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Alloc space for fiemap */ 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_buf_size = EXTENT_MAX_COUNT * sizeof(struct fiemap_extent); 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fie_buf_size = sizeof(struct fiemap) + ext_buf_size; 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 859116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch fiemap_buf = malloc(fie_buf_size); 860116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (fiemap_buf == NULL) 861116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return -1; 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 863eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ext_buf = fiemap_buf->fm_extents; 864116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch memset(fiemap_buf, 0, fie_buf_size); 865116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch fiemap_buf->fm_length = FIEMAP_MAX_OFFSET; 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fiemap_buf->fm_flags |= FIEMAP_FLAG_SYNC; 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fiemap_buf->fm_extent_count = EXTENT_MAX_COUNT; 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fiemap_buf->fm_start = pos; 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(ext_buf, 0, ext_buf_size); 8725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret = ioctl(fd, FS_IOC_FIEMAP, fiemap_buf); 8735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ret < 0 || fiemap_buf->fm_mapped_extents == 0) 8745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) goto out; 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < fiemap_buf->fm_mapped_extents; i++) { 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list = NULL; 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list = malloc(sizeof(struct fiemap_extent_list)); 8785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ext_list == NULL) 8795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) goto out; 8805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 881c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ext_list->data.physical = ext_buf[i].fe_physical 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) / block_size; 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list->data.logical = ext_buf[i].fe_logical 8845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) / block_size; 8855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ext_list->data.len = ext_buf[i].fe_length 8865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) / block_size; 8871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = insert_extent_by_physical( 8895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ext_list_head, ext_list); 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret < 0) { 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FREE(ext_list); 8921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) goto out; 8931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Record file's logical offset this time */ 8967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch pos = ext_buf[EXTENT_MAX_COUNT-1].fe_logical + 8977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ext_buf[EXTENT_MAX_COUNT-1].fe_length; 8987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) /* 8997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * If fm_extents array has been filled and 9007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * there are extents left, continue to cycle. 9017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) */ 9025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } while (fiemap_buf->fm_mapped_extents 9035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) == EXTENT_MAX_COUNT && 9045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !(ext_buf[EXTENT_MAX_COUNT-1].fe_flags 905116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch & FIEMAP_EXTENT_LAST)); 9067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 9077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) FREE(fiemap_buf); 9085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return 0; 9095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)out: 9105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FREE(fiemap_buf); 911116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return -1; 9127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 9137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 9147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)/* 9157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * get_logical_count() - Get the file logical extents count. 9167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) * 9173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch * @logical_list_head: the head of the logical extent list. 9183240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch */ 9191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic int get_logical_count(struct fiemap_extent_list *logical_list_head) 9203240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch{ 9217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int ret = 0; 9227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch struct fiemap_extent_list *ext_list_tmp = logical_list_head; 9237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 9247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) do { 9257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ret++; 9267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ext_list_tmp = ext_list_tmp->next; 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (ext_list_tmp != logical_list_head); 9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ret; 93046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 93146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * get_physical_count() - Get the file physical extents count. 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @physical_list_head: the head of the physical extent list. 9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int get_physical_count(struct fiemap_extent_list *physical_list_head) 9386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles){ 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret = 0; 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *ext_list_tmp = physical_list_head; 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 94390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if ((ext_list_tmp->data.physical + ext_list_tmp->data.len) 9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) != ext_list_tmp->next->data.physical) { 9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* This extent and next extent are not continuous. */ 9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret++; 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list_tmp = ext_list_tmp->next; 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (ext_list_tmp != physical_list_head); 9512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 95390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 95446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * change_physical_to_logical() - Change list from physical to logical. 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @physical_list_head: the head of physical extent list. 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @logical_list_head: the head of logical extent list. 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int change_physical_to_logical( 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list **physical_list_head, 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list **logical_list_head) 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 9655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int ret; 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *ext_list_tmp = *physical_list_head; 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *ext_list_next = ext_list_tmp->next; 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (1) { 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ext_list_tmp == ext_list_next) { 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = insert_extent_by_logical( 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logical_list_head, ext_list_tmp); 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret < 0) 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *physical_list_head = NULL; 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list_tmp->prev->next = ext_list_tmp->next; 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list_tmp->next->prev = ext_list_tmp->prev; 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *physical_list_head = ext_list_next; 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = insert_extent_by_logical( 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logical_list_head, ext_list_tmp); 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret < 0) { 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FREE(ext_list_tmp); 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list_tmp = ext_list_next; 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list_next = ext_list_next->next; 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch/* get_file_blocks() - Get total file blocks. 9980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch * 999effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * @ext_list_head: the extent list head of the target file 1000effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch */ 1001effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic ext4_fsblk_t get_file_blocks(struct fiemap_extent_list *ext_list_head) 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 10035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ext4_fsblk_t blk_count = 0; 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *ext_list_tmp = ext_list_head; 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 1007effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch blk_count += ext_list_tmp->data.len; 1008effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ext_list_tmp = ext_list_tmp->next; 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (ext_list_tmp != ext_list_head); 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return blk_count; 1012effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 1013effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1014effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch/* 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * free_ext() - Free the extent list. 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 101746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * @ext_list_head: the extent list head of which will be free. 101846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) */ 101946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)static void free_ext(struct fiemap_extent_list *ext_list_head) 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *ext_list_tmp = NULL; 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 102346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (ext_list_head == NULL) 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (ext_list_head->next != ext_list_head) { 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list_tmp = ext_list_head; 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list_head->prev->next = ext_list_head->next; 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list_head->next->prev = ext_list_head->prev; 103046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ext_list_head = ext_list_head->next; 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(ext_list_tmp); 10322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(ext_list_head); 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 103646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)/* 103746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * free_exts_group() - Free the exts_group. 1038d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * 10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @*ext_group_head: the exts_group list head which will be free. 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void free_exts_group(struct fiemap_extent_group *ext_group_head) 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_group *ext_group_tmp = NULL; 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (ext_group_head == NULL) 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 10480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch while (ext_group_head->next != ext_group_head) { 10490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ext_group_tmp = ext_group_head; 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_group_head->prev->next = ext_group_head->next; 10515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ext_group_head->next->prev = ext_group_head->prev; 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_group_head = ext_group_head->next; 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(ext_group_tmp); 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(ext_group_head); 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * get_best_count() - Get the file best extents count. 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @block_count: the file's physical block count. 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int get_best_count(ext4_fsblk_t block_count) 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret; 1066effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch unsigned int flex_bg_num; 1067effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1068effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch /* Calcuate best extents count */ 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) { 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flex_bg_num = 1 << log_groups_per_flex; 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = ((block_count - 1) / 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((ext4_fsblk_t)blocks_per_group * 10732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flex_bg_num)) + 1; 10742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else 10752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = ((block_count - 1) / blocks_per_group) + 1; 1076a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1077a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return ret; 107803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 107903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 108003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 10817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch/* 10827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * file_statistic() - Get statistic info of the file's fragments. 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @file: the file's name. 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @buf: the pointer of the struct stat64. 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @flag: file type. 1087effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * @ftwbuf: the pointer of a struct FTW. 1088effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch */ 1089effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic int file_statistic(const char *file, const struct stat64 *buf, 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flag EXT2FS_ATTR((unused)), 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct FTW *ftwbuf EXT2FS_ATTR((unused))) 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 10935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int fd; 10945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int ret; 10955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int now_ext_count, best_ext_count = 0, physical_ext_count; 10965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int i, j; 10975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) __u64 size_per_ext = 0; 10985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) float ratio = 0.0; 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext4_fsblk_t blk_count = 0; 110090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) char msg_buffer[PATH_MAX + 24]; 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *physical_list_head = NULL; 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *logical_list_head = NULL; 11032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) defraged_file_count++; 1105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 11062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mode_flag & DETAIL) { 11072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (total_count == 1 && regular_count == 1) 11082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("<File>\n"); 11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else { 11102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("[%u/%u]", defraged_file_count, total_count); 11112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fflush(stdout); 11122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (lost_found_dir[0] != '\0' && 11152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !memcmp(file, lost_found_dir, strnlen(lost_found_dir, PATH_MAX))) { 1116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (mode_flag & DETAIL) { 11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PRINT_FILE_NAME(file); 11182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STATISTIC_ERR_MSG(NGMSG_LOST_FOUND); 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return 0; 1121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 11222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!S_ISREG(buf->st_mode)) { 1124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (mode_flag & DETAIL) { 11255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PRINT_FILE_NAME(file); 11265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) STATISTIC_ERR_MSG(NGMSG_FILE_UNREG); 11275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 11287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return 0; 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) /* Access authority */ 1132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (current_uid != ROOT_UID && 1133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) buf->st_uid != current_uid) { 1134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (mode_flag & DETAIL) { 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_FILE_NAME(file); 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATISTIC_ERR_MSG( 1137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "File is not current user's file" 1138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) " or current user is not root"); 1139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return 0; 1141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Empty file */ 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buf->st_size == 0) { 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 1146c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch PRINT_FILE_NAME(file); 1147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch STATISTIC_ERR_MSG("File size is 0"); 1148c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return 0; 1150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Has no blocks */ 1153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (buf->st_blocks == 0) { 1154c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (mode_flag & DETAIL) { 1155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch PRINT_FILE_NAME(file); 1156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch STATISTIC_ERR_MSG("File has no blocks"); 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fd = open64(file, O_RDONLY); 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fd < 0) { 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_FILE_NAME(file); 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATISTIC_ERR_MSG_WITH_ERRNO(NGMSG_FILE_OPEN); 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Get file's physical extents */ 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = get_file_extents(fd, &physical_list_head); 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret < 0) { 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_FILE_NAME(file); 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATISTIC_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Get the count of file's continuous physical region */ 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) physical_ext_count = get_physical_count(physical_list_head); 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Change list from physical to logical */ 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = change_physical_to_logical(&physical_list_head, 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &logical_list_head); 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret < 0) { 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 1188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch PRINT_FILE_NAME(file); 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATISTIC_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Count file fragments before defrag */ 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now_ext_count = get_logical_count(logical_list_head); 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_uid == ROOT_UID) { 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Calculate the size per extent */ 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blk_count = get_file_blocks(logical_list_head); 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_ext_count = get_best_count(blk_count); 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* e4defrag rounds size_per_ext up to a block size boundary */ 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_per_ext = blk_count * (buf->st_blksize / 1024) / 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now_ext_count; 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ratio = (float)(physical_ext_count - best_ext_count) * 100 / 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blk_count; 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extents_before_defrag += now_ext_count; 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extents_after_defrag += best_ext_count; 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) files_block_count += blk_count; 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (total_count == 1 && regular_count == 1) { 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* File only */ 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *ext_list_tmp = 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logical_list_head; 12215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 12225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) /* Print extents info */ 12235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) do { 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count++; 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("[ext %d]:\tstart %llu:\tlogical " 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%llu:\tlen %llu\n", count, 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list_tmp->data.physical, 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list_tmp->data.logical, 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list_tmp->data.len); 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext_list_tmp = ext_list_tmp->next; 12312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } while (ext_list_tmp != logical_list_head); 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("%-40s%10s/%-10s%9s\n", 1235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch "<File>", "now", "best", "size/ext"); 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_uid == ROOT_UID) { 1237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (strlen(file) > 40) 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("%s\n%50d/%-10d%6llu KB\n", 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file, now_ext_count, 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_ext_count, size_per_ext); 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 12421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) printf("%-40s%10d/%-10d%6llu KB\n", 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file, now_ext_count, 12445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) best_ext_count, size_per_ext); 12455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strlen(file) > 40) 12475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) printf("%s\n%50d/%-10s%7s\n", 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file, now_ext_count, 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "-", "-"); 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) printf("%-40s%10d/%-10s%7s\n", 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file, now_ext_count, 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "-", "-"); 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) succeed_cnt++; 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Print statistic info */ 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sprintf(msg_buffer, "[%u/%u]%s", 1263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) defraged_file_count, total_count, file); 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_uid == ROOT_UID) { 12655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (strlen(msg_buffer) > 40) 12665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) printf("\033[79;0H\033[K%s\n" 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%50d/%-10d%6llu KB\n", 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_buffer, now_ext_count, 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_ext_count, size_per_ext); 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 12715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) printf("\033[79;0H\033[K%-40s" 12725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "%10d/%-10d%6llu KB\n", 1273a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) msg_buffer, now_ext_count, 12745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) best_ext_count, size_per_ext); 12755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1276a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (strlen(msg_buffer) > 40) 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("\033[79;0H\033[K%s\n%50d/%-10s%7s\n", 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_buffer, now_ext_count, 1279a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "-", "-"); 12805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else 1281a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) printf("\033[79;0H\033[K%-40s%10d/%-10s%7s\n", 1282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) msg_buffer, now_ext_count, 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "-", "-"); 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 128558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 128658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 128758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) for (i = 0; i < SHOW_FRAG_FILES; i++) { 128858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (ratio >= frag_rank[i].ratio) { 12891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (j = SHOW_FRAG_FILES - 1; j > i; j--) { 1290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) memset(&frag_rank[j], 0, 1291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sizeof(struct frag_statistic_ino)); 12925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) strncpy(frag_rank[j].msg_buffer, 1293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) frag_rank[j - 1].msg_buffer, 1294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) strnlen(frag_rank[j - 1].msg_buffer, 12955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PATH_MAX)); 12965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frag_rank[j].now_count = 1297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) frag_rank[j - 1].now_count; 129858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) frag_rank[j].best_count = 129958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) frag_rank[j - 1].best_count; 13005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) frag_rank[j].size_per_ext = 13015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) frag_rank[j - 1].size_per_ext; 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frag_rank[j].ratio = 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frag_rank[j - 1].ratio; 13045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 13055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) memset(&frag_rank[i], 0, 13065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sizeof(struct frag_statistic_ino)); 13075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) strncpy(frag_rank[i].msg_buffer, file, 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strnlen(file, PATH_MAX)); 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frag_rank[i].now_count = now_ext_count; 131090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) frag_rank[i].best_count = best_ext_count; 131190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) frag_rank[i].size_per_ext = size_per_ext; 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frag_rank[i].ratio = ratio; 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 131590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) succeed_cnt++; 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)out: 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close(fd); 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free_ext(physical_list_head); 1322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) free_ext(logical_list_head); 1323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return 0; 1324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 1325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* 1327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * print_progress - Print defrag progress 1328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @file: file name. 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @start: logical offset for defrag target file 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @file_size: defrag target filesize 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void print_progress(const char *file, loff_t start, loff_t file_size) 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 13352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int percent = (start * 100) / file_size; 13362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("\033[79;0H\033[K[%u/%u]%s:\t%3d%%", 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) defraged_file_count, total_count, file, min(percent, 100)); 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fflush(stdout); 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 1341ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 1342ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1343ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch/* 1344ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch * call_defrag() - Execute the defrag program. 1345ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch * 1346ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch * @fd: target file descriptor. 1347ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch * @donor_fd: donor file descriptor. 1348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @file: target file name. 1349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @buf: pointer of the struct stat64. 1350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @ext_list_head: head of the extent list. 1351ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch */ 1352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int call_defrag(int fd, int donor_fd, const char *file, 13535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const struct stat64 *buf, struct fiemap_extent_list *ext_list_head) 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loff_t start = 0; 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int page_num; 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char *vec = NULL; 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int defraged_ret = 0; 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret; 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct move_extent move_data; 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *ext_list_tmp = NULL; 1362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&move_data, 0, sizeof(struct move_extent)); 1364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) move_data.donor_fd = donor_fd; 1365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1366ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch /* Print defrag progress */ 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print_progress(file, start, buf->st_size); 1368ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ext_list_tmp = ext_list_head; 1370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) do { 13711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) move_data.orig_start = ext_list_tmp->data.logical; 1372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /* Logical offset of orig and donor should be same */ 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) move_data.donor_start = move_data.orig_start; 13742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) move_data.len = ext_list_tmp->data.len; 13752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) move_data.moved_len = 0; 13762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1377a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ret = page_in_core(fd, move_data, &vec, &page_num); 1378a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (ret < 0) { 13795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (mode_flag & DETAIL) { 1380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) printf("\n"); 1381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO( 13825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Failed to get file map"); 13831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } else { 13841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) printf("\t[ NG ]\n"); 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return -1; 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* EXT4_IOC_MOVE_EXT */ 1390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) defraged_ret = 1391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ioctl(fd, EXT4_IOC_MOVE_EXT, &move_data); 1392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /* Free pages */ 1394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ret = defrag_fadvise(fd, move_data, vec, page_num); 1395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (vec) { 1396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) free(vec); 1397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) vec = NULL; 1398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (ret < 0) { 1400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (mode_flag & DETAIL) { 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("\n"); 1402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO( 1403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "Failed to free page"); 14045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) printf("\t[ NG ]\n"); 14062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 14082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (defraged_ret < 0) { 14115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (mode_flag & DETAIL) { 14125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) printf("\n"); 14135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO( 14145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Failed to defrag with " 14155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "EXT4_IOC_MOVE_EXT ioctl"); 14165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (errno == ENOTTY) 14172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("\tAt least 2.6.31-rc1 of " 14182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "vanilla kernel is required\n"); 14192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 14205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) printf("\t[ NG ]\n"); 14211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 14221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return -1; 14232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Adjust logical offset for next ioctl */ 14255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) move_data.orig_start += move_data.moved_len; 14262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) move_data.donor_start = move_data.orig_start; 14272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) start = move_data.orig_start * buf->st_blksize; 14292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* Print defrag progress */ 14312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) print_progress(file, start, buf->st_size); 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1433f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) /* End of file */ 14342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (start >= buf->st_size) 14352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 14362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ext_list_tmp = ext_list_tmp->next; 14382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } while (ext_list_tmp != ext_list_head); 14392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return 0; 1441f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 1442effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1443effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch/* 14442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * file_defrag() - Check file attributes and call ioctl to defrag. 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @file: the file's name. 14472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @buf: the pointer of the struct stat64. 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @flag: file type. 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ftwbuf: the pointer of a struct FTW. 1450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 1451ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstatic int file_defrag(const char *file, const struct stat64 *buf, 1452116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int flag EXT2FS_ATTR((unused)), 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct FTW *ftwbuf EXT2FS_ATTR((unused))) 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd; 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int donor_fd = -1; 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret; 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int best; 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int file_frags_start, file_frags_end; 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int orig_physical_cnt, donor_physical_cnt = 0; 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char tmp_inode_name[PATH_MAX + 8]; 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext4_fsblk_t blk_count = 0; 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *orig_list_physical = NULL; 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *orig_list_logical = NULL; 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *donor_list_physical = NULL; 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_list *donor_list_logical = NULL; 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_group *orig_group_head = NULL; 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct fiemap_extent_group *orig_group_tmp = NULL; 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) defraged_file_count++; 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("[%u/%u]", defraged_file_count, total_count); 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fflush(stdout); 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 147790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (lost_found_dir[0] != '\0' && 14781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) !memcmp(file, lost_found_dir, strnlen(lost_found_dir, PATH_MAX))) { 1479f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (mode_flag & DETAIL) { 1480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PRINT_FILE_NAME(file); 1481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IN_FTW_PRINT_ERR_MSG(NGMSG_LOST_FOUND); 148290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 148390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 0; 148490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 1485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!S_ISREG(buf->st_mode)) { 1487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (mode_flag & DETAIL) { 1488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PRINT_FILE_NAME(file); 1489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IN_FTW_PRINT_ERR_MSG(NGMSG_FILE_UNREG); 149090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 149190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 0; 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Empty file */ 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buf->st_size == 0) { 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_FILE_NAME(file); 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IN_FTW_PRINT_ERR_MSG("File size is 0"); 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 15038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) /* Has no blocks */ 15041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (buf->st_blocks == 0) { 150546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (mode_flag & DETAIL) { 150646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PRINT_FILE_NAME(file); 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STATISTIC_ERR_MSG("File has no blocks"); 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1509ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return 0; 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fd = open64(file, O_RDWR); 1513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (fd < 0) { 15142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mode_flag & DETAIL) { 15152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PRINT_FILE_NAME(file); 15162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_OPEN); 1517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 15182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 15192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 15202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 15212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* Get file's extents */ 15222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = get_file_extents(fd, &orig_list_physical); 15232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ret < 0) { 15242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mode_flag & DETAIL) { 15252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PRINT_FILE_NAME(file); 15262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); 15272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 1529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Get the count of file's continuous physical region */ 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) orig_physical_cnt = get_physical_count(orig_list_physical); 1533cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1534cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /* Change list from physical to logical */ 1535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ret = change_physical_to_logical(&orig_list_physical, 1536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &orig_list_logical); 1537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (ret < 0) { 1538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (mode_flag & DETAIL) { 1539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PRINT_FILE_NAME(file); 15402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 154246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) goto out; 154346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) /* Count file fragments before defrag */ 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_frags_start = get_logical_count(orig_list_logical); 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) blk_count = get_file_blocks(orig_list_logical); 15492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (file_check(fd, buf, file, file_frags_start, blk_count) < 0) 15502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) goto out; 1551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fsync(fd) < 0) { 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_FILE_NAME(file); 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO("Failed to sync(fsync)"); 15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) goto out; 15585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 15595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 15607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (current_uid == ROOT_UID) 15612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) best = get_best_count(blk_count); 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best = 1; 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (file_frags_start <= best) 1566effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch goto check_improvement; 1567effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 156858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) /* Combine extents to group */ 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = join_extents(orig_list_logical, &orig_group_head); 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret < 0) { 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_FILE_NAME(file); 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); 1574f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Create donor inode */ 1579effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch memset(tmp_inode_name, 0, PATH_MAX + 8); 1580116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sprintf(tmp_inode_name, "%.*s.defrag", 1581116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch (int)strnlen(file, PATH_MAX), file); 1582116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch donor_fd = open64(tmp_inode_name, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR); 1583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (donor_fd < 0) { 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_FILE_NAME(file); 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (errno == EEXIST) 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO( 15882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "File is being defraged by other program"); 15892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_OPEN); 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 15952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* Unlink donor inode */ 1596a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ret = unlink(tmp_inode_name); 1597a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (ret < 0) { 1598a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (mode_flag & DETAIL) { 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_FILE_NAME(file); 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO("Failed to unlink"); 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1604effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Allocate space for donor inode */ 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) orig_group_tmp = orig_group_head; 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = fallocate64(donor_fd, 0, 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (loff_t)orig_group_tmp->start->data.logical * block_size, 1610effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch (loff_t)orig_group_tmp->len * block_size); 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret < 0) { 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_FILE_NAME(file); 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO("Failed to fallocate"); 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1616f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) goto out; 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) orig_group_tmp = orig_group_tmp->next; 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (orig_group_tmp != orig_group_head); 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Get donor inode's extents */ 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = get_file_extents(donor_fd, &donor_list_physical); 16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret < 0) { 16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_FILE_NAME(file); 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1629f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) goto out; 1630a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 1631a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1632a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) /* Calcuate donor inode's continuous physical region */ 1633a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) donor_physical_cnt = get_physical_count(donor_list_physical); 1634a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1635a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) /* Change donor extent list from physical to logical */ 1636a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ret = change_physical_to_logical(&donor_list_physical, 1637a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) &donor_list_logical); 1638a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (ret < 0) { 1639a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (mode_flag & DETAIL) { 1640a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) PRINT_FILE_NAME(file); 16412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT); 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 16442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 16452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 164646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)check_improvement: 164746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (mode_flag & DETAIL) { 16482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (file_frags_start != 1) 16492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frag_files_before_defrag++; 16502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 16512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extents_before_defrag += file_frags_start; 16522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 16535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (file_frags_start <= best || 16555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) orig_physical_cnt <= donor_physical_cnt) { 16565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) printf("\033[79;0H\033[K[%u/%u]%s:\t%3d%%", 16575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) defraged_file_count, total_count, file, 100); 16585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (mode_flag & DETAIL) 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf(" extents: %d -> %d", 16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_frags_start, file_frags_start); 16612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 16622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("\t[ OK ]\n"); 1663f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) succeed_cnt++; 1664f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1665f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (file_frags_start != 1) 1666a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) frag_files_after_defrag++; 1667a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1668a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) extents_after_defrag += file_frags_start; 1669f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) goto out; 1670a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 1671effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1672effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch /* Defrag the file */ 16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = call_defrag(fd, donor_fd, file, buf, donor_list_logical); 16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch /* Count file fragments after defrag and print extents info */ 16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 16772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) file_frags_end = file_frag_count(fd); 16782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (file_frags_end < 0) { 1679a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) printf("\n"); 16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_INFO); 16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1683c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1684c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (file_frags_end != 1) 1685e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch frag_files_after_defrag++; 1686a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1687a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) extents_after_defrag += file_frags_end; 1688a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1689f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (ret < 0) 1690a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) goto out; 1691effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1692effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch printf(" extents: %d -> %d", 16932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) file_frags_start, file_frags_end); 1694c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch fflush(stdout); 1695c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1696a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1697a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (ret < 0) 1698a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) goto out; 1699f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch printf("\t[ OK ]\n"); 1701effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch fflush(stdout); 1702effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch succeed_cnt++; 1703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochout: 17052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) close(fd); 1706a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (donor_fd != -1) 1707a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) close(donor_fd); 1708f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) free_ext(orig_list_physical); 1709effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch free_ext(orig_list_logical); 1710effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch free_ext(donor_list_physical); 17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free_exts_group(orig_group_head); 17122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 17151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/* 17161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * main() - Ext4 online defrag. 17171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * 17181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @argc: the number of parameter. 17192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @argv[]: the pointer array of parameter. 17202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 17212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int main(int argc, char *argv[]) 1722f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles){ 1723effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int opt; 1724effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int i, j, ret = 0; 17252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int flags = FTW_PHYS | FTW_MOUNT; 1726cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int arg_type = -1; 1727f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int success_flag = 0; 1728f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) char dir_name[PATH_MAX + 1]; 1729a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) char dev_name[PATH_MAX + 1]; 1730effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch struct stat64 buf; 1731effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ext2_filsys fs = NULL; 1732cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Parse arguments */ 17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (argc == 1) 17352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) goto out; 17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch while ((opt = getopt(argc, argv, "vc")) != EOF) { 1738eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch switch (opt) { 17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'v': 1740eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch mode_flag |= DETAIL; 1741eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 1742eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case 'c': 1743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch mode_flag |= STATISTIC; 1744eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 1745eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch default: 1746eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch goto out; 1747eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 17485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (argc == optind) 1751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch goto out; 1752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1753c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch current_uid = getuid(); 1754c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1755c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch /* Main process */ 1756c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch for (i = optind; i < argc; i++) { 1757eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch succeed_cnt = 0; 1758eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch regular_count = 0; 1759eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch total_count = 0; 1760eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frag_files_before_defrag = 0; 1761eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frag_files_after_defrag = 0; 1762eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch extents_before_defrag = 0; 1763eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch extents_after_defrag = 0; 1764eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch defraged_file_count = 0; 1765eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch files_block_count = 0; 1766eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch blocks_per_group = 0; 17672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) feature_incompat = 0; 17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log_groups_per_flex = 0; 17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memset(dir_name, 0, PATH_MAX + 1); 17712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memset(dev_name, 0, PATH_MAX + 1); 17722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memset(lost_found_dir, 0, PATH_MAX + 1); 17732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memset(frag_rank, 0, 1774868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sizeof(struct frag_statistic_ino) * SHOW_FRAG_FILES); 1775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((mode_flag & STATISTIC) && i > optind) 1777cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) printf("\n"); 17782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN 17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_ERR_MSG("Endian's type is not big/little endian"); 1781cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PRINT_FILE_NAME(argv[i]); 17822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 17832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1784cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1785cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (lstat64(argv[i], &buf) < 0) { 178690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) perror(NGMSG_FILE_INFO); 178790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PRINT_FILE_NAME(argv[i]); 178890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) continue; 178990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 179090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 179190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) /* Handle i.e. lvm device symlinks */ 179290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (S_ISLNK(buf.st_mode)) { 179390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) struct stat64 buf2; 1794cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1795cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (stat64(argv[i], &buf2) == 0 && 1796cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) S_ISBLK(buf2.st_mode)) 1797cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) buf = buf2; 17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (S_ISBLK(buf.st_mode)) { 1801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) /* Block device */ 18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strncpy(dev_name, argv[i], strnlen(argv[i], PATH_MAX)); 1803f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (get_mount_point(argv[i], dir_name, PATH_MAX) < 0) 1804cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 1805cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (lstat64(dir_name, &buf) < 0) { 18062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) perror(NGMSG_FILE_INFO); 18072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PRINT_FILE_NAME(argv[i]); 18082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 18092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) arg_type = DEVNAME; 18112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!(mode_flag & STATISTIC)) 18122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("ext4 defragmentation for device(%s)\n", 18132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) argv[i]); 18142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (S_ISDIR(buf.st_mode)) { 1815f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) /* Directory */ 1816116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (access(argv[i], R_OK) < 0) { 1817eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch perror(argv[i]); 1818eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch continue; 1819eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1820116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch arg_type = DIRNAME; 1821eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch strncpy(dir_name, argv[i], strnlen(argv[i], PATH_MAX)); 18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (S_ISREG(buf.st_mode)) { 18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Regular file */ 1824cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) arg_type = FILENAME; 1825cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 1826cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /* Irregular file */ 1827cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PRINT_ERR_MSG(NGMSG_FILE_UNREG); 1828cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PRINT_FILE_NAME(argv[i]); 18295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue; 18305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 18315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 18325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /* Set blocksize */ 18335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) block_size = buf.st_blksize; 1834cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1835cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /* For device case, 1836cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * filesystem type checked in get_mount_point() 1837cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 1838cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (arg_type == FILENAME || arg_type == DIRNAME) { 18395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (is_ext4(argv[i], dev_name) < 0) 18405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue; 1841cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (realpath(argv[i], dir_name) == NULL) { 1842cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) perror("Couldn't get full path"); 1843cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PRINT_FILE_NAME(argv[i]); 1844cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 1845cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1846cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1847cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1848cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (current_uid == ROOT_UID) { 1849cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /* Get super block info */ 1850cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ret = ext2fs_open(dev_name, 0, 0, block_size, 1851cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unix_io_manager, &fs); 1852cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (ret) { 1853cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (mode_flag & DETAIL) { 18545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) perror("Can't get super block info"); 1855cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PRINT_FILE_NAME(argv[i]); 1856cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1857cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 1858cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1859cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1860cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) blocks_per_group = fs->super->s_blocks_per_group; 1861cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) feature_incompat = fs->super->s_feature_incompat; 1862cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) log_groups_per_flex = fs->super->s_log_groups_per_flex; 1863cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1864cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ext2fs_close(fs); 18655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 18665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1867cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) switch (arg_type) { 18685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int mount_dir_len = 0; 1869cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1870cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case DIRNAME: 1871cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!(mode_flag & STATISTIC)) 1872cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) printf("ext4 defragmentation " 18735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "for directory(%s)\n", argv[i]); 18745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 18755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mount_dir_len = strnlen(lost_found_dir, PATH_MAX); 18765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 18775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) strncat(lost_found_dir, "/lost+found", 18785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PATH_MAX - strnlen(lost_found_dir, PATH_MAX)); 18795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 18805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /* Not the case("e4defrag mount_piont_dir") */ 18815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (dir_name[mount_dir_len] != '\0') { 18825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /* 18835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * "e4defrag mount_piont_dir/lost+found" 18845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * or "e4defrag mount_piont_dir/lost+found/" 18855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 18865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (strncmp(lost_found_dir, dir_name, 18875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) strnlen(lost_found_dir, 18885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PATH_MAX)) == 0 && 1889cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (dir_name[strnlen(lost_found_dir, 1890cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PATH_MAX)] == '\0' || 1891116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch dir_name[strnlen(lost_found_dir, 1892f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) PATH_MAX)] == '/')) { 1893cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PRINT_ERR_MSG(NGMSG_LOST_FOUND); 1894cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PRINT_FILE_NAME(argv[i]); 1895cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 1896cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 18972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* "e4defrag mount_piont_dir/else_dir" */ 1899eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch memset(lost_found_dir, 0, PATH_MAX + 1); 19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DEVNAME: 19021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (arg_type == DEVNAME) { 19031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci strncpy(lost_found_dir, dir_name, 19041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci strnlen(dir_name, PATH_MAX)); 19051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci strncat(lost_found_dir, "/lost+found/", 19061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PATH_MAX - strnlen(lost_found_dir, 19071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PATH_MAX)); 19081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 19091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 19101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci nftw64(dir_name, calc_entry_counts, FTW_OPEN_FD, flags); 19111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 19121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (mode_flag & STATISTIC) { 19131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (mode_flag & DETAIL) 19141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci printf("%-40s%10s/%-10s%9s\n", 19151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "<File>", "now", "best", "size/ext"); 19161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 19171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!(mode_flag & DETAIL) && 19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_uid != ROOT_UID) { 19195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) printf(" Done.\n"); 19205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) success_flag = 1; 19215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 19221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nftw64(dir_name, file_statistic, 19250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FTW_OPEN_FD, flags); 19260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 19270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (succeed_cnt != 0 && 19280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch current_uid == ROOT_UID) { 19290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (mode_flag & DETAIL) 19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("\n"); 19316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) printf("%-40s%10s/%-10s%9s\n", 19325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "<Fragmented files>", "now", 19335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "best", "size/ext"); 19345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (j = 0; j < SHOW_FRAG_FILES; j++) { 1935a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (strlen(frag_rank[j]. 1936a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) msg_buffer) > 37) { 19375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) printf("%d. %s\n%50d/" 1938a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) "%-10d%6llu KB\n", 1939a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) j + 1, 1940a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) frag_rank[j].msg_buffer, 19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frag_rank[j].now_count, 19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frag_rank[j].best_count, 19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frag_rank[j]. 19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_per_ext); 19455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else if (strlen(frag_rank[j]. 19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg_buffer) > 0) { 19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("%d. %-37s%10d/" 19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%-10d%6llu KB\n", 19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j + 1, 19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frag_rank[j].msg_buffer, 19512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frag_rank[j].now_count, 19522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frag_rank[j].best_count, 19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frag_rank[j]. 19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_per_ext); 19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else 195603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) break; 19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* File tree walk */ 19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nftw64(dir_name, file_defrag, FTW_OPEN_FD, flags); 19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("\n\tSuccess:\t\t\t[ %u/%u ]\n", succeed_cnt, 19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_count); 19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("\tFailure:\t\t\t[ %u/%u ]\n", 19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_count - succeed_cnt, total_count); 19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) { 19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("\tTotal extents:\t\t\t%4d->%d\n", 19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extents_before_defrag, 19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extents_after_defrag); 19712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf("\tFragmented percentage:\t\t" 19722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "%3llu%%->%llu%%\n", 19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !regular_count ? 0 : 19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((unsigned long long) 19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frag_files_before_defrag * 100) / 19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) regular_count, 19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !regular_count ? 0 : 19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((unsigned long long) 19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frag_files_after_defrag * 100) / 19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) regular_count); 19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILENAME: 19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_count = 1; 19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) regular_count = 1; 19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strncat(lost_found_dir, "/lost+found/", 19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PATH_MAX - strnlen(lost_found_dir, 19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PATH_MAX)); 19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strncmp(lost_found_dir, dir_name, 19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strnlen(lost_found_dir, 19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PATH_MAX)) == 0) { 19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_ERR_MSG(NGMSG_LOST_FOUND); 19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRINT_FILE_NAME(argv[i]); 19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 19954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & STATISTIC) { 19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_statistic(argv[i], &buf, FTW_F, NULL); 19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2000ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else 20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("ext4 defragmentation for %s\n", 20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) argv[i]); 20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Defrag single file process */ 20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_defrag(argv[i], &buf, FTW_F, NULL); 20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (succeed_cnt != 0) 20062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf(" Success:\t\t\t[1/1]\n"); 20072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 20082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printf(" Success:\t\t\t[0/1]\n"); 20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (succeed_cnt != 0) 20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success_flag = 1; 20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & STATISTIC) { 2016116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (current_uid != ROOT_UID) { 20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf(" Done.\n"); 20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!succeed_cnt) { 20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mode_flag & DETAIL) 20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("\n"); 20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (arg_type == DEVNAME) 20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf(" In this device(%s), " 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "none can be defragmented.\n", argv[i]); 20286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) else if (arg_type == DIRNAME) 20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf(" In this directory(%s), " 20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "none can be defragmented.\n", argv[i]); 20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf(" This file(%s) " 20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "can't be defragmented.\n", argv[i]); 20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float files_ratio = 0.0; 20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score = 0.0; 20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __u64 size_per_ext = files_block_count * 20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (buf.st_blksize / 1024) / 20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extents_before_defrag; 20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) files_ratio = (float)(extents_before_defrag - 20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extents_after_defrag) * 20425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 100 / files_block_count; 20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) score = CALC_SCORE(files_ratio); 20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("\n Total/best extents\t\t\t\t%d/%d\n" 20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " Average size per extent" 20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\t\t\t%llu KB\n" 20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " Fragmentation score\t\t\t\t%.0f\n", 20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extents_before_defrag, 20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extents_after_defrag, 20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_per_ext, score); 20515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) printf(" [0-30 no problem:" 20525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " 31-55 a little bit fragmented:" 20535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) " 56- needs defrag]\n"); 20545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (arg_type == DEVNAME) 20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf(" This device (%s) ", argv[i]); 20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (arg_type == DIRNAME) 20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf(" This directory (%s) ", 20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) argv[i]); 20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 206190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) printf(" This file (%s) ", argv[i]); 20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (score > BOUND_SCORE) 20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("needs defragmentation.\n"); 20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("does not need " 20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "defragmentation.\n"); 20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf(" Done.\n"); 20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success_flag) 20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) exit(1); 20785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)out: 20800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) printf(MSG_USAGE); 20810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) exit(1); 20820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 20835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)