xref: /aosp_15_r20/external/e2fsprogs/misc/e4defrag.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
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