Page MenuHomeFreeBSD

D48711.1790971505.diff
No OneTemporary

Size
8 KB
Referenced Files
None
Subscribers
None

D48711.1790971505.diff

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

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)

Event Timeline