diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 24 |
1 files changed, 11 insertions, 13 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 20c60ddaa5a1..3e20831119a9 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -2788,9 +2788,9 @@ build_unc_path_to_root(const struct smb_vol *volume_info, | |||
2788 | /* | 2788 | /* |
2789 | * Perform a dfs referral query for a share and (optionally) prefix | 2789 | * Perform a dfs referral query for a share and (optionally) prefix |
2790 | * | 2790 | * |
2791 | * If a referral is found, mount_data will be set to point at a newly | 2791 | * If a referral is found, cifs_sb->mountdata will be (re-)allocated |
2792 | * allocated string containing updated options for the submount. | 2792 | * to a string containing updated options for the submount. Otherwise it |
2793 | * Otherwise it will be left untouched. | 2793 | * will be left untouched. |
2794 | * | 2794 | * |
2795 | * Returns the rc from get_dfs_path to the caller, which can be used to | 2795 | * Returns the rc from get_dfs_path to the caller, which can be used to |
2796 | * determine whether there were referrals. | 2796 | * determine whether there were referrals. |
@@ -2798,7 +2798,7 @@ build_unc_path_to_root(const struct smb_vol *volume_info, | |||
2798 | static int | 2798 | static int |
2799 | expand_dfs_referral(int xid, struct cifsSesInfo *pSesInfo, | 2799 | expand_dfs_referral(int xid, struct cifsSesInfo *pSesInfo, |
2800 | struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb, | 2800 | struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb, |
2801 | char **mount_data, int check_prefix) | 2801 | int check_prefix) |
2802 | { | 2802 | { |
2803 | int rc; | 2803 | int rc; |
2804 | unsigned int num_referrals = 0; | 2804 | unsigned int num_referrals = 0; |
@@ -2826,11 +2826,14 @@ expand_dfs_referral(int xid, struct cifsSesInfo *pSesInfo, | |||
2826 | free_dfs_info_array(referrals, num_referrals); | 2826 | free_dfs_info_array(referrals, num_referrals); |
2827 | kfree(fake_devname); | 2827 | kfree(fake_devname); |
2828 | 2828 | ||
2829 | if (cifs_sb->mountdata != NULL) | ||
2830 | kfree(cifs_sb->mountdata); | ||
2831 | |||
2829 | if (IS_ERR(mdata)) { | 2832 | if (IS_ERR(mdata)) { |
2830 | rc = PTR_ERR(mdata); | 2833 | rc = PTR_ERR(mdata); |
2831 | mdata = NULL; | 2834 | mdata = NULL; |
2832 | } | 2835 | } |
2833 | *mount_data = mdata; | 2836 | cifs_sb->mountdata = mdata; |
2834 | } | 2837 | } |
2835 | kfree(full_path); | 2838 | kfree(full_path); |
2836 | return rc; | 2839 | return rc; |
@@ -2853,6 +2856,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2853 | #ifdef CONFIG_CIFS_DFS_UPCALL | 2856 | #ifdef CONFIG_CIFS_DFS_UPCALL |
2854 | int referral_walks_count = 0; | 2857 | int referral_walks_count = 0; |
2855 | try_mount_again: | 2858 | try_mount_again: |
2859 | mount_data = cifs_sb->mountdata; | ||
2856 | 2860 | ||
2857 | /* cleanup activities if we're chasing a referral */ | 2861 | /* cleanup activities if we're chasing a referral */ |
2858 | if (referral_walks_count) { | 2862 | if (referral_walks_count) { |
@@ -2986,7 +2990,7 @@ remote_path_check: | |||
2986 | */ | 2990 | */ |
2987 | if (referral_walks_count == 0) { | 2991 | if (referral_walks_count == 0) { |
2988 | int refrc = expand_dfs_referral(xid, pSesInfo, volume_info, | 2992 | int refrc = expand_dfs_referral(xid, pSesInfo, volume_info, |
2989 | cifs_sb, &mount_data, false); | 2993 | cifs_sb, false); |
2990 | if (!refrc) { | 2994 | if (!refrc) { |
2991 | referral_walks_count++; | 2995 | referral_walks_count++; |
2992 | goto try_mount_again; | 2996 | goto try_mount_again; |
@@ -3028,17 +3032,13 @@ remote_path_check: | |||
3028 | convert_delimiter(cifs_sb->prepath, | 3032 | convert_delimiter(cifs_sb->prepath, |
3029 | CIFS_DIR_SEP(cifs_sb)); | 3033 | CIFS_DIR_SEP(cifs_sb)); |
3030 | 3034 | ||
3031 | if (mount_data != mount_data_global) | ||
3032 | kfree(mount_data); | ||
3033 | |||
3034 | rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb, | 3035 | rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb, |
3035 | &mount_data, true); | 3036 | true); |
3036 | 3037 | ||
3037 | if (!rc) { | 3038 | if (!rc) { |
3038 | referral_walks_count++; | 3039 | referral_walks_count++; |
3039 | goto try_mount_again; | 3040 | goto try_mount_again; |
3040 | } | 3041 | } |
3041 | mount_data = NULL; | ||
3042 | goto mount_fail_check; | 3042 | goto mount_fail_check; |
3043 | #else /* No DFS support, return error on mount */ | 3043 | #else /* No DFS support, return error on mount */ |
3044 | rc = -EOPNOTSUPP; | 3044 | rc = -EOPNOTSUPP; |
@@ -3072,8 +3072,6 @@ remote_path_check: | |||
3072 | mount_fail_check: | 3072 | mount_fail_check: |
3073 | /* on error free sesinfo and tcon struct if needed */ | 3073 | /* on error free sesinfo and tcon struct if needed */ |
3074 | if (rc) { | 3074 | if (rc) { |
3075 | if (mount_data != mount_data_global) | ||
3076 | kfree(mount_data); | ||
3077 | /* If find_unc succeeded then rc == 0 so we can not end */ | 3075 | /* If find_unc succeeded then rc == 0 so we can not end */ |
3078 | /* up accidentally freeing someone elses tcon struct */ | 3076 | /* up accidentally freeing someone elses tcon struct */ |
3079 | if (tcon) | 3077 | if (tcon) |