diff options
Diffstat (limited to 'fs/inode.c')
| -rw-r--r-- | fs/inode.c | 36 | 
1 files changed, 35 insertions, 1 deletions
diff --git a/fs/inode.c b/fs/inode.c index 0f1e3b563c47..fef457a42882 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -181,6 +181,9 @@ int inode_init_always(struct super_block *sb, struct inode *inode)  	mapping->flags = 0;  	mapping->wb_err = 0;  	atomic_set(&mapping->i_mmap_writable, 0); +#ifdef CONFIG_READ_ONLY_THP_FOR_FS +	atomic_set(&mapping->nr_thps, 0); +#endif  	mapping_set_gfp_mask(mapping, GFP_HIGHUSER_MOVABLE);  	mapping->private_data = NULL;  	mapping->writeback_index = 0; @@ -2167,6 +2170,37 @@ struct timespec64 timespec64_trunc(struct timespec64 t, unsigned gran)  EXPORT_SYMBOL(timespec64_trunc);  /** + * timestamp_truncate - Truncate timespec to a granularity + * @t: Timespec + * @inode: inode being updated + * + * Truncate a timespec to the granularity supported by the fs + * containing the inode. Always rounds down. gran must + * not be 0 nor greater than a second (NSEC_PER_SEC, or 10^9 ns). + */ +struct timespec64 timestamp_truncate(struct timespec64 t, struct inode *inode) +{ +	struct super_block *sb = inode->i_sb; +	unsigned int gran = sb->s_time_gran; + +	t.tv_sec = clamp(t.tv_sec, sb->s_time_min, sb->s_time_max); +	if (unlikely(t.tv_sec == sb->s_time_max || t.tv_sec == sb->s_time_min)) +		t.tv_nsec = 0; + +	/* Avoid division in the common cases 1 ns and 1 s. */ +	if (gran == 1) +		; /* nothing */ +	else if (gran == NSEC_PER_SEC) +		t.tv_nsec = 0; +	else if (gran > 1 && gran < NSEC_PER_SEC) +		t.tv_nsec -= t.tv_nsec % gran; +	else +		WARN(1, "invalid file time granularity: %u", gran); +	return t; +} +EXPORT_SYMBOL(timestamp_truncate); + +/**   * current_time - Return FS time   * @inode: inode.   * @@ -2187,7 +2221,7 @@ struct timespec64 current_time(struct inode *inode)  		return now;  	} -	return timespec64_trunc(now, inode->i_sb->s_time_gran); +	return timestamp_truncate(now, inode);  }  EXPORT_SYMBOL(current_time);  |