[Y2038] [RFC 15/15] fs: Drop CONFIG_FS_USES_64BIT_TIME

2016-01-06 Thread Deepa Dinamani
All file system code is using 64 bit time already and this config
is no longer required.

Signed-off-by: Deepa Dinamani 
---
 fs/Kconfig | 10 --
 1 file changed, 10 deletions(-)

diff --git a/fs/Kconfig b/fs/Kconfig
index bfeefce..922893f 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -8,16 +8,6 @@ menu "File systems"
 config DCACHE_WORD_ACCESS
bool
 
-#use 64 bit timestamps
-config FS_USES_64BIT_TIME
-   bool
-   default y
-   help
-Temporary configuration to switch over all file systems to
-use 64 bit time.
-Need to be enabled only after all individual file system
-and vfs changes are in place.
-
 if BLOCK
 
 source "fs/ext2/Kconfig"
-- 
1.9.1

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [RFC 11/15] fs: ext4: replace inode_timespec with timespec64

2016-01-06 Thread Deepa Dinamani
Substitute inode_timespec aliases with timespec64.
Since CONFIG_FS_USES_64BIT_TIME is enabled, internally
all inode_timespec references are using timespec64
already.

Signed-off-by: Deepa Dinamani 
---
 fs/ext4/ext4.h| 14 +++---
 fs/ext4/extents.c |  6 +++---
 fs/ext4/ialloc.c  |  2 +-
 fs/ext4/inline.c  |  4 ++--
 fs/ext4/inode.c   |  6 +++---
 fs/ext4/ioctl.c   |  2 +-
 fs/ext4/namei.c   | 10 +-
 fs/ext4/super.c   |  2 +-
 8 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 4bb2604..2d4bef0 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -754,14 +754,14 @@ struct move_extent {
  * affected filesystem before 2242.
  */
 
-static inline __le32 ext4_encode_extra_time(struct inode_timespec *time)
+static inline __le32 ext4_encode_extra_time(struct timespec64 *time)
 {
u32 extra = sizeof(time->tv_sec) > 4 ?
((time->tv_sec - (s32)time->tv_sec) >> 32) & EXT4_EPOCH_MASK : 
0;
return cpu_to_le32(extra | (time->tv_nsec << EXT4_EPOCH_BITS));
 }
 
-static inline void ext4_decode_extra_time(struct inode_timespec *time,
+static inline void ext4_decode_extra_time(struct timespec64 *time,
  __le32 extra)
 {
if (unlikely(sizeof(time->tv_sec) > 4 &&
@@ -787,7 +787,7 @@ static inline void ext4_decode_extra_time(struct 
inode_timespec *time,
 
 #define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode)  
\
 do {   
\
-   struct inode_timespec __ts = VFS_INODE_GET_XTIME(xtime, inode); 
\
+   struct timespec64 __ts = VFS_INODE_GET_XTIME(xtime, inode); 
\
(raw_inode)->xtime = cpu_to_le32(__ts.tv_sec);  
\
if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra))  
\
(raw_inode)->xtime ## _extra =  
\
@@ -805,7 +805,7 @@ do {
   \
 
 #define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode)  
\
 do {   
\
-   struct inode_timespec __ts = VFS_INODE_GET_XTIME(xtime, inode); 
\
+   struct timespec64 __ts = VFS_INODE_GET_XTIME(xtime, inode); 
\
__ts.tv_sec = (signed)le32_to_cpu((raw_inode)->xtime);  
\
if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra))  
\
ext4_decode_extra_time(&__ts,   
\
@@ -935,9 +935,9 @@ struct ext4_inode_info {
 
/*
 * File creation time. Its function is same as that of
-* struct inode_timespec i_{a,c,m}time in the generic inode.
+* struct timespec64 i_{a,c,m}time in the generic inode.
 */
-   struct inode_timespec i_crtime;
+   struct timespec64 i_crtime;
 
/* mballoc */
struct list_head i_prealloc_list;
@@ -1445,7 +1445,7 @@ static inline struct ext4_inode_info *EXT4_I(struct inode 
*inode)
return container_of(inode, struct ext4_inode_info, vfs_inode);
 }
 
-static inline struct inode_timespec ext4_current_time(struct inode *inode)
+static inline struct timespec64 ext4_current_time(struct inode *inode)
 {
return (inode->i_sb->s_time_gran < NSEC_PER_SEC) ?
current_fs_time(inode->i_sb) : current_fs_time_sec(inode->i_sb);
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 99c4800..ec1a912 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4756,7 +4756,7 @@ static long ext4_zero_range(struct file *file, loff_t 
offset,
loff_t len, int mode)
 {
struct inode *inode = file_inode(file);
-   struct inode_timespec now;
+   struct timespec64 now;
handle_t *handle = NULL;
unsigned int max_blocks;
loff_t new_size = 0;
@@ -5465,7 +5465,7 @@ int ext4_collapse_range(struct inode *inode, loff_t 
offset, loff_t len)
 {
struct super_block *sb = inode->i_sb;
ext4_lblk_t punch_start, punch_stop;
-   struct inode_timespec now;
+   struct timespec64 now;
handle_t *handle;
unsigned int credits;
loff_t new_size, ioffset;
@@ -5616,7 +5616,7 @@ int ext4_insert_range(struct inode *inode, loff_t offset, 
loff_t len)
struct ext4_ext_path *path;
struct ext4_extent *extent;
ext4_lblk_t offset_lblk, len_lblk, ee_start_lblk = 0;
-   struct inode_timespec now;
+   struct timespec64 now;
unsigned int credits, ee_len;
int ret = 0, depth, split_flag = 0;
loff_t ioffset;
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 6f16598..929c092 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -756,7 +756,7 @@ struct inode *__ext4_new_inode(handle_t *handle, struct 
inode *dir,
 

[Y2038] [RFC 05/15] fs: cifs: Add support for cifs to use 64 bit time

2016-01-06 Thread Deepa Dinamani
Change all struct timespec references to struct inode_timespec.
Use inode timestamp accessors to access inode time fields.
This will help the switch to struct timespec64 when
CONFIG_FS_USES_64BIT_TIME is enabled.

Use current_fs_time() instead of CURRENT_TIME macros to help
range and precision checks.

Truncate and perform range checks before saving the times in
struct inode.

Switch over connection times to use SYSTEM_TIME macro instead
of CURRENT_TIME. Since SYSTEM_TIME is also under the
CONFIG_FS_USES_64BIT_TIME this will help the switch to use
timespec64.

Use long long for seconds field in cnvrtDosUnixTm(). This will
help represent 64 bit time.
Since DOS uses 1980 epoch, all the timestamps are positive when
represented in UNIX format. Change all arithmetic to unsigned.
Note that even though the theoretical max on DOS times is 2107,
its api's only support until the year 2099. This means we can
get away with 32 bit unsigned sec field. But, the  sec field uses
long long to maintain uniformity in the kernel, where everyone
uses the theoretical max.

Signed-off-by: Deepa Dinamani 
---
 fs/cifs/cache.c   | 16 -
 fs/cifs/cifsencrypt.c |  2 +-
 fs/cifs/cifsglob.h|  6 ++---
 fs/cifs/cifsproto.h   |  9 +++
 fs/cifs/cifssmb.c | 17 +-
 fs/cifs/file.c|  9 ---
 fs/cifs/inode.c   | 65 +--
 fs/cifs/netmisc.c | 26 +++--
 8 files changed, 92 insertions(+), 58 deletions(-)

diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c
index 6c665bf..8d27e69b 100644
--- a/fs/cifs/cache.c
+++ b/fs/cifs/cache.c
@@ -221,8 +221,8 @@ const struct fscache_cookie_def 
cifs_fscache_super_index_def = {
  * Auxiliary data attached to CIFS inode within the cache
  */
 struct cifs_fscache_inode_auxdata {
-   struct timespec last_write_time;
-   struct timespec last_change_time;
+   struct inode_timespec   last_write_time;
+   struct inode_timespec   last_change_time;
u64 eof;
 };
 
@@ -259,8 +259,10 @@ cifs_fscache_inode_get_aux(const void *cookie_netfs_data, 
void *buffer,
 
memset(, 0, sizeof(auxdata));
auxdata.eof = cifsi->server_eof;
-   auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
-   auxdata.last_change_time = cifsi->vfs_inode.i_ctime;
+   auxdata.last_write_time =
+   VFS_INODE_GET_XTIME(i_mtime, >vfs_inode);
+   auxdata.last_change_time =
+   VFS_INODE_GET_XTIME(i_ctime, >vfs_inode);
 
if (maxbuf > sizeof(auxdata))
maxbuf = sizeof(auxdata);
@@ -283,8 +285,10 @@ fscache_checkaux cifs_fscache_inode_check_aux(void 
*cookie_netfs_data,
 
memset(, 0, sizeof(auxdata));
auxdata.eof = cifsi->server_eof;
-   auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
-   auxdata.last_change_time = cifsi->vfs_inode.i_ctime;
+   auxdata.last_write_time =
+   VFS_INODE_GET_XTIME(i_mtime, >vfs_inode);
+   auxdata.last_change_time =
+   VFS_INODE_GET_XTIME(i_ctime, >vfs_inode);
 
if (memcmp(data, , datalen) != 0)
return FSCACHE_CHECKAUX_OBSOLETE;
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index afa09fc..b0ef587 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -483,7 +483,7 @@ find_timestamp(struct cifs_ses *ses)
blobptr += attrsize; /* advance attr value */
}
 
-   return cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
+   return cpu_to_le64(cifs_UnixTimeToNT(FS_TIME));
 }
 
 static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index a25b251..c95dce7 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1393,9 +1393,9 @@ struct cifs_fattr {
dev_t   cf_rdev;
unsigned intcf_nlink;
unsigned intcf_dtype;
-   struct timespec cf_atime;
-   struct timespec cf_mtime;
-   struct timespec cf_ctime;
+   struct inode_timespec   cf_atime;
+   struct inode_timespec   cf_mtime;
+   struct inode_timespec   cf_ctime;
 };
 
 static inline void free_dfs_info_param(struct dfs_info3_param *param)
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index eed7ff5..9979c74 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -126,10 +126,11 @@ extern enum securityEnum select_sectype(struct 
TCP_Server_Info *server,
enum securityEnum requested);
 extern int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
  const struct nls_table *nls_cp);
-extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601);
-extern u64 cifs_UnixTimeToNT(struct timespec);
-extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
- int offset);
+extern struct inode_timespec
+   cifs_NTtimeToUnix(__le64 

[Y2038] [RFC 04/15] vfs: Add support for vfs code to use 64 bit time

2016-01-06 Thread Deepa Dinamani
VFS currently uses struct timespec timestamps which are not
y2038 safe.

Change all the struct inode timestamps accesses through
accessor macros only. This will help the switch over
to 64 bit times seamlessly.

Use struct inode_timespec aliases everywhere.
This will change timestamp data types to  struct timespec64
when 64 bit time switch occurs.

Change all calls to CURRENT_TIME to current_fs_time().
The CURRENT_TIME macro is not accurate for file system code
as it does not perform range checks on timestamps nor does it
cater to individual file system timestamp granularity.
Change all calls to timespec_trunc() to fs_time_trunc().
The latter supports range checking on timestamps.

Signed-off-by: Deepa Dinamani 
---
 fs/attr.c| 15 +++---
 fs/bad_inode.c   | 10 +++--
 fs/binfmt_misc.c |  7 +--
 fs/inode.c   | 53 
 fs/libfs.c   | 45 
 fs/locks.c   |  5 ++---
 fs/nsfs.c|  6 +-
 fs/pipe.c|  6 +-
 fs/posix_acl.c   |  2 +-
 fs/stack.c   |  6 +++---
 fs/stat.c|  6 +++---
 fs/utimes.c  |  6 --
 include/linux/fs_stack.h |  9 
 13 files changed, 121 insertions(+), 55 deletions(-)

diff --git a/fs/attr.c b/fs/attr.c
index 6530ced..4156239 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -148,14 +148,14 @@ void setattr_copy(struct inode *inode, const struct iattr 
*attr)
if (ia_valid & ATTR_GID)
inode->i_gid = attr->ia_gid;
if (ia_valid & ATTR_ATIME)
-   inode->i_atime = timespec_trunc(attr->ia_atime,
-   inode->i_sb->s_time_gran);
+   VFS_INODE_SET_XTIME(i_atime, inode,
+   fs_time_trunc(attr->ia_atime, inode->i_sb));
if (ia_valid & ATTR_MTIME)
-   inode->i_mtime = timespec_trunc(attr->ia_mtime,
-   inode->i_sb->s_time_gran);
+   VFS_INODE_SET_XTIME(i_mtime, inode,
+   fs_time_trunc(attr->ia_mtime, inode->i_sb));
if (ia_valid & ATTR_CTIME)
-   inode->i_ctime = timespec_trunc(attr->ia_ctime,
-   inode->i_sb->s_time_gran);
+   VFS_INODE_SET_XTIME(i_ctime, inode,
+   fs_time_trunc(attr->ia_ctime, inode->i_sb));
if (ia_valid & ATTR_MODE) {
umode_t mode = attr->ia_mode;
 
@@ -192,7 +192,7 @@ int notify_change(struct dentry * dentry, struct iattr * 
attr, struct inode **de
struct inode *inode = dentry->d_inode;
umode_t mode = inode->i_mode;
int error;
-   struct timespec now;
+   struct inode_timespec now;
unsigned int ia_valid = attr->ia_valid;
 
WARN_ON_ONCE(!mutex_is_locked(>i_mutex));
@@ -210,7 +210,6 @@ int notify_change(struct dentry * dentry, struct iattr * 
attr, struct inode **de
}
 
now = current_fs_time(inode->i_sb);
-
attr->ia_ctime = now;
if (!(ia_valid & ATTR_ATIME_SET))
attr->ia_atime = now;
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 103f5d7..3c51e22 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -169,11 +169,17 @@ static const struct inode_operations bad_inode_ops =
  
 void make_bad_inode(struct inode *inode)
 {
+   struct inode_timespec now;
+
remove_inode_hash(inode);
 
inode->i_mode = S_IFREG;
-   inode->i_atime = inode->i_mtime = inode->i_ctime =
-   current_fs_time(inode->i_sb);
+
+   now = current_fs_time(inode->i_sb);
+
+   VFS_INODE_SET_XTIME(i_atime, inode, now);
+   VFS_INODE_SET_XTIME(i_mtime, inode, now);
+   VFS_INODE_SET_XTIME(i_ctime, inode, now);
inode->i_op = _inode_ops;   
inode->i_fop = _file_ops;   
 }
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 78f005f..4fd4437 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -562,12 +562,15 @@ static void entry_status(Node *e, char *page)
 static struct inode *bm_get_inode(struct super_block *sb, int mode)
 {
struct inode *inode = new_inode(sb);
+   struct inode_timespec now;
 
if (inode) {
inode->i_ino = get_next_ino();
inode->i_mode = mode;
-   inode->i_atime = inode->i_mtime = inode->i_ctime =
-   current_fs_time(inode->i_sb);
+   now = current_fs_time(inode->i_sb);
+   VFS_INODE_SET_XTIME(i_atime, inode, now);
+   VFS_INODE_SET_XTIME(i_mtime, inode, now);
+   VFS_INODE_SET_XTIME(i_ctime, inode, now);
}
return inode;
 }
diff --git a/fs/inode.c b/fs/inode.c
index 4c8f719..d3d64dc 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1532,27 +1532,36 @@ EXPORT_SYMBOL(bmap);
  * passed since the last atime 

[Y2038] [RFC 03/15] kernel: time: Add macros and functions to support 64 bit time

2016-01-06 Thread Deepa Dinamani
The current_fs_time function is not y2038 safe because
of the use of struct timespec.

The macros CURRENT_TIME and CURRENT_TIME_SEC do not represent
file system times correctly as they cannnot perform range checks
or truncations. These are also not y2038 safe. Add 64 bit versions
of the above macros.

Provide a new set of FS_TIME macros which will return time in
timespec or timespec64 based on CONFIG_FS_USES_64_BIT_TIME.
These are meant to be used only within file systems because of
being tied to the above config. Once the config is enabled,
the timespec version of it can be deleted and the 64 bit time version
can be used elsewhere also.

Add struct timespec64 version for current_fs_time().
Current version of current_fs_time() can be dropped after enabling
CONFIG_FS_USES_64BIT_TIME.

Provide an alternative to timespec_trunc(): fs_time_trunc().
This function takes super block as an argument in addition to
timestamp so that it can include range and precision checks.
Additionally, the function uses y2038 safe timespec64 instead of
timespec for timestamp representation.

Add function: current_fs_time_sec() to obtain only the seconds
portion of the current time(Equivalent to CURRENT_TIME_SEC).
This function has two versions selected by the config
CONFIG_FS_USES_64BIT_TIME.
The 32 bit version support can be dropped after the above config
is enabled globally.

All calls to timespec_trunc() will be eventually replaced by
fs_time_trunc(). At which point, timespec_trunc() can be deleted.

All the above function calls use fs_time_range_check() to clamp
the timestamps.

Inodes that are saved in memory and on disk always have valid
timestamps. But, the accessors can detect a clamped timestamp
while saving the timestamps into inodes.
The clamped timestamp handling is split into two seperate cases:
a. Mounting a fs that has exceeded it's current timestamp needs.
b. A mounted fs exceeds timestamps needs.
Both the above cases are handled using seperate callbacks:
superblock bad_timestamp_mount and bad_timestamp operations.

Motivation for the above callbacks being that the Linux kernel does
not internally use timestamps and it cannot decide how catastrophic
these timestamp clamps can be for the on disk file system or
user space applications that use it.

Signed-off-by: Deepa Dinamani 
---
 fs/libfs.c |   5 ++
 fs/super.c |  10 
 include/linux/fs.h |  50 ++--
 include/linux/time64.h |   4 ++
 kernel/time/time.c | 156 +
 5 files changed, 196 insertions(+), 29 deletions(-)

diff --git a/fs/libfs.c b/fs/libfs.c
index 8dc37fc..4fa2002 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -227,6 +227,9 @@ struct dentry *mount_pseudo(struct file_system_type 
*fs_type, char *name,
s->s_magic = magic;
s->s_op = ops ? ops : _super_operations;
s->s_time_gran = 1;
+   s->s_time_min = FS_DEFAULT_MIN_TIMESTAMP;
+   s->s_time_max = FS_DEFAULT_MAX_TIMESTAMP;
+
root = new_inode(s);
if (!root)
goto Enomem;
@@ -482,6 +485,8 @@ int simple_fill_super(struct super_block *s, unsigned long 
magic,
s->s_magic = magic;
s->s_op = _super_operations;
s->s_time_gran = 1;
+   s->s_time_min = FS_DEFAULT_MIN_TIMESTAMP;
+   s->s_time_max = FS_DEFAULT_MAX_TIMESTAMP;
 
inode = new_inode(s);
if (!inode)
diff --git a/fs/super.c b/fs/super.c
index 7ea56de..3f53def 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -239,6 +239,8 @@ static struct super_block *alloc_super(struct 
file_system_type *type, int flags)
s->s_maxbytes = MAX_NON_LFS;
s->s_op = _op;
s->s_time_gran = 10;
+   s->s_time_min = FS_DEFAULT_MIN_TIMESTAMP;
+   s->s_time_max = FS_DEFAULT_MAX_TIMESTAMP;
s->cleancache_poolid = CLEANCACHE_NO_POOL;
 
s->s_shrink.seeks = DEFAULT_SEEKS;
@@ -1143,6 +1145,14 @@ mount_fs(struct file_system_type *type, int flags, const 
char *name, void *data)
WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to "
"negative value (%lld)\n", type->name, sb->s_maxbytes);
 
+   /* check timestamp range */
+   if (unlikely(is_fs_timestamp_bad(current_fs_time(sb))) &&
+   (sb->s_op->bad_timestamp_mount)) {
+   error = sb->s_op->bad_timestamp_mount(sb);
+   if (error)
+   goto out_sb;
+   }
+
up_write(>s_umount);
free_secdata(secdata);
return root;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b9f3cee..5112bc2 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -693,8 +693,14 @@ struct inode {
 #define VFS_INODE_SET_XTIME(xtime, inode, ts64)\
do {\
struct inode_timespec __ts = (ts64);\
+   struct super_block *__sb = inode->i_sb;   

[Y2038] [RFC 06/15] fs: fat: convert fat to 64 bit time

2016-01-06 Thread Deepa Dinamani
FAT filesystem supports timestamps until the year 2099
even though the theoretical max is 2107.
But, the struct timespec overflows in the year 2038 on
32 bit systems.

Use inode_timespec throughout the file system code so
that the timestamps can switch to y2038 safe
struct timespec64 when CONFIG_FS_USES_64BIT_TIME is
turned on.

Use a larger data type for seconds in fat_time_fat2unix().
This extends timestamps beyond the year 2038.

Signed-off-by: Deepa Dinamani 
---
 fs/fat/dir.c |  7 +--
 fs/fat/fat.h |  8 +---
 fs/fat/file.c| 10 --
 fs/fat/inode.c   | 46 --
 fs/fat/misc.c|  7 ---
 fs/fat/namei_msdos.c | 40 +---
 fs/fat/namei_vfat.c  | 41 +++--
 7 files changed, 106 insertions(+), 53 deletions(-)

diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 7def96c..fa8a922 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -1034,6 +1034,7 @@ int fat_remove_entries(struct inode *dir, struct 
fat_slot_info *sinfo)
struct super_block *sb = dir->i_sb;
struct msdos_dir_entry *de;
struct buffer_head *bh;
+   struct inode_timespec now;
int err = 0, nr_slots;
 
/*
@@ -1071,7 +1072,9 @@ int fat_remove_entries(struct inode *dir, struct 
fat_slot_info *sinfo)
}
}
 
-   dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC;
+   now = current_fs_time_sec(sb);
+   VFS_INODE_SET_XTIME(i_mtime, dir, now);
+   VFS_INODE_SET_XTIME(i_atime, dir, now);
if (IS_DIRSYNC(dir))
(void)fat_sync_inode(dir);
else
@@ -1130,7 +1133,7 @@ error:
return err;
 }
 
-int fat_alloc_new_dir(struct inode *dir, struct timespec *ts)
+int fat_alloc_new_dir(struct inode *dir, struct inode_timespec *ts)
 {
struct super_block *sb = dir->i_sb;
struct msdos_sb_info *sbi = MSDOS_SB(sb);
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index e6b764a..cabb0fd 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -303,7 +303,7 @@ extern int fat_scan_logstart(struct inode *dir, int 
i_logstart,
 struct fat_slot_info *sinfo);
 extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
struct msdos_dir_entry **de);
-extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts);
+extern int fat_alloc_new_dir(struct inode *dir, struct inode_timespec *ts);
 extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
   struct fat_slot_info *sinfo);
 extern int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo);
@@ -405,9 +405,11 @@ void fat_msg(struct super_block *sb, const char *level, 
const char *fmt, ...);
 } while (0)
 extern int fat_clusters_flush(struct super_block *sb);
 extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster);
-extern void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts,
+extern void fat_time_fat2unix(struct msdos_sb_info *sbi,
+ struct inode_timespec *ts,
  __le16 __time, __le16 __date, u8 time_cs);
-extern void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts,
+extern void fat_time_unix2fat(struct msdos_sb_info *sbi,
+ struct inode_timespec *ts,
  __le16 *time, __le16 *date, u8 *time_cs);
 extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
 
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 43d3475..e7f060f 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -188,13 +188,16 @@ static int fat_cont_expand(struct inode *inode, loff_t 
size)
 {
struct address_space *mapping = inode->i_mapping;
loff_t start = inode->i_size, count = size - inode->i_size;
+   struct inode_timespec ts;
int err;
 
err = generic_cont_expand_simple(inode, size);
if (err)
goto out;
 
-   inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+   ts = current_fs_time_sec(inode->i_sb);
+   VFS_INODE_SET_XTIME(i_ctime, inode, ts);
+   VFS_INODE_SET_XTIME(i_mtime, inode, ts);
mark_inode_dirty(inode);
if (IS_SYNC(inode)) {
int err2;
@@ -280,6 +283,7 @@ error:
 static int fat_free(struct inode *inode, int skip)
 {
struct super_block *sb = inode->i_sb;
+   struct inode_timespec ts;
int err, wait, free_start, i_start, i_logstart;
 
if (MSDOS_I(inode)->i_start == 0)
@@ -297,7 +301,9 @@ static int fat_free(struct inode *inode, int skip)
MSDOS_I(inode)->i_logstart = 0;
}
MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
-   inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+   ts = current_fs_time_sec(sb);
+   VFS_INODE_SET_XTIME(i_ctime, inode, ts);
+   VFS_INODE_SET_XTIME(i_mtime, inode, ts);

[Y2038] [RFC 07/15] fs: ext4: convert to use 64 bit time

2016-01-06 Thread Deepa Dinamani
struct timespec is not y2038 safe.
The ext4 uses time_extra fields to extend {a,c,m,cr} times until
2446.

Use struct inode_timespec to replace timespec.
inode_timespec will eventually be replaced by struct timespec64
when CONFIG_FS_USES_64BIT_TIME is enabled.

Signed-off-by: Deepa Dinamani 
---
 fs/ext4/acl.c |  3 ++-
 fs/ext4/ext4.h| 44 
 fs/ext4/extents.c | 25 +++--
 fs/ext4/ialloc.c  |  9 +++--
 fs/ext4/inline.c  | 10 --
 fs/ext4/inode.c   | 16 
 fs/ext4/ioctl.c   | 16 ++--
 fs/ext4/namei.c   | 40 
 fs/ext4/super.c   |  6 +-
 fs/ext4/xattr.c   |  2 +-
 10 files changed, 116 insertions(+), 55 deletions(-)

diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index 69b1e73..e8073d5 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -200,7 +200,8 @@ __ext4_set_acl(handle_t *handle, struct inode *inode, int 
type,
if (error < 0)
return error;
else {
-   inode->i_ctime = ext4_current_time(inode);
+   VFS_INODE_SET_XTIME(i_ctime, inode,
+   ext4_current_time(inode));
ext4_mark_inode_dirty(handle, inode);
if (error == 0)
acl = NULL;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index c569430..4bb2604 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -754,14 +754,15 @@ struct move_extent {
  * affected filesystem before 2242.
  */
 
-static inline __le32 ext4_encode_extra_time(struct timespec *time)
+static inline __le32 ext4_encode_extra_time(struct inode_timespec *time)
 {
u32 extra = sizeof(time->tv_sec) > 4 ?
((time->tv_sec - (s32)time->tv_sec) >> 32) & EXT4_EPOCH_MASK : 
0;
return cpu_to_le32(extra | (time->tv_nsec << EXT4_EPOCH_BITS));
 }
 
-static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
+static inline void ext4_decode_extra_time(struct inode_timespec *time,
+ __le32 extra)
 {
if (unlikely(sizeof(time->tv_sec) > 4 &&
(extra & cpu_to_le32(EXT4_EPOCH_MASK {
@@ -784,12 +785,13 @@ static inline void ext4_decode_extra_time(struct timespec 
*time, __le32 extra)
time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> 
EXT4_EPOCH_BITS;
 }
 
-#define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \
-do {  \
-   (raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec);   \
-   if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \
-   (raw_inode)->xtime ## _extra = \
-   ext4_encode_extra_time(&(inode)->xtime);   \
+#define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode)  
\
+do {   
\
+   struct inode_timespec __ts = VFS_INODE_GET_XTIME(xtime, inode); 
\
+   (raw_inode)->xtime = cpu_to_le32(__ts.tv_sec);  
\
+   if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra))  
\
+   (raw_inode)->xtime ## _extra =  
\
+   ext4_encode_extra_time(&__ts);  
\
 } while (0)
 
 #define EXT4_EINODE_SET_XTIME(xtime, einode, raw_inode)
   \
@@ -801,14 +803,16 @@ do {  
   \
ext4_encode_extra_time(&(einode)->xtime);  \
 } while (0)
 
-#define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \
-do {  \
-   (inode)->xtime.tv_sec = (signed)le32_to_cpu((raw_inode)->xtime);   \
-   if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \
-   ext4_decode_extra_time(&(inode)->xtime,\
-  raw_inode->xtime ## _extra);\
-   else   \
-   (inode)->xtime.tv_nsec = 0;\
+#define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode)  
\
+do {   
\
+   struct inode_timespec __ts = VFS_INODE_GET_XTIME(xtime, inode); 
\
+   __ts.tv_sec = (signed)le32_to_cpu((raw_inode)->xtime);  
\
+   if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## 

[Y2038] [RFC 14/15] vfs: Remove inode_timespec aliases

2016-01-06 Thread Deepa Dinamani
Now that CONFIG_FS_USES_64BIT_TIME is enabled, the aliases
for inode_timespec are no longer used and can be removed.

Signed-off-by: Deepa Dinamani 
---
 include/linux/time64.h | 21 -
 1 file changed, 21 deletions(-)

diff --git a/include/linux/time64.h b/include/linux/time64.h
index eb3cdc0..f30c910 100644
--- a/include/linux/time64.h
+++ b/include/linux/time64.h
@@ -26,27 +26,6 @@ struct itimerspec64 {
 
 #endif
 
-#ifdef CONFIG_FS_USES_64BIT_TIME
-
-/* Place holder defines until CONFIG_FS_USES_64BIT_TIME
- * is enabled.
- * timespec64 data type and functions will be used at that
- * time directly and these defines will be deleted.
- */
-#define inode_timespec timespec64
-
-#define inode_timespec_compare timespec64_compare
-#define inode_timespec_equal   timespec64_equal
-
-#else
-
-#define inode_timespec timespec
-
-#define inode_timespec_compare timespec_compare
-#define inode_timespec_equal   timespec_equal
-
-#endif
-
 #define CURRENT_TIME64 (current_kernel_time64())
 #define CURRENT_TIME64_SEC \
((struct timespec64) { ktime_get_real_seconds(), 0 })
-- 
1.9.1

___
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038


[Y2038] [RFC 09/15] fs: cifs: replace inode_timespec with timespec64

2016-01-06 Thread Deepa Dinamani
Substitute inode_timespec aliases with timespec64.
Since CONFIG_FS_USES_64BIT_TIME is enabled, internally
all inode_timespec references are using timespec64
already.

Signed-off-by: Deepa Dinamani 
---
 fs/cifs/cache.c |  4 ++--
 fs/cifs/cifsglob.h  |  6 +++---
 fs/cifs/cifsproto.h |  6 +++---
 fs/cifs/cifssmb.c   |  4 ++--
 fs/cifs/file.c  |  2 +-
 fs/cifs/inode.c | 12 ++--
 fs/cifs/netmisc.c   | 10 +-
 7 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c
index 8d27e69b..61c21bf 100644
--- a/fs/cifs/cache.c
+++ b/fs/cifs/cache.c
@@ -221,8 +221,8 @@ const struct fscache_cookie_def 
cifs_fscache_super_index_def = {
  * Auxiliary data attached to CIFS inode within the cache
  */
 struct cifs_fscache_inode_auxdata {
-   struct inode_timespec   last_write_time;
-   struct inode_timespec   last_change_time;
+   struct timespec64   last_write_time;
+   struct timespec64   last_change_time;
u64 eof;
 };
 
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index c95dce7..7dfb0e2 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1393,9 +1393,9 @@ struct cifs_fattr {
dev_t   cf_rdev;
unsigned intcf_nlink;
unsigned intcf_dtype;
-   struct inode_timespec   cf_atime;
-   struct inode_timespec   cf_mtime;
-   struct inode_timespec   cf_ctime;
+   struct timespec64   cf_atime;
+   struct timespec64   cf_mtime;
+   struct timespec64   cf_ctime;
 };
 
 static inline void free_dfs_info_param(struct dfs_info3_param *param)
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 9979c74..663b8a4 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -126,10 +126,10 @@ extern enum securityEnum select_sectype(struct 
TCP_Server_Info *server,
enum securityEnum requested);
 extern int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
  const struct nls_table *nls_cp);
-extern struct inode_timespec
+extern struct timespec64
cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601);
-extern u64 cifs_UnixTimeToNT(struct inode_timespec);
-extern struct inode_timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
+extern u64 cifs_UnixTimeToNT(struct timespec64);
+extern struct timespec64 cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
int offset);
 extern void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock);
 extern int cifs_get_writer(struct cifsInodeInfo *cinode);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index a813bcd..465e089 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -478,7 +478,7 @@ decode_lanman_negprot_rsp(struct TCP_Server_Info *server, 
NEGOTIATE_RSP *pSMBr)
 * this requirement.
 */
int val, seconds, remain, result;
-   struct inode_timespec ts, utc;
+   struct timespec64 ts, utc;
 
utc = FS_TIME;
ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
@@ -4004,7 +4004,7 @@ QInfRetry:
if (rc) {
cifs_dbg(FYI, "Send error in QueryInfo = %d\n", rc);
} else if (data) {
-   struct inode_timespec ts;
+   struct timespec64 ts;
 
__u32 time = le32_to_cpu(pSMBr->last_write_time);
 
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 2d226cf..656e799 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1839,7 +1839,7 @@ static int cifs_partialpagewrite(struct page *page, 
unsigned from, unsigned to)
int bytes_written = 0;
struct inode *inode;
struct cifsFileInfo *open_file;
-   struct inode_timespec now;
+   struct timespec64 now;
 
if (!mapping || !mapping->host)
return -EFAULT;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index bb91bf7..c65d7e3 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -92,7 +92,7 @@ static void
 cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
 {
struct cifsInodeInfo *cifs_i = CIFS_I(inode);
-   struct inode_timespec mtime;
+   struct timespec64 mtime;
 
cifs_dbg(FYI, "%s: revalidating inode %llu\n",
 __func__, cifs_i->uniqueid);
@@ -112,7 +112,7 @@ cifs_revalidate_cache(struct inode *inode, struct 
cifs_fattr *fattr)
 
 /* revalidate if mtime or size have changed */
mtime = VFS_INODE_GET_XTIME(i_mtime, inode);
-   if (inode_timespec_equal(, >cf_mtime)
+   if (timespec64_equal(, >cf_mtime)
&& cifs_i->server_eof == fattr->cf_eof) {
cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
  __func__, cifs_i->uniqueid);
@@ -320,7 +320,7 @@ static void
 cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
 {
struct cifs_sb_info *cifs_sb =