cifs: auto disable 'serverino' in dfs mounts
authorAurelien Aptel <aaptel@suse.com>
Fri, 16 Nov 2018 15:13:25 +0000 (16:13 +0100)
committerSteve French <stfrench@microsoft.com>
Mon, 24 Dec 2018 05:05:11 +0000 (23:05 -0600)
Different servers have different set of file ids.

After failover, unique IDs will be different so we can't validate
them.

Signed-off-by: Aurelien Aptel <aaptel@suse.com>
Reviewed-by: Paulo Alcantara <palcantara@suse.de>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/connect.c
fs/cifs/inode.c
fs/cifs/misc.c

index bab4422f58157fab2debcb176c5acbbc3cc7d7a5..d0de4fb8ee4307639fde73ca1bb36add9e1aa5b6 100644 (file)
@@ -4220,6 +4220,12 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
        if (rc)
                goto error;
 
+       /*
+        * After reconnecting to a different server, unique ids won't
+        * match anymore, so we disable serverino. This prevents
+        * dentry revalidation to think the dentry are stale (ESTALE).
+        */
+       cifs_autodisable_serverino(cifs_sb);
 out:
        free_xid(xid);
        return mount_setup_tlink(cifs_sb, ses, tcon);
index 1fe9f3b01703f1a05ccf4b6f1ac407da6a3d8f6d..13fb59aadebcb2ee4c558457273f7f945fe619f5 100644 (file)
@@ -730,7 +730,6 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
                    FILE_ALL_INFO *data, struct super_block *sb, int xid,
                    const struct cifs_fid *fid)
 {
-       bool validinum = false;
        __u16 srchflgs;
        int rc = 0, tmprc = ENOSYS;
        struct cifs_tcon *tcon;
@@ -821,7 +820,6 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
                        (FILE_DIRECTORY_INFO *)data, cifs_sb);
                        fattr.cf_uniqueid = le64_to_cpu(
                        ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
-                       validinum = true;
 
                        cifs_buf_release(srchinf->ntwrk_buf_start);
                }
@@ -840,31 +838,29 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
         */
        if (*inode == NULL) {
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
-                       if (validinum == false) {
-                               if (server->ops->get_srv_inum)
-                                       tmprc = server->ops->get_srv_inum(xid,
-                                               tcon, cifs_sb, full_path,
-                                               &fattr.cf_uniqueid, data);
-                               if (tmprc) {
-                                       cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
-                                                tmprc);
-                                       fattr.cf_uniqueid = iunique(sb, ROOT_I);
-                                       cifs_autodisable_serverino(cifs_sb);
-                               } else if ((fattr.cf_uniqueid == 0) &&
-                                               strlen(full_path) == 0) {
-                                       /* some servers ret bad root ino ie 0 */
-                                       cifs_dbg(FYI, "Invalid (0) inodenum\n");
-                                       fattr.cf_flags |=
-                                               CIFS_FATTR_FAKE_ROOT_INO;
-                                       fattr.cf_uniqueid =
-                                               simple_hashstr(tcon->treeName);
-                               }
+                       if (server->ops->get_srv_inum)
+                               tmprc = server->ops->get_srv_inum(xid,
+                                                                 tcon, cifs_sb, full_path,
+                                                                 &fattr.cf_uniqueid, data);
+                       if (tmprc) {
+                               cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
+                                        tmprc);
+                               fattr.cf_uniqueid = iunique(sb, ROOT_I);
+                               cifs_autodisable_serverino(cifs_sb);
+                       } else if ((fattr.cf_uniqueid == 0) &&
+                                  strlen(full_path) == 0) {
+                               /* some servers ret bad root ino ie 0 */
+                               cifs_dbg(FYI, "Invalid (0) inodenum\n");
+                               fattr.cf_flags |=
+                                       CIFS_FATTR_FAKE_ROOT_INO;
+                               fattr.cf_uniqueid =
+                                       simple_hashstr(tcon->treeName);
                        }
                } else
                        fattr.cf_uniqueid = iunique(sb, ROOT_I);
        } else {
-               if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
-                   validinum == false && server->ops->get_srv_inum) {
+               if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
+                   && server->ops->get_srv_inum) {
                        /*
                         * Pass a NULL tcon to ensure we don't make a round
                         * trip to the server. This only works for SMB2+.
index 8a41f4eba7264fd37584b92bbcaa3035b487c649..f7c0c6fde5521c53d8e140671fe6c4e4a8d46308 100644 (file)
@@ -525,9 +525,17 @@ void
 cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
 {
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
+               struct cifs_tcon *tcon = NULL;
+
+               if (cifs_sb->master_tlink)
+                       tcon = cifs_sb_master_tcon(cifs_sb);
+
                cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
-               cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s. This server doesn't seem to support them properly. Hardlinks will not be recognized on this mount. Consider mounting with the \"noserverino\" option to silence this message.\n",
-                        cifs_sb_master_tcon(cifs_sb)->treeName);
+               cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s.\n",
+                        tcon ? tcon->treeName : "new server");
+               cifs_dbg(VFS, "The server doesn't seem to support them properly or the files might be on different servers (DFS).\n");
+               cifs_dbg(VFS, "Hardlinks will not be recognized on this mount. Consider mounting with the \"noserverino\" option to silence this message.\n");
+
        }
 }