diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-11 15:48:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-11 15:48:24 -0400 |
commit | 71a1b44b036457169e7974eea0b5b37f64176952 (patch) | |
tree | f6756944ee46e2cb9225c46941a08db824094140 /fs | |
parent | c891f2cd89c7a2b4d51d009e94c74a1e31626528 (diff) | |
parent | f484b5d001a972a42129570e98086a2a6d216ce0 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
cifs: drop spinlock before calling cifs_put_tlink
cifs: fix expand_dfs_referral
cifs: move bdi_setup_and_register outside of CONFIG_CIFS_DFS_UPCALL
cifs: factor smb_vol allocation out of cifs_setup_volume_info
cifs: have cifs_cleanup_volume_info not take a double pointer
cifs: fix build_unc_path_to_root to account for a prefixpath
cifs: remove bogus call to cifs_cleanup_volume_info
Diffstat (limited to 'fs')
-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 |