aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifsfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifsfs.c')
-rw-r--r--fs/cifs/cifsfs.c192
1 files changed, 98 insertions, 94 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 989442dcfb45..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
106static int 106static int
107cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, 107cifs_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
175out_mount_failed:
176 bdi_destroy(&cifs_sb->bdi);
177 return rc; 166 return rc;
178} 167}
179 168
180static void 169static void cifs_kill_sb(struct super_block *sb)
181cifs_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
206static int 176static int
@@ -257,9 +227,6 @@ static int cifs_permission(struct inode *inode, int mask, unsigned int flags)
257{ 227{
258 struct cifs_sb_info *cifs_sb; 228 struct cifs_sb_info *cifs_sb;
259 229
260 if (flags & IPERM_FLAG_RCU)
261 return -ECHILD;
262
263 cifs_sb = CIFS_SB(inode->i_sb); 230 cifs_sb = CIFS_SB(inode->i_sb);
264 231
265 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { 232 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
@@ -352,6 +319,37 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
352 } 319 }
353} 320}
354 321
322static void
323cifs_show_security(struct seq_file *s, struct TCP_Server_Info *server)
324{
325 seq_printf(s, ",sec=");
326
327 switch (server->secType) {
328 case LANMAN:
329 seq_printf(s, "lanman");
330 break;
331 case NTLMv2:
332 seq_printf(s, "ntlmv2");
333 break;
334 case NTLM:
335 seq_printf(s, "ntlm");
336 break;
337 case Kerberos:
338 seq_printf(s, "krb5");
339 break;
340 case RawNTLMSSP:
341 seq_printf(s, "ntlmssp");
342 break;
343 default:
344 /* shouldn't ever happen */
345 seq_printf(s, "unknown");
346 break;
347 }
348
349 if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
350 seq_printf(s, "i");
351}
352
355/* 353/*
356 * cifs_show_options() is for displaying mount options in /proc/mounts. 354 * cifs_show_options() is for displaying mount options in /proc/mounts.
357 * Not all settable options are displayed but most of the important 355 * Not all settable options are displayed but most of the important
@@ -365,6 +363,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
365 struct sockaddr *srcaddr; 363 struct sockaddr *srcaddr;
366 srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr; 364 srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr;
367 365
366 cifs_show_security(s, tcon->ses->server);
367
368 seq_printf(s, ",unc=%s", tcon->treeName); 368 seq_printf(s, ",unc=%s", tcon->treeName);
369 369
370 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) 370 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
@@ -518,7 +518,6 @@ static int cifs_drop_inode(struct inode *inode)
518} 518}
519 519
520static const struct super_operations cifs_super_ops = { 520static const struct super_operations cifs_super_ops = {
521 .put_super = cifs_put_super,
522 .statfs = cifs_statfs, 521 .statfs = cifs_statfs,
523 .alloc_inode = cifs_alloc_inode, 522 .alloc_inode = cifs_alloc_inode,
524 .destroy_inode = cifs_destroy_inode, 523 .destroy_inode = cifs_destroy_inode,
@@ -555,7 +554,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
555 full_path = cifs_build_path_to_root(vol, cifs_sb, 554 full_path = cifs_build_path_to_root(vol, cifs_sb,
556 cifs_sb_master_tcon(cifs_sb)); 555 cifs_sb_master_tcon(cifs_sb));
557 if (full_path == NULL) 556 if (full_path == NULL)
558 return NULL; 557 return ERR_PTR(-ENOMEM);
559 558
560 cFYI(1, "Get root dentry for %s", full_path); 559 cFYI(1, "Get root dentry for %s", full_path);
561 560
@@ -584,7 +583,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
584 dchild = d_alloc(dparent, &name); 583 dchild = d_alloc(dparent, &name);
585 if (dchild == NULL) { 584 if (dchild == NULL) {
586 dput(dparent); 585 dput(dparent);
587 dparent = NULL; 586 dparent = ERR_PTR(-ENOMEM);
588 goto out; 587 goto out;
589 } 588 }
590 } 589 }
@@ -602,7 +601,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
602 if (rc) { 601 if (rc) {
603 dput(dchild); 602 dput(dchild);
604 dput(dparent); 603 dput(dparent);
605 dparent = NULL; 604 dparent = ERR_PTR(rc);
606 goto out; 605 goto out;
607 } 606 }
608 alias = d_materialise_unique(dchild, inode); 607 alias = d_materialise_unique(dchild, inode);
@@ -610,7 +609,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
610 dput(dchild); 609 dput(dchild);
611 if (IS_ERR(alias)) { 610 if (IS_ERR(alias)) {
612 dput(dparent); 611 dput(dparent);
613 dparent = NULL; 612 dparent = ERR_PTR(-EINVAL); /* XXX */
614 goto out; 613 goto out;
615 } 614 }
616 dchild = alias; 615 dchild = alias;
@@ -630,6 +629,13 @@ out:
630 return dparent; 629 return dparent;
631} 630}
632 631
632static 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
633static struct dentry * 639static struct dentry *
634cifs_do_mount(struct file_system_type *fs_type, 640cifs_do_mount(struct file_system_type *fs_type,
635 int flags, const char *dev_name, void *data) 641 int flags, const char *dev_name, void *data)
@@ -650,75 +656,73 @@ cifs_do_mount(struct file_system_type *fs_type,
650 cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); 656 cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL);
651 if (cifs_sb == NULL) { 657 if (cifs_sb == NULL) {
652 root = ERR_PTR(-ENOMEM); 658 root = ERR_PTR(-ENOMEM);
653 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;
654 } 666 }
655 667
656 cifs_setup_cifs_sb(volume_info, cifs_sb); 668 cifs_setup_cifs_sb(volume_info, cifs_sb);
657 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
658 mnt_data.vol = volume_info; 678 mnt_data.vol = volume_info;
659 mnt_data.cifs_sb = cifs_sb; 679 mnt_data.cifs_sb = cifs_sb;
660 mnt_data.flags = flags; 680 mnt_data.flags = flags;
661 681
662 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);
663 if (IS_ERR(sb)) { 683 if (IS_ERR(sb)) {
664 root = ERR_CAST(sb); 684 root = ERR_CAST(sb);
665 goto out_cifs_sb; 685 cifs_umount(cifs_sb);
686 goto out;
666 } 687 }
667 688
668 if (sb->s_fs_info) { 689 if (sb->s_root) {
669 cFYI(1, "Use existing superblock"); 690 cFYI(1, "Use existing superblock");
670 goto out_shared; 691 cifs_umount(cifs_sb);
671 } 692 } else {
672 693 sb->s_flags = flags;
673 /* 694 /* BB should we make this contingent on mount parm? */
674 * Copy mount params for use in submounts. Better to do 695 sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
675 * the copy here and deal with the error before cleanup gets 696
676 * complicated post-mount. 697 rc = cifs_read_super(sb);
677 */ 698 if (rc) {
678 cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); 699 root = ERR_PTR(rc);
679 if (cifs_sb->mountdata == NULL) { 700 goto out_super;
680 root = ERR_PTR(-ENOMEM); 701 }
681 goto out_super;
682 }
683
684 sb->s_flags = flags;
685 /* BB should we make this contingent on mount parm? */
686 sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
687 sb->s_fs_info = cifs_sb;
688 702
689 rc = cifs_read_super(sb, volume_info, dev_name, 703 sb->s_flags |= MS_ACTIVE;
690 flags & MS_SILENT ? 1 : 0);
691 if (rc) {
692 root = ERR_PTR(rc);
693 goto out_super;
694 } 704 }
695 705
696 sb->s_flags |= MS_ACTIVE;
697
698 root = cifs_get_root(volume_info, sb); 706 root = cifs_get_root(volume_info, sb);
699 if (root == NULL) 707 if (IS_ERR(root))
700 goto out_super; 708 goto out_super;
701 709
702 cFYI(1, "dentry root is: %p", root); 710 cFYI(1, "dentry root is: %p", root);
703 goto out; 711 goto out;
704 712
705out_shared:
706 root = cifs_get_root(volume_info, sb);
707 if (root)
708 cFYI(1, "dentry root is: %p", root);
709 goto out;
710
711out_super: 713out_super:
712 kfree(cifs_sb->mountdata);
713 deactivate_locked_super(sb); 714 deactivate_locked_super(sb);
714
715out_cifs_sb:
716 unload_nls(cifs_sb->local_nls);
717 kfree(cifs_sb);
718
719out: 715out:
720 cifs_cleanup_volume_info(&volume_info); 716 cifs_cleanup_volume_info(&volume_info);
721 return root; 717 return root;
718
719out_mountdata:
720 kfree(cifs_sb->mountdata);
721out_cifs_sb:
722 kfree(cifs_sb);
723out_nls:
724 unload_nls(volume_info->local_nls);
725 goto out;
722} 726}
723 727
724static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, 728static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
@@ -807,7 +811,7 @@ struct file_system_type cifs_fs_type = {
807 .owner = THIS_MODULE, 811 .owner = THIS_MODULE,
808 .name = "cifs", 812 .name = "cifs",
809 .mount = cifs_do_mount, 813 .mount = cifs_do_mount,
810 .kill_sb = kill_anon_super, 814 .kill_sb = cifs_kill_sb,
811 /* .fs_flags */ 815 /* .fs_flags */
812}; 816};
813const struct inode_operations cifs_dir_inode_ops = { 817const struct inode_operations cifs_dir_inode_ops = {