aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-03-21 20:59:22 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-03-21 20:59:22 -0400
commit9217cbb8df31c10efc96362227b2ebdbb9fe996c (patch)
tree9cb7a5daf362fd4847756f6f3f75c7e0966ff903
parentd3c926264a92e5ea448add3e883530e1edad3ce2 (diff)
parentf853c616883a8de966873a1dab283f1369e275a1 (diff)
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull CIFS fixes from Steve French: "Three small CIFS Fixes (the most important of the three fixes a recent problem authenticating to Windows 8 using cifs rather than SMB2)" * 'for-next' of git://git.samba.org/sfrench/cifs-2.6: cifs: ignore everything in SPNEGO blob after mechTypes cifs: delay super block destruction until all cifsFileInfo objects are gone cifs: map NT_STATUS_SHARING_VIOLATION to EBUSY instead of ETXTBSY
-rw-r--r--fs/cifs/asn1.c53
-rw-r--r--fs/cifs/cifsfs.c24
-rw-r--r--fs/cifs/cifsfs.h4
-rw-r--r--fs/cifs/file.c6
-rw-r--r--fs/cifs/inode.c10
-rw-r--r--fs/cifs/netmisc.c2
6 files changed, 43 insertions, 56 deletions
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index cfd1ce34e0bc..1d36db114772 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -614,53 +614,10 @@ decode_negTokenInit(unsigned char *security_blob, int length,
614 } 614 }
615 } 615 }
616 616
617 /* mechlistMIC */ 617 /*
618 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 618 * We currently ignore anything at the end of the SPNEGO blob after
619 /* Check if we have reached the end of the blob, but with 619 * the mechTypes have been parsed, since none of that info is
620 no mechListMic (e.g. NTLMSSP instead of KRB5) */ 620 * used at the moment.
621 if (ctx.error == ASN1_ERR_DEC_EMPTY) 621 */
622 goto decode_negtoken_exit;
623 cFYI(1, "Error decoding last part negTokenInit exit3");
624 return 0;
625 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
626 /* tag = 3 indicating mechListMIC */
627 cFYI(1, "Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
628 cls, con, tag, end, *end);
629 return 0;
630 }
631
632 /* sequence */
633 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
634 cFYI(1, "Error decoding last part negTokenInit exit5");
635 return 0;
636 } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
637 || (tag != ASN1_SEQ)) {
638 cFYI(1, "cls = %d con = %d tag = %d end = %p (%d)",
639 cls, con, tag, end, *end);
640 }
641
642 /* sequence of */
643 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
644 cFYI(1, "Error decoding last part negTokenInit exit 7");
645 return 0;
646 } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
647 cFYI(1, "Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
648 cls, con, tag, end, *end);
649 return 0;
650 }
651
652 /* general string */
653 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
654 cFYI(1, "Error decoding last part negTokenInit exit9");
655 return 0;
656 } else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
657 || (tag != ASN1_GENSTR)) {
658 cFYI(1, "Exit10 cls = %d con = %d tag = %d end = %p (%d)",
659 cls, con, tag, end, *end);
660 return 0;
661 }
662 cFYI(1, "Need to call asn1_octets_decode() function for %s",
663 ctx.pointer); /* is this UTF-8 or ASCII? */
664decode_negtoken_exit:
665 return 1; 622 return 1;
666} 623}
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 3cf8a15af916..345fc89c4286 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -91,6 +91,30 @@ struct workqueue_struct *cifsiod_wq;
91__u8 cifs_client_guid[SMB2_CLIENT_GUID_SIZE]; 91__u8 cifs_client_guid[SMB2_CLIENT_GUID_SIZE];
92#endif 92#endif
93 93
94/*
95 * Bumps refcount for cifs super block.
96 * Note that it should be only called if a referece to VFS super block is
97 * already held, e.g. in open-type syscalls context. Otherwise it can race with
98 * atomic_dec_and_test in deactivate_locked_super.
99 */
100void
101cifs_sb_active(struct super_block *sb)
102{
103 struct cifs_sb_info *server = CIFS_SB(sb);
104
105 if (atomic_inc_return(&server->active) == 1)
106 atomic_inc(&sb->s_active);
107}
108
109void
110cifs_sb_deactive(struct super_block *sb)
111{
112 struct cifs_sb_info *server = CIFS_SB(sb);
113
114 if (atomic_dec_and_test(&server->active))
115 deactivate_super(sb);
116}
117
94static int 118static int
95cifs_read_super(struct super_block *sb) 119cifs_read_super(struct super_block *sb)
96{ 120{
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 7163419cecd9..0e32c3446ce9 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -41,6 +41,10 @@ extern struct file_system_type cifs_fs_type;
41extern const struct address_space_operations cifs_addr_ops; 41extern const struct address_space_operations cifs_addr_ops;
42extern const struct address_space_operations cifs_addr_ops_smallbuf; 42extern const struct address_space_operations cifs_addr_ops_smallbuf;
43 43
44/* Functions related to super block operations */
45extern void cifs_sb_active(struct super_block *sb);
46extern void cifs_sb_deactive(struct super_block *sb);
47
44/* Functions related to inodes */ 48/* Functions related to inodes */
45extern const struct inode_operations cifs_dir_inode_ops; 49extern const struct inode_operations cifs_dir_inode_ops;
46extern struct inode *cifs_root_iget(struct super_block *); 50extern struct inode *cifs_root_iget(struct super_block *);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 8c0d85577314..7a0dd99e4507 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -300,6 +300,8 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
300 INIT_WORK(&cfile->oplock_break, cifs_oplock_break); 300 INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
301 mutex_init(&cfile->fh_mutex); 301 mutex_init(&cfile->fh_mutex);
302 302
303 cifs_sb_active(inode->i_sb);
304
303 /* 305 /*
304 * If the server returned a read oplock and we have mandatory brlocks, 306 * If the server returned a read oplock and we have mandatory brlocks,
305 * set oplock level to None. 307 * set oplock level to None.
@@ -349,7 +351,8 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
349 struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink); 351 struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink);
350 struct TCP_Server_Info *server = tcon->ses->server; 352 struct TCP_Server_Info *server = tcon->ses->server;
351 struct cifsInodeInfo *cifsi = CIFS_I(inode); 353 struct cifsInodeInfo *cifsi = CIFS_I(inode);
352 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 354 struct super_block *sb = inode->i_sb;
355 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
353 struct cifsLockInfo *li, *tmp; 356 struct cifsLockInfo *li, *tmp;
354 struct cifs_fid fid; 357 struct cifs_fid fid;
355 struct cifs_pending_open open; 358 struct cifs_pending_open open;
@@ -414,6 +417,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
414 417
415 cifs_put_tlink(cifs_file->tlink); 418 cifs_put_tlink(cifs_file->tlink);
416 dput(cifs_file->dentry); 419 dput(cifs_file->dentry);
420 cifs_sb_deactive(sb);
417 kfree(cifs_file); 421 kfree(cifs_file);
418} 422}
419 423
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 0079696305c9..20887bf63121 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1043,7 +1043,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1043 cifs_sb->mnt_cifs_flags & 1043 cifs_sb->mnt_cifs_flags &
1044 CIFS_MOUNT_MAP_SPECIAL_CHR); 1044 CIFS_MOUNT_MAP_SPECIAL_CHR);
1045 if (rc != 0) { 1045 if (rc != 0) {
1046 rc = -ETXTBSY; 1046 rc = -EBUSY;
1047 goto undo_setattr; 1047 goto undo_setattr;
1048 } 1048 }
1049 1049
@@ -1062,7 +1062,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1062 if (rc == -ENOENT) 1062 if (rc == -ENOENT)
1063 rc = 0; 1063 rc = 0;
1064 else if (rc != 0) { 1064 else if (rc != 0) {
1065 rc = -ETXTBSY; 1065 rc = -EBUSY;
1066 goto undo_rename; 1066 goto undo_rename;
1067 } 1067 }
1068 cifsInode->delete_pending = true; 1068 cifsInode->delete_pending = true;
@@ -1169,15 +1169,13 @@ psx_del_no_retry:
1169 cifs_drop_nlink(inode); 1169 cifs_drop_nlink(inode);
1170 } else if (rc == -ENOENT) { 1170 } else if (rc == -ENOENT) {
1171 d_drop(dentry); 1171 d_drop(dentry);
1172 } else if (rc == -ETXTBSY) { 1172 } else if (rc == -EBUSY) {
1173 if (server->ops->rename_pending_delete) { 1173 if (server->ops->rename_pending_delete) {
1174 rc = server->ops->rename_pending_delete(full_path, 1174 rc = server->ops->rename_pending_delete(full_path,
1175 dentry, xid); 1175 dentry, xid);
1176 if (rc == 0) 1176 if (rc == 0)
1177 cifs_drop_nlink(inode); 1177 cifs_drop_nlink(inode);
1178 } 1178 }
1179 if (rc == -ETXTBSY)
1180 rc = -EBUSY;
1181 } else if ((rc == -EACCES) && (dosattr == 0) && inode) { 1179 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
1182 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); 1180 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1183 if (attrs == NULL) { 1181 if (attrs == NULL) {
@@ -1518,7 +1516,7 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1518 * source. Note that cross directory moves do not work with 1516 * source. Note that cross directory moves do not work with
1519 * rename by filehandle to various Windows servers. 1517 * rename by filehandle to various Windows servers.
1520 */ 1518 */
1521 if (rc == 0 || rc != -ETXTBSY) 1519 if (rc == 0 || rc != -EBUSY)
1522 goto do_rename_exit; 1520 goto do_rename_exit;
1523 1521
1524 /* open-file renames don't work across directories */ 1522 /* open-file renames don't work across directories */
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index a82bc51fdc82..c0b25b28be6c 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -62,7 +62,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
62 {ERRdiffdevice, -EXDEV}, 62 {ERRdiffdevice, -EXDEV},
63 {ERRnofiles, -ENOENT}, 63 {ERRnofiles, -ENOENT},
64 {ERRwriteprot, -EROFS}, 64 {ERRwriteprot, -EROFS},
65 {ERRbadshare, -ETXTBSY}, 65 {ERRbadshare, -EBUSY},
66 {ERRlock, -EACCES}, 66 {ERRlock, -EACCES},
67 {ERRunsup, -EINVAL}, 67 {ERRunsup, -EINVAL},
68 {ERRnosuchshare, -ENXIO}, 68 {ERRnosuchshare, -ENXIO},