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