cifs: improve checking of DFS links over STATUS_OBJECT_NAME_INVALID
[linux-2.6-microblaze.git] / fs / cifs / smb2ops.c
index f79b075..6dfb865 100644 (file)
@@ -796,7 +796,6 @@ static int
 smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
                        struct cifs_sb_info *cifs_sb, const char *full_path)
 {
-       int rc;
        __le16 *utf16_path;
        __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
        int err_buftype = CIFS_NO_BUFFER;
@@ -804,6 +803,8 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
        struct kvec err_iov = {};
        struct cifs_fid fid;
        struct cached_fid *cfid;
+       bool islink;
+       int rc, rc2;
 
        rc = open_cached_dir(xid, tcon, full_path, cifs_sb, true, &cfid);
        if (!rc) {
@@ -833,15 +834,17 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
 
                if (unlikely(!hdr || err_buftype == CIFS_NO_BUFFER))
                        goto out;
-               /*
-                * Handle weird Windows SMB server behaviour. It responds with
-                * STATUS_OBJECT_NAME_INVALID code to SMB2 QUERY_INFO request
-                * for "\<server>\<dfsname>\<linkpath>" DFS reference,
-                * where <dfsname> contains non-ASCII unicode symbols.
-                */
-               if (rc != -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) &&
-                   hdr->Status == STATUS_OBJECT_NAME_INVALID)
-                       rc = -EREMOTE;
+
+               if (rc != -EREMOTE && hdr->Status == STATUS_OBJECT_NAME_INVALID) {
+                       rc2 = cifs_inval_name_dfs_link_error(xid, tcon, cifs_sb,
+                                                            full_path, &islink);
+                       if (rc2) {
+                               rc = rc2;
+                               goto out;
+                       }
+                       if (islink)
+                               rc = -EREMOTE;
+               }
                if (rc == -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) && cifs_sb &&
                    (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS))
                        rc = -EOPNOTSUPP;