When 256-byte inodes are used, ext4 attempts to extend the tv_sec portion of file timestamps from 32 to 34 bits on 64-bit systems, presumably to defer the Y2038 problem. However the code to do this still fails in 2038. Nevertheless, some timestamps beyond the year 2038 work correctly. Using 2.6.35/x86_64 on ext4 with 256-byte inodes: markh@zacc:~$ touch -d 2038-01-31 /test/2038 markh@zacc:~$ touch -d 2106-02-22 /test/2106 markh@zacc:~$ ls -l /test/2038 /test/2106 -rw-r--r-- 1 markh markh 0 2038-01-31 00:00 /test/2038 -rw-r--r-- 1 markh markh 0 2106-02-22 00:00 /test/2106 markh@zacc:~$ sudo umount /test markh@zacc:~$ sudo mount /dev/sda2 /test markh@zacc:~$ ls -l /test/2038 /test/2106 -rw-r--r-- 1 markh markh 0 1901-12-25 17:31 /test/2038 -rw-r--r-- 1 markh markh 0 2106-02-22 00:00 /test/2106 markh@zacc:~$ The problem is in fs/ext4/ext.h. The macros EXT4_INODE_GET_XTIME and EXT4_EINODE_GET_XTIME sign-extend the low 32 bits of tv_sec, and then ext4_decode_extra_time uses "|=" to tack on the 2 additional bits. However if bit 31 is 1, bits 32..63 will always be 1 due to the sign extension regardless of the 2 extra bits: static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra) { if (sizeof(time->tv_sec) > 4) time->tv_sec |= (__u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK) << 32; time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS; } ... #define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \ do { \ (inode)->xtime.tv_sec = (signed)le32_to_cpu((raw_inode)->xtime); \ if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \ ext4_decode_extra_time(&(inode)->xtime, \ raw_inode->xtime ## _extra); \ } while (0) It is not clear what time range was intended to be handled, but the range should be continuous. Preferably it would be the range -0x80000000 (1901-12-13) to 0x37fffffff (2446-05-10), in order to handle all legacy 32-bit timestamps and as many consecutive future dates as possible.
Impressively, this bug is still present in v3.14-rc8. $ touch -d 2038-01-31 test-123 $ sudo sh -c "echo 3 > /proc/sys/vm/drop_caches" $ ls -ld test-123 drwxrwxr-x 2 cmeyer cmeyer 4096 Dec 25 1901 test-123
Patch submitted, seems to fix the issue on my system. https://lkml.org/lkml/2014/3/30/40
34 (signed) bits of seconds gets us to Y2242: $ touch -d 2242-01-01 test-123 $ sync ;sudo sh -c "echo 3 > /proc/sys/vm/drop_caches"; sleep 1; sudo sh -c "echo 3 > /proc/sys/vm/drop_caches"; sleep 1; ls -ld test-123 drwxrwxr-x 2 cmeyer cmeyer 4096 Jan 1 2242 test-123 $ touch -d 2243-01-01 test-123 $ sync ;sudo sh -c "echo 3 > /proc/sys/vm/drop_caches"; sleep 1; sudo sh -c "echo 3 > /proc/sys/vm/drop_caches"; sleep 1; ls -ld test-123 drwxrwxr-x 2 cmeyer cmeyer 4096 Aug 3 1698 test-123
(Which we expect, given:) $ echo $((1970+(2038-1970)*4)) 2242
Hm, ignore my patch I guess. Some historical context: http://thread.gmane.org/gmane.comp.file-systems.ext4/40978
> RESOLVED CODE_FIX Alan, what patch fixed it (sha1)? Thanks!
I don't have the number. I re-ran your test case [root@localhost next]# touch -d 2038-01-31 test-123 [root@localhost next]# ls -l test-123 -rw-r--r--. 1 root root 0 Jan 31 2038 test-123 [root@localhost next]# echo 3 >/proc/sys/vm/drop_caches [root@localhost next]# ls -l test-123 -rw-r--r--. 1 root root 0 Jan 31 2038 test-123
The test case is 'touch -d 2243-01-01 test-123'... 2038 works fine.
Hm, 2243 appears to work now too. *Shrug*.
I'm not sure why the test cases have been passing but the true fix hasn't been applied yet. This is due to my not having time and the need for us to have better test cases in e2fsprogs (for both the old and new encodings, etc.) As usual, the highly urgent problems with short-term deadlines tend to get higher priority from the important long-term items. Specifically, I want to be able to convert time strings to integers using both the old the new encodings, and then have test cases to make sure that e2fsck and the kernel are doing the right thing and coverting as necessary as we had determined in the migration plan for this bug.
This has been fixed in the latest kernel and e2fsprogs