if (debugfs_read_inode(inode, &inode_buf, 0))
return;
- inode_buf.i_dtime = current_fs->now ? current_fs->now : time(0);
+ ext2fs_set_dtime(current_fs, &inode_buf);
if (debugfs_write_inode(inode, &inode_buf, 0))
return;
if (ext2fs_inode_has_valid_blocks2(current_fs, &inode_buf)) {
ext2fs_mark_super_dirty(fs);
fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
inode.i_links_count = 0;
- inode.i_dtime = ctx->now;
+ ext2fs_set_dtime(fs, &inode);
if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
goto err_out;
if (!inode->i_dtime && inode->i_mode) {
if (fix_problem(ctx,
PR_1_ZERO_DTIME, &pctx)) {
- inode->i_dtime = ctx->now;
+ ext2fs_set_dtime(fs, inode);
e2fsck_write_inode(ctx, ino, inode,
"pass1");
failed_csum = 0;
inode->i_flags = 0;
inode->i_links_count = 0;
ext2fs_icount_store(ctx->inode_link_info, ino, 0);
- inode->i_dtime = ctx->now;
+ ext2fs_set_dtime(ctx->fs, inode);
/*
* If a special inode has such rotten block mappings that we
ext2fs_inode_alloc_stats2(fs, *ino, -1,
LINUX_S_ISDIR(inode.i_mode));
ctx->free_inodes++;
- inode.i_dtime = ctx->now;
+ ext2fs_set_dtime(fs, EXT2_INODE(&inode));
} else {
inode.i_dtime = 0;
}
return EXT4_HTREE_LEVEL_COMPAT;
}
+/*
+ * We explicitly decided not to reserve space for a 64-bit dtime,
+ * since it's never displayed or exposed to userspace. The dtime
+ * field is used a linked list for the ophan list, and for forensic
+ * purposes when trying to determine when an inode was deleted. So
+ * right after the 2038 epoch, a deleted inode might end up with a
+ * dtime which is zero or smaller than the number of inodes, which
+ * will result in e2fsck reporting a potential problems. So when we
+ * set the dtime, make sure that the dtime won't be mistaken for an
+ * inode number.
+ */
+static inline void ext2fs_set_dtime(ext2_filsys fs, struct ext2_inode *inode)
+{
+ __u32 t;
+
+ if (fs->now || (fs->flags2 & EXT2_FLAG2_USE_FAKE_TIME))
+ t = fs->now & 0xFFFFFFFF;
+ else
+ t = time(NULL) & 0xFFFFFFFF;
+ if (t < fs->super->s_inodes_count)
+ t = fs->super->s_inodes_count;
+ inode->i_dtime = t;
+}
+
#ifdef __cplusplus
}
#endif
goto write_out;
inode.i_links_count = 0;
- inode.i_dtime = ext2fsP_get_time(fs);
+ ext2fs_set_dtime(fs, EXT2_INODE(&inode));
ret = ext2fs_free_ext_attr(fs, ino, &inode);
if (ret)
break;
if (qtype != MAXQUOTAS) {
- inode.i_dtime = fs->now ? fs->now : time(0);
+ ext2fs_set_dtime(fs, &inode);
if (!ext2fs_inode_has_valid_blocks2(fs, &inode))
return 0;
err = ext2fs_punch(fs, ino, &inode, NULL, 0, ~0ULL);
return 0; /* XXX: already done? */
case 1:
inode.i_links_count--;
- inode.i_dtime = fs->now ? fs->now : time(0);
+ ext2fs_set_dtime(fs, EXT2_INODE(&inode));
break;
default:
inode.i_links_count--;
return 0; /* XXX: already done? */
case 1:
inode.i_links_count--;
- inode.i_dtime = fs->now ? fs->now : time(0);
+ ext2fs_set_dtime(fs, EXT2_INODE(&inode));
break;
default:
inode.i_links_count--;