e4defrag: relevant file fragmentation with base_file
PATCH 1/1 e4defrag: relevant file fragmentation with base_file
hi Kazuya Mio,
as I promised the implementation of the new interface
e4defrag -r base_file move_file..
Feel free to change.
Andreas
misc/e4defrag.c +42 -13
@@ -125,7 +125,8 @@#define MSG_USAGE \ "Usage : e4defrag [-v] file...| directory...| device...\n\ : e4defrag -c file...| directory...| device...\n\ - : e4defrag -r directory...| device...\n" + : e4defrag -r directory...| device...\n\ + : e4defrag -r base_file move_file...\n"#define NGMSG_EXT4 "Filesystem is not ext4 filesystem"#define NGMSG_FILE_EXTENT "Failed to get file extents"
@@ -133,7 +134,6 @@#define NGMSG_FILE_OPEN "Failed to open"#define NGMSG_FILE_UNREG "File is not regular file"#define NGMSG_LOST_FOUND "Can not process \"lost+found\"" -#define NGMSG_FILE_UNDIR "Target is not directory"/* Data type for filesystem-wide blocks number */ typedef unsigned long long ext4_fsblk_t ;
@@ -1593,7 +1593,7 @@ static int call_defrag(int fd, int donor_fd, const char *file,return 0 ; } -static unsigned long long get_dir_offset (const int fd,int *ret) +static unsigned long long get_physical_offset (const int fd,int *ret) {struct fiemap *fiemap_buf;char *fiebuf;
@@ -2129,13 +2129,6 @@ int main(int argc, char *argv[])continue ; } -/* -r mode can defrag only directory. */ -if ((mode_flag &RELEVANT ) && arg_type ==FILENAME ) { -PRINT_ERR_MSG (NGMSG_FILE_UNDIR ); -PRINT_FILE_NAME (argv[i]); -continue ; - } -/* Set blocksize */ block_size = buf.st_blksize;
@@ -2223,7 +2216,7 @@ int main(int argc, char *argv[])continue ; } - r_pstart =get_dir_offset (fd, &ret); + r_pstart =get_physical_offset (fd, &ret);if (ret <0 ) {if (mode_flag &DETAIL ) {perror ("failed to fiemap\n" );
@@ -2327,8 +2320,44 @@ int main(int argc, char *argv[]) }else printf ("ext4 defragmentation for %s\n" , argv[i]); -/* Defrag single file process */ -file_defrag (argv[i], &buf,FTW_F ,NULL ); + +if (mode_flag &RELEVANT && i == optind) { +if (i - argc ==1 ) +/* not enought arguemnts */ + goto out; + +/* +* call defrag for base_file +* don't move extents to r_pstart +*/ + mode_flag &= ~RELEVANT ; +file_defrag (argv[i], &buf,FTW_F ,NULL ); + mode_flag |=RELEVANT ; + +/* get physical start of base_file for PA */ +int fd, ret; + fd =open (argv[i],O_RDONLY ); +if (fd <0 ) { +if (mode_flag &DETAIL ) { +PRINT_FILE_NAME (argv[i]); +STATISTIC_ERR_MSG_WITH_ERRNO (NGMSG_FILE_OPEN ); + } + goto out; + } + + r_pstart =get_physical_offset (fd, &ret); +if (ret <0 ) { +if (mode_flag &DETAIL ) { +perror ("failed to fiemap\n" ); +PRINT_FILE_NAME (dir_name); + } + goto out; + } +close (fd); + }else +/* Defrag single file process */ +file_defrag (argv[i], &buf,FTW_F ,NULL ); +if (succeed_cnt !=0 )printf (" Success:\t\t\t[1/1]\n" );else
misc/e4defrag.c int main(int argc, char *argv[]) · line 2327
Quoted 11 lines · Andreas Rid
misc/e4defrag.c +5
-2@@ -2327,8 +2320,44 @@ int main(int argc, char *argv[]) }else printf ("ext4 defragmentation for %s\n" , argv[i]); -/* Defrag single file process */ -file_defrag (argv[i],&buf,FTW_F ,NULL ); + +if (mode_flag&RELEVANT && i == optind) { +if (i - argc ==1 ) +/* not enought arguemnts */ + goto out;
I think this condition should be "argc - optind == 1" because "i" is smaller than argc at all times.
misc/e4defrag.c int main(int argc, char *argv[])
Quoted 4 lines
misc/e4defrag.c +4
-0+ goto out; + } + + r_pstart =get_physical_offset (fd,&ret);
If e4defrag is executed with the following arguments, e4defrag will move the extents of "move_file" near the "directory".
# e4defrag -r base_file directory move_file
To prevent this case, r_pstart should not be changed even if directories or devices are set to the argument of e4defrag after the physical block number of the "base_file" was assigned to r_pstart.
I will fix your patch in above way. Any comments?
Regards,
Kazuya Mio