|
@@ -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;
|
|
|
}
|
|
|
|