diff options
| -rw-r--r-- | fs/cifs/cifsfs.c | 8 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 6 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 116 |
3 files changed, 73 insertions, 57 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 35f9154615fa..3e2989976297 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -649,9 +649,9 @@ cifs_do_mount(struct file_system_type *fs_type, | |||
| 649 | 649 | ||
| 650 | cFYI(1, "Devname: %s flags: %d ", dev_name, flags); | 650 | cFYI(1, "Devname: %s flags: %d ", dev_name, flags); |
| 651 | 651 | ||
| 652 | rc = cifs_setup_volume_info(&volume_info, (char *)data, dev_name); | 652 | volume_info = cifs_get_volume_info((char *)data, dev_name); |
| 653 | if (rc) | 653 | if (IS_ERR(volume_info)) |
| 654 | return ERR_PTR(rc); | 654 | return ERR_CAST(volume_info); |
| 655 | 655 | ||
| 656 | cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); | 656 | cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); |
| 657 | if (cifs_sb == NULL) { | 657 | if (cifs_sb == NULL) { |
| @@ -713,7 +713,7 @@ cifs_do_mount(struct file_system_type *fs_type, | |||
| 713 | out_super: | 713 | out_super: |
| 714 | deactivate_locked_super(sb); | 714 | deactivate_locked_super(sb); |
| 715 | out: | 715 | out: |
| 716 | cifs_cleanup_volume_info(&volume_info); | 716 | cifs_cleanup_volume_info(volume_info); |
| 717 | return root; | 717 | return root; |
| 718 | 718 | ||
| 719 | out_mountdata: | 719 | out_mountdata: |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 257f312ede42..8df28e925e5b 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -154,9 +154,9 @@ extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, | |||
| 154 | extern void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | 154 | extern void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, |
| 155 | struct cifs_sb_info *cifs_sb); | 155 | struct cifs_sb_info *cifs_sb); |
| 156 | extern int cifs_match_super(struct super_block *, void *); | 156 | extern int cifs_match_super(struct super_block *, void *); |
| 157 | extern void cifs_cleanup_volume_info(struct smb_vol **pvolume_info); | 157 | extern void cifs_cleanup_volume_info(struct smb_vol *pvolume_info); |
| 158 | extern int cifs_setup_volume_info(struct smb_vol **pvolume_info, | 158 | extern struct smb_vol *cifs_get_volume_info(char *mount_data, |
| 159 | char *mount_data, const char *devname); | 159 | const char *devname); |
| 160 | extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *); | 160 | extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *); |
| 161 | extern void cifs_umount(struct cifs_sb_info *); | 161 | extern void cifs_umount(struct cifs_sb_info *); |
| 162 | extern void cifs_dfs_release_automount_timer(void); | 162 | extern void cifs_dfs_release_automount_timer(void); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c8cb83ef6f6f..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 | ||
| @@ -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 |
