aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSachin Prabhu <sprabhu@redhat.com>2013-12-02 11:37:43 -0500
committerSteve French <smfrench@gmail.com>2014-01-20 01:14:14 -0500
commit924e3fa48c627ad45d3be9412a93df34ab0fb482 (patch)
treedf68cc1d3802579fa8704452425336f6e11ff511
parent0ecdb4f572f6ab2219a01e3af349863f6e8b45af (diff)
cifs: Add support for follow_link on dfs shares under posix extensions
When using posix extensions, dfs shares in the dfs root show up as symlinks resulting in userland tools such as 'ls' calling readlink() on these shares. Since these are dfs shares, we end up returning -EREMOTE. $ ls -l /mnt ls: cannot read symbolic link /mnt/test: Object is remote total 0 lrwxrwxrwx. 1 root root 19 Nov 6 09:47 test With added follow_link() support for dfs shares, when using unix extensions, we call GET_DFS_REFERRAL to obtain the DFS referral and return the first node returned. The dfs share in the dfs root is now displayed in the following manner. $ ls -l /mnt total 0 lrwxrwxrwx. 1 root root 19 Nov 6 09:47 test -> \vm140-31\test Signed-off-by: Sachin Prabhu <sprabhu@redhat.com> Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com>
-rw-r--r--fs/cifs/smb1ops.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 988fddb72025..abd2cc9515c9 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -908,6 +908,33 @@ cifs_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
908} 908}
909 909
910static int 910static int
911cifs_unix_dfs_readlink(const unsigned int xid, struct cifs_tcon *tcon,
912 const unsigned char *searchName, char **symlinkinfo,
913 const struct nls_table *nls_codepage)
914{
915#ifdef CONFIG_CIFS_DFS_UPCALL
916 int rc;
917 unsigned int num_referrals = 0;
918 struct dfs_info3_param *referrals = NULL;
919
920 rc = get_dfs_path(xid, tcon->ses, searchName, nls_codepage,
921 &num_referrals, &referrals, 0);
922
923 if (!rc && num_referrals > 0) {
924 *symlinkinfo = kstrndup(referrals->node_name,
925 strlen(referrals->node_name),
926 GFP_KERNEL);
927 if (!*symlinkinfo)
928 rc = -ENOMEM;
929 free_dfs_info_array(referrals, num_referrals);
930 }
931 return rc;
932#else /* No DFS support */
933 return -EREMOTE;
934#endif
935}
936
937static int
911cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, 938cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
912 const char *full_path, char **target_path, 939 const char *full_path, char **target_path,
913 struct cifs_sb_info *cifs_sb) 940 struct cifs_sb_info *cifs_sb)
@@ -922,6 +949,11 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
922 if (cap_unix(tcon->ses)) { 949 if (cap_unix(tcon->ses)) {
923 rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path, 950 rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path,
924 cifs_sb->local_nls); 951 cifs_sb->local_nls);
952 if (rc == -EREMOTE)
953 rc = cifs_unix_dfs_readlink(xid, tcon, full_path,
954 target_path,
955 cifs_sb->local_nls);
956
925 goto out; 957 goto out;
926 } 958 }
927 959