diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/asn1.c | 53 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 25 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 2 | ||||
-rw-r--r-- | fs/cifs/connect.c | 16 | ||||
-rw-r--r-- | fs/cifs/file.c | 6 | ||||
-rw-r--r-- | fs/cifs/inode.c | 21 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 2 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 1 |
9 files changed, 57 insertions, 73 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? */ | ||
664 | decode_negtoken_exit: | ||
665 | return 1; | 622 | return 1; |
666 | } | 623 | } |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 1a052c0eee8e..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 | */ | ||
100 | void | ||
101 | cifs_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 | |||
109 | void | ||
110 | cifs_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 | |||
94 | static int | 118 | static int |
95 | cifs_read_super(struct super_block *sb) | 119 | cifs_read_super(struct super_block *sb) |
96 | { | 120 | { |
@@ -777,6 +801,7 @@ struct file_system_type cifs_fs_type = { | |||
777 | .kill_sb = cifs_kill_sb, | 801 | .kill_sb = cifs_kill_sb, |
778 | /* .fs_flags */ | 802 | /* .fs_flags */ |
779 | }; | 803 | }; |
804 | MODULE_ALIAS_FS("cifs"); | ||
780 | const struct inode_operations cifs_dir_inode_ops = { | 805 | const struct inode_operations cifs_dir_inode_ops = { |
781 | .create = cifs_create, | 806 | .create = cifs_create, |
782 | .atomic_open = cifs_atomic_open, | 807 | .atomic_open = cifs_atomic_open, |
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; | |||
41 | extern const struct address_space_operations cifs_addr_ops; | 41 | extern const struct address_space_operations cifs_addr_ops; |
42 | extern const struct address_space_operations cifs_addr_ops_smallbuf; | 42 | extern const struct address_space_operations cifs_addr_ops_smallbuf; |
43 | 43 | ||
44 | /* Functions related to super block operations */ | ||
45 | extern void cifs_sb_active(struct super_block *sb); | ||
46 | extern void cifs_sb_deactive(struct super_block *sb); | ||
47 | |||
44 | /* Functions related to inodes */ | 48 | /* Functions related to inodes */ |
45 | extern const struct inode_operations cifs_dir_inode_ops; | 49 | extern const struct inode_operations cifs_dir_inode_ops; |
46 | extern struct inode *cifs_root_iget(struct super_block *); | 50 | extern struct inode *cifs_root_iget(struct super_block *); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 7353bc5d73d7..8e2e799e7a24 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -1909,12 +1909,12 @@ cifs_writev_requeue(struct cifs_writedata *wdata) | |||
1909 | } while (rc == -EAGAIN); | 1909 | } while (rc == -EAGAIN); |
1910 | 1910 | ||
1911 | for (i = 0; i < wdata->nr_pages; i++) { | 1911 | for (i = 0; i < wdata->nr_pages; i++) { |
1912 | unlock_page(wdata->pages[i]); | ||
1912 | if (rc != 0) { | 1913 | if (rc != 0) { |
1913 | SetPageError(wdata->pages[i]); | 1914 | SetPageError(wdata->pages[i]); |
1914 | end_page_writeback(wdata->pages[i]); | 1915 | end_page_writeback(wdata->pages[i]); |
1915 | page_cache_release(wdata->pages[i]); | 1916 | page_cache_release(wdata->pages[i]); |
1916 | } | 1917 | } |
1917 | unlock_page(wdata->pages[i]); | ||
1918 | } | 1918 | } |
1919 | 1919 | ||
1920 | mapping_set_error(inode->i_mapping, rc); | 1920 | mapping_set_error(inode->i_mapping, rc); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 54125e04fd0c..991c63c6bdd0 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -97,7 +97,7 @@ enum { | |||
97 | Opt_user, Opt_pass, Opt_ip, | 97 | Opt_user, Opt_pass, Opt_ip, |
98 | Opt_unc, Opt_domain, | 98 | Opt_unc, Opt_domain, |
99 | Opt_srcaddr, Opt_prefixpath, | 99 | Opt_srcaddr, Opt_prefixpath, |
100 | Opt_iocharset, Opt_sockopt, | 100 | Opt_iocharset, |
101 | Opt_netbiosname, Opt_servern, | 101 | Opt_netbiosname, Opt_servern, |
102 | Opt_ver, Opt_vers, Opt_sec, Opt_cache, | 102 | Opt_ver, Opt_vers, Opt_sec, Opt_cache, |
103 | 103 | ||
@@ -202,7 +202,6 @@ static const match_table_t cifs_mount_option_tokens = { | |||
202 | { Opt_srcaddr, "srcaddr=%s" }, | 202 | { Opt_srcaddr, "srcaddr=%s" }, |
203 | { Opt_prefixpath, "prefixpath=%s" }, | 203 | { Opt_prefixpath, "prefixpath=%s" }, |
204 | { Opt_iocharset, "iocharset=%s" }, | 204 | { Opt_iocharset, "iocharset=%s" }, |
205 | { Opt_sockopt, "sockopt=%s" }, | ||
206 | { Opt_netbiosname, "netbiosname=%s" }, | 205 | { Opt_netbiosname, "netbiosname=%s" }, |
207 | { Opt_servern, "servern=%s" }, | 206 | { Opt_servern, "servern=%s" }, |
208 | { Opt_ver, "ver=%s" }, | 207 | { Opt_ver, "ver=%s" }, |
@@ -1752,19 +1751,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1752 | */ | 1751 | */ |
1753 | cFYI(1, "iocharset set to %s", string); | 1752 | cFYI(1, "iocharset set to %s", string); |
1754 | break; | 1753 | break; |
1755 | case Opt_sockopt: | ||
1756 | string = match_strdup(args); | ||
1757 | if (string == NULL) | ||
1758 | goto out_nomem; | ||
1759 | |||
1760 | if (strnicmp(string, "TCP_NODELAY", 11) == 0) { | ||
1761 | printk(KERN_WARNING "CIFS: the " | ||
1762 | "sockopt=TCP_NODELAY option has been " | ||
1763 | "deprecated and will be removed " | ||
1764 | "in 3.9\n"); | ||
1765 | vol->sockopt_tcp_nodelay = 1; | ||
1766 | } | ||
1767 | break; | ||
1768 | case Opt_netbiosname: | 1754 | case Opt_netbiosname: |
1769 | string = match_strdup(args); | 1755 | string = match_strdup(args); |
1770 | if (string == NULL) | 1756 | if (string == NULL) |
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 83f2606c76d0..20887bf63121 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -995,6 +995,15 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
995 | return PTR_ERR(tlink); | 995 | return PTR_ERR(tlink); |
996 | tcon = tlink_tcon(tlink); | 996 | tcon = tlink_tcon(tlink); |
997 | 997 | ||
998 | /* | ||
999 | * We cannot rename the file if the server doesn't support | ||
1000 | * CAP_INFOLEVEL_PASSTHRU | ||
1001 | */ | ||
1002 | if (!(tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)) { | ||
1003 | rc = -EBUSY; | ||
1004 | goto out; | ||
1005 | } | ||
1006 | |||
998 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, | 1007 | rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, |
999 | DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, | 1008 | DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, |
1000 | &netfid, &oplock, NULL, cifs_sb->local_nls, | 1009 | &netfid, &oplock, NULL, cifs_sb->local_nls, |
@@ -1023,7 +1032,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1023 | current->tgid); | 1032 | current->tgid); |
1024 | /* although we would like to mark the file hidden | 1033 | /* although we would like to mark the file hidden |
1025 | if that fails we will still try to rename it */ | 1034 | if that fails we will still try to rename it */ |
1026 | if (rc != 0) | 1035 | if (!rc) |
1027 | cifsInode->cifsAttrs = dosattr; | 1036 | cifsInode->cifsAttrs = dosattr; |
1028 | else | 1037 | else |
1029 | dosattr = origattr; /* since not able to change them */ | 1038 | dosattr = origattr; /* since not able to change them */ |
@@ -1034,7 +1043,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1034 | cifs_sb->mnt_cifs_flags & | 1043 | cifs_sb->mnt_cifs_flags & |
1035 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1044 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1036 | if (rc != 0) { | 1045 | if (rc != 0) { |
1037 | rc = -ETXTBSY; | 1046 | rc = -EBUSY; |
1038 | goto undo_setattr; | 1047 | goto undo_setattr; |
1039 | } | 1048 | } |
1040 | 1049 | ||
@@ -1053,7 +1062,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1053 | if (rc == -ENOENT) | 1062 | if (rc == -ENOENT) |
1054 | rc = 0; | 1063 | rc = 0; |
1055 | else if (rc != 0) { | 1064 | else if (rc != 0) { |
1056 | rc = -ETXTBSY; | 1065 | rc = -EBUSY; |
1057 | goto undo_rename; | 1066 | goto undo_rename; |
1058 | } | 1067 | } |
1059 | cifsInode->delete_pending = true; | 1068 | cifsInode->delete_pending = true; |
@@ -1160,15 +1169,13 @@ psx_del_no_retry: | |||
1160 | cifs_drop_nlink(inode); | 1169 | cifs_drop_nlink(inode); |
1161 | } else if (rc == -ENOENT) { | 1170 | } else if (rc == -ENOENT) { |
1162 | d_drop(dentry); | 1171 | d_drop(dentry); |
1163 | } else if (rc == -ETXTBSY) { | 1172 | } else if (rc == -EBUSY) { |
1164 | if (server->ops->rename_pending_delete) { | 1173 | if (server->ops->rename_pending_delete) { |
1165 | rc = server->ops->rename_pending_delete(full_path, | 1174 | rc = server->ops->rename_pending_delete(full_path, |
1166 | dentry, xid); | 1175 | dentry, xid); |
1167 | if (rc == 0) | 1176 | if (rc == 0) |
1168 | cifs_drop_nlink(inode); | 1177 | cifs_drop_nlink(inode); |
1169 | } | 1178 | } |
1170 | if (rc == -ETXTBSY) | ||
1171 | rc = -EBUSY; | ||
1172 | } else if ((rc == -EACCES) && (dosattr == 0) && inode) { | 1179 | } else if ((rc == -EACCES) && (dosattr == 0) && inode) { |
1173 | attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); | 1180 | attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); |
1174 | if (attrs == NULL) { | 1181 | if (attrs == NULL) { |
@@ -1509,7 +1516,7 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, | |||
1509 | * source. Note that cross directory moves do not work with | 1516 | * source. Note that cross directory moves do not work with |
1510 | * rename by filehandle to various Windows servers. | 1517 | * rename by filehandle to various Windows servers. |
1511 | */ | 1518 | */ |
1512 | if (rc == 0 || rc != -ETXTBSY) | 1519 | if (rc == 0 || rc != -EBUSY) |
1513 | goto do_rename_exit; | 1520 | goto do_rename_exit; |
1514 | 1521 | ||
1515 | /* 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}, |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index c9c7aa7ed966..bceffe7b8f8d 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -744,4 +744,5 @@ struct smb_version_values smb30_values = { | |||
744 | .cap_unix = 0, | 744 | .cap_unix = 0, |
745 | .cap_nt_find = SMB2_NT_FIND, | 745 | .cap_nt_find = SMB2_NT_FIND, |
746 | .cap_large_files = SMB2_LARGE_FILES, | 746 | .cap_large_files = SMB2_LARGE_FILES, |
747 | .oplock_read = SMB2_OPLOCK_LEVEL_II, | ||
747 | }; | 748 | }; |