Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F149816756
D48711.1790971505.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D48711.1790971505.diff
View Options
diff --git a/lib/libufs/inode.c b/lib/libufs/inode.c
--- a/lib/libufs/inode.c
+++ b/lib/libufs/inode.c
@@ -43,6 +43,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
#include <libufs.h>
@@ -53,6 +54,7 @@
ino_t min, max;
caddr_t inoblock;
struct fs *fs;
+ struct timespec now;
ERROR(disk, NULL);
@@ -65,6 +67,10 @@
min = disk->d_inomin;
max = disk->d_inomax;
+ if (clock_gettime(CLOCK_REALTIME_FAST, &now) != 0) {
+ ERROR(disk, "cannot get current time of day");
+ return (-1);
+ }
if (inum >= min && inum < max)
goto gotit;
bread(disk, fsbtodb(fs, ino_to_fsba(fs, inum)), inoblock,
@@ -74,6 +80,8 @@
gotit: switch (disk->d_ufs) {
case 1:
disk->d_dp.dp1 = &((struct ufs1_dinode *)inoblock)[inum - min];
+ if (ffs_oldfscompat_inode_read(fs, disk->d_dp, now.tv_sec))
+ putinode(disk);
if (dp != NULL)
*dp = disk->d_dp;
return (0);
@@ -81,8 +89,12 @@
disk->d_dp.dp2 = &((struct ufs2_dinode *)inoblock)[inum - min];
if (dp != NULL)
*dp = disk->d_dp;
- if (ffs_verify_dinode_ckhash(fs, disk->d_dp.dp2) == 0)
+ if (ffs_verify_dinode_ckhash(fs, disk->d_dp.dp2) == 0) {
+ if (ffs_oldfscompat_inode_read(fs, disk->d_dp,
+ now.tv_sec))
+ putinode(disk);
return (0);
+ }
ERROR(disk, "check-hash failed for inode read from disk");
return (-1);
default:
diff --git a/lib/libufs/libufs.h b/lib/libufs/libufs.h
--- a/lib/libufs/libufs.h
+++ b/lib/libufs/libufs.h
@@ -29,6 +29,7 @@
#ifndef __LIBUFS_H__
#define __LIBUFS_H__
+#include <stdbool.h>
/*
* Various disk controllers require their buffers to be aligned to the size
@@ -120,6 +121,7 @@
void ffs_fragacct(struct fs *, int, int32_t [], int);
int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t);
int ffs_isfreeblock(struct fs *, u_char *, ufs1_daddr_t);
+bool ffs_oldfscompat_inode_read(struct fs *, union dinodep, time_t);
int ffs_sbsearch(void *, struct fs **, int, char *,
int (*)(void *, off_t, void **, int));
void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t);
diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c
--- a/sbin/fsck_ffs/inode.c
+++ b/sbin/fsck_ffs/inode.c
@@ -46,6 +46,7 @@
#include "fsck.h"
struct bufarea *icachebp; /* inode cache buffer */
+static time_t now; /* current time of day */
static int iblock(struct inodesc *, off_t isize, int type);
static ufs2_daddr_t indir_blkatoff(ufs2_daddr_t, ino_t, ufs_lbn_t, ufs_lbn_t,
@@ -429,6 +430,7 @@
ginode(ino_t inumber, struct inode *ip)
{
ufs2_daddr_t iblk;
+ union dinodep dpp;
struct ufs2_dinode *dp;
if (inumber < UFS_ROOTINO || inumber >= maxino)
@@ -466,10 +468,14 @@
if (sblock.fs_magic == FS_UFS1_MAGIC) {
ip->i_dp = (union dinode *)
&ip->i_bp->b_un.b_dinode1[inumber - ip->i_bp->b_index];
+ dpp.dp1 = (struct ufs1_dinode *)ip->i_dp;
+ if (ffs_oldfscompat_inode_read(&sblock, dpp, now))
+ inodirty(ip);
return;
}
ip->i_dp = (union dinode *)
&ip->i_bp->b_un.b_dinode2[inumber - ip->i_bp->b_index];
+ dpp.dp2 = dp = (struct ufs2_dinode *)ip->i_dp;
/* Do not check hash of inodes being created */
if (dp->di_mode != 0 && ffs_verify_dinode_ckhash(&sblock, dp)) {
pwarn("INODE CHECK-HASH FAILED");
@@ -481,6 +487,8 @@
inodirty(ip);
}
}
+ if (ffs_oldfscompat_inode_read(&sblock, dpp, now))
+ inodirty(ip);
}
/*
@@ -519,6 +527,7 @@
mode_t mode;
ufs2_daddr_t ndb, blk;
union dinode *dp;
+ union dinodep dpp;
struct inode ip;
static caddr_t nextinop;
@@ -551,8 +560,10 @@
dp = (union dinode *)nextinop;
if (sblock.fs_magic == FS_UFS1_MAGIC) {
nextinop += sizeof(struct ufs1_dinode);
+ dpp.dp1 = (struct ufs1_dinode *)dp;
} else {
nextinop += sizeof(struct ufs2_dinode);
+ dpp.dp2 = (struct ufs2_dinode *)dp;
}
if ((ckhashadd & CK_INODE) != 0) {
ffs_update_dinode_ckhash(&sblock, (struct ufs2_dinode *)dp);
@@ -572,6 +583,8 @@
dirty(&inobuf);
}
}
+ if (ffs_oldfscompat_inode_read(&sblock, dpp, now))
+ dirty(&inobuf);
if (rebuiltcg && (char *)dp == inobuf.b_un.b_buf) {
/*
* Try to determine if we have reached the end of the
@@ -625,8 +638,19 @@
void
setinodebuf(int cg, ino_t inosused)
{
+ struct timespec time;
ino_t inum;
+ /*
+ * Get the current value of the present time.
+ * This will happen before each cylinder group is scanned.
+ * If for some reason getting the time fails, we will use
+ * the last time that the superblock was updated.
+ */
+ if (clock_gettime(CLOCK_REALTIME_FAST, &time) == 0)
+ now = time.tv_sec;
+ else
+ now = sblock.fs_time;
inum = cg * sblock.fs_ipg;
lastvalidinum = inum + inosused - 1;
nextinum = inum;
diff --git a/share/man/man4/ffs.4 b/share/man/man4/ffs.4
--- a/share/man/man4/ffs.4
+++ b/share/man/man4/ffs.4
@@ -285,6 +285,11 @@
Enable support for the rearrangement of blocks
to be contiguous.
.Pq Default: 1 .
+.It Va vfs.ffs.prttimechgs
+Print a console message when timestamps for UFS1 filesystems are found
+to be in the future and are changed to be the present time.
+.Pq Default: 0 .
+.El
.El
.Sh HISTORY
The
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -83,6 +83,7 @@
int ffs_isblock(struct fs *, uint8_t *, ufs1_daddr_t);
int ffs_isfreeblock(struct fs *, uint8_t *, ufs1_daddr_t);
void ffs_oldfscompat_write(struct fs *);
+bool ffs_oldfscompat_inode_read(struct fs *, union dinodep, time_t);
int ffs_own_mount(const struct mount *mp);
int ffs_sbsearch(void *, struct fs **, int, struct malloc_type *,
int (*)(void *, off_t, void **, int));
diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c
--- a/sys/ufs/ffs/ffs_subr.c
+++ b/sys/ufs/ffs/ffs_subr.c
@@ -34,6 +34,7 @@
#include <sys/limits.h>
#ifndef _KERNEL
+#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -59,6 +60,7 @@
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/ucred.h>
+#include <sys/sysctl.h>
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
@@ -395,6 +397,63 @@
}
}
+/*
+ * Sanity checks for loading old filesystem inodes.
+ *
+ * XXX - Parts get retired eventually.
+ * Unfortunately new bits get added.
+ */
+static int prttimechgs = 0;
+#ifdef _KERNEL
+SYSCTL_DECL(_vfs_ffs);
+SYSCTL_INT(_vfs_ffs, OID_AUTO, prttimechgs, CTLFLAG_RWTUN, &prttimechgs, 0,
+ "print UFS1 time changes made to inodes");
+#endif /* _KERNEL */
+bool
+ffs_oldfscompat_inode_read(struct fs *fs, union dinodep dp, time_t now)
+{
+ bool change;
+
+ change = false;
+ switch (fs->fs_magic) {
+ case FS_UFS2_MAGIC:
+ /* No changes for now */
+ break;
+
+ case FS_UFS1_MAGIC:
+ /*
+ * With the change to unsigned time values in UFS1, times set
+ * before Jan 1, 1970 will appear to be in the future. Check
+ * for future times and set them to be the current time.
+ */
+ if (dp.dp1->di_ctime > now) {
+ if (prttimechgs)
+ printf("ctime %ud changed to %ld\n",
+ dp.dp1->di_ctime, (long)now);
+ dp.dp1->di_ctime = now;
+ change = true;
+ }
+ if (dp.dp1->di_mtime > now) {
+ if (prttimechgs)
+ printf("mtime %ud changed to %ld\n",
+ dp.dp1->di_mtime, (long)now);
+ dp.dp1->di_mtime = now;
+ dp.dp1->di_ctime = now;
+ change = true;
+ }
+ if (dp.dp1->di_atime > now) {
+ if (prttimechgs)
+ printf("atime %ud changed to %ld\n",
+ dp.dp1->di_atime, (long)now);
+ dp.dp1->di_atime = now;
+ dp.dp1->di_ctime = now;
+ change = true;
+ }
+ break;
+ }
+ return (change);
+}
+
/*
* Verify the filesystem values.
*/
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -203,6 +203,9 @@
ip->i_gen = dip1->di_gen;
ip->i_uid = dip1->di_uid;
ip->i_gid = dip1->di_gid;
+ if (ffs_oldfscompat_inode_read(fs, ip->i_dp, time_second) &&
+ fs->fs_ronly == 0)
+ UFS_INODE_SET_FLAG(ip, IN_MODIFIED);
return (0);
}
dip2 = ((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
@@ -222,6 +225,9 @@
ip->i_gen = dip2->di_gen;
ip->i_uid = dip2->di_uid;
ip->i_gid = dip2->di_gid;
+ if (ffs_oldfscompat_inode_read(fs, ip->i_dp, time_second) &&
+ fs->fs_ronly == 0)
+ UFS_INODE_SET_FLAG(ip, IN_MODIFIED);
return (0);
}
diff --git a/sys/ufs/ufs/dinode.h b/sys/ufs/ufs/dinode.h
--- a/sys/ufs/ufs/dinode.h
+++ b/sys/ufs/ufs/dinode.h
@@ -185,11 +185,11 @@
uint32_t di_dirdepth; /* 4: IFDIR: depth from root dir */
};
uint64_t di_size; /* 8: File byte count. */
- int32_t di_atime; /* 16: Last access time. */
+ uint32_t di_atime; /* 16: Last access time. */
int32_t di_atimensec; /* 20: Last access time. */
- int32_t di_mtime; /* 24: Last modified time. */
+ uint32_t di_mtime; /* 24: Last modified time. */
int32_t di_mtimensec; /* 28: Last modified time. */
- int32_t di_ctime; /* 32: Last inode change time. */
+ uint32_t di_ctime; /* 32: Last inode change time. */
int32_t di_ctimensec; /* 36: Last inode change time. */
union {
struct {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Oct 2, 8:05 PM (7 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30108217
Default Alt Text
D48711.1790971505.diff (8 KB)
Attached To
Mode
D48711: Defer the January 19, 2038 date limit in UFS1 filesystems to February 7, 2106
Attached
Detach File
Event Timeline
Log In to Comment