OSDN Git Service

smb3: Fix regression in time handling
authorSteve French <stfrench@microsoft.com>
Tue, 8 Oct 2019 05:27:14 +0000 (00:27 -0500)
committerSteve French <stfrench@microsoft.com>
Wed, 9 Oct 2019 05:10:38 +0000 (00:10 -0500)
Fixes: cb7a69e60590 ("cifs: Initialize filesystem timestamp ranges")

Only very old servers (e.g. OS/2 and DOS) did not support
DCE TIME (100 nanosecond granularity).  Fix the checks used
to set minimum and maximum times.

Fixes xfstest generic/258 (on 5.4-rc1 and later)

CC: Deepa Dinamani <deepa.kernel@gmail.com>
Acked-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
fs/cifs/cifsfs.c

index 2e9c7f4..c049c7b 100644 (file)
@@ -169,18 +169,26 @@ cifs_read_super(struct super_block *sb)
        else
                sb->s_maxbytes = MAX_NON_LFS;
 
-       /* BB FIXME fix time_gran to be larger for LANMAN sessions */
-       sb->s_time_gran = 100;
-
-       if (tcon->unix_ext) {
-               ts = cifs_NTtimeToUnix(0);
+       /* Some very old servers like DOS and OS/2 used 2 second granularity */
+       if ((tcon->ses->server->vals->protocol_id == SMB10_PROT_ID) &&
+           ((tcon->ses->capabilities &
+             tcon->ses->server->vals->cap_nt_find) == 0) &&
+           !tcon->unix_ext) {
+               sb->s_time_gran = 1000000000; /* 1 second is max allowed gran */
+               ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MIN), 0, 0);
                sb->s_time_min = ts.tv_sec;
-               ts = cifs_NTtimeToUnix(cpu_to_le64(S64_MAX));
+               ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MAX),
+                                   cpu_to_le16(SMB_TIME_MAX), 0);
                sb->s_time_max = ts.tv_sec;
        } else {
-               ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MIN), 0, 0);
+               /*
+                * Almost every server, including all SMB2+, uses DCE TIME
+                * ie 100 nanosecond units, since 1601.  See MS-DTYP and MS-FSCC
+                */
+               sb->s_time_gran = 100;
+               ts = cifs_NTtimeToUnix(0);
                sb->s_time_min = ts.tv_sec;
-               ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MAX), cpu_to_le16(SMB_TIME_MAX), 0);
+               ts = cifs_NTtimeToUnix(cpu_to_le64(S64_MAX));
                sb->s_time_max = ts.tv_sec;
        }