diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 132 |
1 files changed, 74 insertions, 58 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 7f540df52527..dbd669cc5bc7 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -65,6 +65,8 @@ static int ip_connect(struct TCP_Server_Info *server); | |||
65 | static int generic_ip_connect(struct TCP_Server_Info *server); | 65 | static int generic_ip_connect(struct TCP_Server_Info *server); |
66 | static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); | 66 | static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); |
67 | static void cifs_prune_tlinks(struct work_struct *work); | 67 | static void cifs_prune_tlinks(struct work_struct *work); |
68 | static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data, | ||
69 | const char *devname); | ||
68 | 70 | ||
69 | /* | 71 | /* |
70 | * cifs tcp session reconnection | 72 | * cifs tcp session reconnection |
@@ -2240,8 +2242,8 @@ cifs_match_super(struct super_block *sb, void *data) | |||
2240 | 2242 | ||
2241 | rc = compare_mount_options(sb, mnt_data); | 2243 | rc = compare_mount_options(sb, mnt_data); |
2242 | out: | 2244 | out: |
2243 | cifs_put_tlink(tlink); | ||
2244 | spin_unlock(&cifs_tcp_ses_lock); | 2245 | spin_unlock(&cifs_tcp_ses_lock); |
2246 | cifs_put_tlink(tlink); | ||
2245 | return rc; | 2247 | return rc; |
2246 | } | 2248 | } |
2247 | 2249 | ||
@@ -2474,14 +2476,6 @@ generic_ip_connect(struct TCP_Server_Info *server) | |||
2474 | if (rc < 0) | 2476 | if (rc < 0) |
2475 | return rc; | 2477 | return rc; |
2476 | 2478 | ||
2477 | rc = socket->ops->connect(socket, saddr, slen, 0); | ||
2478 | if (rc < 0) { | ||
2479 | cFYI(1, "Error %d connecting to server", rc); | ||
2480 | sock_release(socket); | ||
2481 | server->ssocket = NULL; | ||
2482 | return rc; | ||
2483 | } | ||
2484 | |||
2485 | /* | 2479 | /* |
2486 | * Eventually check for other socket options to change from | 2480 | * Eventually check for other socket options to change from |
2487 | * the default. sock_setsockopt not used because it expects | 2481 | * the default. sock_setsockopt not used because it expects |
@@ -2510,6 +2504,14 @@ generic_ip_connect(struct TCP_Server_Info *server) | |||
2510 | socket->sk->sk_sndbuf, | 2504 | socket->sk->sk_sndbuf, |
2511 | socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); | 2505 | socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); |
2512 | 2506 | ||
2507 | rc = socket->ops->connect(socket, saddr, slen, 0); | ||
2508 | if (rc < 0) { | ||
2509 | cFYI(1, "Error %d connecting to server", rc); | ||
2510 | sock_release(socket); | ||
2511 | server->ssocket = NULL; | ||
2512 | return rc; | ||
2513 | } | ||
2514 | |||
2513 | if (sport == htons(RFC1001_PORT)) | 2515 | if (sport == htons(RFC1001_PORT)) |
2514 | rc = ip_rfc1001_connect(server); | 2516 | rc = ip_rfc1001_connect(server); |
2515 | 2517 | ||
@@ -2830,15 +2832,9 @@ is_path_accessible(int xid, struct cifs_tcon *tcon, | |||
2830 | return rc; | 2832 | return rc; |
2831 | } | 2833 | } |
2832 | 2834 | ||
2833 | void | 2835 | static void |
2834 | cifs_cleanup_volume_info(struct smb_vol **pvolume_info) | 2836 | cleanup_volume_info_contents(struct smb_vol *volume_info) |
2835 | { | 2837 | { |
2836 | struct smb_vol *volume_info; | ||
2837 | |||
2838 | if (!pvolume_info || !*pvolume_info) | ||
2839 | return; | ||
2840 | |||
2841 | volume_info = *pvolume_info; | ||
2842 | kfree(volume_info->username); | 2838 | kfree(volume_info->username); |
2843 | kzfree(volume_info->password); | 2839 | kzfree(volume_info->password); |
2844 | kfree(volume_info->UNC); | 2840 | kfree(volume_info->UNC); |
@@ -2846,28 +2842,44 @@ cifs_cleanup_volume_info(struct smb_vol **pvolume_info) | |||
2846 | kfree(volume_info->domainname); | 2842 | kfree(volume_info->domainname); |
2847 | kfree(volume_info->iocharset); | 2843 | kfree(volume_info->iocharset); |
2848 | kfree(volume_info->prepath); | 2844 | kfree(volume_info->prepath); |
2845 | } | ||
2846 | |||
2847 | void | ||
2848 | cifs_cleanup_volume_info(struct smb_vol *volume_info) | ||
2849 | { | ||
2850 | if (!volume_info) | ||
2851 | return; | ||
2852 | cleanup_volume_info_contents(volume_info); | ||
2849 | kfree(volume_info); | 2853 | kfree(volume_info); |
2850 | *pvolume_info = NULL; | ||
2851 | return; | ||
2852 | } | 2854 | } |
2853 | 2855 | ||
2856 | |||
2854 | #ifdef CONFIG_CIFS_DFS_UPCALL | 2857 | #ifdef CONFIG_CIFS_DFS_UPCALL |
2855 | /* build_path_to_root returns full path to root when | 2858 | /* build_path_to_root returns full path to root when |
2856 | * we do not have an exiting connection (tcon) */ | 2859 | * we do not have an exiting connection (tcon) */ |
2857 | static char * | 2860 | static char * |
2858 | build_unc_path_to_root(const struct smb_vol *volume_info, | 2861 | build_unc_path_to_root(const struct smb_vol *vol, |
2859 | const struct cifs_sb_info *cifs_sb) | 2862 | const struct cifs_sb_info *cifs_sb) |
2860 | { | 2863 | { |
2861 | char *full_path; | 2864 | char *full_path, *pos; |
2865 | unsigned int pplen = vol->prepath ? strlen(vol->prepath) : 0; | ||
2866 | unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1); | ||
2862 | 2867 | ||
2863 | int unc_len = strnlen(volume_info->UNC, MAX_TREE_SIZE + 1); | 2868 | full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL); |
2864 | full_path = kmalloc(unc_len + 1, GFP_KERNEL); | ||
2865 | if (full_path == NULL) | 2869 | if (full_path == NULL) |
2866 | return ERR_PTR(-ENOMEM); | 2870 | return ERR_PTR(-ENOMEM); |
2867 | 2871 | ||
2868 | strncpy(full_path, volume_info->UNC, unc_len); | 2872 | strncpy(full_path, vol->UNC, unc_len); |
2869 | full_path[unc_len] = 0; /* add trailing null */ | 2873 | pos = full_path + unc_len; |
2874 | |||
2875 | if (pplen) { | ||
2876 | strncpy(pos, vol->prepath, pplen); | ||
2877 | pos += pplen; | ||
2878 | } | ||
2879 | |||
2880 | *pos = '\0'; /* add trailing null */ | ||
2870 | convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb)); | 2881 | convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb)); |
2882 | cFYI(1, "%s: full_path=%s", __func__, full_path); | ||
2871 | return full_path; | 2883 | return full_path; |
2872 | } | 2884 | } |
2873 | 2885 | ||
@@ -2910,15 +2922,18 @@ expand_dfs_referral(int xid, struct cifs_ses *pSesInfo, | |||
2910 | &fake_devname); | 2922 | &fake_devname); |
2911 | 2923 | ||
2912 | free_dfs_info_array(referrals, num_referrals); | 2924 | free_dfs_info_array(referrals, num_referrals); |
2913 | kfree(fake_devname); | ||
2914 | |||
2915 | if (cifs_sb->mountdata != NULL) | ||
2916 | kfree(cifs_sb->mountdata); | ||
2917 | 2925 | ||
2918 | if (IS_ERR(mdata)) { | 2926 | if (IS_ERR(mdata)) { |
2919 | rc = PTR_ERR(mdata); | 2927 | rc = PTR_ERR(mdata); |
2920 | mdata = NULL; | 2928 | mdata = NULL; |
2929 | } else { | ||
2930 | cleanup_volume_info_contents(volume_info); | ||
2931 | memset(volume_info, '\0', sizeof(*volume_info)); | ||
2932 | rc = cifs_setup_volume_info(volume_info, mdata, | ||
2933 | fake_devname); | ||
2921 | } | 2934 | } |
2935 | kfree(fake_devname); | ||
2936 | kfree(cifs_sb->mountdata); | ||
2922 | cifs_sb->mountdata = mdata; | 2937 | cifs_sb->mountdata = mdata; |
2923 | } | 2938 | } |
2924 | kfree(full_path); | 2939 | kfree(full_path); |
@@ -2926,33 +2941,20 @@ expand_dfs_referral(int xid, struct cifs_ses *pSesInfo, | |||
2926 | } | 2941 | } |
2927 | #endif | 2942 | #endif |
2928 | 2943 | ||
2929 | int cifs_setup_volume_info(struct smb_vol **pvolume_info, char *mount_data, | 2944 | static int |
2930 | const char *devname) | 2945 | cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data, |
2946 | const char *devname) | ||
2931 | { | 2947 | { |
2932 | struct smb_vol *volume_info; | ||
2933 | int rc = 0; | 2948 | int rc = 0; |
2934 | 2949 | ||
2935 | *pvolume_info = NULL; | 2950 | if (cifs_parse_mount_options(mount_data, devname, volume_info)) |
2936 | 2951 | return -EINVAL; | |
2937 | volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL); | ||
2938 | if (!volume_info) { | ||
2939 | rc = -ENOMEM; | ||
2940 | goto out; | ||
2941 | } | ||
2942 | |||
2943 | if (cifs_parse_mount_options(mount_data, devname, | ||
2944 | volume_info)) { | ||
2945 | rc = -EINVAL; | ||
2946 | goto out; | ||
2947 | } | ||
2948 | 2952 | ||
2949 | if (volume_info->nullauth) { | 2953 | if (volume_info->nullauth) { |
2950 | cFYI(1, "null user"); | 2954 | cFYI(1, "null user"); |
2951 | volume_info->username = kzalloc(1, GFP_KERNEL); | 2955 | volume_info->username = kzalloc(1, GFP_KERNEL); |
2952 | if (volume_info->username == NULL) { | 2956 | if (volume_info->username == NULL) |
2953 | rc = -ENOMEM; | 2957 | return -ENOMEM; |
2954 | goto out; | ||
2955 | } | ||
2956 | } else if (volume_info->username) { | 2958 | } else if (volume_info->username) { |
2957 | /* BB fixme parse for domain name here */ | 2959 | /* BB fixme parse for domain name here */ |
2958 | cFYI(1, "Username: %s", volume_info->username); | 2960 | cFYI(1, "Username: %s", volume_info->username); |
@@ -2960,8 +2962,7 @@ int cifs_setup_volume_info(struct smb_vol **pvolume_info, char *mount_data, | |||
2960 | cifserror("No username specified"); | 2962 | cifserror("No username specified"); |
2961 | /* In userspace mount helper we can get user name from alternate | 2963 | /* In userspace mount helper we can get user name from alternate |
2962 | locations such as env variables and files on disk */ | 2964 | locations such as env variables and files on disk */ |
2963 | rc = -EINVAL; | 2965 | return -EINVAL; |
2964 | goto out; | ||
2965 | } | 2966 | } |
2966 | 2967 | ||
2967 | /* this is needed for ASCII cp to Unicode converts */ | 2968 | /* this is needed for ASCII cp to Unicode converts */ |
@@ -2973,18 +2974,32 @@ int cifs_setup_volume_info(struct smb_vol **pvolume_info, char *mount_data, | |||
2973 | if (volume_info->local_nls == NULL) { | 2974 | if (volume_info->local_nls == NULL) { |
2974 | cERROR(1, "CIFS mount error: iocharset %s not found", | 2975 | cERROR(1, "CIFS mount error: iocharset %s not found", |
2975 | volume_info->iocharset); | 2976 | volume_info->iocharset); |
2976 | rc = -ELIBACC; | 2977 | return -ELIBACC; |
2977 | goto out; | ||
2978 | } | 2978 | } |
2979 | } | 2979 | } |
2980 | 2980 | ||
2981 | *pvolume_info = volume_info; | ||
2982 | return rc; | ||
2983 | out: | ||
2984 | cifs_cleanup_volume_info(&volume_info); | ||
2985 | return rc; | 2981 | return rc; |
2986 | } | 2982 | } |
2987 | 2983 | ||
2984 | struct smb_vol * | ||
2985 | cifs_get_volume_info(char *mount_data, const char *devname) | ||
2986 | { | ||
2987 | int rc; | ||
2988 | struct smb_vol *volume_info; | ||
2989 | |||
2990 | volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL); | ||
2991 | if (!volume_info) | ||
2992 | return ERR_PTR(-ENOMEM); | ||
2993 | |||
2994 | rc = cifs_setup_volume_info(volume_info, mount_data, devname); | ||
2995 | if (rc) { | ||
2996 | cifs_cleanup_volume_info(volume_info); | ||
2997 | volume_info = ERR_PTR(rc); | ||
2998 | } | ||
2999 | |||
3000 | return volume_info; | ||
3001 | } | ||
3002 | |||
2988 | int | 3003 | int |
2989 | cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) | 3004 | cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) |
2990 | { | 3005 | { |
@@ -2997,6 +3012,7 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) | |||
2997 | struct tcon_link *tlink; | 3012 | struct tcon_link *tlink; |
2998 | #ifdef CONFIG_CIFS_DFS_UPCALL | 3013 | #ifdef CONFIG_CIFS_DFS_UPCALL |
2999 | int referral_walks_count = 0; | 3014 | int referral_walks_count = 0; |
3015 | #endif | ||
3000 | 3016 | ||
3001 | rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); | 3017 | rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); |
3002 | if (rc) | 3018 | if (rc) |
@@ -3004,6 +3020,7 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) | |||
3004 | 3020 | ||
3005 | cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; | 3021 | cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; |
3006 | 3022 | ||
3023 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
3007 | try_mount_again: | 3024 | try_mount_again: |
3008 | /* cleanup activities if we're chasing a referral */ | 3025 | /* cleanup activities if we're chasing a referral */ |
3009 | if (referral_walks_count) { | 3026 | if (referral_walks_count) { |
@@ -3012,7 +3029,6 @@ try_mount_again: | |||
3012 | else if (pSesInfo) | 3029 | else if (pSesInfo) |
3013 | cifs_put_smb_ses(pSesInfo); | 3030 | cifs_put_smb_ses(pSesInfo); |
3014 | 3031 | ||
3015 | cifs_cleanup_volume_info(&volume_info); | ||
3016 | FreeXid(xid); | 3032 | FreeXid(xid); |
3017 | } | 3033 | } |
3018 | #endif | 3034 | #endif |