Using EXT4_IOC_MIGRATE on a non-extent directory seems to have terrible consequences. Consider the following example. "dir" is a old directory without extents. $ ls -la dir/ total 12 drwxr-xr-x 2 benjamin benjamin 4096 Aug 3 20:42 . drwxr-xr-x 47 benjamin benjamin 4096 Aug 3 20:42 .. -rw-r----- 1 benjamin benjamin 7 Aug 3 20:42 something.txt $ cat migrate.c #include <fcntl.h> #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { const char *fn = argv[1]; int fd, ret; fd = open(fn, O_RDONLY); /* This invokes EXT4_IOC_MIGRATE. */ ret = ioctl(fd, 0x6609); close(fd); if (ret < 0) { fprintf(stderr, "ioctl failed\n"); return 1; } printf("Migration successful?\n"); return 0; } $ gcc -o migrate migrate.c $ ./migrate dir Migration successful? $ ls -la dir total 0 # !!!!!!!!!!!!!! Also, we why are you allowed to migrate stuff with only O_RDONLY access?
Tested with 3.0, and it works here. git log shows that a possible fix should be 74e4e6db3 which is included in 3.0. One thing you could confirm is to run: debugfs 'stat dir' /dev/sdx to see whether the EXTENTS flags is set or not. If it isn't set, it should be the root cause.
When I ran e2fsck on the partition, it reported EXTENTS_FL was not set.
Indeed, it is now fixed. Thanks.