On Mon, 25 Nov 2013 17:09:55 +0000
Sachin Prabhu <[email protected]> wrote:

> 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, readlink fails with -EREMOTE.
> 
> With added support for dfs shares on readlink 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
> 

nit: I know that DFS referrals are prefixed with a single backslash,
but it might look more like a UNC with a double backslash prefix:

    lrwxrwxrwx. 1 root root 19 Nov  6 09:47 test -> \\vm140-31\test

...but I don't feel too strongly about it.

> Red Hat BZ: 1020715
> 
> Signed-off-by: Sachin Prabhu <[email protected]>
> ---
>  fs/cifs/smb1ops.c | 34 +++++++++++++++++++++++++++++++++-
>  1 file changed, 33 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
> index 2d822dd..abd2cc9 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,
>  }
>  
>  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,
>                  struct cifs_sb_info *cifs_sb)
> @@ -920,8 +947,13 @@ cifs_query_symlink(const unsigned int xid, struct 
> cifs_tcon *tcon,
>  
>       /* Check for unix extensions */
>       if (cap_unix(tcon->ses)) {
> -             rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
> +             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;
>       }
>  


Either way, this is a marked improvement:

Reviewed-by: Jeff Layton <[email protected]>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to