summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/fs/ext2fs/ext2_alloc.c18
-rwxr-xr-xsys/fs/ext2fs/ext2_dinode.h18
-rw-r--r--sys/fs/ext2fs/ext2_inode_cnv.c17
-rw-r--r--sys/fs/ext2fs/ext2_vfsops.c22
-rw-r--r--sys/fs/ext2fs/ext2_vnops.c12
-rwxr-xr-xsys/fs/ext2fs/ext2fs.h8
-rw-r--r--sys/fs/ext2fs/inode.h2
7 files changed, 74 insertions, 23 deletions
diff --git a/sys/fs/ext2fs/ext2_alloc.c b/sys/fs/ext2fs/ext2_alloc.c
index c834077..15d938c 100644
--- a/sys/fs/ext2fs/ext2_alloc.c
+++ b/sys/fs/ext2fs/ext2_alloc.c
@@ -344,6 +344,7 @@ ext2_valloc(pvp, mode, cred, vpp)
struct ucred *cred;
struct vnode **vpp;
{
+ struct timespec ts;
struct inode *pip;
struct m_ext2fs *fs;
struct inode *ip;
@@ -385,14 +386,14 @@ ext2_valloc(pvp, mode, cred, vpp)
}
ip = VTOI(*vpp);
- /*
- the question is whether using VGET was such good idea at all -
- Linux doesn't read the old inode in when it's allocating a
- new one. I will set at least i_size & i_blocks the zero.
- */
- ip->i_mode = 0;
+ /*
+ * The question is whether using VGET was such good idea at all:
+ * Linux doesn't read the old inode in when it is allocating a
+ * new one. I will set at least i_size and i_blocks to zero.
+ */
ip->i_size = 0;
ip->i_blocks = 0;
+ ip->i_mode = 0;
ip->i_flags = 0;
/* now we want to make sure that the block pointers are zeroed out */
for (i = 0; i < NDADDR; i++)
@@ -406,6 +407,11 @@ ext2_valloc(pvp, mode, cred, vpp)
*/
if (ip->i_gen == 0 || ++ip->i_gen == 0)
ip->i_gen = random() / 2 + 1;
+
+ vfs_timestamp(&ts);
+ ip->i_birthtime = ts.tv_sec;
+ ip->i_birthnsec = ts.tv_nsec;
+
/*
printf("ext2_valloc: allocated inode %d\n", ino);
*/
diff --git a/sys/fs/ext2fs/ext2_dinode.h b/sys/fs/ext2fs/ext2_dinode.h
index 6893ccc..1a7bf2d 100755
--- a/sys/fs/ext2fs/ext2_dinode.h
+++ b/sys/fs/ext2fs/ext2_dinode.h
@@ -61,6 +61,16 @@
#define EXT2_NODUMP 0x00000040 /* do not dump file */
#define EXT2_NOATIME 0x00000080 /* do not update atime */
+/*
+ * Definitions for nanosecond timestamps.
+ * Ext3 inode versioning, 2006-12-13.
+ */
+#define EXT3_EPOCH_BITS 2
+#define EXT3_EPOCH_MASK ((1 << EXT3_EPOCH_BITS) - 1)
+#define EXT3_NSEC_MASK (~0UL << EXT3_EPOCH_BITS)
+
+#define E2DI_HAS_XTIME(ip) (EXT2_INODE_SIZE((ip)->i_e2fs) > \
+ E2FS_REV0_INODE_SIZE)
/*
* Structure of an inode on the disk
@@ -77,7 +87,7 @@ struct ext2fs_dinode {
uint16_t e2di_nlink; /* 26: File link count */
uint32_t e2di_nblock; /* 28: Blocks count */
uint32_t e2di_flags; /* 32: Status flags (chflags) */
- uint32_t e2di_linux_reserved1; /* 36 */
+ uint32_t e2di_version; /* 36: Low 32 bits inode version */
uint32_t e2di_blocks[EXT2_N_BLOCKS]; /* 40: disk blocks */
uint32_t e2di_gen; /* 100: generation number */
uint32_t e2di_facl; /* 104: file ACL (not implemented) */
@@ -91,6 +101,12 @@ struct ext2fs_dinode {
uint32_t e2di_linux_reserved3; /* 124 */
uint16_t e2di_extra_isize;
uint16_t e2di_pad1;
+ uint32_t e2di_ctime_extra; /* Extra change time */
+ uint32_t e2di_mtime_extra; /* Extra modification time */
+ uint32_t e2di_atime_extra; /* Extra access time */
+ uint32_t e2di_crtime; /* Creation (birth)time */
+ uint32_t e2di_crtime_extra; /* Extra creation (birth)time */
+ uint32_t e2di_version_hi; /* High 30 bits of inode version */
};
#endif /* !_FS_EXT2FS_EXT2_DINODE_H_ */
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;
diff --git a/sys/fs/ext2fs/ext2_vfsops.c b/sys/fs/ext2fs/ext2_vfsops.c
index 8f7e8b8..48d5cb2 100644
--- a/sys/fs/ext2fs/ext2_vfsops.c
+++ b/sys/fs/ext2fs/ext2_vfsops.c
@@ -47,6 +47,7 @@
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/conf.h>
+#include <sys/endian.h>
#include <sys/fcntl.h>
#include <sys/malloc.h>
#include <sys/stat.h>
@@ -339,14 +340,21 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es,
/*
* Simple sanity check for superblock inode size value.
*/
- if (fs->e2fs_isize < E2FS_REV0_INODE_SIZE ||
- fs->e2fs_isize > fs->e2fs_bsize ||
+ if (EXT2_INODE_SIZE(fs) < E2FS_REV0_INODE_SIZE ||
+ EXT2_INODE_SIZE(fs) > fs->e2fs_bsize ||
(fs->e2fs_isize & (fs->e2fs_isize - 1)) != 0) {
- printf("EXT2-fs: invalid inode size %d\n",
+ printf("ext2fs: invalid inode size %d\n",
fs->e2fs_isize);
return (EIO);
}
}
+ /* Check for extra isize in big inodes. */
+ if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT4F_ROCOMPAT_EXTRA_ISIZE) &&
+ EXT2_INODE_SIZE(fs) < sizeof(struct ext2fs_dinode)) {
+ printf("ext2fs: no space for extra inode timestamps\n");
+ return (EINVAL);
+ }
+
fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs);
fs->e2fs_itpg = fs->e2fs_ipg /fs->e2fs_ipb;
fs->e2fs_descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
@@ -358,8 +366,8 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es,
fs->e2fs_gdbcount = db_count;
fs->e2fs_gd = malloc(db_count * fs->e2fs_bsize,
M_EXT2MNT, M_WAITOK);
- fs->e2fs_contigdirs = malloc(fs->e2fs_gcount * sizeof(*fs->e2fs_contigdirs),
- M_EXT2MNT, M_WAITOK);
+ fs->e2fs_contigdirs = malloc(fs->e2fs_gcount *
+ sizeof(*fs->e2fs_contigdirs), M_EXT2MNT, M_WAITOK);
/*
* Adjust logic_sb_block.
@@ -390,7 +398,7 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es,
fs->e2fs_contigdirs[i] = 0;
}
if (es->e2fs_rev == E2FS_REV0 ||
- (es->e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE) == 0)
+ !EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_LARGEFILE))
fs->e2fs_maxfilesize = 0x7fffffff;
else
fs->e2fs_maxfilesize = 0x7fffffffffffffff;
@@ -967,8 +975,6 @@ ext2_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
ip->i_block_group = ino_to_cg(fs, ino);
ip->i_next_alloc_block = 0;
ip->i_next_alloc_goal = 0;
- ip->i_prealloc_count = 0;
- ip->i_prealloc_block = 0;
/*
* Now we want to make sure that block pointers for unused
diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c
index c357a2a..136654c 100644
--- a/sys/fs/ext2fs/ext2_vnops.c
+++ b/sys/fs/ext2fs/ext2_vnops.c
@@ -360,11 +360,15 @@ ext2_getattr(ap)
vap->va_rdev = ip->i_rdev;
vap->va_size = ip->i_size;
vap->va_atime.tv_sec = ip->i_atime;
- vap->va_atime.tv_nsec = ip->i_atimensec;
+ vap->va_atime.tv_nsec = E2DI_HAS_XTIME(ip) ? ip->i_atimensec : 0;
vap->va_mtime.tv_sec = ip->i_mtime;
- vap->va_mtime.tv_nsec = ip->i_mtimensec;
+ vap->va_mtime.tv_nsec = E2DI_HAS_XTIME(ip) ? ip->i_mtimensec : 0;
vap->va_ctime.tv_sec = ip->i_ctime;
- vap->va_ctime.tv_nsec = ip->i_ctimensec;
+ vap->va_ctime.tv_nsec = E2DI_HAS_XTIME(ip) ? ip->i_ctimensec : 0;
+ if E2DI_HAS_XTIME(ip) {
+ vap->va_birthtime.tv_sec = ip->i_birthtime;
+ vap->va_birthtime.tv_nsec = ip->i_birthnsec;
+ }
vap->va_flags = ip->i_flags;
vap->va_gen = ip->i_gen;
vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
@@ -501,6 +505,8 @@ ext2_setattr(ap)
ip->i_mtime = vap->va_mtime.tv_sec;
ip->i_mtimensec = vap->va_mtime.tv_nsec;
}
+ ip->i_birthtime = vap->va_birthtime.tv_sec;
+ ip->i_birthnsec = vap->va_birthtime.tv_nsec;
error = ext2_update(vp, 0);
if (error)
return (error);
diff --git a/sys/fs/ext2fs/ext2fs.h b/sys/fs/ext2fs/ext2fs.h
index 14027ab..83e2a68 100755
--- a/sys/fs/ext2fs/ext2fs.h
+++ b/sys/fs/ext2fs/ext2fs.h
@@ -129,7 +129,7 @@ struct ext2fs {
uint32_t e4fs_rbcount_hi; /* reserved blocks count */
uint32_t e4fs_fbcount_hi; /* free blocks count */
uint16_t e4fs_min_extra_isize;/* all inodes have at least some bytes */
- uint16_t e4fs_want_extra_isize; /* new inodes should reserve some bytes */
+ uint16_t e4fs_want_extra_isize; /* inodes must reserve some bytes */
uint32_t e4fs_flags; /* miscellaneous flags */
uint16_t e4fs_raid_stride; /* RAID stride */
uint16_t e4fs_mmpintv; /* number of seconds to wait in MMP checking */
@@ -214,6 +214,7 @@ struct m_ext2fs {
#define EXT2F_ROCOMPAT_SPARSESUPER 0x0001
#define EXT2F_ROCOMPAT_LARGEFILE 0x0002
#define EXT2F_ROCOMPAT_BTREE_DIR 0x0004
+#define EXT4F_ROCOMPAT_EXTRA_ISIZE 0x0040
#define EXT2F_INCOMPAT_COMP 0x0001
#define EXT2F_INCOMPAT_FTYPE 0x0002
@@ -227,8 +228,9 @@ struct m_ext2fs {
* - EXT2F_INCOMPAT_FTYPE
*/
#define EXT2F_COMPAT_SUPP 0x0000
-#define EXT2F_ROCOMPAT_SUPP (EXT2F_ROCOMPAT_SPARSESUPER \
- | EXT2F_ROCOMPAT_LARGEFILE)
+#define EXT2F_ROCOMPAT_SUPP (EXT2F_ROCOMPAT_SPARSESUPER | \
+ EXT2F_ROCOMPAT_LARGEFILE | \
+ EXT4F_ROCOMPAT_EXTRA_ISIZE)
#define EXT2F_INCOMPAT_SUPP EXT2F_INCOMPAT_FTYPE
/* Assume that user mode programs are passing in an ext2fs superblock, not
diff --git a/sys/fs/ext2fs/inode.h b/sys/fs/ext2fs/inode.h
index 659b950..100a076 100644
--- a/sys/fs/ext2fs/inode.h
+++ b/sys/fs/ext2fs/inode.h
@@ -77,8 +77,6 @@ struct inode {
uint32_t i_block_group;
uint32_t i_next_alloc_block;
uint32_t i_next_alloc_goal;
- uint32_t i_prealloc_block;
- uint32_t i_prealloc_count;
/* Fields from struct dinode in UFS. */
uint16_t i_mode; /* IFMT, permissions; see below. */
OpenPOWER on IntegriCloud