diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 988fddb72025b7216a684a21279d6bfcac9afdbc..abd2cc9515c939213d7d3d4e793c00d974445737 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -907,6 +907,33 @@ cifs_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset, (__u8)type, wait, 0); } +static int +cifs_unix_dfs_readlink(const unsigned int xid, struct cifs_tcon *tcon, + const unsigned char *searchName, char **symlinkinfo, + const struct nls_table *nls_codepage) +{ +#ifdef CONFIG_CIFS_DFS_UPCALL + int rc; + unsigned int num_referrals = 0; + struct dfs_info3_param *referrals = NULL; + + rc = get_dfs_path(xid, tcon->ses, searchName, nls_codepage, + &num_referrals, &referrals, 0); + + if (!rc && num_referrals > 0) { + *symlinkinfo = kstrndup(referrals->node_name, + strlen(referrals->node_name), + GFP_KERNEL); + if (!*symlinkinfo) + rc = -ENOMEM; + free_dfs_info_array(referrals, num_referrals); + } + return rc; +#else /* No DFS support */ + return -EREMOTE; +#endif +} + static int cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, const char *full_path, char **target_path, @@ -922,6 +949,11 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, if (cap_unix(tcon->ses)) { rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path, cifs_sb->local_nls); + if (rc == -EREMOTE) + rc = cifs_unix_dfs_readlink(xid, tcon, full_path, + target_path, + cifs_sb->local_nls); + goto out; }