diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-26 22:39:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-26 22:39:22 -0400 |
commit | 804a007f5401f87fc6e7da1e8884dc32912e35d0 (patch) | |
tree | c94fda93a6c85b655bb8c13703a97295ce4314f6 /fs | |
parent | 8abf55883431a91d4877933240c8419b7fc17274 (diff) | |
parent | 9403c9c598e91d473c0582066e47ed2289292e45 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
cifs: propagate errors from cifs_get_root() to mount(2)
cifs: tidy cifs_do_mount() up a bit
cifs: more breakage on mount failures
cifs: close sget() races
cifs: pull freeing mountdata/dropping nls/freeing cifs_sb into cifs_umount()
cifs: move cifs_umount() call into ->kill_sb()
cifs: pull cifs_mount() call up
sanitize cifs_umount() prototype
cifs: initialize ->tlink_tree in cifs_setup_cifs_sb()
cifs: allocate mountdata earlier
cifs: leak on mount if we share superblock
cifs: don't pass superblock to cifs_mount()
cifs: don't leak nls on mount failure
cifs: double free on mount failure
take bdi setup/destruction into cifs_mount/cifs_umount
Acked-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifs_fs_sb.h | 1 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 156 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 8 | ||||
-rw-r--r-- | fs/cifs/connect.c | 49 |
4 files changed, 98 insertions, 116 deletions
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index ffb1459dc6ec..7260e11e21f8 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ | 42 | #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ |
43 | #define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ | 43 | #define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ |
44 | #define CIFS_MOUNT_RWPIDFORWARD 0x80000 /* use pid forwarding for rw */ | 44 | #define CIFS_MOUNT_RWPIDFORWARD 0x80000 /* use pid forwarding for rw */ |
45 | #define CIFS_MOUNT_POSIXACL 0x100000 /* mirror of MS_POSIXACL in mnt_cifs_flags */ | ||
45 | 46 | ||
46 | struct cifs_sb_info { | 47 | struct cifs_sb_info { |
47 | struct rb_root tlink_tree; | 48 | struct rb_root tlink_tree; |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 2f0c58646c10..35f9154615fa 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -104,8 +104,7 @@ 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, struct smb_vol *volume_info, | 107 | cifs_read_super(struct super_block *sb) |
108 | const char *devname, int silent) | ||
109 | { | 108 | { |
110 | struct inode *inode; | 109 | struct inode *inode; |
111 | struct cifs_sb_info *cifs_sb; | 110 | struct cifs_sb_info *cifs_sb; |
@@ -113,22 +112,16 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, | |||
113 | 112 | ||
114 | cifs_sb = CIFS_SB(sb); | 113 | cifs_sb = CIFS_SB(sb); |
115 | 114 | ||
116 | spin_lock_init(&cifs_sb->tlink_tree_lock); | 115 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL) |
117 | cifs_sb->tlink_tree = RB_ROOT; | 116 | sb->s_flags |= MS_POSIXACL; |
118 | 117 | ||
119 | rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); | 118 | if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES) |
120 | if (rc) | 119 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
121 | return rc; | 120 | else |
122 | 121 | sb->s_maxbytes = MAX_NON_LFS; | |
123 | cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; | ||
124 | 122 | ||
125 | rc = cifs_mount(sb, cifs_sb, volume_info, devname); | 123 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ |
126 | 124 | sb->s_time_gran = 100; | |
127 | if (rc) { | ||
128 | if (!silent) | ||
129 | cERROR(1, "cifs_mount failed w/return code = %d", rc); | ||
130 | goto out_mount_failed; | ||
131 | } | ||
132 | 125 | ||
133 | sb->s_magic = CIFS_MAGIC_NUMBER; | 126 | sb->s_magic = CIFS_MAGIC_NUMBER; |
134 | sb->s_op = &cifs_super_ops; | 127 | sb->s_op = &cifs_super_ops; |
@@ -170,37 +163,14 @@ out_no_root: | |||
170 | if (inode) | 163 | if (inode) |
171 | iput(inode); | 164 | iput(inode); |
172 | 165 | ||
173 | cifs_umount(sb, cifs_sb); | ||
174 | |||
175 | out_mount_failed: | ||
176 | bdi_destroy(&cifs_sb->bdi); | ||
177 | return rc; | 166 | return rc; |
178 | } | 167 | } |
179 | 168 | ||
180 | static void | 169 | static void cifs_kill_sb(struct super_block *sb) |
181 | cifs_put_super(struct super_block *sb) | ||
182 | { | 170 | { |
183 | int rc = 0; | 171 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
184 | struct cifs_sb_info *cifs_sb; | 172 | kill_anon_super(sb); |
185 | 173 | cifs_umount(cifs_sb); | |
186 | cFYI(1, "In cifs_put_super"); | ||
187 | cifs_sb = CIFS_SB(sb); | ||
188 | if (cifs_sb == NULL) { | ||
189 | cFYI(1, "Empty cifs superblock info passed to unmount"); | ||
190 | return; | ||
191 | } | ||
192 | |||
193 | rc = cifs_umount(sb, cifs_sb); | ||
194 | if (rc) | ||
195 | cERROR(1, "cifs_umount failed with return code %d", rc); | ||
196 | if (cifs_sb->mountdata) { | ||
197 | kfree(cifs_sb->mountdata); | ||
198 | cifs_sb->mountdata = NULL; | ||
199 | } | ||
200 | |||
201 | unload_nls(cifs_sb->local_nls); | ||
202 | bdi_destroy(&cifs_sb->bdi); | ||
203 | kfree(cifs_sb); | ||
204 | } | 174 | } |
205 | 175 | ||
206 | static int | 176 | static int |
@@ -548,7 +518,6 @@ static int cifs_drop_inode(struct inode *inode) | |||
548 | } | 518 | } |
549 | 519 | ||
550 | static const struct super_operations cifs_super_ops = { | 520 | static const struct super_operations cifs_super_ops = { |
551 | .put_super = cifs_put_super, | ||
552 | .statfs = cifs_statfs, | 521 | .statfs = cifs_statfs, |
553 | .alloc_inode = cifs_alloc_inode, | 522 | .alloc_inode = cifs_alloc_inode, |
554 | .destroy_inode = cifs_destroy_inode, | 523 | .destroy_inode = cifs_destroy_inode, |
@@ -585,7 +554,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) | |||
585 | full_path = cifs_build_path_to_root(vol, cifs_sb, | 554 | full_path = cifs_build_path_to_root(vol, cifs_sb, |
586 | cifs_sb_master_tcon(cifs_sb)); | 555 | cifs_sb_master_tcon(cifs_sb)); |
587 | if (full_path == NULL) | 556 | if (full_path == NULL) |
588 | return NULL; | 557 | return ERR_PTR(-ENOMEM); |
589 | 558 | ||
590 | cFYI(1, "Get root dentry for %s", full_path); | 559 | cFYI(1, "Get root dentry for %s", full_path); |
591 | 560 | ||
@@ -614,7 +583,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) | |||
614 | dchild = d_alloc(dparent, &name); | 583 | dchild = d_alloc(dparent, &name); |
615 | if (dchild == NULL) { | 584 | if (dchild == NULL) { |
616 | dput(dparent); | 585 | dput(dparent); |
617 | dparent = NULL; | 586 | dparent = ERR_PTR(-ENOMEM); |
618 | goto out; | 587 | goto out; |
619 | } | 588 | } |
620 | } | 589 | } |
@@ -632,7 +601,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) | |||
632 | if (rc) { | 601 | if (rc) { |
633 | dput(dchild); | 602 | dput(dchild); |
634 | dput(dparent); | 603 | dput(dparent); |
635 | dparent = NULL; | 604 | dparent = ERR_PTR(rc); |
636 | goto out; | 605 | goto out; |
637 | } | 606 | } |
638 | alias = d_materialise_unique(dchild, inode); | 607 | alias = d_materialise_unique(dchild, inode); |
@@ -640,7 +609,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) | |||
640 | dput(dchild); | 609 | dput(dchild); |
641 | if (IS_ERR(alias)) { | 610 | if (IS_ERR(alias)) { |
642 | dput(dparent); | 611 | dput(dparent); |
643 | dparent = NULL; | 612 | dparent = ERR_PTR(-EINVAL); /* XXX */ |
644 | goto out; | 613 | goto out; |
645 | } | 614 | } |
646 | dchild = alias; | 615 | dchild = alias; |
@@ -660,6 +629,13 @@ out: | |||
660 | return dparent; | 629 | return dparent; |
661 | } | 630 | } |
662 | 631 | ||
632 | static int cifs_set_super(struct super_block *sb, void *data) | ||
633 | { | ||
634 | struct cifs_mnt_data *mnt_data = data; | ||
635 | sb->s_fs_info = mnt_data->cifs_sb; | ||
636 | return set_anon_super(sb, NULL); | ||
637 | } | ||
638 | |||
663 | static struct dentry * | 639 | static struct dentry * |
664 | cifs_do_mount(struct file_system_type *fs_type, | 640 | cifs_do_mount(struct file_system_type *fs_type, |
665 | int flags, const char *dev_name, void *data) | 641 | int flags, const char *dev_name, void *data) |
@@ -680,75 +656,73 @@ cifs_do_mount(struct file_system_type *fs_type, | |||
680 | cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); | 656 | cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); |
681 | if (cifs_sb == NULL) { | 657 | if (cifs_sb == NULL) { |
682 | root = ERR_PTR(-ENOMEM); | 658 | root = ERR_PTR(-ENOMEM); |
683 | goto out; | 659 | goto out_nls; |
660 | } | ||
661 | |||
662 | cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); | ||
663 | if (cifs_sb->mountdata == NULL) { | ||
664 | root = ERR_PTR(-ENOMEM); | ||
665 | goto out_cifs_sb; | ||
684 | } | 666 | } |
685 | 667 | ||
686 | cifs_setup_cifs_sb(volume_info, cifs_sb); | 668 | cifs_setup_cifs_sb(volume_info, cifs_sb); |
687 | 669 | ||
670 | rc = cifs_mount(cifs_sb, volume_info); | ||
671 | if (rc) { | ||
672 | if (!(flags & MS_SILENT)) | ||
673 | cERROR(1, "cifs_mount failed w/return code = %d", rc); | ||
674 | root = ERR_PTR(rc); | ||
675 | goto out_mountdata; | ||
676 | } | ||
677 | |||
688 | mnt_data.vol = volume_info; | 678 | mnt_data.vol = volume_info; |
689 | mnt_data.cifs_sb = cifs_sb; | 679 | mnt_data.cifs_sb = cifs_sb; |
690 | mnt_data.flags = flags; | 680 | mnt_data.flags = flags; |
691 | 681 | ||
692 | sb = sget(fs_type, cifs_match_super, set_anon_super, &mnt_data); | 682 | sb = sget(fs_type, cifs_match_super, cifs_set_super, &mnt_data); |
693 | if (IS_ERR(sb)) { | 683 | if (IS_ERR(sb)) { |
694 | root = ERR_CAST(sb); | 684 | root = ERR_CAST(sb); |
695 | goto out_cifs_sb; | 685 | cifs_umount(cifs_sb); |
686 | goto out; | ||
696 | } | 687 | } |
697 | 688 | ||
698 | if (sb->s_fs_info) { | 689 | if (sb->s_root) { |
699 | cFYI(1, "Use existing superblock"); | 690 | cFYI(1, "Use existing superblock"); |
700 | goto out_shared; | 691 | cifs_umount(cifs_sb); |
701 | } | 692 | } else { |
702 | 693 | sb->s_flags = flags; | |
703 | /* | 694 | /* BB should we make this contingent on mount parm? */ |
704 | * Copy mount params for use in submounts. Better to do | 695 | sb->s_flags |= MS_NODIRATIME | MS_NOATIME; |
705 | * the copy here and deal with the error before cleanup gets | 696 | |
706 | * complicated post-mount. | 697 | rc = cifs_read_super(sb); |
707 | */ | 698 | if (rc) { |
708 | cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); | 699 | root = ERR_PTR(rc); |
709 | if (cifs_sb->mountdata == NULL) { | 700 | goto out_super; |
710 | root = ERR_PTR(-ENOMEM); | 701 | } |
711 | goto out_super; | ||
712 | } | ||
713 | |||
714 | sb->s_flags = flags; | ||
715 | /* BB should we make this contingent on mount parm? */ | ||
716 | sb->s_flags |= MS_NODIRATIME | MS_NOATIME; | ||
717 | sb->s_fs_info = cifs_sb; | ||
718 | 702 | ||
719 | rc = cifs_read_super(sb, volume_info, dev_name, | 703 | sb->s_flags |= MS_ACTIVE; |
720 | flags & MS_SILENT ? 1 : 0); | ||
721 | if (rc) { | ||
722 | root = ERR_PTR(rc); | ||
723 | goto out_super; | ||
724 | } | 704 | } |
725 | 705 | ||
726 | sb->s_flags |= MS_ACTIVE; | ||
727 | |||
728 | root = cifs_get_root(volume_info, sb); | 706 | root = cifs_get_root(volume_info, sb); |
729 | if (root == NULL) | 707 | if (IS_ERR(root)) |
730 | goto out_super; | 708 | goto out_super; |
731 | 709 | ||
732 | cFYI(1, "dentry root is: %p", root); | 710 | cFYI(1, "dentry root is: %p", root); |
733 | goto out; | 711 | goto out; |
734 | 712 | ||
735 | out_shared: | ||
736 | root = cifs_get_root(volume_info, sb); | ||
737 | if (root) | ||
738 | cFYI(1, "dentry root is: %p", root); | ||
739 | goto out; | ||
740 | |||
741 | out_super: | 713 | out_super: |
742 | kfree(cifs_sb->mountdata); | ||
743 | deactivate_locked_super(sb); | 714 | deactivate_locked_super(sb); |
744 | |||
745 | out_cifs_sb: | ||
746 | unload_nls(cifs_sb->local_nls); | ||
747 | kfree(cifs_sb); | ||
748 | |||
749 | out: | 715 | out: |
750 | cifs_cleanup_volume_info(&volume_info); | 716 | cifs_cleanup_volume_info(&volume_info); |
751 | return root; | 717 | return root; |
718 | |||
719 | out_mountdata: | ||
720 | kfree(cifs_sb->mountdata); | ||
721 | out_cifs_sb: | ||
722 | kfree(cifs_sb); | ||
723 | out_nls: | ||
724 | unload_nls(volume_info->local_nls); | ||
725 | goto out; | ||
752 | } | 726 | } |
753 | 727 | ||
754 | static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | 728 | static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, |
@@ -837,7 +811,7 @@ struct file_system_type cifs_fs_type = { | |||
837 | .owner = THIS_MODULE, | 811 | .owner = THIS_MODULE, |
838 | .name = "cifs", | 812 | .name = "cifs", |
839 | .mount = cifs_do_mount, | 813 | .mount = cifs_do_mount, |
840 | .kill_sb = kill_anon_super, | 814 | .kill_sb = cifs_kill_sb, |
841 | /* .fs_flags */ | 815 | /* .fs_flags */ |
842 | }; | 816 | }; |
843 | const struct inode_operations cifs_dir_inode_ops = { | 817 | const struct inode_operations cifs_dir_inode_ops = { |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 953f84413c77..257f312ede42 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -157,9 +157,8 @@ 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 int cifs_setup_volume_info(struct smb_vol **pvolume_info, |
159 | char *mount_data, const char *devname); | 159 | char *mount_data, const char *devname); |
160 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, | 160 | extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *); |
161 | struct smb_vol *, const char *); | 161 | extern void cifs_umount(struct cifs_sb_info *); |
162 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); | ||
163 | extern void cifs_dfs_release_automount_timer(void); | 162 | extern void cifs_dfs_release_automount_timer(void); |
164 | void cifs_proc_init(void); | 163 | void cifs_proc_init(void); |
165 | void cifs_proc_clean(void); | 164 | void cifs_proc_clean(void); |
@@ -218,7 +217,8 @@ extern int get_dfs_path(int xid, struct cifs_ses *pSesInfo, | |||
218 | struct dfs_info3_param **preferrals, | 217 | struct dfs_info3_param **preferrals, |
219 | int remap); | 218 | int remap); |
220 | extern void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, | 219 | extern void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, |
221 | struct super_block *sb, struct smb_vol *vol); | 220 | struct cifs_sb_info *cifs_sb, |
221 | struct smb_vol *vol); | ||
222 | extern int CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, | 222 | extern int CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, |
223 | struct kstatfs *FSData); | 223 | struct kstatfs *FSData); |
224 | extern int SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, | 224 | extern int SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c761935eab8c..7f540df52527 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -2546,7 +2546,7 @@ ip_connect(struct TCP_Server_Info *server) | |||
2546 | } | 2546 | } |
2547 | 2547 | ||
2548 | void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, | 2548 | void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, |
2549 | struct super_block *sb, struct smb_vol *vol_info) | 2549 | struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info) |
2550 | { | 2550 | { |
2551 | /* if we are reconnecting then should we check to see if | 2551 | /* if we are reconnecting then should we check to see if |
2552 | * any requested capabilities changed locally e.g. via | 2552 | * any requested capabilities changed locally e.g. via |
@@ -2600,22 +2600,23 @@ void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, | |||
2600 | cap &= ~CIFS_UNIX_POSIX_ACL_CAP; | 2600 | cap &= ~CIFS_UNIX_POSIX_ACL_CAP; |
2601 | else if (CIFS_UNIX_POSIX_ACL_CAP & cap) { | 2601 | else if (CIFS_UNIX_POSIX_ACL_CAP & cap) { |
2602 | cFYI(1, "negotiated posix acl support"); | 2602 | cFYI(1, "negotiated posix acl support"); |
2603 | if (sb) | 2603 | if (cifs_sb) |
2604 | sb->s_flags |= MS_POSIXACL; | 2604 | cifs_sb->mnt_cifs_flags |= |
2605 | CIFS_MOUNT_POSIXACL; | ||
2605 | } | 2606 | } |
2606 | 2607 | ||
2607 | if (vol_info && vol_info->posix_paths == 0) | 2608 | if (vol_info && vol_info->posix_paths == 0) |
2608 | cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; | 2609 | cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; |
2609 | else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { | 2610 | else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { |
2610 | cFYI(1, "negotiate posix pathnames"); | 2611 | cFYI(1, "negotiate posix pathnames"); |
2611 | if (sb) | 2612 | if (cifs_sb) |
2612 | CIFS_SB(sb)->mnt_cifs_flags |= | 2613 | cifs_sb->mnt_cifs_flags |= |
2613 | CIFS_MOUNT_POSIX_PATHS; | 2614 | CIFS_MOUNT_POSIX_PATHS; |
2614 | } | 2615 | } |
2615 | 2616 | ||
2616 | if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) { | 2617 | if (cifs_sb && (cifs_sb->rsize > 127 * 1024)) { |
2617 | if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) { | 2618 | if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) { |
2618 | CIFS_SB(sb)->rsize = 127 * 1024; | 2619 | cifs_sb->rsize = 127 * 1024; |
2619 | cFYI(DBG2, "larger reads not supported by srv"); | 2620 | cFYI(DBG2, "larger reads not supported by srv"); |
2620 | } | 2621 | } |
2621 | } | 2622 | } |
@@ -2662,6 +2663,9 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | |||
2662 | { | 2663 | { |
2663 | INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks); | 2664 | INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks); |
2664 | 2665 | ||
2666 | spin_lock_init(&cifs_sb->tlink_tree_lock); | ||
2667 | cifs_sb->tlink_tree = RB_ROOT; | ||
2668 | |||
2665 | if (pvolume_info->rsize > CIFSMaxBufSize) { | 2669 | if (pvolume_info->rsize > CIFSMaxBufSize) { |
2666 | cERROR(1, "rsize %d too large, using MaxBufSize", | 2670 | cERROR(1, "rsize %d too large, using MaxBufSize", |
2667 | pvolume_info->rsize); | 2671 | pvolume_info->rsize); |
@@ -2982,8 +2986,7 @@ out: | |||
2982 | } | 2986 | } |
2983 | 2987 | ||
2984 | int | 2988 | int |
2985 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | 2989 | cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) |
2986 | struct smb_vol *volume_info, const char *devname) | ||
2987 | { | 2990 | { |
2988 | int rc = 0; | 2991 | int rc = 0; |
2989 | int xid; | 2992 | int xid; |
@@ -2994,6 +2997,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2994 | struct tcon_link *tlink; | 2997 | struct tcon_link *tlink; |
2995 | #ifdef CONFIG_CIFS_DFS_UPCALL | 2998 | #ifdef CONFIG_CIFS_DFS_UPCALL |
2996 | int referral_walks_count = 0; | 2999 | int referral_walks_count = 0; |
3000 | |||
3001 | rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); | ||
3002 | if (rc) | ||
3003 | return rc; | ||
3004 | |||
3005 | cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; | ||
3006 | |||
2997 | try_mount_again: | 3007 | try_mount_again: |
2998 | /* cleanup activities if we're chasing a referral */ | 3008 | /* cleanup activities if we're chasing a referral */ |
2999 | if (referral_walks_count) { | 3009 | if (referral_walks_count) { |
@@ -3018,6 +3028,7 @@ try_mount_again: | |||
3018 | srvTcp = cifs_get_tcp_session(volume_info); | 3028 | srvTcp = cifs_get_tcp_session(volume_info); |
3019 | if (IS_ERR(srvTcp)) { | 3029 | if (IS_ERR(srvTcp)) { |
3020 | rc = PTR_ERR(srvTcp); | 3030 | rc = PTR_ERR(srvTcp); |
3031 | bdi_destroy(&cifs_sb->bdi); | ||
3021 | goto out; | 3032 | goto out; |
3022 | } | 3033 | } |
3023 | 3034 | ||
@@ -3029,14 +3040,6 @@ try_mount_again: | |||
3029 | goto mount_fail_check; | 3040 | goto mount_fail_check; |
3030 | } | 3041 | } |
3031 | 3042 | ||
3032 | if (pSesInfo->capabilities & CAP_LARGE_FILES) | ||
3033 | sb->s_maxbytes = MAX_LFS_FILESIZE; | ||
3034 | else | ||
3035 | sb->s_maxbytes = MAX_NON_LFS; | ||
3036 | |||
3037 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ | ||
3038 | sb->s_time_gran = 100; | ||
3039 | |||
3040 | /* search for existing tcon to this server share */ | 3043 | /* search for existing tcon to this server share */ |
3041 | tcon = cifs_get_tcon(pSesInfo, volume_info); | 3044 | tcon = cifs_get_tcon(pSesInfo, volume_info); |
3042 | if (IS_ERR(tcon)) { | 3045 | if (IS_ERR(tcon)) { |
@@ -3049,7 +3052,7 @@ try_mount_again: | |||
3049 | if (tcon->ses->capabilities & CAP_UNIX) { | 3052 | if (tcon->ses->capabilities & CAP_UNIX) { |
3050 | /* reset of caps checks mount to see if unix extensions | 3053 | /* reset of caps checks mount to see if unix extensions |
3051 | disabled for just this mount */ | 3054 | disabled for just this mount */ |
3052 | reset_cifs_unix_caps(xid, tcon, sb, volume_info); | 3055 | reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info); |
3053 | if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) && | 3056 | if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) && |
3054 | (le64_to_cpu(tcon->fsUnixInfo.Capability) & | 3057 | (le64_to_cpu(tcon->fsUnixInfo.Capability) & |
3055 | CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) { | 3058 | CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) { |
@@ -3172,6 +3175,7 @@ mount_fail_check: | |||
3172 | cifs_put_smb_ses(pSesInfo); | 3175 | cifs_put_smb_ses(pSesInfo); |
3173 | else | 3176 | else |
3174 | cifs_put_tcp_session(srvTcp); | 3177 | cifs_put_tcp_session(srvTcp); |
3178 | bdi_destroy(&cifs_sb->bdi); | ||
3175 | goto out; | 3179 | goto out; |
3176 | } | 3180 | } |
3177 | 3181 | ||
@@ -3346,8 +3350,8 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses, | |||
3346 | return rc; | 3350 | return rc; |
3347 | } | 3351 | } |
3348 | 3352 | ||
3349 | int | 3353 | void |
3350 | cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | 3354 | cifs_umount(struct cifs_sb_info *cifs_sb) |
3351 | { | 3355 | { |
3352 | struct rb_root *root = &cifs_sb->tlink_tree; | 3356 | struct rb_root *root = &cifs_sb->tlink_tree; |
3353 | struct rb_node *node; | 3357 | struct rb_node *node; |
@@ -3368,7 +3372,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
3368 | } | 3372 | } |
3369 | spin_unlock(&cifs_sb->tlink_tree_lock); | 3373 | spin_unlock(&cifs_sb->tlink_tree_lock); |
3370 | 3374 | ||
3371 | return 0; | 3375 | bdi_destroy(&cifs_sb->bdi); |
3376 | kfree(cifs_sb->mountdata); | ||
3377 | unload_nls(cifs_sb->local_nls); | ||
3378 | kfree(cifs_sb); | ||
3372 | } | 3379 | } |
3373 | 3380 | ||
3374 | int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses) | 3381 | int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses) |