1 vfs: don't let the dirty time inodes get more than a day stale
3 Guarantee that the on-disk timestamps will be no more than 24 hours
6 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
8 fs/fs-writeback.c | 1 +
9 fs/inode.c | 19 +++++++++++++++++++
10 include/linux/fs.h | 1 +
11 3 files changed, 21 insertions(+)
13 diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
14 index ef8c5d8..529480a 100644
15 --- a/fs/fs-writeback.c
16 +++ b/fs/fs-writeback.c
17 @@ -1143,6 +1143,7 @@ void __mark_inode_dirty(struct inode *inode, int flags)
18 if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
19 trace_writeback_dirty_inode_start(inode, flags);
21 + inode->i_ts_dirty_day = 0;
22 if (sb->s_op->dirty_inode)
23 sb->s_op->dirty_inode(inode, flags);
25 diff --git a/fs/inode.c b/fs/inode.c
26 index 009d9c5..c8ad78b 100644
29 @@ -1510,6 +1510,8 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
31 static int update_time(struct inode *inode, struct timespec *time, int flags)
33 + struct timespec uptime;
34 + unsigned short days_since_boot;
37 if (inode->i_op->is_readonly) {
38 @@ -1532,6 +1534,22 @@ static int update_time(struct inode *inode, struct timespec *time, int flags)
39 !(inode->i_state & (I_DIRTY_SYNC | I_DIRTY_DATASYNC))) {
40 if (inode->i_state & I_DIRTY_TIME)
42 + get_monotonic_boottime(&uptime);
43 + days_since_boot = div_u64(uptime.tv_sec, 86400);
45 + * If i_ts_dirty_day is zero, then either we have not
46 + * deferred timestamp updates, or the system has been
47 + * up for less than a day (so days_since_boot is
48 + * zero), so we can defer timestamp updates in that
49 + * case. If a day or more has passed, then
50 + * i_ts_dirty_day will be different from
51 + * days_since_boot, and then we should update the
52 + * on-disk inode and then we can clear i_ts_dirty_day.
54 + if (inode->i_ts_dirty_day &&
55 + (inode->i_ts_dirty_day != days_since_boot))
58 spin_lock(&inode->i_lock);
59 if (inode->i_state & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
60 spin_unlock(&inode->i_lock);
61 @@ -1542,6 +1560,7 @@ static int update_time(struct inode *inode, struct timespec *time, int flags)
64 inode->i_state |= I_DIRTY_TIME;
65 + inode->i_ts_dirty_day = days_since_boot;
66 spin_unlock(&inode->i_lock);
67 inode_requeue_dirtytime(inode);
69 diff --git a/include/linux/fs.h b/include/linux/fs.h
70 index 6a6f56b..070f6c6 100644
71 --- a/include/linux/fs.h
72 +++ b/include/linux/fs.h
73 @@ -575,6 +575,7 @@ struct inode {
74 struct timespec i_ctime;
75 spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
76 unsigned short i_bytes;
77 + unsigned short i_ts_dirty_day;
78 unsigned int i_blkbits;