[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20141107215545.883.38390.stgit@birch.djwong.org>
Date: Fri, 07 Nov 2014 13:55:45 -0800
From: "Darrick J. Wong" <darrick.wong@...cle.com>
To: tytso@....edu, darrick.wong@...cle.com
Cc: linux-ext4@...r.kernel.org
Subject: [PATCH 46/47] fuse2fs: handle 64-bit dates correctly
Fix fuse2fs' interpretation of 64-bit date quantities to match the
kernel.
Signed-off-by: Darrick J. Wong <darrick.wong@...cle.com>
---
misc/fuse2fs.c | 31 ++++++++++++++++++++++---------
1 file changed, 22 insertions(+), 9 deletions(-)
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index 9d0af5b..022b0ef 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -353,15 +353,24 @@ static int __translate_error(ext2_filsys fs, errcode_t err, ext2_ino_t ino,
static inline __u32 ext4_encode_extra_time(const struct timespec *time)
{
- return (sizeof(time->tv_sec) > 4 ?
- (time->tv_sec >> 32) & EXT4_EPOCH_MASK : 0) |
- ((time->tv_nsec << EXT4_EPOCH_BITS) & EXT4_NSEC_MASK);
+ __u32 extra = sizeof(time->tv_sec) > 4 ?
+ ((time->tv_sec - (__s32)time->tv_sec) >> 32) &
+ EXT4_EPOCH_MASK : 0;
+ return extra | (time->tv_nsec << EXT4_EPOCH_BITS);
}
static inline void ext4_decode_extra_time(struct timespec *time, __u32 extra)
{
- if (sizeof(time->tv_sec) > 4)
- time->tv_sec |= (__u64)((extra) & EXT4_EPOCH_MASK) << 32;
+ if (sizeof(time->tv_sec) > 4 && (extra & EXT4_EPOCH_MASK)) {
+ __u64 extra_bits = extra & EXT4_EPOCH_MASK;
+ /*
+ * Prior to kernel 3.14?, we had a broken decode function,
+ * wherein we effectively did this:
+ * if (extra_bits == 3)
+ * extra_bits = 0;
+ */
+ time->tv_sec += extra_bits << 32;
+ }
time->tv_nsec = ((extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
}
@@ -387,7 +396,7 @@ do { \
(timespec)->tv_sec = (signed)((raw_inode)->xtime); \
if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
ext4_decode_extra_time((timespec), \
- raw_inode->xtime ## _extra); \
+ (raw_inode)->xtime ## _extra); \
else \
(timespec)->tv_nsec = 0; \
} while (0)
@@ -749,6 +758,7 @@ static int stat_inode(ext2_filsys fs, ext2_ino_t ino, struct stat *statbuf)
dev_t fakedev = 0;
errcode_t err;
int ret = 0;
+ struct timespec tv;
memset(&inode, 0, sizeof(inode));
err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
@@ -766,9 +776,12 @@ static int stat_inode(ext2_filsys fs, ext2_ino_t ino, struct stat *statbuf)
statbuf->st_size = EXT2_I_SIZE(&inode);
statbuf->st_blksize = fs->blocksize;
statbuf->st_blocks = blocks_from_inode(fs, &inode);
- statbuf->st_atime = inode.i_atime;
- statbuf->st_mtime = inode.i_mtime;
- statbuf->st_ctime = inode.i_ctime;
+ EXT4_INODE_GET_XTIME(i_atime, &tv, &inode);
+ statbuf->st_atime = tv.tv_sec;
+ EXT4_INODE_GET_XTIME(i_mtime, &tv, &inode);
+ statbuf->st_mtime = tv.tv_sec;
+ EXT4_INODE_GET_XTIME(i_ctime, &tv, &inode);
+ statbuf->st_ctime = tv.tv_sec;
if (LINUX_S_ISCHR(inode.i_mode) ||
LINUX_S_ISBLK(inode.i_mode)) {
if (inode.i_block[0])
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists