diff options
-rw-r--r-- | fs/cifs/cifsfs.c | 88 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 8 | ||||
-rw-r--r-- | fs/cifs/connect.c | 89 |
3 files changed, 114 insertions, 71 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 493b74ca5648..131afadce0e0 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -104,19 +104,16 @@ cifs_sb_deactive(struct super_block *sb) | |||
104 | } | 104 | } |
105 | 105 | ||
106 | static int | 106 | static int |
107 | cifs_read_super(struct super_block *sb, void *data, | 107 | cifs_read_super(struct super_block *sb, struct cifs_sb_info *cifs_sb, |
108 | const char *devname, int silent) | 108 | void *data, struct smb_vol *volume_info, const char *devname, |
109 | int silent) | ||
109 | { | 110 | { |
110 | struct inode *inode; | 111 | struct inode *inode; |
111 | struct cifs_sb_info *cifs_sb; | ||
112 | int rc = 0; | 112 | int rc = 0; |
113 | 113 | ||
114 | /* BB should we make this contingent on mount parm? */ | 114 | /* BB should we make this contingent on mount parm? */ |
115 | sb->s_flags |= MS_NODIRATIME | MS_NOATIME; | 115 | sb->s_flags |= MS_NODIRATIME | MS_NOATIME; |
116 | sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); | 116 | sb->s_fs_info = cifs_sb; |
117 | cifs_sb = CIFS_SB(sb); | ||
118 | if (cifs_sb == NULL) | ||
119 | return -ENOMEM; | ||
120 | 117 | ||
121 | spin_lock_init(&cifs_sb->tlink_tree_lock); | 118 | spin_lock_init(&cifs_sb->tlink_tree_lock); |
122 | cifs_sb->tlink_tree = RB_ROOT; | 119 | cifs_sb->tlink_tree = RB_ROOT; |
@@ -128,22 +125,10 @@ cifs_read_super(struct super_block *sb, void *data, | |||
128 | } | 125 | } |
129 | cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; | 126 | cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; |
130 | 127 | ||
131 | /* | 128 | if (data) |
132 | * Copy mount params to sb for use in submounts. Better to do | 129 | cifs_sb->mountdata = data; |
133 | * the copy here and deal with the error before cleanup gets | ||
134 | * complicated post-mount. | ||
135 | */ | ||
136 | if (data) { | ||
137 | cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); | ||
138 | if (cifs_sb->mountdata == NULL) { | ||
139 | bdi_destroy(&cifs_sb->bdi); | ||
140 | kfree(sb->s_fs_info); | ||
141 | sb->s_fs_info = NULL; | ||
142 | return -ENOMEM; | ||
143 | } | ||
144 | } | ||
145 | 130 | ||
146 | rc = cifs_mount(sb, cifs_sb, devname); | 131 | rc = cifs_mount(sb, cifs_sb, volume_info, devname); |
147 | 132 | ||
148 | if (rc) { | 133 | if (rc) { |
149 | if (!silent) | 134 | if (!silent) |
@@ -561,27 +546,68 @@ static const struct super_operations cifs_super_ops = { | |||
561 | 546 | ||
562 | static struct dentry * | 547 | static struct dentry * |
563 | cifs_do_mount(struct file_system_type *fs_type, | 548 | cifs_do_mount(struct file_system_type *fs_type, |
564 | int flags, const char *dev_name, void *data) | 549 | int flags, const char *dev_name, void *data) |
565 | { | 550 | { |
566 | int rc; | 551 | int rc; |
567 | struct super_block *sb; | 552 | struct super_block *sb; |
568 | 553 | struct cifs_sb_info *cifs_sb; | |
569 | sb = sget(fs_type, NULL, set_anon_super, NULL); | 554 | struct smb_vol *volume_info; |
555 | struct dentry *root; | ||
556 | char *copied_data = NULL; | ||
570 | 557 | ||
571 | cFYI(1, "Devname: %s flags: %d ", dev_name, flags); | 558 | cFYI(1, "Devname: %s flags: %d ", dev_name, flags); |
572 | 559 | ||
573 | if (IS_ERR(sb)) | 560 | rc = cifs_setup_volume_info(&volume_info, (char *)data, dev_name); |
574 | return ERR_CAST(sb); | 561 | if (rc) |
562 | return ERR_PTR(rc); | ||
563 | |||
564 | cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); | ||
565 | if (cifs_sb == NULL) { | ||
566 | root = ERR_PTR(-ENOMEM); | ||
567 | goto out; | ||
568 | } | ||
569 | |||
570 | cifs_setup_cifs_sb(volume_info, cifs_sb); | ||
571 | |||
572 | sb = sget(fs_type, NULL, set_anon_super, NULL); | ||
573 | if (IS_ERR(sb)) { | ||
574 | kfree(cifs_sb); | ||
575 | root = ERR_CAST(sb); | ||
576 | goto out; | ||
577 | } | ||
575 | 578 | ||
576 | sb->s_flags = flags; | 579 | sb->s_flags = flags; |
577 | 580 | ||
578 | rc = cifs_read_super(sb, data, dev_name, flags & MS_SILENT ? 1 : 0); | 581 | /* |
582 | * Copy mount params for use in submounts. Better to do | ||
583 | * the copy here and deal with the error before cleanup gets | ||
584 | * complicated post-mount. | ||
585 | */ | ||
586 | copied_data = kstrndup(data, PAGE_SIZE, GFP_KERNEL); | ||
587 | if (copied_data == NULL) { | ||
588 | root = ERR_PTR(-ENOMEM); | ||
589 | goto err_out; | ||
590 | } | ||
591 | |||
592 | rc = cifs_read_super(sb, cifs_sb, copied_data, volume_info, dev_name, | ||
593 | flags & MS_SILENT ? 1 : 0); | ||
579 | if (rc) { | 594 | if (rc) { |
580 | deactivate_locked_super(sb); | 595 | root = ERR_PTR(rc); |
581 | return ERR_PTR(rc); | 596 | goto err_out; |
582 | } | 597 | } |
598 | |||
583 | sb->s_flags |= MS_ACTIVE; | 599 | sb->s_flags |= MS_ACTIVE; |
584 | return dget(sb->s_root); | 600 | |
601 | root = dget(sb->s_root); | ||
602 | out: | ||
603 | cifs_cleanup_volume_info(&volume_info); | ||
604 | return root; | ||
605 | |||
606 | err_out: | ||
607 | kfree(cifs_sb); | ||
608 | deactivate_locked_super(sb); | ||
609 | cifs_cleanup_volume_info(&volume_info); | ||
610 | return root; | ||
585 | } | 611 | } |
586 | 612 | ||
587 | static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | 613 | static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 3738a322cbef..fdc0dc2c083c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -150,8 +150,14 @@ extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, | |||
150 | extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, | 150 | extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, |
151 | const char *); | 151 | const char *); |
152 | 152 | ||
153 | extern void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | ||
154 | struct cifs_sb_info *cifs_sb); | ||
155 | extern int cifs_match_super(struct super_block *, void *); | ||
156 | extern void cifs_cleanup_volume_info(struct smb_vol **pvolume_info); | ||
157 | extern int cifs_setup_volume_info(struct smb_vol **pvolume_info, | ||
158 | char *mount_data, const char *devname); | ||
153 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, | 159 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, |
154 | const char *); | 160 | struct smb_vol *, const char *); |
155 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); | 161 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); |
156 | extern void cifs_dfs_release_automount_timer(void); | 162 | extern void cifs_dfs_release_automount_timer(void); |
157 | void cifs_proc_init(void); | 163 | void cifs_proc_init(void); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 37b8ead2f60e..273cf42b2915 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -2614,8 +2614,8 @@ convert_delimiter(char *path, char delim) | |||
2614 | } | 2614 | } |
2615 | } | 2615 | } |
2616 | 2616 | ||
2617 | static void setup_cifs_sb(struct smb_vol *pvolume_info, | 2617 | void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, |
2618 | struct cifs_sb_info *cifs_sb) | 2618 | struct cifs_sb_info *cifs_sb) |
2619 | { | 2619 | { |
2620 | INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks); | 2620 | INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks); |
2621 | 2621 | ||
@@ -2671,6 +2671,7 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, | |||
2671 | cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode); | 2671 | cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode); |
2672 | 2672 | ||
2673 | cifs_sb->actimeo = pvolume_info->actimeo; | 2673 | cifs_sb->actimeo = pvolume_info->actimeo; |
2674 | cifs_sb->local_nls = pvolume_info->local_nls; | ||
2674 | 2675 | ||
2675 | if (pvolume_info->noperm) | 2676 | if (pvolume_info->noperm) |
2676 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; | 2677 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; |
@@ -2747,8 +2748,8 @@ is_path_accessible(int xid, struct cifsTconInfo *tcon, | |||
2747 | return rc; | 2748 | return rc; |
2748 | } | 2749 | } |
2749 | 2750 | ||
2750 | static void | 2751 | void |
2751 | cleanup_volume_info(struct smb_vol **pvolume_info) | 2752 | cifs_cleanup_volume_info(struct smb_vol **pvolume_info) |
2752 | { | 2753 | { |
2753 | struct smb_vol *volume_info; | 2754 | struct smb_vol *volume_info; |
2754 | 2755 | ||
@@ -2854,40 +2855,13 @@ expand_dfs_referral(int xid, struct cifsSesInfo *pSesInfo, | |||
2854 | } | 2855 | } |
2855 | #endif | 2856 | #endif |
2856 | 2857 | ||
2857 | int | 2858 | int cifs_setup_volume_info(struct smb_vol **pvolume_info, char *mount_data, |
2858 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | 2859 | const char *devname) |
2859 | const char *devname) | ||
2860 | { | 2860 | { |
2861 | int rc; | ||
2862 | int xid; | ||
2863 | struct smb_vol *volume_info; | 2861 | struct smb_vol *volume_info; |
2864 | struct cifsSesInfo *pSesInfo; | 2862 | int rc = 0; |
2865 | struct cifsTconInfo *tcon; | ||
2866 | struct TCP_Server_Info *srvTcp; | ||
2867 | char *full_path; | ||
2868 | struct tcon_link *tlink; | ||
2869 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
2870 | int referral_walks_count = 0; | ||
2871 | try_mount_again: | ||
2872 | /* cleanup activities if we're chasing a referral */ | ||
2873 | if (referral_walks_count) { | ||
2874 | if (tcon) | ||
2875 | cifs_put_tcon(tcon); | ||
2876 | else if (pSesInfo) | ||
2877 | cifs_put_smb_ses(pSesInfo); | ||
2878 | |||
2879 | cleanup_volume_info(&volume_info); | ||
2880 | FreeXid(xid); | ||
2881 | } | ||
2882 | #endif | ||
2883 | rc = 0; | ||
2884 | tcon = NULL; | ||
2885 | pSesInfo = NULL; | ||
2886 | srvTcp = NULL; | ||
2887 | full_path = NULL; | ||
2888 | tlink = NULL; | ||
2889 | 2863 | ||
2890 | xid = GetXid(); | 2864 | *pvolume_info = NULL; |
2891 | 2865 | ||
2892 | volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL); | 2866 | volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL); |
2893 | if (!volume_info) { | 2867 | if (!volume_info) { |
@@ -2895,7 +2869,7 @@ try_mount_again: | |||
2895 | goto out; | 2869 | goto out; |
2896 | } | 2870 | } |
2897 | 2871 | ||
2898 | if (cifs_parse_mount_options(cifs_sb->mountdata, devname, | 2872 | if (cifs_parse_mount_options(mount_data, devname, |
2899 | volume_info)) { | 2873 | volume_info)) { |
2900 | rc = -EINVAL; | 2874 | rc = -EINVAL; |
2901 | goto out; | 2875 | goto out; |
@@ -2928,7 +2902,46 @@ try_mount_again: | |||
2928 | goto out; | 2902 | goto out; |
2929 | } | 2903 | } |
2930 | } | 2904 | } |
2931 | cifs_sb->local_nls = volume_info->local_nls; | 2905 | |
2906 | *pvolume_info = volume_info; | ||
2907 | return rc; | ||
2908 | out: | ||
2909 | cifs_cleanup_volume_info(&volume_info); | ||
2910 | return rc; | ||
2911 | } | ||
2912 | |||
2913 | int | ||
2914 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | ||
2915 | struct smb_vol *volume_info, const char *devname) | ||
2916 | { | ||
2917 | int rc = 0; | ||
2918 | int xid; | ||
2919 | struct cifsSesInfo *pSesInfo; | ||
2920 | struct cifsTconInfo *tcon; | ||
2921 | struct TCP_Server_Info *srvTcp; | ||
2922 | char *full_path; | ||
2923 | struct tcon_link *tlink; | ||
2924 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
2925 | int referral_walks_count = 0; | ||
2926 | try_mount_again: | ||
2927 | /* cleanup activities if we're chasing a referral */ | ||
2928 | if (referral_walks_count) { | ||
2929 | if (tcon) | ||
2930 | cifs_put_tcon(tcon); | ||
2931 | else if (pSesInfo) | ||
2932 | cifs_put_smb_ses(pSesInfo); | ||
2933 | |||
2934 | cifs_cleanup_volume_info(&volume_info); | ||
2935 | FreeXid(xid); | ||
2936 | } | ||
2937 | #endif | ||
2938 | tcon = NULL; | ||
2939 | pSesInfo = NULL; | ||
2940 | srvTcp = NULL; | ||
2941 | full_path = NULL; | ||
2942 | tlink = NULL; | ||
2943 | |||
2944 | xid = GetXid(); | ||
2932 | 2945 | ||
2933 | /* get a reference to a tcp session */ | 2946 | /* get a reference to a tcp session */ |
2934 | srvTcp = cifs_get_tcp_session(volume_info); | 2947 | srvTcp = cifs_get_tcp_session(volume_info); |
@@ -2945,7 +2958,6 @@ try_mount_again: | |||
2945 | goto mount_fail_check; | 2958 | goto mount_fail_check; |
2946 | } | 2959 | } |
2947 | 2960 | ||
2948 | setup_cifs_sb(volume_info, cifs_sb); | ||
2949 | if (pSesInfo->capabilities & CAP_LARGE_FILES) | 2961 | if (pSesInfo->capabilities & CAP_LARGE_FILES) |
2950 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 2962 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
2951 | else | 2963 | else |
@@ -3101,7 +3113,6 @@ mount_fail_check: | |||
3101 | password will be freed at unmount time) */ | 3113 | password will be freed at unmount time) */ |
3102 | out: | 3114 | out: |
3103 | /* zero out password before freeing */ | 3115 | /* zero out password before freeing */ |
3104 | cleanup_volume_info(&volume_info); | ||
3105 | FreeXid(xid); | 3116 | FreeXid(xid); |
3106 | return rc; | 3117 | return rc; |
3107 | } | 3118 | } |