diff options
Diffstat (limited to 'misc/e4defrag.c')
-rw-r--r-- | misc/e4defrag.c | 161 |
1 files changed, 68 insertions, 93 deletions
diff --git a/misc/e4defrag.c b/misc/e4defrag.c index 6491edd6..0db5e4bd 100644 --- a/misc/e4defrag.c +++ b/misc/e4defrag.c @@ -34,13 +34,11 @@ #include <unistd.h> #include <ext2fs/ext2_types.h> #include <ext2fs/ext2fs.h> -#include <linux/fs.h> #include <sys/ioctl.h> #include <ext2fs/fiemap.h> #include <sys/mman.h> #include <sys/stat.h> #include <sys/statfs.h> -#include <sys/syscall.h> #include <sys/vfs.h> /* A relatively new ioctl interface ... */ @@ -164,95 +162,44 @@ struct frag_statistic_ino { char msg_buffer[PATH_MAX + 1]; /* pathname of the file */ }; -char lost_found_dir[PATH_MAX + 1]; -int block_size; -int extents_before_defrag; -int extents_after_defrag; -int mode_flag; -unsigned int current_uid; -unsigned int defraged_file_count; -unsigned int frag_files_before_defrag; -unsigned int frag_files_after_defrag; -unsigned int regular_count; -unsigned int succeed_cnt; -unsigned int total_count; -__u8 log_groups_per_flex; -__u32 blocks_per_group; -__u32 feature_incompat; -ext4_fsblk_t files_block_count; -struct frag_statistic_ino frag_rank[SHOW_FRAG_FILES]; - - -/* Local definitions of some syscalls glibc may not yet have */ - -#ifndef HAVE_POSIX_FADVISE -#warning Using locally defined posix_fadvise interface. - -#ifndef __NR_fadvise64_64 -#error Your kernel headers dont define __NR_fadvise64_64 -#endif - -/* - * fadvise() - Give advice about file access. - * - * @fd: defrag target file's descriptor. - * @offset: file offset. - * @len: area length. - * @advise: process flag. - */ -static int posix_fadvise(int fd, loff_t offset, size_t len, int advise) -{ - return syscall(__NR_fadvise64_64, fd, offset, len, advise); -} -#endif /* ! HAVE_FADVISE64_64 */ - -#ifndef HAVE_SYNC_FILE_RANGE -#warning Using locally defined sync_file_range interface. +static char lost_found_dir[PATH_MAX + 1]; +static int block_size; +static int extents_before_defrag; +static int extents_after_defrag; +static int mode_flag; +static unsigned int current_uid; +static unsigned int defraged_file_count; +static unsigned int frag_files_before_defrag; +static unsigned int frag_files_after_defrag; +static unsigned int regular_count; +static unsigned int succeed_cnt; +static unsigned int total_count; +static __u8 log_groups_per_flex; +static __u32 blocks_per_group; +static __u32 feature_incompat; +static ext4_fsblk_t files_block_count; +static struct frag_statistic_ino frag_rank[SHOW_FRAG_FILES]; -#ifndef __NR_sync_file_range -#ifndef __NR_sync_file_range2 /* ppc */ -#error Your kernel headers dont define __NR_sync_file_range -#endif -#endif /* - * sync_file_range() - Sync file region. - * - * @fd: defrag target file's descriptor. - * @offset: file offset. - * @length: area length. - * @flag: process flag. + * We prefer posix_fadvise64 when available, as it allows 64bit offset on + * 32bit systems */ -int sync_file_range(int fd, loff_t offset, loff_t length, unsigned int flag) -{ -#ifdef __NR_sync_file_range - return syscall(__NR_sync_file_range, fd, offset, length, flag); -#else - return syscall(__NR_sync_file_range2, fd, flag, offset, length); +#if defined(HAVE_POSIX_FADVISE64) +#define posix_fadvise posix_fadvise64 +#elif defined(HAVE_FADVISE64) +#define posix_fadvise fadvise64 +#elif !defined(HAVE_POSIX_FADVISE) +#error posix_fadvise not available! #endif -} + +#ifndef HAVE_SYNC_FILE_RANGE +#error sync_file_range not available! #endif /* ! HAVE_SYNC_FILE_RANGE */ #ifndef HAVE_FALLOCATE64 -#warning Using locally defined fallocate syscall interface. - -#ifndef __NR_fallocate -#error Your kernel headers dont define __NR_fallocate -#endif - -/* - * fallocate64() - Manipulate file space. - * - * @fd: defrag target file's descriptor. - * @mode: process flag. - * @offset: file offset. - * @len: file size. - */ -static int fallocate64(int fd, int mode, loff_t offset, loff_t len) -{ - return syscall(__NR_fallocate, fd, mode, offset, len); -} -#endif /* ! HAVE_FALLOCATE */ +#error fallocate64 not available! +#endif /* ! HAVE_FALLOCATE64 */ /* * get_mount_point() - Get device's mount point. @@ -266,8 +213,15 @@ static int get_mount_point(const char *devname, char *mount_point, { /* Refer to /etc/mtab */ const char *mtab = MOUNTED; - FILE *fp = NULL; + FILE *fp = NULL; struct mntent *mnt = NULL; + struct stat64 sb; + + if (stat64(devname, &sb) < 0) { + perror(NGMSG_FILE_INFO); + PRINT_FILE_NAME(devname); + return -1; + } fp = setmntent(mtab, "r"); if (fp == NULL) { @@ -276,7 +230,15 @@ static int get_mount_point(const char *devname, char *mount_point, } while ((mnt = getmntent(fp)) != NULL) { - if (strcmp(devname, mnt->mnt_fsname) != 0) + struct stat64 ms; + + /* + * To handle device symlinks, we see if the + * device number matches, not the name + */ + if (stat64(mnt->mnt_fsname, &ms) < 0) + continue; + if (sb.st_rdev != ms.st_rdev) continue; endmntent(fp); @@ -359,7 +321,7 @@ static int is_ext4(const char *file, char *devname) } endmntent(fp); - if (strcmp(mnt_type, FS_EXT4) == 0) { + if (mnt_type && strcmp(mnt_type, FS_EXT4) == 0) { FREE(mnt_type); return 0; } else { @@ -458,6 +420,9 @@ static int defrag_fadvise(int fd, struct move_extent defrag_data, unsigned int i; loff_t offset; + if (pagesize < 1) + return -1; + offset = (loff_t)defrag_data.orig_start * block_size; offset = (offset / pagesize) * pagesize; @@ -1770,6 +1735,15 @@ int main(int argc, char *argv[]) continue; } + /* Handle i.e. lvm device symlinks */ + if (S_ISLNK(buf.st_mode)) { + struct stat64 buf2; + + if (stat64(argv[i], &buf2) == 0 && + S_ISBLK(buf2.st_mode)) + buf = buf2; + } + if (S_ISBLK(buf.st_mode)) { /* Block device */ strncpy(dev_name, argv[i], strnlen(argv[i], PATH_MAX)); @@ -1820,13 +1794,13 @@ int main(int argc, char *argv[]) if (current_uid == ROOT_UID) { /* Get super block info */ - ret = ext2fs_open(dev_name, 0, 0, block_size, - unix_io_manager, &fs); + ret = ext2fs_open(dev_name, EXT2_FLAG_64BITS, 0, + block_size, unix_io_manager, &fs); if (ret) { - if (mode_flag & DETAIL) { - perror("Can't get super block info"); - PRINT_FILE_NAME(argv[i]); - } + if (mode_flag & DETAIL) + com_err(argv[1], ret, + "while trying to open file system: %s", + dev_name); continue; } @@ -1838,12 +1812,13 @@ int main(int argc, char *argv[]) } switch (arg_type) { + int mount_dir_len = 0; + case DIRNAME: if (!(mode_flag & STATISTIC)) printf("ext4 defragmentation " "for directory(%s)\n", argv[i]); - int mount_dir_len = 0; mount_dir_len = strnlen(lost_found_dir, PATH_MAX); strncat(lost_found_dir, "/lost+found", |