aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsfs.c88
-rw-r--r--fs/cifs/cifsproto.h8
-rw-r--r--fs/cifs/connect.c89
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
106static int 106static int
107cifs_read_super(struct super_block *sb, void *data, 107cifs_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
562static struct dentry * 547static struct dentry *
563cifs_do_mount(struct file_system_type *fs_type, 548cifs_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);
602out:
603 cifs_cleanup_volume_info(&volume_info);
604 return root;
605
606err_out:
607 kfree(cifs_sb);
608 deactivate_locked_super(sb);
609 cifs_cleanup_volume_info(&volume_info);
610 return root;
585} 611}
586 612
587static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, 613static 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 *,
150extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, 150extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
151 const char *); 151 const char *);
152 152
153extern void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
154 struct cifs_sb_info *cifs_sb);
155extern int cifs_match_super(struct super_block *, void *);
156extern void cifs_cleanup_volume_info(struct smb_vol **pvolume_info);
157extern int cifs_setup_volume_info(struct smb_vol **pvolume_info,
158 char *mount_data, const char *devname);
153extern int cifs_mount(struct super_block *, struct cifs_sb_info *, 159extern int cifs_mount(struct super_block *, struct cifs_sb_info *,
154 const char *); 160 struct smb_vol *, const char *);
155extern int cifs_umount(struct super_block *, struct cifs_sb_info *); 161extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
156extern void cifs_dfs_release_automount_timer(void); 162extern void cifs_dfs_release_automount_timer(void);
157void cifs_proc_init(void); 163void 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
2617static void setup_cifs_sb(struct smb_vol *pvolume_info, 2617void 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
2750static void 2751void
2751cleanup_volume_info(struct smb_vol **pvolume_info) 2752cifs_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
2857int 2858int cifs_setup_volume_info(struct smb_vol **pvolume_info, char *mount_data,
2858cifs_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;
2871try_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;
2908out:
2909 cifs_cleanup_volume_info(&volume_info);
2910 return rc;
2911}
2912
2913int
2914cifs_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;
2926try_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) */
3102out: 3114out:
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}