cifs: smb1: Try failing back to SetFileInfo if SetPathInfo fails
authorRonnie Sahlberg <lsahlber@redhat.com>
Tue, 14 Jul 2020 22:18:05 +0000 (08:18 +1000)
committerSteve French <stfrench@microsoft.com>
Sun, 2 Aug 2020 23:00:25 +0000 (18:00 -0500)
RHBZ 1145308

Some very old server may not support SetPathInfo to adjust the timestamps
of directories. For these servers, try to open the directory and use SetFileInfo.

Minor correction to patch included that was
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Tested-by: Kenneth D'souza <kdsouza@redhat.com>
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/smb1ops.c

index ed13be38a2659a6ed0ebc0be59dad244dee6d797..336feff99c93a51f0349f9d556a859a3c798a175 100644 (file)
@@ -345,7 +345,7 @@ extern int CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
 extern int CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
                        const char *fileName, const FILE_BASIC_INFO *data,
                        const struct nls_table *nls_codepage,
-                       int remap_special_chars);
+                       struct cifs_sb_info *cifs_sb);
 extern int CIFSSMBSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
                        const FILE_BASIC_INFO *data, __u16 fid,
                        __u32 pid_of_opener);
index bf41ee048396d09b5484e41823d5980553d61179..dc62e2620cc8fa0f8d537d5c62a16fbba50ef81a 100644 (file)
@@ -5913,10 +5913,42 @@ CIFSSMBSetFileDisposition(const unsigned int xid, struct cifs_tcon *tcon,
        return rc;
 }
 
+static int
+CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon,
+                    const char *fileName, const FILE_BASIC_INFO *data,
+                    const struct nls_table *nls_codepage,
+                    struct cifs_sb_info *cifs_sb)
+{
+       int oplock = 0;
+       struct cifs_open_parms oparms;
+       struct cifs_fid fid;
+       int rc;
+
+       oparms.tcon = tcon;
+       oparms.cifs_sb = cifs_sb;
+       oparms.desired_access = GENERIC_WRITE;
+       oparms.create_options = cifs_create_options(cifs_sb, 0);
+       oparms.disposition = FILE_OPEN;
+       oparms.path = fileName;
+       oparms.fid = &fid;
+       oparms.reconnect = false;
+
+       rc = CIFS_open(xid, &oparms, &oplock, NULL);
+       if (rc)
+               goto out;
+
+       rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid);
+       CIFSSMBClose(xid, tcon, fid.netfid);
+out:
+
+       return rc;
+}
+
 int
 CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
                   const char *fileName, const FILE_BASIC_INFO *data,
-                  const struct nls_table *nls_codepage, int remap)
+                  const struct nls_table *nls_codepage,
+                    struct cifs_sb_info *cifs_sb)
 {
        TRANSACTION2_SPI_REQ *pSMB = NULL;
        TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -5925,6 +5957,7 @@ CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
        int bytes_returned = 0;
        char *data_offset;
        __u16 params, param_offset, offset, byte_count, count;
+       int remap = cifs_remap(cifs_sb);
 
        cifs_dbg(FYI, "In SetTimes\n");
 
@@ -5987,6 +6020,10 @@ SetTimesRetry:
        if (rc == -EAGAIN)
                goto SetTimesRetry;
 
+       if (rc == -EOPNOTSUPP)
+               return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data,
+                                           nls_codepage, cifs_sb);
+
        return rc;
 }
 
index 197ed455e6572777260897bafacdef2fa66495c8..80287c26cfac0cce1e0d514bdfa94bd5305a4486 100644 (file)
@@ -688,7 +688,7 @@ cifs_mkdir_setinfo(struct inode *inode, const char *full_path,
        dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
        info.Attributes = cpu_to_le32(dosattrs);
        rc = CIFSSMBSetPathInfo(xid, tcon, full_path, &info, cifs_sb->local_nls,
-                               cifs_remap(cifs_sb));
+                               cifs_sb);
        if (rc == 0)
                cifsInode->cifsAttrs = dosattrs;
 }
@@ -783,7 +783,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
        tcon = tlink_tcon(tlink);
 
        rc = CIFSSMBSetPathInfo(xid, tcon, full_path, buf, cifs_sb->local_nls,
-                               cifs_remap(cifs_sb));
+                               cifs_sb);
        if (rc == 0) {
                cinode->cifsAttrs = le32_to_cpu(buf->Attributes);
                goto out;