diff options
author | pfg <pfg@FreeBSD.org> | 2012-03-08 21:06:05 +0000 |
---|---|---|
committer | pfg <pfg@FreeBSD.org> | 2012-03-08 21:06:05 +0000 |
commit | f8fecfb833f40bb660b5205908a6a91a075e7bd6 (patch) | |
tree | 302d15881b70001d180f475978b302c04f755ec7 /sys/fs/ext2fs/ext2_inode_cnv.c | |
parent | 81cae127b038c1d057cde65bd0457d72894c7d86 (diff) | |
download | FreeBSD-src-f8fecfb833f40bb660b5205908a6a91a075e7bd6.zip FreeBSD-src-f8fecfb833f40bb660b5205908a6a91a075e7bd6.tar.gz |
Add support for ns timestamps and birthtime to the ext2/3 driver.
When using big inodes there is sufficient space in ext3 to
keep extra resolution and birthtime (creation) timestamps.
The appropriate fields in the on-disk inode have been approved
for a long time but support for this in ext3 has not been
widely distributed.
In preparation for ext4 most linux distributions have enabled
by default such bigger inodes and some people use nanosecond
timestamps in ext3. We now support those when the inode is big
enough and while we do recognize the EXT4F_ROCOMPAT_EXTRA_ISIZE,
we maintain the extra timestamps even when they are not used.
An additional note by Bruce Evans:
We blindly accept unrepresentable tv_nsec in VOP_SETATTR(), but
all file systems have always done that. When POSIX gets around
to specifying the behaviour, it will probably require certain
rounding to the fs's resolution and not rejecting the request.
This unfortunately means that syscalls that set times can't
really tell if they succeeded without reading back the times
using stat() or similar and checking that they were set close
enough.
Reviewed by: bde
Approved by: jhb (mentor)
MFC after: 2 weeks
Diffstat (limited to 'sys/fs/ext2fs/ext2_inode_cnv.c')
-rw-r--r-- | sys/fs/ext2fs/ext2_inode_cnv.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/sys/fs/ext2fs/ext2_inode_cnv.c b/sys/fs/ext2fs/ext2_inode_cnv.c index b042a5a..20361a7 100644 --- a/sys/fs/ext2fs/ext2_inode_cnv.c +++ b/sys/fs/ext2fs/ext2_inode_cnv.c @@ -36,6 +36,9 @@ #include <fs/ext2fs/ext2_extern.h> #include <fs/ext2fs/ext2_dinode.h> +#define XTIME_TO_NSEC(x) ((x & EXT3_NSEC_MASK) >> 2) +#define NSEC_TO_XTIME(t) ((t << 2) & EXT3_NSEC_MASK) + void ext2_print_inode( in ) struct inode *in; @@ -83,6 +86,13 @@ ext2_ei2i(ei, ip) ip->i_atime = ei->e2di_atime; ip->i_mtime = ei->e2di_mtime; ip->i_ctime = ei->e2di_ctime; + if (E2DI_HAS_XTIME(ip)) { + ip->i_atimensec = XTIME_TO_NSEC(ei->e2di_atime_extra); + ip->i_mtimensec = XTIME_TO_NSEC(ei->e2di_mtime_extra); + ip->i_ctimensec = XTIME_TO_NSEC(ei->e2di_ctime_extra); + ip->i_birthtime = ei->e2di_crtime; + ip->i_birthnsec = XTIME_TO_NSEC(ei->e2di_crtime_extra); + } ip->i_flags = 0; ip->i_flags |= (ei->e2di_flags & EXT2_APPEND) ? SF_APPEND : 0; ip->i_flags |= (ei->e2di_flags & EXT2_IMMUTABLE) ? SF_IMMUTABLE : 0; @@ -121,6 +131,13 @@ ext2_i2ei(ip, ei) ei->e2di_atime = ip->i_atime; ei->e2di_mtime = ip->i_mtime; ei->e2di_ctime = ip->i_ctime; + if (E2DI_HAS_XTIME(ip)) { + ei->e2di_ctime_extra = NSEC_TO_XTIME(ip->i_ctimensec); + ei->e2di_mtime_extra = NSEC_TO_XTIME(ip->i_mtimensec); + ei->e2di_atime_extra = NSEC_TO_XTIME(ip->i_atimensec); + ei->e2di_crtime = ip->i_birthtime; + ei->e2di_crtime_extra = NSEC_TO_XTIME(ip->i_birthnsec); + } ei->e2di_flags = ip->i_flags; ei->e2di_flags = 0; ei->e2di_flags |= (ip->i_flags & SF_APPEND) ? EXT2_APPEND: 0; |