Commit 5fc7fcd0 authored by Aurelien Aptel's avatar Aurelien Aptel Committed by Steve French

cifs: auto disable 'serverino' in dfs mounts

Different servers have different set of file ids.

After failover, unique IDs will be different so we can't validate
them.
Signed-off-by: default avatarAurelien Aptel <aaptel@suse.com>
Reviewed-by: default avatarPaulo Alcantara <palcantara@suse.de>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent d9345e0a
...@@ -4220,6 +4220,12 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol) ...@@ -4220,6 +4220,12 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
if (rc) if (rc)
goto error; 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: out:
free_xid(xid); free_xid(xid);
return mount_setup_tlink(cifs_sb, ses, tcon); return mount_setup_tlink(cifs_sb, ses, tcon);
......
...@@ -730,7 +730,6 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, ...@@ -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, FILE_ALL_INFO *data, struct super_block *sb, int xid,
const struct cifs_fid *fid) const struct cifs_fid *fid)
{ {
bool validinum = false;
__u16 srchflgs; __u16 srchflgs;
int rc = 0, tmprc = ENOSYS; int rc = 0, tmprc = ENOSYS;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
...@@ -821,7 +820,6 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, ...@@ -821,7 +820,6 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
(FILE_DIRECTORY_INFO *)data, cifs_sb); (FILE_DIRECTORY_INFO *)data, cifs_sb);
fattr.cf_uniqueid = le64_to_cpu( fattr.cf_uniqueid = le64_to_cpu(
((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId); ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
validinum = true;
cifs_buf_release(srchinf->ntwrk_buf_start); cifs_buf_release(srchinf->ntwrk_buf_start);
} }
...@@ -840,31 +838,29 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, ...@@ -840,31 +838,29 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
*/ */
if (*inode == NULL) { if (*inode == NULL) {
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
if (validinum == false) { if (server->ops->get_srv_inum)
if (server->ops->get_srv_inum) tmprc = server->ops->get_srv_inum(xid,
tmprc = server->ops->get_srv_inum(xid, tcon, cifs_sb, full_path,
tcon, cifs_sb, full_path, &fattr.cf_uniqueid, data);
&fattr.cf_uniqueid, data); if (tmprc) {
if (tmprc) { cifs_dbg(FYI, "GetSrvInodeNum rc %d\n",
cifs_dbg(FYI, "GetSrvInodeNum rc %d\n", tmprc);
tmprc); fattr.cf_uniqueid = iunique(sb, ROOT_I);
fattr.cf_uniqueid = iunique(sb, ROOT_I); cifs_autodisable_serverino(cifs_sb);
cifs_autodisable_serverino(cifs_sb); } else if ((fattr.cf_uniqueid == 0) &&
} else if ((fattr.cf_uniqueid == 0) && strlen(full_path) == 0) {
strlen(full_path) == 0) { /* some servers ret bad root ino ie 0 */
/* some servers ret bad root ino ie 0 */ cifs_dbg(FYI, "Invalid (0) inodenum\n");
cifs_dbg(FYI, "Invalid (0) inodenum\n"); fattr.cf_flags |=
fattr.cf_flags |= CIFS_FATTR_FAKE_ROOT_INO;
CIFS_FATTR_FAKE_ROOT_INO; fattr.cf_uniqueid =
fattr.cf_uniqueid = simple_hashstr(tcon->treeName);
simple_hashstr(tcon->treeName);
}
} }
} else } else
fattr.cf_uniqueid = iunique(sb, ROOT_I); fattr.cf_uniqueid = iunique(sb, ROOT_I);
} else { } else {
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) && if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
validinum == false && server->ops->get_srv_inum) { && server->ops->get_srv_inum) {
/* /*
* Pass a NULL tcon to ensure we don't make a round * Pass a NULL tcon to ensure we don't make a round
* trip to the server. This only works for SMB2+. * trip to the server. This only works for SMB2+.
......
...@@ -525,9 +525,17 @@ void ...@@ -525,9 +525,17 @@ void
cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
{ {
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 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_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_dbg(VFS, "Autodisabling the use of server inode numbers on %s.\n",
cifs_sb_master_tcon(cifs_sb)->treeName); 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");
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment