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