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