Pull cifs updates from Steve French: "Mostly cleanup, including smb1 refactoring: - multichannel perf improvement - move additional SMB1 code to not be compiled in when legacy support is disabled. - bug fixes, including one important one for memory leak - various cleanup patches We are still working on and testing some deferred close improvements including an important lease break fix for case when multiple deferred closes are still open, and also some additional perf improvements - those are not included here" * tag '5.20-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6: cifs: update internal module number cifs: alloc_mid function should be marked as static cifs: remove "cifs_" prefix from init/destroy mids functions cifs: remove useless DeleteMidQEntry() cifs: when insecure legacy is disabled shrink amount of SMB1 code cifs: trivial style fixup cifs: fix wrong unlock before return from cifs_tree_connect() cifs: avoid use of global locks for high contention data cifs: remove remaining build warnings cifs: list_for_each() -> list_for_each_entry() cifs: update MAINTAINERS file with reviewers smb2: small refactor in smb2_check_message() cifs: Fix memory leak when using fscache cifs: remove minor build warning cifs: remove some camelCase and also some static build warnings cifs: remove unnecessary (void*) conversions. cifs: remove unnecessary type castings cifs: remove redundant initialization to variable mnt_sign_enabled smb3: check xattr value length earlier
Unified · Split
| @@ -5123,12 +5123,15 @@ F: include/linux/clk/ · 5122 unmodified lines | ||
| 5123 | 5123 | F: include/linux/of_clk.h |
| 5124 | 5124 | X: drivers/clk/clkdev.c |
| 5125 | 5125 | |
| 5126 | −COMMON INTERNET FILE SYSTEM CLIENT (CIFS) | |
| 5126 | +COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3) | |
| 5127 | 5127 | M: Steve French <sfrench@samba.org> |
| 5128 | +R: Paulo Alcantara <pc@cjr.nz> (DFS, global name space) | |
| 5129 | +R: Ronnie Sahlberg <lsahlber@redhat.com> (directory leases, sparse files) | |
| 5130 | +R: Shyam Prasad N <sprasad@microsoft.com> (multichannel) | |
| 5128 | 5131 | L: linux-cifs@vger.kernel.org |
| 5129 | 5132 | L: samba-technical@lists.samba.org (moderated for non-subscribers) |
| 5130 | 5133 | S: Supported |
| 5131 | −W: http://linux-cifs.samba.org/ | |
| 5134 | +W: https://wiki.samba.org/index.php/LinuxCIFS | |
| 5132 | 5135 | T: git git://git.samba.org/sfrench/cifs-2.6.git |
| 5133 | 5136 | F: Documentation/admin-guide/cifs/ |
| 5134 | 5137 | F: fs/cifs/ |
| @@ -5,7 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | ccflags-y += -I$(src) # needed for trace events |
| 6 | 6 | obj-$(CONFIG_CIFS) += cifs.o |
| 7 | 7 | |
| 8 | −cifs-y := trace.o cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o \ | |
| 8 | +cifs-y := trace.o cifsfs.o cifs_debug.o connect.o dir.o file.o \ | |
| 9 | 9 | inode.o link.o misc.o netmisc.o smbencrypt.o transport.o \ |
| 10 | 10 | cifs_unicode.o nterr.o cifsencrypt.o \ |
| 11 | 11 | readdir.o ioctl.o sess.o export.o unc.o winucase.o \ |
| @@ -31,4 +31,4 @@ cifs-$(CONFIG_CIFS_SMB_DIRECT) += smbdirect.o · 19 unmodified lines | ||
| 31 | 31 | |
| 32 | 32 | cifs-$(CONFIG_CIFS_ROOT) += cifsroot.o |
| 33 | 33 | |
| 34 | −cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) += smb1ops.o | |
| 34 | +cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) += smb1ops.o cifssmb.o | |
| @@ -36,7 +36,7 @@ cifs_dump_mem(char *label, void *data, int length) · 35 unmodified lines | ||
| 36 | 36 | void cifs_dump_detail(void *buf, struct TCP_Server_Info *server) |
| 37 | 37 | { |
| 38 | 38 | #ifdef CONFIG_CIFS_DEBUG2 |
| 39 | − struct smb_hdr *smb = (struct smb_hdr *)buf; | |
| 39 | + struct smb_hdr *smb = buf; | |
| 40 | 40 | |
| 41 | 41 | cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d\n", |
| 42 | 42 | smb->Command, smb->Status.CifsError, |
| @@ -55,7 +55,7 @@ void cifs_dump_mids(struct TCP_Server_Info *server) · 12 unmodified lines | ||
| 55 | 55 | return; |
| 56 | 56 | |
| 57 | 57 | cifs_dbg(VFS, "Dump pending requests:\n"); |
| 58 | − spin_lock(&GlobalMid_Lock); | |
| 58 | + spin_lock(&server->mid_lock); | |
| 59 | 59 | list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { |
| 60 | 60 | cifs_dbg(VFS, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu\n", |
| 61 | 61 | mid_entry->mid_state, |
| @@ -78,7 +78,7 @@ void cifs_dump_mids(struct TCP_Server_Info *server) · 16 unmodified lines | ||
| 78 | 78 | mid_entry->resp_buf, 62); |
| 79 | 79 | } |
| 80 | 80 | } |
| 81 | − spin_unlock(&GlobalMid_Lock); | |
| 81 | + spin_unlock(&server->mid_lock); | |
| 82 | 82 | #endif /* CONFIG_CIFS_DEBUG2 */ |
| 83 | 83 | } |
| 84 | 84 | |
| @@ -168,7 +168,6 @@ cifs_dump_iface(struct seq_file *m, struct cifs_server_iface *iface) · 83 unmodified lines | ||
| 168 | 168 | |
| 169 | 169 | static int cifs_debug_files_proc_show(struct seq_file *m, void *v) |
| 170 | 170 | { |
| 171 | − struct list_head *tmp, *tmp1, *tmp2; | |
| 172 | 171 | struct TCP_Server_Info *server; |
| 173 | 172 | struct cifs_ses *ses; |
| 174 | 173 | struct cifs_tcon *tcon; |
| @@ -184,14 +183,10 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v) · 9 unmodified lines | ||
| 184 | 183 | #endif /* CIFS_DEBUG2 */ |
| 185 | 184 | spin_lock(&cifs_tcp_ses_lock); |
| 186 | 185 | list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { |
| 187 | − list_for_each(tmp, &server->smb_ses_list) { | |
| 188 | − ses = list_entry(tmp, struct cifs_ses, smb_ses_list); | |
| 189 | − list_for_each(tmp1, &ses->tcon_list) { | |
| 190 | − tcon = list_entry(tmp1, struct cifs_tcon, tcon_list); | |
| 186 | + list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { | |
| 187 | + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { | |
| 191 | 188 | spin_lock(&tcon->open_file_lock); |
| 192 | − list_for_each(tmp2, &tcon->openFileList) { | |
| 193 | − cfile = list_entry(tmp2, struct cifsFileInfo, | |
| 194 | − tlist); | |
| 189 | + list_for_each_entry(cfile, &tcon->openFileList, tlist) { | |
| 195 | 190 | seq_printf(m, |
| 196 | 191 | "0x%x 0x%llx 0x%x %d %d %d %pd", |
| 197 | 192 | tcon->tid, |
| @@ -218,7 +213,6 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v) · 20 unmodified lines | ||
| 218 | 213 | |
| 219 | 214 | static int cifs_debug_data_proc_show(struct seq_file *m, void *v) |
| 220 | 215 | { |
| 221 | − struct list_head *tmp2, *tmp3; | |
| 222 | 216 | struct mid_q_entry *mid_entry; |
| 223 | 217 | struct TCP_Server_Info *server; |
| 224 | 218 | struct cifs_ses *ses; |
| @@ -381,9 +375,7 @@ skip_rdma: · 156 unmodified lines | ||
| 381 | 375 | |
| 382 | 376 | seq_printf(m, "\n\n\tSessions: "); |
| 383 | 377 | i = 0; |
| 384 | − list_for_each(tmp2, &server->smb_ses_list) { | |
| 385 | − ses = list_entry(tmp2, struct cifs_ses, | |
| 386 | − smb_ses_list); | |
| 378 | + list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { | |
| 387 | 379 | i++; |
| 388 | 380 | if ((ses->serverDomain == NULL) || |
| 389 | 381 | (ses->serverOS == NULL) || |
| @@ -447,9 +439,7 @@ skip_rdma: · 57 unmodified lines | ||
| 447 | 439 | else |
| 448 | 440 | seq_puts(m, "none\n"); |
| 449 | 441 | |
| 450 | − list_for_each(tmp3, &ses->tcon_list) { | |
| 451 | − tcon = list_entry(tmp3, struct cifs_tcon, | |
| 452 | − tcon_list); | |
| 442 | + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { | |
| 453 | 443 | ++j; |
| 454 | 444 | seq_printf(m, "\n\t%d) ", j); |
| 455 | 445 | cifs_debug_tcon(m, tcon); |
| @@ -473,10 +463,8 @@ skip_rdma: · 17 unmodified lines | ||
| 473 | 463 | seq_printf(m, "\n\t\t[NONE]"); |
| 474 | 464 | |
| 475 | 465 | seq_puts(m, "\n\n\tMIDs: "); |
| 476 | − spin_lock(&GlobalMid_Lock); | |
| 477 | − list_for_each(tmp3, &server->pending_mid_q) { | |
| 478 | − mid_entry = list_entry(tmp3, struct mid_q_entry, | |
| 479 | − qhead); | |
| 466 | + spin_lock(&server->mid_lock); | |
| 467 | + list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { | |
| 480 | 468 | seq_printf(m, "\n\tState: %d com: %d pid:" |
| 481 | 469 | " %d cbdata: %p mid %llu\n", |
| 482 | 470 | mid_entry->mid_state, |
| @@ -485,7 +473,7 @@ skip_rdma: · 2 unmodified lines | ||
| 485 | 473 | mid_entry->callback_data, |
| 486 | 474 | mid_entry->mid); |
| 487 | 475 | } |
| 488 | − spin_unlock(&GlobalMid_Lock); | |
| 476 | + spin_unlock(&server->mid_lock); | |
| 489 | 477 | seq_printf(m, "\n--\n"); |
| 490 | 478 | } |
| 491 | 479 | if (c == 0) |
| @@ -504,7 +492,6 @@ static ssize_t cifs_stats_proc_write(struct file *file, · 12 unmodified lines | ||
| 504 | 492 | { |
| 505 | 493 | bool bv; |
| 506 | 494 | int rc; |
| 507 | − struct list_head *tmp1, *tmp2, *tmp3; | |
| 508 | 495 | struct TCP_Server_Info *server; |
| 509 | 496 | struct cifs_ses *ses; |
| 510 | 497 | struct cifs_tcon *tcon; |
| @@ -514,8 +501,8 @@ static ssize_t cifs_stats_proc_write(struct file *file, · 3 unmodified lines | ||
| 514 | 501 | #ifdef CONFIG_CIFS_STATS2 |
| 515 | 502 | int i; |
| 516 | 503 | |
| 517 | − atomic_set(&totBufAllocCount, 0); | |
| 518 | − atomic_set(&totSmBufAllocCount, 0); | |
| 504 | + atomic_set(&total_buf_alloc_count, 0); | |
| 505 | + atomic_set(&total_small_buf_alloc_count, 0); | |
| 519 | 506 | #endif /* CONFIG_CIFS_STATS2 */ |
| 520 | 507 | atomic_set(&tcpSesReconnectCount, 0); |
| 521 | 508 | atomic_set(&tconInfoReconnectCount, 0); |
| @@ -525,9 +512,7 @@ static ssize_t cifs_stats_proc_write(struct file *file, · 3 unmodified lines | ||
| 525 | 512 | GlobalCurrentXid = 0; |
| 526 | 513 | spin_unlock(&GlobalMid_Lock); |
| 527 | 514 | spin_lock(&cifs_tcp_ses_lock); |
| 528 | − list_for_each(tmp1, &cifs_tcp_ses_list) { | |
| 529 | − server = list_entry(tmp1, struct TCP_Server_Info, | |
| 530 | − tcp_ses_list); | |
| 515 | + list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { | |
| 531 | 516 | server->max_in_flight = 0; |
| 532 | 517 | #ifdef CONFIG_CIFS_STATS2 |
| 533 | 518 | for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) { |
| @@ -538,13 +523,8 @@ static ssize_t cifs_stats_proc_write(struct file *file, · 4 unmodified lines | ||
| 538 | 523 | server->fastest_cmd[0] = 0; |
| 539 | 524 | } |
| 540 | 525 | #endif /* CONFIG_CIFS_STATS2 */ |
| 541 | − list_for_each(tmp2, &server->smb_ses_list) { | |
| 542 | − ses = list_entry(tmp2, struct cifs_ses, | |
| 543 | − smb_ses_list); | |
| 544 | − list_for_each(tmp3, &ses->tcon_list) { | |
| 545 | − tcon = list_entry(tmp3, | |
| 546 | − struct cifs_tcon, | |
| 547 | − tcon_list); | |
| 526 | + list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { | |
| 527 | + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { | |
| 548 | 528 | atomic_set(&tcon->num_smbs_sent, 0); |
| 549 | 529 | spin_lock(&tcon->stat_lock); |
| 550 | 530 | tcon->bytes_read = 0; |
| @@ -569,7 +549,6 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v) · 18 unmodified lines | ||
| 569 | 549 | #ifdef CONFIG_CIFS_STATS2 |
| 570 | 550 | int j; |
| 571 | 551 | #endif /* STATS2 */ |
| 572 | − struct list_head *tmp2, *tmp3; | |
| 573 | 552 | struct TCP_Server_Info *server; |
| 574 | 553 | struct cifs_ses *ses; |
| 575 | 554 | struct cifs_tcon *tcon; |
| @@ -579,17 +558,17 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v) · 3 unmodified lines | ||
| 579 | 558 | seq_printf(m, "Share (unique mount targets): %d\n", |
| 580 | 559 | tconInfoAllocCount.counter); |
| 581 | 560 | seq_printf(m, "SMB Request/Response Buffer: %d Pool size: %d\n", |
| 582 | − bufAllocCount.counter, | |
| 561 | + buf_alloc_count.counter, | |
| 583 | 562 | cifs_min_rcv + tcpSesAllocCount.counter); |
| 584 | 563 | seq_printf(m, "SMB Small Req/Resp Buffer: %d Pool size: %d\n", |
| 585 | − smBufAllocCount.counter, cifs_min_small); | |
| 564 | + small_buf_alloc_count.counter, cifs_min_small); | |
| 586 | 565 | #ifdef CONFIG_CIFS_STATS2 |
| 587 | 566 | seq_printf(m, "Total Large %d Small %d Allocations\n", |
| 588 | − atomic_read(&totBufAllocCount), | |
| 589 | − atomic_read(&totSmBufAllocCount)); | |
| 567 | + atomic_read(&total_buf_alloc_count), | |
| 568 | + atomic_read(&total_small_buf_alloc_count)); | |
| 590 | 569 | #endif /* CONFIG_CIFS_STATS2 */ |
| 591 | 570 | |
| 592 | − seq_printf(m, "Operations (MIDs): %d\n", atomic_read(&midCount)); | |
| 571 | + seq_printf(m, "Operations (MIDs): %d\n", atomic_read(&mid_count)); | |
| 593 | 572 | seq_printf(m, |
| 594 | 573 | "\n%d session %d share reconnects\n", |
| 595 | 574 | tcpSesReconnectCount.counter, tconInfoReconnectCount.counter); |
| @@ -619,13 +598,8 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v) · 23 unmodified lines | ||
| 619 | 598 | atomic_read(&server->smb2slowcmd[j]), |
| 620 | 599 | server->hostname, j); |
| 621 | 600 | #endif /* STATS2 */ |
| 622 | − list_for_each(tmp2, &server->smb_ses_list) { | |
| 623 | − ses = list_entry(tmp2, struct cifs_ses, | |
| 624 | − smb_ses_list); | |
| 625 | − list_for_each(tmp3, &ses->tcon_list) { | |
| 626 | − tcon = list_entry(tmp3, | |
| 627 | − struct cifs_tcon, | |
| 628 | − tcon_list); | |
| 601 | + list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { | |
| 602 | + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { | |
| 629 | 603 | i++; |
| 630 | 604 | seq_printf(m, "\n%d) %s", i, tcon->treeName); |
| 631 | 605 | if (tcon->need_reconnect) |
| @@ -1379,6 +1379,7 @@ chown_chgrp_exit: · 1378 unmodified lines | ||
| 1379 | 1379 | return rc; |
| 1380 | 1380 | } |
| 1381 | 1381 | |
| 1382 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1382 | 1383 | struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, |
| 1383 | 1384 | const struct cifs_fid *cifsfid, u32 *pacllen, |
| 1384 | 1385 | u32 __maybe_unused unused) |
| @@ -1512,6 +1513,7 @@ out: · 127 unmodified lines | ||
| 1512 | 1513 | cifs_put_tlink(tlink); |
| 1513 | 1514 | return rc; |
| 1514 | 1515 | } |
| 1516 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1515 | 1517 | |
| 1516 | 1518 | /* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */ |
| 1517 | 1519 | int |
| @@ -141,13 +141,13 @@ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server, · 140 unmodified lines | ||
| 141 | 141 | if ((cifs_pdu == NULL) || (server == NULL)) |
| 142 | 142 | return -EINVAL; |
| 143 | 143 | |
| 144 | − spin_lock(&cifs_tcp_ses_lock); | |
| 144 | + spin_lock(&server->srv_lock); | |
| 145 | 145 | if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) || |
| 146 | 146 | server->tcpStatus == CifsNeedNegotiate) { |
| 147 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 147 | + spin_unlock(&server->srv_lock); | |
| 148 | 148 | return rc; |
| 149 | 149 | } |
| 150 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 150 | + spin_unlock(&server->srv_lock); | |
| 151 | 151 | |
| 152 | 152 | if (!server->session_estab) { |
| 153 | 153 | memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8); |
| @@ -68,6 +68,34 @@ bool enable_negotiate_signing; /* false by default */ · 67 unmodified lines | ||
| 68 | 68 | unsigned int global_secflags = CIFSSEC_DEF; |
| 69 | 69 | /* unsigned int ntlmv2_support = 0; */ |
| 70 | 70 | unsigned int sign_CIFS_PDUs = 1; |
| 71 | + | |
| 72 | +/* | |
| 73 | + * Global transaction id (XID) information | |
| 74 | + */ | |
| 75 | +unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */ | |
| 76 | +unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */ | |
| 77 | +unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */ | |
| 78 | +spinlock_t GlobalMid_Lock; /* protects above & list operations on midQ entries */ | |
| 79 | + | |
| 80 | +/* | |
| 81 | + * Global counters, updated atomically | |
| 82 | + */ | |
| 83 | +atomic_t sesInfoAllocCount; | |
| 84 | +atomic_t tconInfoAllocCount; | |
| 85 | +atomic_t tcpSesNextId; | |
| 86 | +atomic_t tcpSesAllocCount; | |
| 87 | +atomic_t tcpSesReconnectCount; | |
| 88 | +atomic_t tconInfoReconnectCount; | |
| 89 | + | |
| 90 | +atomic_t mid_count; | |
| 91 | +atomic_t buf_alloc_count; | |
| 92 | +atomic_t small_buf_alloc_count; | |
| 93 | +#ifdef CONFIG_CIFS_STATS2 | |
| 94 | +atomic_t total_buf_alloc_count; | |
| 95 | +atomic_t total_small_buf_alloc_count; | |
| 96 | +#endif/* STATS2 */ | |
| 97 | +struct list_head cifs_tcp_ses_list; | |
| 98 | +spinlock_t cifs_tcp_ses_lock; | |
| 71 | 99 | static const struct super_operations cifs_super_ops; |
| 72 | 100 | unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; |
| 73 | 101 | module_param(CIFSMaxBufSize, uint, 0444); |
| @@ -703,14 +731,17 @@ static void cifs_umount_begin(struct super_block *sb) · 629 unmodified lines | ||
| 703 | 731 | tcon = cifs_sb_master_tcon(cifs_sb); |
| 704 | 732 | |
| 705 | 733 | spin_lock(&cifs_tcp_ses_lock); |
| 734 | + spin_lock(&tcon->tc_lock); | |
| 706 | 735 | if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) { |
| 707 | 736 | /* we have other mounts to same share or we have |
| 708 | 737 | already tried to force umount this and woken up |
| 709 | 738 | all waiting network requests, nothing to do */ |
| 739 | + spin_unlock(&tcon->tc_lock); | |
| 710 | 740 | spin_unlock(&cifs_tcp_ses_lock); |
| 711 | 741 | return; |
| 712 | 742 | } else if (tcon->tc_count == 1) |
| 713 | 743 | tcon->status = TID_EXITING; |
| 744 | + spin_unlock(&tcon->tc_lock); | |
| 714 | 745 | spin_unlock(&cifs_tcp_ses_lock); |
| 715 | 746 | |
| 716 | 747 | /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */ |
| @@ -1537,8 +1568,7 @@ cifs_destroy_request_bufs(void) · 820 unmodified lines | ||
| 1537 | 1568 | kmem_cache_destroy(cifs_sm_req_cachep); |
| 1538 | 1569 | } |
| 1539 | 1570 | |
| 1540 | −static int | |
| 1541 | −cifs_init_mids(void) | |
| 1571 | +static int init_mids(void) | |
| 1542 | 1572 | { |
| 1543 | 1573 | cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids", |
| 1544 | 1574 | sizeof(struct mid_q_entry), 0, |
| @@ -1556,8 +1586,7 @@ cifs_init_mids(void) · 11 unmodified lines | ||
| 1556 | 1586 | return 0; |
| 1557 | 1587 | } |
| 1558 | 1588 | |
| 1559 | −static void | |
| 1560 | −cifs_destroy_mids(void) | |
| 1589 | +static void destroy_mids(void) | |
| 1561 | 1590 | { |
| 1562 | 1591 | mempool_destroy(cifs_mid_poolp); |
| 1563 | 1592 | kmem_cache_destroy(cifs_mid_cachep); |
| @@ -1579,11 +1608,11 @@ init_cifs(void) · 15 unmodified lines | ||
| 1579 | 1608 | atomic_set(&tcpSesReconnectCount, 0); |
| 1580 | 1609 | atomic_set(&tconInfoReconnectCount, 0); |
| 1581 | 1610 | |
| 1582 | − atomic_set(&bufAllocCount, 0); | |
| 1583 | − atomic_set(&smBufAllocCount, 0); | |
| 1611 | + atomic_set(&buf_alloc_count, 0); | |
| 1612 | + atomic_set(&small_buf_alloc_count, 0); | |
| 1584 | 1613 | #ifdef CONFIG_CIFS_STATS2 |
| 1585 | − atomic_set(&totBufAllocCount, 0); | |
| 1586 | − atomic_set(&totSmBufAllocCount, 0); | |
| 1614 | + atomic_set(&total_buf_alloc_count, 0); | |
| 1615 | + atomic_set(&total_small_buf_alloc_count, 0); | |
| 1587 | 1616 | if (slow_rsp_threshold < 1) |
| 1588 | 1617 | cifs_dbg(FYI, "slow_response_threshold msgs disabled\n"); |
| 1589 | 1618 | else if (slow_rsp_threshold > 32767) |
| @@ -1591,7 +1620,7 @@ init_cifs(void) · 1 unmodified line | ||
| 1591 | 1620 | "slow response threshold set higher than recommended (0 to 32767)\n"); |
| 1592 | 1621 | #endif /* CONFIG_CIFS_STATS2 */ |
| 1593 | 1622 | |
| 1594 | − atomic_set(&midCount, 0); | |
| 1623 | + atomic_set(&mid_count, 0); | |
| 1595 | 1624 | GlobalCurrentXid = 0; |
| 1596 | 1625 | GlobalTotalActiveXid = 0; |
| 1597 | 1626 | GlobalMaxActiveXid = 0; |
| @@ -1654,7 +1683,7 @@ init_cifs(void) · 56 unmodified lines | ||
| 1654 | 1683 | if (rc) |
| 1655 | 1684 | goto out_destroy_deferredclose_wq; |
| 1656 | 1685 | |
| 1657 | − rc = cifs_init_mids(); | |
| 1686 | + rc = init_mids(); | |
| 1658 | 1687 | if (rc) |
| 1659 | 1688 | goto out_destroy_inodecache; |
| 1660 | 1689 | |
| @@ -1711,7 +1740,7 @@ out_destroy_request_bufs: · 50 unmodified lines | ||
| 1711 | 1740 | #endif |
| 1712 | 1741 | cifs_destroy_request_bufs(); |
| 1713 | 1742 | out_destroy_mids: |
| 1714 | − cifs_destroy_mids(); | |
| 1743 | + destroy_mids(); | |
| 1715 | 1744 | out_destroy_inodecache: |
| 1716 | 1745 | cifs_destroy_inodecache(); |
| 1717 | 1746 | out_destroy_deferredclose_wq: |
| @@ -1747,7 +1776,7 @@ exit_cifs(void) · 29 unmodified lines | ||
| 1747 | 1776 | dfs_cache_destroy(); |
| 1748 | 1777 | #endif |
| 1749 | 1778 | cifs_destroy_request_bufs(); |
| 1750 | − cifs_destroy_mids(); | |
| 1779 | + destroy_mids(); | |
| 1751 | 1780 | cifs_destroy_inodecache(); |
| 1752 | 1781 | destroy_workqueue(deferredclose_wq); |
| 1753 | 1782 | destroy_workqueue(cifsoplockd_wq); |
| @@ -153,6 +153,6 @@ extern const struct export_operations cifs_export_ops; · 152 unmodified lines | ||
| 153 | 153 | #endif /* CONFIG_CIFS_NFSD_EXPORT */ |
| 154 | 154 | |
| 155 | 155 | /* when changing internal version - update following two lines at same time */ |
| 156 | −#define SMB3_PRODUCT_BUILD 37 | |
| 157 | −#define CIFS_VERSION "2.37" | |
| 156 | +#define SMB3_PRODUCT_BUILD 38 | |
| 157 | +#define CIFS_VERSION "2.38" | |
| 158 | 158 | #endif /* _CIFSFS_H */ |
| @@ -605,6 +605,7 @@ inc_rfc1001_len(void *buf, int count) · 604 unmodified lines | ||
| 605 | 605 | struct TCP_Server_Info { |
| 606 | 606 | struct list_head tcp_ses_list; |
| 607 | 607 | struct list_head smb_ses_list; |
| 608 | + spinlock_t srv_lock; /* protect anything here that is not protected */ | |
| 608 | 609 | __u64 conn_id; /* connection identifier (useful for debugging) */ |
| 609 | 610 | int srv_count; /* reference counter */ |
| 610 | 611 | /* 15 character server name + 0x20 16th byte indicating type = srv */ |
| @@ -622,6 +623,7 @@ struct TCP_Server_Info { · 11 unmodified lines | ||
| 622 | 623 | #endif |
| 623 | 624 | wait_queue_head_t response_q; |
| 624 | 625 | wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/ |
| 626 | + spinlock_t mid_lock; /* protect mid queue and it's entries */ | |
| 625 | 627 | struct list_head pending_mid_q; |
| 626 | 628 | bool noblocksnd; /* use blocking sendmsg */ |
| 627 | 629 | bool noautotune; /* do not autotune send buf sizes */ |
| @@ -1008,6 +1010,7 @@ struct cifs_ses { · 380 unmodified lines | ||
| 1008 | 1010 | struct list_head rlist; /* reconnect list */ |
| 1009 | 1011 | struct list_head tcon_list; |
| 1010 | 1012 | struct cifs_tcon *tcon_ipc; |
| 1013 | + spinlock_t ses_lock; /* protect anything here that is not protected */ | |
| 1011 | 1014 | struct mutex session_mutex; |
| 1012 | 1015 | struct TCP_Server_Info *server; /* pointer to server info */ |
| 1013 | 1016 | int ses_count; /* reference counter */ |
| @@ -1169,6 +1172,7 @@ struct cifs_tcon { · 155 unmodified lines | ||
| 1169 | 1172 | struct list_head tcon_list; |
| 1170 | 1173 | int tc_count; |
| 1171 | 1174 | struct list_head rlist; /* reconnect list */ |
| 1175 | + spinlock_t tc_lock; /* protect anything here that is not protected */ | |
| 1172 | 1176 | atomic_t num_local_opens; /* num of all opens including disconnected */ |
| 1173 | 1177 | atomic_t num_remote_opens; /* num of all network opens on server */ |
| 1174 | 1178 | struct list_head openFileList; |
| @@ -1899,33 +1903,78 @@ require use of the stronger protocol */ · 724 unmodified lines | ||
| 1899 | 1903 | */ |
| 1900 | 1904 | |
| 1901 | 1905 | /**************************************************************************** |
| 1902 | − * Locking notes. All updates to global variables and lists should be | |
| 1903 | − * protected by spinlocks or semaphores. | |
| 1906 | + * Here are all the locks (spinlock, mutex, semaphore) in cifs.ko, arranged according | |
| 1907 | + * to the locking order. i.e. if two locks are to be held together, the lock that | |
| 1908 | + * appears higher in this list needs to be taken before the other. | |
| 1904 | 1909 | * |
| 1905 | − * Spinlocks | |
| 1906 | − * --------- | |
| 1907 | − * GlobalMid_Lock protects: | |
| 1908 | − * list operations on pending_mid_q and oplockQ | |
| 1909 | − * updates to XID counters, multiplex id and SMB sequence numbers | |
| 1910 | − * list operations on global DnotifyReqList | |
| 1911 | − * updates to ses->status and TCP_Server_Info->tcpStatus | |
| 1912 | − * updates to server->CurrentMid | |
| 1913 | − * tcp_ses_lock protects: | |
| 1914 | − * list operations on tcp and SMB session lists | |
| 1915 | − * tcon->open_file_lock protects the list of open files hanging off the tcon | |
| 1916 | − * inode->open_file_lock protects the openFileList hanging off the inode | |
| 1917 | − * cfile->file_info_lock protects counters and fields in cifs file struct | |
| 1918 | − * f_owner.lock protects certain per file struct operations | |
| 1919 | − * mapping->page_lock protects certain per page operations | |
| 1910 | + * If you hold a lock that is lower in this list, and you need to take a higher lock | |
| 1911 | + * (or if you think that one of the functions that you're calling may need to), first | |
| 1912 | + * drop the lock you hold, pick up the higher lock, then the lower one. This will | |
| 1913 | + * ensure that locks are picked up only in one direction in the below table | |
| 1914 | + * (top to bottom). | |
| 1920 | 1915 | * |
| 1921 | − * Note that the cifs_tcon.open_file_lock should be taken before | |
| 1922 | − * not after the cifsInodeInfo.open_file_lock | |
| 1916 | + * Also, if you expect a function to be called with a lock held, explicitly document | |
| 1917 | + * this in the comments on top of your function definition. | |
| 1923 | 1918 | * |
| 1924 | − * Semaphores | |
| 1925 | − * ---------- | |
| 1926 | − * cifsInodeInfo->lock_sem protects: | |
| 1927 | − * the list of locks held by the inode | |
| 1919 | + * And also, try to keep the critical sections (lock hold time) to be as minimal as | |
| 1920 | + * possible. Blocking / calling other functions with a lock held always increase | |
| 1921 | + * the risk of a possible deadlock. | |
| 1928 | 1922 | * |
| 1923 | + * Following this rule will avoid unnecessary deadlocks, which can get really hard to | |
| 1924 | + * debug. Also, any new lock that you introduce, please add to this list in the correct | |
| 1925 | + * order. | |
| 1926 | + * | |
| 1927 | + * Please populate this list whenever you introduce new locks in your changes. Or in | |
| 1928 | + * case I've missed some existing locks. Please ensure that it's added in the list | |
| 1929 | + * based on the locking order expected. | |
| 1930 | + * | |
| 1931 | + * ===================================================================================== | |
| 1932 | + * Lock Protects Initialization fn | |
| 1933 | + * ===================================================================================== | |
| 1934 | + * vol_list_lock | |
| 1935 | + * vol_info->ctx_lock vol_info->ctx | |
| 1936 | + * cifs_sb_info->tlink_tree_lock cifs_sb_info->tlink_tree cifs_setup_cifs_sb | |
| 1937 | + * TCP_Server_Info-> TCP_Server_Info cifs_get_tcp_session | |
| 1938 | + * reconnect_mutex | |
| 1939 | + * TCP_Server_Info->srv_mutex TCP_Server_Info cifs_get_tcp_session | |
| 1940 | + * cifs_ses->session_mutex cifs_ses sesInfoAlloc | |
| 1941 | + * cifs_tcon | |
| 1942 | + * cifs_tcon->open_file_lock cifs_tcon->openFileList tconInfoAlloc | |
| 1943 | + * cifs_tcon->pending_opens | |
| 1944 | + * cifs_tcon->stat_lock cifs_tcon->bytes_read tconInfoAlloc | |
| 1945 | + * cifs_tcon->bytes_written | |
| 1946 | + * cifs_tcp_ses_lock cifs_tcp_ses_list sesInfoAlloc | |
| 1947 | + * GlobalMid_Lock GlobalMaxActiveXid init_cifs | |
| 1948 | + * GlobalCurrentXid | |
| 1949 | + * GlobalTotalActiveXid | |
| 1950 | + * TCP_Server_Info->srv_lock (anything in struct not protected by another lock and can change) | |
| 1951 | + * TCP_Server_Info->mid_lock TCP_Server_Info->pending_mid_q cifs_get_tcp_session | |
| 1952 | + * ->CurrentMid | |
| 1953 | + * (any changes in mid_q_entry fields) | |
| 1954 | + * TCP_Server_Info->req_lock TCP_Server_Info->in_flight cifs_get_tcp_session | |
| 1955 | + * ->credits | |
| 1956 | + * ->echo_credits | |
| 1957 | + * ->oplock_credits | |
| 1958 | + * ->reconnect_instance | |
| 1959 | + * cifs_ses->ses_lock (anything that is not protected by another lock and can change) | |
| 1960 | + * cifs_ses->iface_lock cifs_ses->iface_list sesInfoAlloc | |
| 1961 | + * ->iface_count | |
| 1962 | + * ->iface_last_update | |
| 1963 | + * cifs_ses->chan_lock cifs_ses->chans | |
| 1964 | + * ->chans_need_reconnect | |
| 1965 | + * ->chans_in_reconnect | |
| 1966 | + * cifs_tcon->tc_lock (anything that is not protected by another lock and can change) | |
| 1967 | + * cifsInodeInfo->open_file_lock cifsInodeInfo->openFileList cifs_alloc_inode | |
| 1968 | + * cifsInodeInfo->writers_lock cifsInodeInfo->writers cifsInodeInfo_alloc | |
| 1969 | + * cifsInodeInfo->lock_sem cifsInodeInfo->llist cifs_init_once | |
| 1970 | + * ->can_cache_brlcks | |
| 1971 | + * cifsInodeInfo->deferred_lock cifsInodeInfo->deferred_closes cifsInodeInfo_alloc | |
| 1972 | + * cached_fid->fid_mutex cifs_tcon->crfid tconInfoAlloc | |
| 1973 | + * cifsFileInfo->fh_mutex cifsFileInfo cifs_new_fileinfo | |
| 1974 | + * cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo | |
| 1975 | + * ->invalidHandle initiate_cifs_search | |
| 1976 | + * ->oplock_break_cancelled | |
| 1977 | + * cifs_aio_ctx->aio_mutex cifs_aio_ctx cifs_aio_ctx_alloc | |
| 1929 | 1978 | ****************************************************************************/ |
| 1930 | 1979 | |
| 1931 | 1980 | #ifdef DECLARE_GLOBALS_HERE |
| @@ -1941,47 +1990,44 @@ require use of the stronger protocol */ · 9 unmodified lines | ||
| 1941 | 1990 | * sessions (and from that the tree connections) can be found |
| 1942 | 1991 | * by iterating over cifs_tcp_ses_list |
| 1943 | 1992 | */ |
| 1944 | −GLOBAL_EXTERN struct list_head cifs_tcp_ses_list; | |
| 1993 | +extern struct list_head cifs_tcp_ses_list; | |
| 1945 | 1994 | |
| 1946 | 1995 | /* |
| 1947 | 1996 | * This lock protects the cifs_tcp_ses_list, the list of smb sessions per |
| 1948 | 1997 | * tcp session, and the list of tcon's per smb session. It also protects |
| 1949 | − * the reference counters for the server, smb session, and tcon. It also | |
| 1950 | − * protects some fields in the TCP_Server_Info struct such as dstaddr. Finally, | |
| 1951 | − * changes to the tcon->tidStatus should be done while holding this lock. | |
| 1998 | + * the reference counters for the server, smb session, and tcon. | |
| 1952 | 1999 | * generally the locks should be taken in order tcp_ses_lock before |
| 1953 | 2000 | * tcon->open_file_lock and that before file->file_info_lock since the |
| 1954 | 2001 | * structure order is cifs_socket-->cifs_ses-->cifs_tcon-->cifs_file |
| 1955 | 2002 | */ |
| 1956 | −GLOBAL_EXTERN spinlock_t cifs_tcp_ses_lock; | |
| 2003 | +extern spinlock_t cifs_tcp_ses_lock; | |
| 1957 | 2004 | |
| 1958 | 2005 | /* |
| 1959 | 2006 | * Global transaction id (XID) information |
| 1960 | 2007 | */ |
| 1961 | −GLOBAL_EXTERN unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */ | |
| 1962 | −GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */ | |
| 1963 | −GLOBAL_EXTERN unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */ | |
| 1964 | −GLOBAL_EXTERN spinlock_t GlobalMid_Lock; /* protects above & list operations */ | |
| 1965 | − /* on midQ entries */ | |
| 2008 | +extern unsigned int GlobalCurrentXid; /* protected by GlobalMid_Sem */ | |
| 2009 | +extern unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */ | |
| 2010 | +extern unsigned int GlobalMaxActiveXid; /* prot by GlobalMid_Sem */ | |
| 2011 | +extern spinlock_t GlobalMid_Lock; /* protects above & list operations on midQ entries */ | |
| 2012 | + | |
| 1966 | 2013 | /* |
| 1967 | 2014 | * Global counters, updated atomically |
| 1968 | 2015 | */ |
| 1969 | −GLOBAL_EXTERN atomic_t sesInfoAllocCount; | |
| 1970 | −GLOBAL_EXTERN atomic_t tconInfoAllocCount; | |
| 1971 | −GLOBAL_EXTERN atomic_t tcpSesNextId; | |
| 1972 | −GLOBAL_EXTERN atomic_t tcpSesAllocCount; | |
| 1973 | −GLOBAL_EXTERN atomic_t tcpSesReconnectCount; | |
| 1974 | −GLOBAL_EXTERN atomic_t tconInfoReconnectCount; | |
| 2016 | +extern atomic_t sesInfoAllocCount; | |
| 2017 | +extern atomic_t tconInfoAllocCount; | |
| 2018 | +extern atomic_t tcpSesNextId; | |
| 2019 | +extern atomic_t tcpSesAllocCount; | |
| 2020 | +extern atomic_t tcpSesReconnectCount; | |
| 2021 | +extern atomic_t tconInfoReconnectCount; | |
| 1975 | 2022 | |
| 1976 | 2023 | /* Various Debug counters */ |
| 1977 | −GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */ | |
| 2024 | +extern atomic_t buf_alloc_count; /* current number allocated */ | |
| 2025 | +extern atomic_t small_buf_alloc_count; | |
| 1978 | 2026 | #ifdef CONFIG_CIFS_STATS2 |
| 1979 | −GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */ | |
| 1980 | −GLOBAL_EXTERN atomic_t totSmBufAllocCount; | |
| 2027 | +extern atomic_t total_buf_alloc_count; /* total allocated over all time */ | |
| 2028 | +extern atomic_t total_small_buf_alloc_count; | |
| 1981 | 2029 | extern unsigned int slow_rsp_threshold; /* number of secs before logging */ |
| 1982 | 2030 | #endif |
| 1983 | −GLOBAL_EXTERN atomic_t smBufAllocCount; | |
| 1984 | −GLOBAL_EXTERN atomic_t midCount; | |
| 1985 | 2031 | |
| 1986 | 2032 | /* Misc globals */ |
| 1987 | 2033 | extern bool enable_oplocks; /* enable or disable oplocks */ |
| @@ -1998,6 +2044,7 @@ extern unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ · 10 unmodified lines | ||
| 1998 | 2044 | extern unsigned int cifs_min_small; /* min size of small buf pool */ |
| 1999 | 2045 | extern unsigned int cifs_max_pending; /* MAX requests at once to server*/ |
| 2000 | 2046 | extern bool disable_legacy_dialects; /* forbid vers=1.0 and vers=2.0 mounts */ |
| 2047 | +extern atomic_t mid_count; | |
| 2001 | 2048 | |
| 2002 | 2049 | void cifs_oplock_break(struct work_struct *work); |
| 2003 | 2050 | void cifs_queue_oplock_break(struct cifsFileInfo *cfile); |
| @@ -78,12 +78,8 @@ extern char *build_wildcard_path_from_dentry(struct dentry *direntry); · 77 unmodified lines | ||
| 78 | 78 | extern char *cifs_compose_mount_options(const char *sb_mountdata, |
| 79 | 79 | const char *fullpath, const struct dfs_info3_param *ref, |
| 80 | 80 | char **devname); |
| 81 | −/* extern void renew_parental_timestamps(struct dentry *direntry);*/ | |
| 82 | −extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer, | |
| 83 | − struct TCP_Server_Info *server); | |
| 84 | −extern void DeleteMidQEntry(struct mid_q_entry *midEntry); | |
| 85 | −extern void cifs_delete_mid(struct mid_q_entry *mid); | |
| 86 | −extern void cifs_mid_q_entry_release(struct mid_q_entry *midEntry); | |
| 81 | +extern void delete_mid(struct mid_q_entry *mid); | |
| 82 | +extern void release_mid(struct mid_q_entry *mid); | |
| 87 | 83 | extern void cifs_wake_up_task(struct mid_q_entry *mid); |
| 88 | 84 | extern int cifs_handle_standard(struct TCP_Server_Info *server, |
| 89 | 85 | struct mid_q_entry *mid); |
| @@ -521,6 +517,7 @@ extern int generate_smb30signingkey(struct cifs_ses *ses, · 431 unmodified lines | ||
| 521 | 517 | extern int generate_smb311signingkey(struct cifs_ses *ses, |
| 522 | 518 | struct TCP_Server_Info *server); |
| 523 | 519 | |
| 520 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 524 | 521 | extern int CIFSSMBCopy(unsigned int xid, |
| 525 | 522 | struct cifs_tcon *source_tcon, |
| 526 | 523 | const char *fromName, |
| @@ -551,6 +548,7 @@ extern int CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon, · 24 unmodified lines | ||
| 551 | 548 | const struct nls_table *nls_codepage, int remap_special_chars); |
| 552 | 549 | extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon, |
| 553 | 550 | const int netfid, __u64 *pExtAttrBits, __u64 *pMask); |
| 551 | +#endif /* CIFS_ALLOW_INSECURE_LEGACY */ | |
| 554 | 552 | extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb); |
| 555 | 553 | extern bool couldbe_mf_symlink(const struct cifs_fattr *fattr); |
| 556 | 554 | extern int check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, |
| @@ -29,7 +29,6 @@ · 28 unmodified lines | ||
| 29 | 29 | #include "cifsproto.h" |
| 30 | 30 | #include "cifs_unicode.h" |
| 31 | 31 | #include "cifs_debug.h" |
| 32 | −#include "smb2proto.h" | |
| 33 | 32 | #include "fscache.h" |
| 34 | 33 | #include "smbdirect.h" |
| 35 | 34 | #ifdef CONFIG_CIFS_DFS_UPCALL |
| @@ -62,52 +61,6 @@ static struct { · 26 unmodified lines | ||
| 62 | 61 | #define CIFS_NUM_PROT 1 |
| 63 | 62 | #endif /* CIFS_POSIX */ |
| 64 | 63 | |
| 65 | −/* | |
| 66 | − * Mark as invalid, all open files on tree connections since they | |
| 67 | − * were closed when session to server was lost. | |
| 68 | − */ | |
| 69 | −void | |
| 70 | −cifs_mark_open_files_invalid(struct cifs_tcon *tcon) | |
| 71 | −{ | |
| 72 | − struct cifsFileInfo *open_file = NULL; | |
| 73 | − struct list_head *tmp; | |
| 74 | − struct list_head *tmp1; | |
| 75 | − | |
| 76 | − /* only send once per connect */ | |
| 77 | − spin_lock(&cifs_tcp_ses_lock); | |
| 78 | − if ((tcon->ses->ses_status != SES_GOOD) || (tcon->status != TID_NEED_RECON)) { | |
| 79 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 80 | − return; | |
| 81 | − } | |
| 82 | − tcon->status = TID_IN_FILES_INVALIDATE; | |
| 83 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 84 | − | |
| 85 | − /* list all files open on tree connection and mark them invalid */ | |
| 86 | − spin_lock(&tcon->open_file_lock); | |
| 87 | − list_for_each_safe(tmp, tmp1, &tcon->openFileList) { | |
| 88 | − open_file = list_entry(tmp, struct cifsFileInfo, tlist); | |
| 89 | − open_file->invalidHandle = true; | |
| 90 | − open_file->oplock_break_cancelled = true; | |
| 91 | − } | |
| 92 | − spin_unlock(&tcon->open_file_lock); | |
| 93 | − | |
| 94 | − mutex_lock(&tcon->crfid.fid_mutex); | |
| 95 | − tcon->crfid.is_valid = false; | |
| 96 | − /* cached handle is not valid, so SMB2_CLOSE won't be sent below */ | |
| 97 | − close_cached_dir_lease_locked(&tcon->crfid); | |
| 98 | − memset(tcon->crfid.fid, 0, sizeof(struct cifs_fid)); | |
| 99 | − mutex_unlock(&tcon->crfid.fid_mutex); | |
| 100 | − | |
| 101 | − spin_lock(&cifs_tcp_ses_lock); | |
| 102 | − if (tcon->status == TID_IN_FILES_INVALIDATE) | |
| 103 | − tcon->status = TID_NEED_TCON; | |
| 104 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 105 | − | |
| 106 | − /* | |
| 107 | − * BB Add call to invalidate_inodes(sb) for all superblocks mounted | |
| 108 | − * to this tcon. | |
| 109 | − */ | |
| 110 | −} | |
| 111 | 64 | |
| 112 | 65 | /* reconnect the socket, tcon, and smb session if needed */ |
| 113 | 66 | static int |
| @@ -134,18 +87,18 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) · 20 unmodified lines | ||
| 134 | 87 | * only tree disconnect, open, and write, (and ulogoff which does not |
| 135 | 88 | * have tcon) are allowed as we start force umount |
| 136 | 89 | */ |
| 137 | − spin_lock(&cifs_tcp_ses_lock); | |
| 90 | + spin_lock(&tcon->tc_lock); | |
| 138 | 91 | if (tcon->status == TID_EXITING) { |
| 139 | 92 | if (smb_command != SMB_COM_WRITE_ANDX && |
| 140 | 93 | smb_command != SMB_COM_OPEN_ANDX && |
| 141 | 94 | smb_command != SMB_COM_TREE_DISCONNECT) { |
| 142 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 95 | + spin_unlock(&tcon->tc_lock); | |
| 143 | 96 | cifs_dbg(FYI, "can not send cmd %d while umounting\n", |
| 144 | 97 | smb_command); |
| 145 | 98 | return -ENODEV; |
| 146 | 99 | } |
| 147 | 100 | } |
| 148 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 101 | + spin_unlock(&tcon->tc_lock); | |
| 149 | 102 | |
| 150 | 103 | retries = server->nr_targets; |
| 151 | 104 | |
| @@ -165,12 +118,12 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) · 13 unmodified lines | ||
| 165 | 118 | } |
| 166 | 119 | |
| 167 | 120 | /* are we still trying to reconnect? */ |
| 168 | − spin_lock(&cifs_tcp_ses_lock); | |
| 121 | + spin_lock(&server->srv_lock); | |
| 169 | 122 | if (server->tcpStatus != CifsNeedReconnect) { |
| 170 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 123 | + spin_unlock(&server->srv_lock); | |
| 171 | 124 | break; |
| 172 | 125 | } |
| 173 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 126 | + spin_unlock(&server->srv_lock); | |
| 174 | 127 | |
| 175 | 128 | if (retries && --retries) |
| 176 | 129 | continue; |
| @@ -201,13 +154,13 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) · 24 unmodified lines | ||
| 201 | 154 | * and the server never sends an answer the socket will be closed |
| 202 | 155 | * and tcpStatus set to reconnect. |
| 203 | 156 | */ |
| 204 | − spin_lock(&cifs_tcp_ses_lock); | |
| 157 | + spin_lock(&server->srv_lock); | |
| 205 | 158 | if (server->tcpStatus == CifsNeedReconnect) { |
| 206 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 159 | + spin_unlock(&server->srv_lock); | |
| 207 | 160 | rc = -EHOSTDOWN; |
| 208 | 161 | goto out; |
| 209 | 162 | } |
| 210 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 163 | + spin_unlock(&server->srv_lock); | |
| 211 | 164 | |
| 212 | 165 | /* |
| 213 | 166 | * need to prevent multiple threads trying to simultaneously |
| @@ -457,52 +410,6 @@ decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr) · 243 unmodified lines | ||
| 457 | 410 | return 0; |
| 458 | 411 | } |
| 459 | 412 | |
| 460 | −int | |
| 461 | −cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required) | |
| 462 | −{ | |
| 463 | − bool srv_sign_required = server->sec_mode & server->vals->signing_required; | |
| 464 | − bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled; | |
| 465 | − bool mnt_sign_enabled = global_secflags & CIFSSEC_MAY_SIGN; | |
| 466 | − | |
| 467 | − /* | |
| 468 | − * Is signing required by mnt options? If not then check | |
| 469 | − * global_secflags to see if it is there. | |
| 470 | − */ | |
| 471 | − if (!mnt_sign_required) | |
| 472 | − mnt_sign_required = ((global_secflags & CIFSSEC_MUST_SIGN) == | |
| 473 | − CIFSSEC_MUST_SIGN); | |
| 474 | − | |
| 475 | − /* | |
| 476 | − * If signing is required then it's automatically enabled too, | |
| 477 | − * otherwise, check to see if the secflags allow it. | |
| 478 | − */ | |
| 479 | − mnt_sign_enabled = mnt_sign_required ? mnt_sign_required : | |
| 480 | − (global_secflags & CIFSSEC_MAY_SIGN); | |
| 481 | − | |
| 482 | − /* If server requires signing, does client allow it? */ | |
| 483 | − if (srv_sign_required) { | |
| 484 | − if (!mnt_sign_enabled) { | |
| 485 | − cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!\n"); | |
| 486 | − return -ENOTSUPP; | |
| 487 | − } | |
| 488 | − server->sign = true; | |
| 489 | − } | |
| 490 | − | |
| 491 | − /* If client requires signing, does server allow it? */ | |
| 492 | − if (mnt_sign_required) { | |
| 493 | − if (!srv_sign_enabled) { | |
| 494 | − cifs_dbg(VFS, "Server does not support signing!\n"); | |
| 495 | − return -ENOTSUPP; | |
| 496 | − } | |
| 497 | − server->sign = true; | |
| 498 | − } | |
| 499 | − | |
| 500 | − if (cifs_rdma_enabled(server) && server->sign) | |
| 501 | − cifs_dbg(VFS, "Signing is enabled, and RDMA read/write will be disabled\n"); | |
| 502 | − | |
| 503 | − return 0; | |
| 504 | −} | |
| 505 | − | |
| 506 | 413 | static bool |
| 507 | 414 | should_set_ext_sec_flag(enum securityEnum sectype) |
| 508 | 415 | { |
| @@ -684,7 +591,7 @@ cifs_echo_callback(struct mid_q_entry *mid) · 175 unmodified lines | ||
| 684 | 591 | struct TCP_Server_Info *server = mid->callback_data; |
| 685 | 592 | struct cifs_credits credits = { .value = 1, .instance = 0 }; |
| 686 | 593 | |
| 687 | − DeleteMidQEntry(mid); | |
| 594 | + release_mid(mid); | |
| 688 | 595 | add_credits(server, &credits, CIFS_ECHO_OP); |
| 689 | 596 | } |
| 690 | 597 | |
| @@ -1379,184 +1286,6 @@ openRetry: · 688 unmodified lines | ||
| 1379 | 1286 | return rc; |
| 1380 | 1287 | } |
| 1381 | 1288 | |
| 1382 | −/* | |
| 1383 | − * Discard any remaining data in the current SMB. To do this, we borrow the | |
| 1384 | − * current bigbuf. | |
| 1385 | − */ | |
| 1386 | −int | |
| 1387 | −cifs_discard_remaining_data(struct TCP_Server_Info *server) | |
| 1388 | −{ | |
| 1389 | − unsigned int rfclen = server->pdu_size; | |
| 1390 | − int remaining = rfclen + server->vals->header_preamble_size - | |
| 1391 | − server->total_read; | |
| 1392 | − | |
| 1393 | − while (remaining > 0) { | |
| 1394 | − int length; | |
| 1395 | − | |
| 1396 | − length = cifs_discard_from_socket(server, | |
| 1397 | − min_t(size_t, remaining, | |
| 1398 | − CIFSMaxBufSize + MAX_HEADER_SIZE(server))); | |
| 1399 | − if (length < 0) | |
| 1400 | − return length; | |
| 1401 | − server->total_read += length; | |
| 1402 | − remaining -= length; | |
| 1403 | − } | |
| 1404 | − | |
| 1405 | − return 0; | |
| 1406 | −} | |
| 1407 | − | |
| 1408 | −static int | |
| 1409 | −__cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid, | |
| 1410 | − bool malformed) | |
| 1411 | −{ | |
| 1412 | − int length; | |
| 1413 | − | |
| 1414 | − length = cifs_discard_remaining_data(server); | |
| 1415 | − dequeue_mid(mid, malformed); | |
| 1416 | − mid->resp_buf = server->smallbuf; | |
| 1417 | − server->smallbuf = NULL; | |
| 1418 | − return length; | |
| 1419 | −} | |
| 1420 | − | |
| 1421 | −static int | |
| 1422 | −cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |
| 1423 | −{ | |
| 1424 | − struct cifs_readdata *rdata = mid->callback_data; | |
| 1425 | − | |
| 1426 | − return __cifs_readv_discard(server, mid, rdata->result); | |
| 1427 | −} | |
| 1428 | − | |
| 1429 | −int | |
| 1430 | −cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |
| 1431 | −{ | |
| 1432 | − int length, len; | |
| 1433 | − unsigned int data_offset, data_len; | |
| 1434 | − struct cifs_readdata *rdata = mid->callback_data; | |
| 1435 | − char *buf = server->smallbuf; | |
| 1436 | − unsigned int buflen = server->pdu_size + | |
| 1437 | − server->vals->header_preamble_size; | |
| 1438 | − bool use_rdma_mr = false; | |
| 1439 | − | |
| 1440 | − cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n", | |
| 1441 | − __func__, mid->mid, rdata->offset, rdata->bytes); | |
| 1442 | − | |
| 1443 | − /* | |
| 1444 | − * read the rest of READ_RSP header (sans Data array), or whatever we | |
| 1445 | − * can if there's not enough data. At this point, we've read down to | |
| 1446 | − * the Mid. | |
| 1447 | − */ | |
| 1448 | − len = min_t(unsigned int, buflen, server->vals->read_rsp_size) - | |
| 1449 | − HEADER_SIZE(server) + 1; | |
| 1450 | − | |
| 1451 | − length = cifs_read_from_socket(server, | |
| 1452 | − buf + HEADER_SIZE(server) - 1, len); | |
| 1453 | − if (length < 0) | |
| 1454 | − return length; | |
| 1455 | − server->total_read += length; | |
| 1456 | − | |
| 1457 | − if (server->ops->is_session_expired && | |
| 1458 | − server->ops->is_session_expired(buf)) { | |
| 1459 | − cifs_reconnect(server, true); | |
| 1460 | − return -1; | |
| 1461 | − } | |
| 1462 | − | |
| 1463 | − if (server->ops->is_status_pending && | |
| 1464 | − server->ops->is_status_pending(buf, server)) { | |
| 1465 | − cifs_discard_remaining_data(server); | |
| 1466 | − return -1; | |
| 1467 | − } | |
| 1468 | − | |
| 1469 | − /* set up first two iov for signature check and to get credits */ | |
| 1470 | − rdata->iov[0].iov_base = buf; | |
| 1471 | − rdata->iov[0].iov_len = server->vals->header_preamble_size; | |
| 1472 | − rdata->iov[1].iov_base = buf + server->vals->header_preamble_size; | |
| 1473 | − rdata->iov[1].iov_len = | |
| 1474 | − server->total_read - server->vals->header_preamble_size; | |
| 1475 | − cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n", | |
| 1476 | − rdata->iov[0].iov_base, rdata->iov[0].iov_len); | |
| 1477 | − cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n", | |
| 1478 | − rdata->iov[1].iov_base, rdata->iov[1].iov_len); | |
| 1479 | − | |
| 1480 | − /* Was the SMB read successful? */ | |
| 1481 | − rdata->result = server->ops->map_error(buf, false); | |
| 1482 | − if (rdata->result != 0) { | |
| 1483 | − cifs_dbg(FYI, "%s: server returned error %d\n", | |
| 1484 | − __func__, rdata->result); | |
| 1485 | − /* normal error on read response */ | |
| 1486 | − return __cifs_readv_discard(server, mid, false); | |
| 1487 | − } | |
| 1488 | − | |
| 1489 | − /* Is there enough to get to the rest of the READ_RSP header? */ | |
| 1490 | − if (server->total_read < server->vals->read_rsp_size) { | |
| 1491 | − cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n", | |
| 1492 | − __func__, server->total_read, | |
| 1493 | − server->vals->read_rsp_size); | |
| 1494 | − rdata->result = -EIO; | |
| 1495 | − return cifs_readv_discard(server, mid); | |
| 1496 | − } | |
| 1497 | − | |
| 1498 | − data_offset = server->ops->read_data_offset(buf) + | |
| 1499 | − server->vals->header_preamble_size; | |
| 1500 | − if (data_offset < server->total_read) { | |
| 1501 | − /* | |
| 1502 | − * win2k8 sometimes sends an offset of 0 when the read | |
| 1503 | − * is beyond the EOF. Treat it as if the data starts just after | |
| 1504 | − * the header. | |
| 1505 | − */ | |
| 1506 | − cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n", | |
| 1507 | − __func__, data_offset); | |
| 1508 | − data_offset = server->total_read; | |
| 1509 | − } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) { | |
| 1510 | − /* data_offset is beyond the end of smallbuf */ | |
| 1511 | − cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n", | |
| 1512 | − __func__, data_offset); | |
| 1513 | − rdata->result = -EIO; | |
| 1514 | − return cifs_readv_discard(server, mid); | |
| 1515 | − } | |
| 1516 | − | |
| 1517 | − cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n", | |
| 1518 | − __func__, server->total_read, data_offset); | |
| 1519 | − | |
| 1520 | − len = data_offset - server->total_read; | |
| 1521 | − if (len > 0) { | |
| 1522 | − /* read any junk before data into the rest of smallbuf */ | |
| 1523 | − length = cifs_read_from_socket(server, | |
| 1524 | − buf + server->total_read, len); | |
| 1525 | − if (length < 0) | |
| 1526 | − return length; | |
| 1527 | − server->total_read += length; | |
| 1528 | − } | |
| 1529 | − | |
| 1530 | − /* how much data is in the response? */ | |
| 1531 | −#ifdef CONFIG_CIFS_SMB_DIRECT | |
| 1532 | − use_rdma_mr = rdata->mr; | |
| 1533 | −#endif | |
| 1534 | − data_len = server->ops->read_data_length(buf, use_rdma_mr); | |
| 1535 | − if (!use_rdma_mr && (data_offset + data_len > buflen)) { | |
| 1536 | − /* data_len is corrupt -- discard frame */ | |
| 1537 | − rdata->result = -EIO; | |
| 1538 | − return cifs_readv_discard(server, mid); | |
| 1539 | − } | |
| 1540 | − | |
| 1541 | − length = rdata->read_into_pages(server, rdata, data_len); | |
| 1542 | − if (length < 0) | |
| 1543 | − return length; | |
| 1544 | − | |
| 1545 | − server->total_read += length; | |
| 1546 | − | |
| 1547 | − cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n", | |
| 1548 | − server->total_read, buflen, data_len); | |
| 1549 | − | |
| 1550 | − /* discard anything left over */ | |
| 1551 | − if (server->total_read < buflen) | |
| 1552 | − return cifs_readv_discard(server, mid); | |
| 1553 | − | |
| 1554 | − dequeue_mid(mid, false); | |
| 1555 | − mid->resp_buf = server->smallbuf; | |
| 1556 | − server->smallbuf = NULL; | |
| 1557 | − return length; | |
| 1558 | −} | |
| 1559 | − | |
| 1560 | 1289 | static void |
| 1561 | 1290 | cifs_readv_callback(struct mid_q_entry *mid) |
| 1562 | 1291 | { |
| @@ -1607,7 +1336,7 @@ cifs_readv_callback(struct mid_q_entry *mid) · 44 unmodified lines | ||
| 1607 | 1336 | } |
| 1608 | 1337 | |
| 1609 | 1338 | queue_work(cifsiod_wq, &rdata->work); |
| 1610 | − DeleteMidQEntry(mid); | |
| 1339 | + release_mid(mid); | |
| 1611 | 1340 | add_credits(server, &credits, 0); |
| 1612 | 1341 | } |
| 1613 | 1342 | |
| @@ -1909,183 +1638,6 @@ CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms, · 295 unmodified lines | ||
| 1909 | 1638 | return rc; |
| 1910 | 1639 | } |
| 1911 | 1640 | |
| 1912 | −void | |
| 1913 | −cifs_writedata_release(struct kref *refcount) | |
| 1914 | −{ | |
| 1915 | − struct cifs_writedata *wdata = container_of(refcount, | |
| 1916 | − struct cifs_writedata, refcount); | |
| 1917 | −#ifdef CONFIG_CIFS_SMB_DIRECT | |
| 1918 | − if (wdata->mr) { | |
| 1919 | − smbd_deregister_mr(wdata->mr); | |
| 1920 | − wdata->mr = NULL; | |
| 1921 | − } | |
| 1922 | −#endif | |
| 1923 | − | |
| 1924 | − if (wdata->cfile) | |
| 1925 | − cifsFileInfo_put(wdata->cfile); | |
| 1926 | − | |
| 1927 | − kvfree(wdata->pages); | |
| 1928 | − kfree(wdata); | |
| 1929 | −} | |
| 1930 | − | |
| 1931 | −/* | |
| 1932 | − * Write failed with a retryable error. Resend the write request. It's also | |
| 1933 | − * possible that the page was redirtied so re-clean the page. | |
| 1934 | − */ | |
| 1935 | −static void | |
| 1936 | −cifs_writev_requeue(struct cifs_writedata *wdata) | |
| 1937 | −{ | |
| 1938 | − int i, rc = 0; | |
| 1939 | − struct inode *inode = d_inode(wdata->cfile->dentry); | |
| 1940 | − struct TCP_Server_Info *server; | |
| 1941 | − unsigned int rest_len; | |
| 1942 | − | |
| 1943 | − server = tlink_tcon(wdata->cfile->tlink)->ses->server; | |
| 1944 | − i = 0; | |
| 1945 | − rest_len = wdata->bytes; | |
| 1946 | − do { | |
| 1947 | − struct cifs_writedata *wdata2; | |
| 1948 | − unsigned int j, nr_pages, wsize, tailsz, cur_len; | |
| 1949 | − | |
| 1950 | − wsize = server->ops->wp_retry_size(inode); | |
| 1951 | − if (wsize < rest_len) { | |
| 1952 | − nr_pages = wsize / PAGE_SIZE; | |
| 1953 | − if (!nr_pages) { | |
| 1954 | − rc = -ENOTSUPP; | |
| 1955 | − break; | |
| 1956 | − } | |
| 1957 | − cur_len = nr_pages * PAGE_SIZE; | |
| 1958 | − tailsz = PAGE_SIZE; | |
| 1959 | − } else { | |
| 1960 | − nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE); | |
| 1961 | − cur_len = rest_len; | |
| 1962 | − tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE; | |
| 1963 | − } | |
| 1964 | − | |
| 1965 | − wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete); | |
| 1966 | − if (!wdata2) { | |
| 1967 | − rc = -ENOMEM; | |
| 1968 | − break; | |
| 1969 | − } | |
| 1970 | − | |
| 1971 | − for (j = 0; j < nr_pages; j++) { | |
| 1972 | − wdata2->pages[j] = wdata->pages[i + j]; | |
| 1973 | − lock_page(wdata2->pages[j]); | |
| 1974 | − clear_page_dirty_for_io(wdata2->pages[j]); | |
| 1975 | − } | |
| 1976 | − | |
| 1977 | − wdata2->sync_mode = wdata->sync_mode; | |
| 1978 | − wdata2->nr_pages = nr_pages; | |
| 1979 | − wdata2->offset = page_offset(wdata2->pages[0]); | |
| 1980 | − wdata2->pagesz = PAGE_SIZE; | |
| 1981 | − wdata2->tailsz = tailsz; | |
| 1982 | − wdata2->bytes = cur_len; | |
| 1983 | − | |
| 1984 | − rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, | |
| 1985 | − &wdata2->cfile); | |
| 1986 | − if (!wdata2->cfile) { | |
| 1987 | − cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n", | |
| 1988 | − rc); | |
| 1989 | − if (!is_retryable_error(rc)) | |
| 1990 | − rc = -EBADF; | |
| 1991 | − } else { | |
| 1992 | − wdata2->pid = wdata2->cfile->pid; | |
| 1993 | − rc = server->ops->async_writev(wdata2, | |
| 1994 | − cifs_writedata_release); | |
| 1995 | − } | |
| 1996 | − | |
| 1997 | − for (j = 0; j < nr_pages; j++) { | |
| 1998 | − unlock_page(wdata2->pages[j]); | |
| 1999 | − if (rc != 0 && !is_retryable_error(rc)) { | |
| 2000 | − SetPageError(wdata2->pages[j]); | |
| 2001 | − end_page_writeback(wdata2->pages[j]); | |
| 2002 | − put_page(wdata2->pages[j]); | |
| 2003 | − } | |
| 2004 | − } | |
| 2005 | − | |
| 2006 | − kref_put(&wdata2->refcount, cifs_writedata_release); | |
| 2007 | − if (rc) { | |
| 2008 | − if (is_retryable_error(rc)) | |
| 2009 | − continue; | |
| 2010 | − i += nr_pages; | |
| 2011 | − break; | |
| 2012 | − } | |
| 2013 | − | |
| 2014 | − rest_len -= cur_len; | |
| 2015 | − i += nr_pages; | |
| 2016 | − } while (i < wdata->nr_pages); | |
| 2017 | − | |
| 2018 | − /* cleanup remaining pages from the original wdata */ | |
| 2019 | − for (; i < wdata->nr_pages; i++) { | |
| 2020 | − SetPageError(wdata->pages[i]); | |
| 2021 | − end_page_writeback(wdata->pages[i]); | |
| 2022 | − put_page(wdata->pages[i]); | |
| 2023 | − } | |
| 2024 | − | |
| 2025 | − if (rc != 0 && !is_retryable_error(rc)) | |
| 2026 | − mapping_set_error(inode->i_mapping, rc); | |
| 2027 | − kref_put(&wdata->refcount, cifs_writedata_release); | |
| 2028 | −} | |
| 2029 | − | |
| 2030 | −void | |
| 2031 | −cifs_writev_complete(struct work_struct *work) | |
| 2032 | −{ | |
| 2033 | − struct cifs_writedata *wdata = container_of(work, | |
| 2034 | − struct cifs_writedata, work); | |
| 2035 | − struct inode *inode = d_inode(wdata->cfile->dentry); | |
| 2036 | − int i = 0; | |
| 2037 | − | |
| 2038 | − if (wdata->result == 0) { | |
| 2039 | − spin_lock(&inode->i_lock); | |
| 2040 | − cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes); | |
| 2041 | − spin_unlock(&inode->i_lock); | |
| 2042 | − cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink), | |
| 2043 | − wdata->bytes); | |
| 2044 | − } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN) | |
| 2045 | − return cifs_writev_requeue(wdata); | |
| 2046 | − | |
| 2047 | − for (i = 0; i < wdata->nr_pages; i++) { | |
| 2048 | − struct page *page = wdata->pages[i]; | |
| 2049 | − if (wdata->result == -EAGAIN) | |
| 2050 | − __set_page_dirty_nobuffers(page); | |
| 2051 | − else if (wdata->result < 0) | |
| 2052 | − SetPageError(page); | |
| 2053 | − end_page_writeback(page); | |
| 2054 | − cifs_readpage_to_fscache(inode, page); | |
| 2055 | − put_page(page); | |
| 2056 | − } | |
| 2057 | − if (wdata->result != -EAGAIN) | |
| 2058 | − mapping_set_error(inode->i_mapping, wdata->result); | |
| 2059 | − kref_put(&wdata->refcount, cifs_writedata_release); | |
| 2060 | −} | |
| 2061 | − | |
| 2062 | −struct cifs_writedata * | |
| 2063 | −cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete) | |
| 2064 | −{ | |
| 2065 | − struct page **pages = | |
| 2066 | − kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS); | |
| 2067 | − if (pages) | |
| 2068 | − return cifs_writedata_direct_alloc(pages, complete); | |
| 2069 | − | |
| 2070 | − return NULL; | |
| 2071 | −} | |
| 2072 | − | |
| 2073 | −struct cifs_writedata * | |
| 2074 | −cifs_writedata_direct_alloc(struct page **pages, work_func_t complete) | |
| 2075 | −{ | |
| 2076 | − struct cifs_writedata *wdata; | |
| 2077 | − | |
| 2078 | − wdata = kzalloc(sizeof(*wdata), GFP_NOFS); | |
| 2079 | − if (wdata != NULL) { | |
| 2080 | − wdata->pages = pages; | |
| 2081 | − kref_init(&wdata->refcount); | |
| 2082 | − INIT_LIST_HEAD(&wdata->list); | |
| 2083 | − init_completion(&wdata->done); | |
| 2084 | − INIT_WORK(&wdata->work, complete); | |
| 2085 | − } | |
| 2086 | − return wdata; | |
| 2087 | −} | |
| 2088 | − | |
| 2089 | 1641 | /* |
| 2090 | 1642 | * Check the mid_state and signature on received buffer (if any), and queue the |
| 2091 | 1643 | * workqueue completion task. |
| @@ -2132,7 +1684,7 @@ cifs_writev_callback(struct mid_q_entry *mid) · 40 unmodified lines | ||
| 2132 | 1684 | } |
| 2133 | 1685 | |
| 2134 | 1686 | queue_work(cifsiod_wq, &wdata->work); |
| 2135 | − DeleteMidQEntry(mid); | |
| 1687 | + release_mid(mid); | |
| 2136 | 1688 | add_credits(tcon->ses->server, &credits, 0); |
| 2137 | 1689 | } |
| 2138 | 1690 | |
| @@ -3660,7 +3212,6 @@ setACLerrorExit: · 1521 unmodified lines | ||
| 3660 | 3212 | return rc; |
| 3661 | 3213 | } |
| 3662 | 3214 | |
| 3663 | −/* BB fix tabs in this function FIXME BB */ | |
| 3664 | 3215 | int |
| 3665 | 3216 | CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon, |
| 3666 | 3217 | const int netfid, __u64 *pExtAttrBits, __u64 *pMask) |
| @@ -3677,7 +3228,7 @@ CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon, · 10 unmodified lines | ||
| 3677 | 3228 | |
| 3678 | 3229 | GetExtAttrRetry: |
| 3679 | 3230 | rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, |
| 3680 | − (void **) &pSMBr); | |
| 3231 | + (void **) &pSMBr); | |
| 3681 | 3232 | if (rc) |
| 3682 | 3233 | return rc; |
| 3683 | 3234 | |
| @@ -3723,7 +3274,7 @@ GetExtAttrRetry: · 39 unmodified lines | ||
| 3723 | 3274 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
| 3724 | 3275 | __u16 count = le16_to_cpu(pSMBr->t2.DataCount); |
| 3725 | 3276 | struct file_chattr_info *pfinfo; |
| 3726 | − /* BB Do we need a cast or hash here ? */ | |
| 3277 | + | |
| 3727 | 3278 | if (count != 16) { |
| 3728 | 3279 | cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n"); |
| 3729 | 3280 | rc = -EIO; |
| @@ -119,10 +119,10 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server) · 118 unmodified lines | ||
| 119 | 119 | goto requeue_resolve; |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | − spin_lock(&cifs_tcp_ses_lock); | |
| 122 | + spin_lock(&server->srv_lock); | |
| 123 | 123 | rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr, |
| 124 | 124 | strlen(ipaddr)); |
| 125 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 125 | + spin_unlock(&server->srv_lock); | |
| 126 | 126 | kfree(ipaddr); |
| 127 | 127 | |
| 128 | 128 | /* rc == 1 means success here */ |
| @@ -205,17 +205,22 @@ cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server, · 76 unmodified lines | ||
| 205 | 205 | /* If server is a channel, select the primary channel */ |
| 206 | 206 | pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server; |
| 207 | 207 | |
| 208 | − spin_lock(&cifs_tcp_ses_lock); | |
| 208 | + spin_lock(&pserver->srv_lock); | |
| 209 | 209 | if (!all_channels) { |
| 210 | 210 | pserver->tcpStatus = CifsNeedReconnect; |
| 211 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 211 | + spin_unlock(&pserver->srv_lock); | |
| 212 | 212 | return; |
| 213 | 213 | } |
| 214 | + spin_unlock(&pserver->srv_lock); | |
| 214 | 215 | |
| 216 | + spin_lock(&cifs_tcp_ses_lock); | |
| 215 | 217 | list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { |
| 216 | 218 | spin_lock(&ses->chan_lock); |
| 217 | − for (i = 0; i < ses->chan_count; i++) | |
| 219 | + for (i = 0; i < ses->chan_count; i++) { | |
| 220 | + spin_lock(&ses->chans[i].server->srv_lock); | |
| 218 | 221 | ses->chans[i].server->tcpStatus = CifsNeedReconnect; |
| 222 | + spin_unlock(&ses->chans[i].server->srv_lock); | |
| 223 | + } | |
| 219 | 224 | spin_unlock(&ses->chan_lock); |
| 220 | 225 | } |
| 221 | 226 | spin_unlock(&cifs_tcp_ses_lock); |
| @@ -252,17 +257,8 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server, · 30 unmodified lines | ||
| 252 | 257 | spin_lock(&cifs_tcp_ses_lock); |
| 253 | 258 | list_for_each_entry_safe(ses, nses, &pserver->smb_ses_list, smb_ses_list) { |
| 254 | 259 | /* check if iface is still active */ |
| 255 | − if (!cifs_chan_is_iface_active(ses, server)) { | |
| 256 | − /* | |
| 257 | − * HACK: drop the lock before calling | |
| 258 | − * cifs_chan_update_iface to avoid deadlock | |
| 259 | − */ | |
| 260 | − ses->ses_count++; | |
| 261 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 260 | + if (!cifs_chan_is_iface_active(ses, server)) | |
| 262 | 261 | cifs_chan_update_iface(ses, server); |
| 263 | − spin_lock(&cifs_tcp_ses_lock); | |
| 264 | − ses->ses_count--; | |
| 265 | − } | |
| 266 | 262 | |
| 267 | 263 | spin_lock(&ses->chan_lock); |
| 268 | 264 | if (!mark_smb_session && cifs_chan_needs_reconnect(ses, server)) |
| @@ -323,7 +319,7 @@ cifs_abort_connection(struct TCP_Server_Info *server) · 54 unmodified lines | ||
| 323 | 319 | /* mark submitted MIDs for retry and issue callback */ |
| 324 | 320 | INIT_LIST_HEAD(&retry_list); |
| 325 | 321 | cifs_dbg(FYI, "%s: moving mids to private list\n", __func__); |
| 326 | − spin_lock(&GlobalMid_Lock); | |
| 322 | + spin_lock(&server->mid_lock); | |
| 327 | 323 | list_for_each_entry_safe(mid, nmid, &server->pending_mid_q, qhead) { |
| 328 | 324 | kref_get(&mid->refcount); |
| 329 | 325 | if (mid->mid_state == MID_REQUEST_SUBMITTED) |
| @@ -331,14 +327,14 @@ cifs_abort_connection(struct TCP_Server_Info *server) · 1 unmodified line | ||
| 331 | 327 | list_move(&mid->qhead, &retry_list); |
| 332 | 328 | mid->mid_flags |= MID_DELETED; |
| 333 | 329 | } |
| 334 | − spin_unlock(&GlobalMid_Lock); | |
| 330 | + spin_unlock(&server->mid_lock); | |
| 335 | 331 | cifs_server_unlock(server); |
| 336 | 332 | |
| 337 | 333 | cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); |
| 338 | 334 | list_for_each_entry_safe(mid, nmid, &retry_list, qhead) { |
| 339 | 335 | list_del_init(&mid->qhead); |
| 340 | 336 | mid->callback(mid); |
| 341 | − cifs_mid_q_entry_release(mid); | |
| 337 | + release_mid(mid); | |
| 342 | 338 | } |
| 343 | 339 | |
| 344 | 340 | if (cifs_rdma_enabled(server)) { |
| @@ -350,11 +346,11 @@ cifs_abort_connection(struct TCP_Server_Info *server) · 5 unmodified lines | ||
| 350 | 346 | |
| 351 | 347 | static bool cifs_tcp_ses_needs_reconnect(struct TCP_Server_Info *server, int num_targets) |
| 352 | 348 | { |
| 353 | − spin_lock(&cifs_tcp_ses_lock); | |
| 349 | + spin_lock(&server->srv_lock); | |
| 354 | 350 | server->nr_targets = num_targets; |
| 355 | 351 | if (server->tcpStatus == CifsExiting) { |
| 356 | 352 | /* the demux thread will exit normally next time through the loop */ |
| 357 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 353 | + spin_unlock(&server->srv_lock); | |
| 358 | 354 | wake_up(&server->response_q); |
| 359 | 355 | return false; |
| 360 | 356 | } |
| @@ -364,7 +360,7 @@ static bool cifs_tcp_ses_needs_reconnect(struct TCP_Server_Info *server, int num · 3 unmodified lines | ||
| 364 | 360 | server->hostname); |
| 365 | 361 | server->tcpStatus = CifsNeedReconnect; |
| 366 | 362 | |
| 367 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 363 | + spin_unlock(&server->srv_lock); | |
| 368 | 364 | return true; |
| 369 | 365 | } |
| 370 | 366 | |
| @@ -414,20 +410,20 @@ static int __cifs_reconnect(struct TCP_Server_Info *server, · 43 unmodified lines | ||
| 414 | 410 | } else { |
| 415 | 411 | atomic_inc(&tcpSesReconnectCount); |
| 416 | 412 | set_credits(server, 1); |
| 417 | − spin_lock(&cifs_tcp_ses_lock); | |
| 413 | + spin_lock(&server->srv_lock); | |
| 418 | 414 | if (server->tcpStatus != CifsExiting) |
| 419 | 415 | server->tcpStatus = CifsNeedNegotiate; |
| 420 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 416 | + spin_unlock(&server->srv_lock); | |
| 421 | 417 | cifs_swn_reset_server_dstaddr(server); |
| 422 | 418 | cifs_server_unlock(server); |
| 423 | 419 | mod_delayed_work(cifsiod_wq, &server->reconnect, 0); |
| 424 | 420 | } |
| 425 | 421 | } while (server->tcpStatus == CifsNeedReconnect); |
| 426 | 422 | |
| 427 | − spin_lock(&cifs_tcp_ses_lock); | |
| 423 | + spin_lock(&server->srv_lock); | |
| 428 | 424 | if (server->tcpStatus == CifsNeedNegotiate) |
| 429 | 425 | mod_delayed_work(cifsiod_wq, &server->echo, 0); |
| 430 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 426 | + spin_unlock(&server->srv_lock); | |
| 431 | 427 | |
| 432 | 428 | wake_up(&server->response_q); |
| 433 | 429 | return rc; |
| @@ -541,10 +537,10 @@ static int reconnect_dfs_server(struct TCP_Server_Info *server) · 107 unmodified lines | ||
| 541 | 537 | */ |
| 542 | 538 | atomic_inc(&tcpSesReconnectCount); |
| 543 | 539 | set_credits(server, 1); |
| 544 | − spin_lock(&cifs_tcp_ses_lock); | |
| 540 | + spin_lock(&server->srv_lock); | |
| 545 | 541 | if (server->tcpStatus != CifsExiting) |
| 546 | 542 | server->tcpStatus = CifsNeedNegotiate; |
| 547 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 543 | + spin_unlock(&server->srv_lock); | |
| 548 | 544 | cifs_swn_reset_server_dstaddr(server); |
| 549 | 545 | cifs_server_unlock(server); |
| 550 | 546 | mod_delayed_work(cifsiod_wq, &server->reconnect, 0); |
| @@ -556,11 +552,10 @@ static int reconnect_dfs_server(struct TCP_Server_Info *server) · 5 unmodified lines | ||
| 556 | 552 | dfs_cache_free_tgts(&tl); |
| 557 | 553 | |
| 558 | 554 | /* Need to set up echo worker again once connection has been established */ |
| 559 | − spin_lock(&cifs_tcp_ses_lock); | |
| 555 | + spin_lock(&server->srv_lock); | |
| 560 | 556 | if (server->tcpStatus == CifsNeedNegotiate) |
| 561 | 557 | mod_delayed_work(cifsiod_wq, &server->echo, 0); |
| 562 | − | |
| 563 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 558 | + spin_unlock(&server->srv_lock); | |
| 564 | 559 | |
| 565 | 560 | wake_up(&server->response_q); |
| 566 | 561 | return rc; |
| @@ -569,12 +564,12 @@ static int reconnect_dfs_server(struct TCP_Server_Info *server) · 2 unmodified lines | ||
| 569 | 564 | int cifs_reconnect(struct TCP_Server_Info *server, bool mark_smb_session) |
| 570 | 565 | { |
| 571 | 566 | /* If tcp session is not an dfs connection, then reconnect to last target server */ |
| 572 | − spin_lock(&cifs_tcp_ses_lock); | |
| 567 | + spin_lock(&server->srv_lock); | |
| 573 | 568 | if (!server->is_dfs_conn) { |
| 574 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 569 | + spin_unlock(&server->srv_lock); | |
| 575 | 570 | return __cifs_reconnect(server, mark_smb_session); |
| 576 | 571 | } |
| 577 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 572 | + spin_unlock(&server->srv_lock); | |
| 578 | 573 | |
| 579 | 574 | mutex_lock(&server->refpath_lock); |
| 580 | 575 | if (!server->origin_fullpath || !server->leaf_fullpath) { |
| @@ -670,18 +665,18 @@ server_unresponsive(struct TCP_Server_Info *server) · 89 unmodified lines | ||
| 670 | 665 | * 65s kernel_recvmsg times out, and we see that we haven't gotten |
| 671 | 666 | * a response in >60s. |
| 672 | 667 | */ |
| 673 | − spin_lock(&cifs_tcp_ses_lock); | |
| 668 | + spin_lock(&server->srv_lock); | |
| 674 | 669 | if ((server->tcpStatus == CifsGood || |
| 675 | 670 | server->tcpStatus == CifsNeedNegotiate) && |
| 676 | 671 | (!server->ops->can_echo || server->ops->can_echo(server)) && |
| 677 | 672 | time_after(jiffies, server->lstrp + 3 * server->echo_interval)) { |
| 678 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 673 | + spin_unlock(&server->srv_lock); | |
| 679 | 674 | cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n", |
| 680 | 675 | (3 * server->echo_interval) / HZ); |
| 681 | 676 | cifs_reconnect(server, false); |
| 682 | 677 | return true; |
| 683 | 678 | } |
| 684 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 679 | + spin_unlock(&server->srv_lock); | |
| 685 | 680 | |
| 686 | 681 | return false; |
| 687 | 682 | } |
| @@ -726,18 +721,18 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg) · 38 unmodified lines | ||
| 726 | 721 | else |
| 727 | 722 | length = sock_recvmsg(server->ssocket, smb_msg, 0); |
| 728 | 723 | |
| 729 | − spin_lock(&cifs_tcp_ses_lock); | |
| 724 | + spin_lock(&server->srv_lock); | |
| 730 | 725 | if (server->tcpStatus == CifsExiting) { |
| 731 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 726 | + spin_unlock(&server->srv_lock); | |
| 732 | 727 | return -ESHUTDOWN; |
| 733 | 728 | } |
| 734 | 729 | |
| 735 | 730 | if (server->tcpStatus == CifsNeedReconnect) { |
| 736 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 731 | + spin_unlock(&server->srv_lock); | |
| 737 | 732 | cifs_reconnect(server, false); |
| 738 | 733 | return -ECONNABORTED; |
| 739 | 734 | } |
| 740 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 735 | + spin_unlock(&server->srv_lock); | |
| 741 | 736 | |
| 742 | 737 | if (length == -ERESTARTSYS || |
| 743 | 738 | length == -EAGAIN || |
| @@ -849,7 +844,7 @@ dequeue_mid(struct mid_q_entry *mid, bool malformed) · 105 unmodified lines | ||
| 849 | 844 | #ifdef CONFIG_CIFS_STATS2 |
| 850 | 845 | mid->when_received = jiffies; |
| 851 | 846 | #endif |
| 852 | − spin_lock(&GlobalMid_Lock); | |
| 847 | + spin_lock(&mid->server->mid_lock); | |
| 853 | 848 | if (!malformed) |
| 854 | 849 | mid->mid_state = MID_RESPONSE_RECEIVED; |
| 855 | 850 | else |
| @@ -859,12 +854,12 @@ dequeue_mid(struct mid_q_entry *mid, bool malformed) · 3 unmodified lines | ||
| 859 | 854 | * function has finished processing it is a bug. |
| 860 | 855 | */ |
| 861 | 856 | if (mid->mid_flags & MID_DELETED) { |
| 862 | − spin_unlock(&GlobalMid_Lock); | |
| 857 | + spin_unlock(&mid->server->mid_lock); | |
| 863 | 858 | pr_warn_once("trying to dequeue a deleted mid\n"); |
| 864 | 859 | } else { |
| 865 | 860 | list_del_init(&mid->qhead); |
| 866 | 861 | mid->mid_flags |= MID_DELETED; |
| 867 | − spin_unlock(&GlobalMid_Lock); | |
| 862 | + spin_unlock(&mid->server->mid_lock); | |
| 868 | 863 | } |
| 869 | 864 | } |
| 870 | 865 | |
| @@ -903,21 +898,68 @@ handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server, · 32 unmodified lines | ||
| 903 | 898 | dequeue_mid(mid, malformed); |
| 904 | 899 | } |
| 905 | 900 | |
| 901 | +int | |
| 902 | +cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required) | |
| 903 | +{ | |
| 904 | + bool srv_sign_required = server->sec_mode & server->vals->signing_required; | |
| 905 | + bool srv_sign_enabled = server->sec_mode & server->vals->signing_enabled; | |
| 906 | + bool mnt_sign_enabled; | |
| 907 | + | |
| 908 | + /* | |
| 909 | + * Is signing required by mnt options? If not then check | |
| 910 | + * global_secflags to see if it is there. | |
| 911 | + */ | |
| 912 | + if (!mnt_sign_required) | |
| 913 | + mnt_sign_required = ((global_secflags & CIFSSEC_MUST_SIGN) == | |
| 914 | + CIFSSEC_MUST_SIGN); | |
| 915 | + | |
| 916 | + /* | |
| 917 | + * If signing is required then it's automatically enabled too, | |
| 918 | + * otherwise, check to see if the secflags allow it. | |
| 919 | + */ | |
| 920 | + mnt_sign_enabled = mnt_sign_required ? mnt_sign_required : | |
| 921 | + (global_secflags & CIFSSEC_MAY_SIGN); | |
| 922 | + | |
| 923 | + /* If server requires signing, does client allow it? */ | |
| 924 | + if (srv_sign_required) { | |
| 925 | + if (!mnt_sign_enabled) { | |
| 926 | + cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!\n"); | |
| 927 | + return -EOPNOTSUPP; | |
| 928 | + } | |
| 929 | + server->sign = true; | |
| 930 | + } | |
| 931 | + | |
| 932 | + /* If client requires signing, does server allow it? */ | |
| 933 | + if (mnt_sign_required) { | |
| 934 | + if (!srv_sign_enabled) { | |
| 935 | + cifs_dbg(VFS, "Server does not support signing!\n"); | |
| 936 | + return -EOPNOTSUPP; | |
| 937 | + } | |
| 938 | + server->sign = true; | |
| 939 | + } | |
| 940 | + | |
| 941 | + if (cifs_rdma_enabled(server) && server->sign) | |
| 942 | + cifs_dbg(VFS, "Signing is enabled, and RDMA read/write will be disabled\n"); | |
| 943 | + | |
| 944 | + return 0; | |
| 945 | +} | |
| 946 | + | |
| 947 | + | |
| 906 | 948 | static void clean_demultiplex_info(struct TCP_Server_Info *server) |
| 907 | 949 | { |
| 908 | 950 | int length; |
| 909 | 951 | |
| 910 | 952 | /* take it off the list, if it's not already */ |
| 911 | − spin_lock(&cifs_tcp_ses_lock); | |
| 953 | + spin_lock(&server->srv_lock); | |
| 912 | 954 | list_del_init(&server->tcp_ses_list); |
| 913 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 955 | + spin_unlock(&server->srv_lock); | |
| 914 | 956 | |
| 915 | 957 | cancel_delayed_work_sync(&server->echo); |
| 916 | 958 | cancel_delayed_work_sync(&server->resolve); |
| 917 | 959 | |
| 918 | − spin_lock(&cifs_tcp_ses_lock); | |
| 960 | + spin_lock(&server->srv_lock); | |
| 919 | 961 | server->tcpStatus = CifsExiting; |
| 920 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 962 | + spin_unlock(&server->srv_lock); | |
| 921 | 963 | wake_up_all(&server->response_q); |
| 922 | 964 | |
| 923 | 965 | /* check if we have blocked requests that need to free */ |
| @@ -948,7 +990,7 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) · 24 unmodified lines | ||
| 948 | 990 | struct list_head *tmp, *tmp2; |
| 949 | 991 | |
| 950 | 992 | INIT_LIST_HEAD(&dispose_list); |
| 951 | − spin_lock(&GlobalMid_Lock); | |
| 993 | + spin_lock(&server->mid_lock); | |
| 952 | 994 | list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { |
| 953 | 995 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
| 954 | 996 | cifs_dbg(FYI, "Clearing mid %llu\n", mid_entry->mid); |
| @@ -957,7 +999,7 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) · 2 unmodified lines | ||
| 957 | 999 | list_move(&mid_entry->qhead, &dispose_list); |
| 958 | 1000 | mid_entry->mid_flags |= MID_DELETED; |
| 959 | 1001 | } |
| 960 | − spin_unlock(&GlobalMid_Lock); | |
| 1002 | + spin_unlock(&server->mid_lock); | |
| 961 | 1003 | |
| 962 | 1004 | /* now walk dispose list and issue callbacks */ |
| 963 | 1005 | list_for_each_safe(tmp, tmp2, &dispose_list) { |
| @@ -965,7 +1007,7 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) · 1 unmodified line | ||
| 965 | 1007 | cifs_dbg(FYI, "Callback mid %llu\n", mid_entry->mid); |
| 966 | 1008 | list_del_init(&mid_entry->qhead); |
| 967 | 1009 | mid_entry->callback(mid_entry); |
| 968 | − cifs_mid_q_entry_release(mid_entry); | |
| 1010 | + release_mid(mid_entry); | |
| 969 | 1011 | } |
| 970 | 1012 | /* 1/8th of sec is more than enough time for them to exit */ |
| 971 | 1013 | msleep(125); |
| @@ -1039,19 +1081,18 @@ int · 67 unmodified lines | ||
| 1039 | 1081 | cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid) |
| 1040 | 1082 | { |
| 1041 | 1083 | char *buf = server->large_buf ? server->bigbuf : server->smallbuf; |
| 1042 | − int length; | |
| 1084 | + int rc; | |
| 1043 | 1085 | |
| 1044 | 1086 | /* |
| 1045 | 1087 | * We know that we received enough to get to the MID as we |
| 1046 | 1088 | * checked the pdu_length earlier. Now check to see |
| 1047 | − * if the rest of the header is OK. We borrow the length | |
| 1048 | − * var for the rest of the loop to avoid a new stack var. | |
| 1089 | + * if the rest of the header is OK. | |
| 1049 | 1090 | * |
| 1050 | 1091 | * 48 bytes is enough to display the header and a little bit |
| 1051 | 1092 | * into the payload for debugging purposes. |
| 1052 | 1093 | */ |
| 1053 | − length = server->ops->check_message(buf, server->total_read, server); | |
| 1054 | − if (length != 0) | |
| 1094 | + rc = server->ops->check_message(buf, server->total_read, server); | |
| 1095 | + if (rc) | |
| 1055 | 1096 | cifs_dump_mem("Bad SMB: ", buf, |
| 1056 | 1097 | min_t(unsigned int, server->total_read, 48)); |
| 1057 | 1098 | |
| @@ -1066,9 +1107,9 @@ cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid) · 8 unmodified lines | ||
| 1066 | 1107 | return -1; |
| 1067 | 1108 | |
| 1068 | 1109 | if (!mid) |
| 1069 | − return length; | |
| 1110 | + return rc; | |
| 1070 | 1111 | |
| 1071 | − handle_mid(mid, server, buf, length); | |
| 1112 | + handle_mid(mid, server, buf, rc); | |
| 1072 | 1113 | return 0; |
| 1073 | 1114 | } |
| 1074 | 1115 | |
| @@ -1205,7 +1246,7 @@ next_pdu: · 130 unmodified lines | ||
| 1205 | 1246 | if (length < 0) { |
| 1206 | 1247 | for (i = 0; i < num_mids; i++) |
| 1207 | 1248 | if (mids[i]) |
| 1208 | − cifs_mid_q_entry_release(mids[i]); | |
| 1249 | + release_mid(mids[i]); | |
| 1209 | 1250 | continue; |
| 1210 | 1251 | } |
| 1211 | 1252 | |
| @@ -1232,7 +1273,7 @@ next_pdu: · 20 unmodified lines | ||
| 1232 | 1273 | if (!mids[i]->multiRsp || mids[i]->multiEnd) |
| 1233 | 1274 | mids[i]->callback(mids[i]); |
| 1234 | 1275 | |
| 1235 | − cifs_mid_q_entry_release(mids[i]); | |
| 1276 | + release_mid(mids[i]); | |
| 1236 | 1277 | } else if (server->ops->is_oplock_break && |
| 1237 | 1278 | server->ops->is_oplock_break(bufs[i], |
| 1238 | 1279 | server)) { |
| @@ -1240,7 +1281,7 @@ next_pdu: · 1 unmodified line | ||
| 1240 | 1281 | cifs_dbg(FYI, "Received oplock break\n"); |
| 1241 | 1282 | } else { |
| 1242 | 1283 | cifs_server_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n", |
| 1243 | − atomic_read(&midCount)); | |
| 1284 | + atomic_read(&mid_count)); | |
| 1244 | 1285 | cifs_dump_mem("Received Data is: ", bufs[i], |
| 1245 | 1286 | HEADER_SIZE(server)); |
| 1246 | 1287 | smb2_add_credits_from_hdr(bufs[i], server); |
| @@ -1411,6 +1452,7 @@ match_security(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) · 164 unmodified lines | ||
| 1411 | 1452 | return true; |
| 1412 | 1453 | } |
| 1413 | 1454 | |
| 1455 | +/* this function must be called with srv_lock held */ | |
| 1414 | 1456 | static int match_server(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) |
| 1415 | 1457 | { |
| 1416 | 1458 | struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr; |
| @@ -1471,6 +1513,7 @@ cifs_find_tcp_session(struct smb3_fs_context *ctx) · 54 unmodified lines | ||
| 1471 | 1513 | |
| 1472 | 1514 | spin_lock(&cifs_tcp_ses_lock); |
| 1473 | 1515 | list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { |
| 1516 | + spin_lock(&server->srv_lock); | |
| 1474 | 1517 | #ifdef CONFIG_CIFS_DFS_UPCALL |
| 1475 | 1518 | /* |
| 1476 | 1519 | * DFS failover implementation in cifs_reconnect() requires unique tcp sessions for |
| @@ -1478,15 +1521,20 @@ cifs_find_tcp_session(struct smb3_fs_context *ctx) · 1 unmodified line | ||
| 1478 | 1521 | * shares or even links that may connect to same server but having completely |
| 1479 | 1522 | * different failover targets. |
| 1480 | 1523 | */ |
| 1481 | − if (server->is_dfs_conn) | |
| 1524 | + if (server->is_dfs_conn) { | |
| 1525 | + spin_unlock(&server->srv_lock); | |
| 1482 | 1526 | continue; |
| 1527 | + } | |
| 1483 | 1528 | #endif |
| 1484 | 1529 | /* |
| 1485 | 1530 | * Skip ses channels since they're only handled in lower layers |
| 1486 | 1531 | * (e.g. cifs_send_recv). |
| 1487 | 1532 | */ |
| 1488 | − if (CIFS_SERVER_IS_CHAN(server) || !match_server(server, ctx)) | |
| 1533 | + if (CIFS_SERVER_IS_CHAN(server) || !match_server(server, ctx)) { | |
| 1534 | + spin_unlock(&server->srv_lock); | |
| 1489 | 1535 | continue; |
| 1536 | + } | |
| 1537 | + spin_unlock(&server->srv_lock); | |
| 1490 | 1538 | |
| 1491 | 1539 | ++server->srv_count; |
| 1492 | 1540 | spin_unlock(&cifs_tcp_ses_lock); |
| @@ -1534,9 +1582,9 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect) · 41 unmodified lines | ||
| 1534 | 1582 | else |
| 1535 | 1583 | cancel_delayed_work_sync(&server->reconnect); |
| 1536 | 1584 | |
| 1537 | − spin_lock(&cifs_tcp_ses_lock); | |
| 1585 | + spin_lock(&server->srv_lock); | |
| 1538 | 1586 | server->tcpStatus = CifsExiting; |
| 1539 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1587 | + spin_unlock(&server->srv_lock); | |
| 1540 | 1588 | |
| 1541 | 1589 | cifs_crypto_secmech_release(server); |
| 1542 | 1590 | |
| @@ -1595,8 +1643,8 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx, · 52 unmodified lines | ||
| 1595 | 1643 | if (primary_server) { |
| 1596 | 1644 | spin_lock(&cifs_tcp_ses_lock); |
| 1597 | 1645 | ++primary_server->srv_count; |
| 1598 | − tcp_ses->primary_server = primary_server; | |
| 1599 | 1646 | spin_unlock(&cifs_tcp_ses_lock); |
| 1647 | + tcp_ses->primary_server = primary_server; | |
| 1600 | 1648 | } |
| 1601 | 1649 | init_waitqueue_head(&tcp_ses->response_q); |
| 1602 | 1650 | init_waitqueue_head(&tcp_ses->request_q); |
| @@ -1612,6 +1660,8 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx, · 9 unmodified lines | ||
| 1612 | 1660 | tcp_ses->lstrp = jiffies; |
| 1613 | 1661 | tcp_ses->compress_algorithm = cpu_to_le16(ctx->compression); |
| 1614 | 1662 | spin_lock_init(&tcp_ses->req_lock); |
| 1663 | + spin_lock_init(&tcp_ses->srv_lock); | |
| 1664 | + spin_lock_init(&tcp_ses->mid_lock); | |
| 1615 | 1665 | INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); |
| 1616 | 1666 | INIT_LIST_HEAD(&tcp_ses->smb_ses_list); |
| 1617 | 1667 | INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request); |
| @@ -1685,9 +1735,9 @@ smbd_connected: · 67 unmodified lines | ||
| 1685 | 1735 | * to the struct since the kernel thread not created yet |
| 1686 | 1736 | * no need to spinlock this update of tcpStatus |
| 1687 | 1737 | */ |
| 1688 | − spin_lock(&cifs_tcp_ses_lock); | |
| 1738 | + spin_lock(&tcp_ses->srv_lock); | |
| 1689 | 1739 | tcp_ses->tcpStatus = CifsNeedNegotiate; |
| 1690 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1740 | + spin_unlock(&tcp_ses->srv_lock); | |
| 1691 | 1741 | |
| 1692 | 1742 | if ((ctx->max_credits < 20) || (ctx->max_credits > 60000)) |
| 1693 | 1743 | tcp_ses->max_credits = SMB2_MAX_CREDITS_AVAILABLE; |
| @@ -1729,6 +1779,7 @@ out_err: · 35 unmodified lines | ||
| 1729 | 1779 | return ERR_PTR(rc); |
| 1730 | 1780 | } |
| 1731 | 1781 | |
| 1782 | +/* this function must be called with ses_lock held */ | |
| 1732 | 1783 | static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx) |
| 1733 | 1784 | { |
| 1734 | 1785 | if (ctx->sectype != Unspecified && |
| @@ -1864,10 +1915,17 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) · 129 unmodified lines | ||
| 1864 | 1915 | |
| 1865 | 1916 | spin_lock(&cifs_tcp_ses_lock); |
| 1866 | 1917 | list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { |
| 1867 | − if (ses->ses_status == SES_EXITING) | |
| 1918 | + spin_lock(&ses->ses_lock); | |
| 1919 | + if (ses->ses_status == SES_EXITING) { | |
| 1920 | + spin_unlock(&ses->ses_lock); | |
| 1868 | 1921 | continue; |
| 1869 | − if (!match_session(ses, ctx)) | |
| 1922 | + } | |
| 1923 | + if (!match_session(ses, ctx)) { | |
| 1924 | + spin_unlock(&ses->ses_lock); | |
| 1870 | 1925 | continue; |
| 1926 | + } | |
| 1927 | + spin_unlock(&ses->ses_lock); | |
| 1928 | + | |
| 1871 | 1929 | ++ses->ses_count; |
| 1872 | 1930 | spin_unlock(&cifs_tcp_ses_lock); |
| 1873 | 1931 | return ses; |
| @@ -1882,26 +1940,28 @@ void cifs_put_smb_ses(struct cifs_ses *ses) · 8 unmodified lines | ||
| 1882 | 1940 | unsigned int chan_count; |
| 1883 | 1941 | struct TCP_Server_Info *server = ses->server; |
| 1884 | 1942 | |
| 1885 | − spin_lock(&cifs_tcp_ses_lock); | |
| 1943 | + spin_lock(&ses->ses_lock); | |
| 1886 | 1944 | if (ses->ses_status == SES_EXITING) { |
| 1887 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1945 | + spin_unlock(&ses->ses_lock); | |
| 1888 | 1946 | return; |
| 1889 | 1947 | } |
| 1948 | + spin_unlock(&ses->ses_lock); | |
| 1890 | 1949 | |
| 1891 | 1950 | cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count); |
| 1892 | 1951 | cifs_dbg(FYI, "%s: ses ipc: %s\n", __func__, ses->tcon_ipc ? ses->tcon_ipc->treeName : "NONE"); |
| 1893 | 1952 | |
| 1953 | + spin_lock(&cifs_tcp_ses_lock); | |
| 1894 | 1954 | if (--ses->ses_count > 0) { |
| 1895 | 1955 | spin_unlock(&cifs_tcp_ses_lock); |
| 1896 | 1956 | return; |
| 1897 | 1957 | } |
| 1958 | + spin_unlock(&cifs_tcp_ses_lock); | |
| 1898 | 1959 | |
| 1899 | 1960 | /* ses_count can never go negative */ |
| 1900 | 1961 | WARN_ON(ses->ses_count < 0); |
| 1901 | 1962 | |
| 1902 | 1963 | if (ses->ses_status == SES_GOOD) |
| 1903 | 1964 | ses->ses_status = SES_EXITING; |
| 1904 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1905 | 1965 | |
| 1906 | 1966 | cifs_free_ipc(ses); |
| 1907 | 1967 | |
| @@ -2236,6 +2296,7 @@ get_ses_fail: · 328 unmodified lines | ||
| 2236 | 2296 | return ERR_PTR(rc); |
| 2237 | 2297 | } |
| 2238 | 2298 | |
| 2299 | +/* this function must be called with tc_lock held */ | |
| 2239 | 2300 | static int match_tcon(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) |
| 2240 | 2301 | { |
| 2241 | 2302 | if (tcon->status == TID_EXITING) |
| @@ -2258,16 +2319,17 @@ static int match_tcon(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) · 16 unmodified lines | ||
| 2258 | 2319 | static struct cifs_tcon * |
| 2259 | 2320 | cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) |
| 2260 | 2321 | { |
| 2261 | − struct list_head *tmp; | |
| 2262 | 2322 | struct cifs_tcon *tcon; |
| 2263 | 2323 | |
| 2264 | 2324 | spin_lock(&cifs_tcp_ses_lock); |
| 2265 | − list_for_each(tmp, &ses->tcon_list) { | |
| 2266 | − tcon = list_entry(tmp, struct cifs_tcon, tcon_list); | |
| 2267 | − | |
| 2268 | − if (!match_tcon(tcon, ctx)) | |
| 2325 | + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { | |
| 2326 | + spin_lock(&tcon->tc_lock); | |
| 2327 | + if (!match_tcon(tcon, ctx)) { | |
| 2328 | + spin_unlock(&tcon->tc_lock); | |
| 2269 | 2329 | continue; |
| 2330 | + } | |
| 2270 | 2331 | ++tcon->tc_count; |
| 2332 | + spin_unlock(&tcon->tc_lock); | |
| 2271 | 2333 | spin_unlock(&cifs_tcp_ses_lock); |
| 2272 | 2334 | return tcon; |
| 2273 | 2335 | } |
| @@ -2644,7 +2706,7 @@ match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data) · 370 unmodified lines | ||
| 2644 | 2706 | int |
| 2645 | 2707 | cifs_match_super(struct super_block *sb, void *data) |
| 2646 | 2708 | { |
| 2647 | − struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data; | |
| 2709 | + struct cifs_mnt_data *mnt_data = data; | |
| 2648 | 2710 | struct smb3_fs_context *ctx; |
| 2649 | 2711 | struct cifs_sb_info *cifs_sb; |
| 2650 | 2712 | struct TCP_Server_Info *tcp_srv; |
| @@ -2667,6 +2729,9 @@ cifs_match_super(struct super_block *sb, void *data) · 16 unmodified lines | ||
| 2667 | 2729 | |
| 2668 | 2730 | ctx = mnt_data->ctx; |
| 2669 | 2731 | |
| 2732 | + spin_lock(&tcp_srv->srv_lock); | |
| 2733 | + spin_lock(&ses->ses_lock); | |
| 2734 | + spin_lock(&tcon->tc_lock); | |
| 2670 | 2735 | if (!match_server(tcp_srv, ctx) || |
| 2671 | 2736 | !match_session(ses, ctx) || |
| 2672 | 2737 | !match_tcon(tcon, ctx) || |
| @@ -2677,6 +2742,10 @@ cifs_match_super(struct super_block *sb, void *data) · 4 unmodified lines | ||
| 2677 | 2742 | |
| 2678 | 2743 | rc = compare_mount_options(sb, mnt_data); |
| 2679 | 2744 | out: |
| 2745 | + spin_unlock(&tcon->tc_lock); | |
| 2746 | + spin_unlock(&ses->ses_lock); | |
| 2747 | + spin_unlock(&tcp_srv->srv_lock); | |
| 2748 | + | |
| 2680 | 2749 | spin_unlock(&cifs_tcp_ses_lock); |
| 2681 | 2750 | cifs_put_tlink(tlink); |
| 2682 | 2751 | return rc; |
| @@ -2954,6 +3023,7 @@ ip_connect(struct TCP_Server_Info *server) · 271 unmodified lines | ||
| 2954 | 3023 | return generic_ip_connect(server); |
| 2955 | 3024 | } |
| 2956 | 3025 | |
| 3026 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 2957 | 3027 | void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon, |
| 2958 | 3028 | struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx) |
| 2959 | 3029 | { |
| @@ -3059,6 +3129,7 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon, · 99 unmodified lines | ||
| 3059 | 3129 | } |
| 3060 | 3130 | } |
| 3061 | 3131 | } |
| 3132 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 3062 | 3133 | |
| 3063 | 3134 | int cifs_setup_cifs_sb(struct cifs_sb_info *cifs_sb) |
| 3064 | 3135 | { |
| @@ -3175,6 +3246,7 @@ static int mount_get_conns(struct mount_ctx *mnt_ctx) · 110 unmodified lines | ||
| 3175 | 3246 | if (tcon->posix_extensions) |
| 3176 | 3247 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; |
| 3177 | 3248 | |
| 3249 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 3178 | 3250 | /* tell server which Unix caps we support */ |
| 3179 | 3251 | if (cap_unix(tcon->ses)) { |
| 3180 | 3252 | /* |
| @@ -3182,16 +3254,17 @@ static int mount_get_conns(struct mount_ctx *mnt_ctx) · 1 unmodified line | ||
| 3182 | 3254 | * for just this mount. |
| 3183 | 3255 | */ |
| 3184 | 3256 | reset_cifs_unix_caps(xid, tcon, cifs_sb, ctx); |
| 3185 | − spin_lock(&cifs_tcp_ses_lock); | |
| 3257 | + spin_lock(&tcon->ses->server->srv_lock); | |
| 3186 | 3258 | if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) && |
| 3187 | 3259 | (le64_to_cpu(tcon->fsUnixInfo.Capability) & |
| 3188 | 3260 | CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) { |
| 3189 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 3261 | + spin_unlock(&tcon->ses->server->srv_lock); | |
| 3190 | 3262 | rc = -EACCES; |
| 3191 | 3263 | goto out; |
| 3192 | 3264 | } |
| 3193 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 3265 | + spin_unlock(&tcon->ses->server->srv_lock); | |
| 3194 | 3266 | } else |
| 3267 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 3195 | 3268 | tcon->unix_ext = 0; /* server does not support them */ |
| 3196 | 3269 | |
| 3197 | 3270 | /* do not care if a following call succeed - informational */ |
| @@ -3273,9 +3346,9 @@ static int mount_get_dfs_conns(struct mount_ctx *mnt_ctx) · 75 unmodified lines | ||
| 3273 | 3346 | rc = mount_get_conns(mnt_ctx); |
| 3274 | 3347 | if (mnt_ctx->server) { |
| 3275 | 3348 | cifs_dbg(FYI, "%s: marking tcp session as a dfs connection\n", __func__); |
| 3276 | − spin_lock(&cifs_tcp_ses_lock); | |
| 3349 | + spin_lock(&mnt_ctx->server->srv_lock); | |
| 3277 | 3350 | mnt_ctx->server->is_dfs_conn = true; |
| 3278 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 3351 | + spin_unlock(&mnt_ctx->server->srv_lock); | |
| 3279 | 3352 | } |
| 3280 | 3353 | return rc; |
| 3281 | 3354 | } |
| @@ -3990,28 +4063,28 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses, · 708 unmodified lines | ||
| 3990 | 4063 | return -ENOSYS; |
| 3991 | 4064 | |
| 3992 | 4065 | /* only send once per connect */ |
| 3993 | − spin_lock(&cifs_tcp_ses_lock); | |
| 4066 | + spin_lock(&server->srv_lock); | |
| 3994 | 4067 | if (!server->ops->need_neg(server) || |
| 3995 | 4068 | server->tcpStatus != CifsNeedNegotiate) { |
| 3996 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4069 | + spin_unlock(&server->srv_lock); | |
| 3997 | 4070 | return 0; |
| 3998 | 4071 | } |
| 3999 | 4072 | server->tcpStatus = CifsInNegotiate; |
| 4000 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4073 | + spin_unlock(&server->srv_lock); | |
| 4001 | 4074 | |
| 4002 | 4075 | rc = server->ops->negotiate(xid, ses, server); |
| 4003 | 4076 | if (rc == 0) { |
| 4004 | − spin_lock(&cifs_tcp_ses_lock); | |
| 4077 | + spin_lock(&server->srv_lock); | |
| 4005 | 4078 | if (server->tcpStatus == CifsInNegotiate) |
| 4006 | 4079 | server->tcpStatus = CifsGood; |
| 4007 | 4080 | else |
| 4008 | 4081 | rc = -EHOSTDOWN; |
| 4009 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4082 | + spin_unlock(&server->srv_lock); | |
| 4010 | 4083 | } else { |
| 4011 | − spin_lock(&cifs_tcp_ses_lock); | |
| 4084 | + spin_lock(&server->srv_lock); | |
| 4012 | 4085 | if (server->tcpStatus == CifsInNegotiate) |
| 4013 | 4086 | server->tcpStatus = CifsNeedNegotiate; |
| 4014 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4087 | + spin_unlock(&server->srv_lock); | |
| 4015 | 4088 | } |
| 4016 | 4089 | |
| 4017 | 4090 | return rc; |
| @@ -4027,7 +4100,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, · 9 unmodified lines | ||
| 4027 | 4100 | struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr; |
| 4028 | 4101 | bool is_binding = false; |
| 4029 | 4102 | |
| 4030 | − spin_lock(&cifs_tcp_ses_lock); | |
| 4103 | + spin_lock(&ses->ses_lock); | |
| 4031 | 4104 | if (server->dstaddr.ss_family == AF_INET6) |
| 4032 | 4105 | scnprintf(ses->ip_addr, sizeof(ses->ip_addr), "%pI6", &addr6->sin6_addr); |
| 4033 | 4106 | else |
| @@ -4036,7 +4109,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, · 2 unmodified lines | ||
| 4036 | 4109 | if (ses->ses_status != SES_GOOD && |
| 4037 | 4110 | ses->ses_status != SES_NEW && |
| 4038 | 4111 | ses->ses_status != SES_NEED_RECON) { |
| 4039 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4112 | + spin_unlock(&ses->ses_lock); | |
| 4040 | 4113 | return 0; |
| 4041 | 4114 | } |
| 4042 | 4115 | |
| @@ -4045,7 +4118,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, · 2 unmodified lines | ||
| 4045 | 4118 | if (CIFS_ALL_CHANS_GOOD(ses) || |
| 4046 | 4119 | cifs_chan_in_reconnect(ses, server)) { |
| 4047 | 4120 | spin_unlock(&ses->chan_lock); |
| 4048 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4121 | + spin_unlock(&ses->ses_lock); | |
| 4049 | 4122 | return 0; |
| 4050 | 4123 | } |
| 4051 | 4124 | is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses); |
| @@ -4054,7 +4127,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, · 2 unmodified lines | ||
| 4054 | 4127 | |
| 4055 | 4128 | if (!is_binding) |
| 4056 | 4129 | ses->ses_status = SES_IN_SETUP; |
| 4057 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4130 | + spin_unlock(&ses->ses_lock); | |
| 4058 | 4131 | |
| 4059 | 4132 | if (!is_binding) { |
| 4060 | 4133 | ses->capabilities = server->capabilities; |
| @@ -4078,22 +4151,22 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, · 17 unmodified lines | ||
| 4078 | 4151 | |
| 4079 | 4152 | if (rc) { |
| 4080 | 4153 | cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc); |
| 4081 | − spin_lock(&cifs_tcp_ses_lock); | |
| 4154 | + spin_lock(&ses->ses_lock); | |
| 4082 | 4155 | if (ses->ses_status == SES_IN_SETUP) |
| 4083 | 4156 | ses->ses_status = SES_NEED_RECON; |
| 4084 | 4157 | spin_lock(&ses->chan_lock); |
| 4085 | 4158 | cifs_chan_clear_in_reconnect(ses, server); |
| 4086 | 4159 | spin_unlock(&ses->chan_lock); |
| 4087 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4160 | + spin_unlock(&ses->ses_lock); | |
| 4088 | 4161 | } else { |
| 4089 | − spin_lock(&cifs_tcp_ses_lock); | |
| 4162 | + spin_lock(&ses->ses_lock); | |
| 4090 | 4163 | if (ses->ses_status == SES_IN_SETUP) |
| 4091 | 4164 | ses->ses_status = SES_GOOD; |
| 4092 | 4165 | spin_lock(&ses->chan_lock); |
| 4093 | 4166 | cifs_chan_clear_in_reconnect(ses, server); |
| 4094 | 4167 | cifs_chan_clear_need_reconnect(ses, server); |
| 4095 | 4168 | spin_unlock(&ses->chan_lock); |
| 4096 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4169 | + spin_unlock(&ses->ses_lock); | |
| 4097 | 4170 | } |
| 4098 | 4171 | |
| 4099 | 4172 | return rc; |
| @@ -4167,8 +4240,10 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid) · 67 unmodified lines | ||
| 4167 | 4240 | goto out; |
| 4168 | 4241 | } |
| 4169 | 4242 | |
| 4243 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 4170 | 4244 | if (cap_unix(ses)) |
| 4171 | 4245 | reset_cifs_unix_caps(0, tcon, NULL, ctx); |
| 4246 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 4172 | 4247 | |
| 4173 | 4248 | out: |
| 4174 | 4249 | kfree(ctx->username); |
| @@ -4557,15 +4632,15 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru · 382 unmodified lines | ||
| 4557 | 4632 | struct dfs_info3_param ref = {0}; |
| 4558 | 4633 | |
| 4559 | 4634 | /* only send once per connect */ |
| 4560 | − spin_lock(&cifs_tcp_ses_lock); | |
| 4635 | + spin_lock(&tcon->tc_lock); | |
| 4561 | 4636 | if (tcon->ses->ses_status != SES_GOOD || |
| 4562 | 4637 | (tcon->status != TID_NEW && |
| 4563 | 4638 | tcon->status != TID_NEED_TCON)) { |
| 4564 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4639 | + spin_unlock(&tcon->tc_lock); | |
| 4565 | 4640 | return 0; |
| 4566 | 4641 | } |
| 4567 | 4642 | tcon->status = TID_IN_TCON; |
| 4568 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4643 | + spin_unlock(&tcon->tc_lock); | |
| 4569 | 4644 | |
| 4570 | 4645 | tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL); |
| 4571 | 4646 | if (!tree) { |
| @@ -4604,15 +4679,15 @@ out: · 32 unmodified lines | ||
| 4604 | 4679 | cifs_put_tcp_super(sb); |
| 4605 | 4680 | |
| 4606 | 4681 | if (rc) { |
| 4607 | − spin_lock(&cifs_tcp_ses_lock); | |
| 4682 | + spin_lock(&tcon->tc_lock); | |
| 4608 | 4683 | if (tcon->status == TID_IN_TCON) |
| 4609 | 4684 | tcon->status = TID_NEED_TCON; |
| 4610 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4685 | + spin_unlock(&tcon->tc_lock); | |
| 4611 | 4686 | } else { |
| 4612 | − spin_lock(&cifs_tcp_ses_lock); | |
| 4687 | + spin_lock(&tcon->tc_lock); | |
| 4613 | 4688 | if (tcon->status == TID_IN_TCON) |
| 4614 | 4689 | tcon->status = TID_GOOD; |
| 4615 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4690 | + spin_unlock(&tcon->tc_lock); | |
| 4616 | 4691 | tcon->need_reconnect = false; |
| 4617 | 4692 | } |
| 4618 | 4693 | |
| @@ -4625,28 +4700,28 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru · 6 unmodified lines | ||
| 4625 | 4700 | const struct smb_version_operations *ops = tcon->ses->server->ops; |
| 4626 | 4701 | |
| 4627 | 4702 | /* only send once per connect */ |
| 4628 | − spin_lock(&cifs_tcp_ses_lock); | |
| 4703 | + spin_lock(&tcon->tc_lock); | |
| 4629 | 4704 | if (tcon->ses->ses_status != SES_GOOD || |
| 4630 | 4705 | (tcon->status != TID_NEW && |
| 4631 | 4706 | tcon->status != TID_NEED_TCON)) { |
| 4632 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4707 | + spin_unlock(&tcon->tc_lock); | |
| 4633 | 4708 | return 0; |
| 4634 | 4709 | } |
| 4635 | 4710 | tcon->status = TID_IN_TCON; |
| 4636 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4711 | + spin_unlock(&tcon->tc_lock); | |
| 4637 | 4712 | |
| 4638 | 4713 | rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc); |
| 4639 | 4714 | if (rc) { |
| 4640 | − spin_lock(&cifs_tcp_ses_lock); | |
| 4715 | + spin_lock(&tcon->tc_lock); | |
| 4641 | 4716 | if (tcon->status == TID_IN_TCON) |
| 4642 | 4717 | tcon->status = TID_NEED_TCON; |
| 4643 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4718 | + spin_unlock(&tcon->tc_lock); | |
| 4644 | 4719 | } else { |
| 4645 | − spin_lock(&cifs_tcp_ses_lock); | |
| 4720 | + spin_lock(&tcon->tc_lock); | |
| 4646 | 4721 | if (tcon->status == TID_IN_TCON) |
| 4647 | 4722 | tcon->status = TID_GOOD; |
| 4648 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 4649 | 4723 | tcon->need_reconnect = false; |
| 4724 | + spin_unlock(&tcon->tc_lock); | |
| 4650 | 4725 | } |
| 4651 | 4726 | |
| 4652 | 4727 | return rc; |
| @@ -1526,15 +1526,21 @@ static void refresh_mounts(struct cifs_ses **sessions) · 1525 unmodified lines | ||
| 1526 | 1526 | |
| 1527 | 1527 | spin_lock(&cifs_tcp_ses_lock); |
| 1528 | 1528 | list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { |
| 1529 | − if (!server->is_dfs_conn) | |
| 1529 | + spin_lock(&server->srv_lock); | |
| 1530 | + if (!server->is_dfs_conn) { | |
| 1531 | + spin_unlock(&server->srv_lock); | |
| 1530 | 1532 | continue; |
| 1533 | + } | |
| 1534 | + spin_unlock(&server->srv_lock); | |
| 1531 | 1535 | |
| 1532 | 1536 | list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { |
| 1533 | 1537 | list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { |
| 1538 | + spin_lock(&tcon->tc_lock); | |
| 1534 | 1539 | if (!tcon->ipc && !tcon->need_reconnect) { |
| 1535 | 1540 | tcon->tc_count++; |
| 1536 | 1541 | list_add_tail(&tcon->ulist, &tcons); |
| 1537 | 1542 | } |
| 1543 | + spin_unlock(&tcon->tc_lock); | |
| 1538 | 1544 | } |
| 1539 | 1545 | } |
| 1540 | 1546 | } |
| @@ -193,6 +193,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, · 192 unmodified lines | ||
| 193 | 193 | return PTR_ERR(full_path); |
| 194 | 194 | } |
| 195 | 195 | |
| 196 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 196 | 197 | if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open && |
| 197 | 198 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
| 198 | 199 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
| @@ -261,6 +262,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, · 62 unmodified lines | ||
| 261 | 262 | * rare for path not covered on files) |
| 262 | 263 | */ |
| 263 | 264 | } |
| 265 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 264 | 266 | |
| 265 | 267 | desired_access = 0; |
| 266 | 268 | if (OPEN_FMODE(oflags) & FMODE_READ) |
| @@ -316,6 +318,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, · 49 unmodified lines | ||
| 316 | 318 | goto out; |
| 317 | 319 | } |
| 318 | 320 | |
| 321 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 319 | 322 | /* |
| 320 | 323 | * If Open reported that we actually created a file then we now have to |
| 321 | 324 | * set the mode if possible. |
| @@ -357,6 +360,9 @@ cifs_create_get_file_info: · 35 unmodified lines | ||
| 357 | 360 | rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb, |
| 358 | 361 | xid); |
| 359 | 362 | else { |
| 363 | +#else | |
| 364 | + { | |
| 365 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 360 | 366 | /* TODO: Add support for calling POSIX query info here, but passing in fid */ |
| 361 | 367 | rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb, |
| 362 | 368 | xid, fid); |
| @@ -377,7 +383,9 @@ cifs_create_get_file_info: · 14 unmodified lines | ||
| 377 | 383 | } |
| 378 | 384 | } |
| 379 | 385 | |
| 386 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 380 | 387 | cifs_create_set_dentry: |
| 388 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 381 | 389 | if (rc != 0) { |
| 382 | 390 | cifs_dbg(FYI, "Create worked, get_inode_info failed rc = %d\n", |
| 383 | 391 | rc); |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | #include "cifspdu.h" |
| 27 | 27 | #include "cifsglob.h" |
| 28 | 28 | #include "cifsproto.h" |
| 29 | +#include "smb2proto.h" | |
| 29 | 30 | #include "cifs_unicode.h" |
| 30 | 31 | #include "cifs_debug.h" |
| 31 | 32 | #include "cifs_fs_sb.h" |
| @@ -34,6 +35,53 @@ · 2 unmodified lines | ||
| 34 | 35 | #include "fs_context.h" |
| 35 | 36 | #include "cifs_ioctl.h" |
| 36 | 37 | |
| 38 | +/* | |
| 39 | + * Mark as invalid, all open files on tree connections since they | |
| 40 | + * were closed when session to server was lost. | |
| 41 | + */ | |
| 42 | +void | |
| 43 | +cifs_mark_open_files_invalid(struct cifs_tcon *tcon) | |
| 44 | +{ | |
| 45 | + struct cifsFileInfo *open_file = NULL; | |
| 46 | + struct list_head *tmp; | |
| 47 | + struct list_head *tmp1; | |
| 48 | + | |
| 49 | + /* only send once per connect */ | |
| 50 | + spin_lock(&tcon->ses->ses_lock); | |
| 51 | + if ((tcon->ses->ses_status != SES_GOOD) || (tcon->status != TID_NEED_RECON)) { | |
| 52 | + spin_unlock(&tcon->ses->ses_lock); | |
| 53 | + return; | |
| 54 | + } | |
| 55 | + tcon->status = TID_IN_FILES_INVALIDATE; | |
| 56 | + spin_unlock(&tcon->ses->ses_lock); | |
| 57 | + | |
| 58 | + /* list all files open on tree connection and mark them invalid */ | |
| 59 | + spin_lock(&tcon->open_file_lock); | |
| 60 | + list_for_each_safe(tmp, tmp1, &tcon->openFileList) { | |
| 61 | + open_file = list_entry(tmp, struct cifsFileInfo, tlist); | |
| 62 | + open_file->invalidHandle = true; | |
| 63 | + open_file->oplock_break_cancelled = true; | |
| 64 | + } | |
| 65 | + spin_unlock(&tcon->open_file_lock); | |
| 66 | + | |
| 67 | + mutex_lock(&tcon->crfid.fid_mutex); | |
| 68 | + tcon->crfid.is_valid = false; | |
| 69 | + /* cached handle is not valid, so SMB2_CLOSE won't be sent below */ | |
| 70 | + close_cached_dir_lease_locked(&tcon->crfid); | |
| 71 | + memset(tcon->crfid.fid, 0, sizeof(struct cifs_fid)); | |
| 72 | + mutex_unlock(&tcon->crfid.fid_mutex); | |
| 73 | + | |
| 74 | + spin_lock(&tcon->tc_lock); | |
| 75 | + if (tcon->status == TID_IN_FILES_INVALIDATE) | |
| 76 | + tcon->status = TID_NEED_TCON; | |
| 77 | + spin_unlock(&tcon->tc_lock); | |
| 78 | + | |
| 79 | + /* | |
| 80 | + * BB Add call to invalidate_inodes(sb) for all superblocks mounted | |
| 81 | + * to this tcon. | |
| 82 | + */ | |
| 83 | +} | |
| 84 | + | |
| 37 | 85 | static inline int cifs_convert_flags(unsigned int flags) |
| 38 | 86 | { |
| 39 | 87 | if ((flags & O_ACCMODE) == O_RDONLY) |
| @@ -52,6 +100,7 @@ static inline int cifs_convert_flags(unsigned int flags) · 12 unmodified lines | ||
| 52 | 100 | FILE_READ_DATA); |
| 53 | 101 | } |
| 54 | 102 | |
| 103 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 55 | 104 | static u32 cifs_posix_convert_flags(unsigned int flags) |
| 56 | 105 | { |
| 57 | 106 | u32 posix_flags = 0; |
| @@ -85,6 +134,7 @@ static u32 cifs_posix_convert_flags(unsigned int flags) · 27 unmodified lines | ||
| 85 | 134 | |
| 86 | 135 | return posix_flags; |
| 87 | 136 | } |
| 137 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 88 | 138 | |
| 89 | 139 | static inline int cifs_get_disposition(unsigned int flags) |
| 90 | 140 | { |
| @@ -100,6 +150,7 @@ static inline int cifs_get_disposition(unsigned int flags) · 9 unmodified lines | ||
| 100 | 150 | return FILE_OPEN; |
| 101 | 151 | } |
| 102 | 152 | |
| 153 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 103 | 154 | int cifs_posix_open(const char *full_path, struct inode **pinode, |
| 104 | 155 | struct super_block *sb, int mode, unsigned int f_flags, |
| 105 | 156 | __u32 *poplock, __u16 *pnetfid, unsigned int xid) |
| @@ -161,6 +212,7 @@ posix_open_ret: · 55 unmodified lines | ||
| 161 | 212 | kfree(presp_data); |
| 162 | 213 | return rc; |
| 163 | 214 | } |
| 215 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 164 | 216 | |
| 165 | 217 | static int |
| 166 | 218 | cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, |
| @@ -579,6 +631,7 @@ int cifs_open(struct inode *inode, struct file *file) · 412 unmodified lines | ||
| 579 | 631 | else |
| 580 | 632 | oplock = 0; |
| 581 | 633 | |
| 634 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 582 | 635 | if (!tcon->broken_posix_open && tcon->unix_ext && |
| 583 | 636 | cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
| 584 | 637 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
| @@ -603,6 +656,7 @@ int cifs_open(struct inode *inode, struct file *file) · 18 unmodified lines | ||
| 603 | 656 | * or DFS errors. |
| 604 | 657 | */ |
| 605 | 658 | } |
| 659 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 606 | 660 | |
| 607 | 661 | if (server->ops->get_lease_key) |
| 608 | 662 | server->ops->get_lease_key(inode, &fid); |
| @@ -630,6 +684,7 @@ int cifs_open(struct inode *inode, struct file *file) · 21 unmodified lines | ||
| 630 | 684 | goto out; |
| 631 | 685 | } |
| 632 | 686 | |
| 687 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 633 | 688 | if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) { |
| 634 | 689 | /* |
| 635 | 690 | * Time to set mode which we can not set earlier due to |
| @@ -647,6 +702,7 @@ int cifs_open(struct inode *inode, struct file *file) · 11 unmodified lines | ||
| 647 | 702 | CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid.netfid, |
| 648 | 703 | cfile->pid); |
| 649 | 704 | } |
| 705 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 650 | 706 | |
| 651 | 707 | use_cache: |
| 652 | 708 | fscache_use_cookie(cifs_inode_cookie(file_inode(file)), |
| @@ -664,7 +720,9 @@ out: · 11 unmodified lines | ||
| 664 | 720 | return rc; |
| 665 | 721 | } |
| 666 | 722 | |
| 723 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 667 | 724 | static int cifs_push_posix_locks(struct cifsFileInfo *cfile); |
| 725 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 668 | 726 | |
| 669 | 727 | /* |
| 670 | 728 | * Try to reacquire byte range locks that were released when session |
| @@ -673,10 +731,12 @@ static int cifs_push_posix_locks(struct cifsFileInfo *cfile); · 2 unmodified lines | ||
| 673 | 731 | static int |
| 674 | 732 | cifs_relock_file(struct cifsFileInfo *cfile) |
| 675 | 733 | { |
| 676 | − struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb); | |
| 677 | 734 | struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); |
| 678 | 735 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
| 679 | 736 | int rc = 0; |
| 737 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 738 | + struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb); | |
| 739 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 680 | 740 | |
| 681 | 741 | down_read_nested(&cinode->lock_sem, SINGLE_DEPTH_NESTING); |
| 682 | 742 | if (cinode->can_cache_brlcks) { |
| @@ -685,11 +745,13 @@ cifs_relock_file(struct cifsFileInfo *cfile) · 2 unmodified lines | ||
| 685 | 745 | return rc; |
| 686 | 746 | } |
| 687 | 747 | |
| 748 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 688 | 749 | if (cap_unix(tcon->ses) && |
| 689 | 750 | (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && |
| 690 | 751 | ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) |
| 691 | 752 | rc = cifs_push_posix_locks(cfile); |
| 692 | 753 | else |
| 754 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 693 | 755 | rc = tcon->ses->server->ops->push_mand_locks(cfile); |
| 694 | 756 | |
| 695 | 757 | up_read(&cinode->lock_sem); |
| @@ -750,6 +812,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) · 54 unmodified lines | ||
| 750 | 812 | else |
| 751 | 813 | oplock = 0; |
| 752 | 814 | |
| 815 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 753 | 816 | if (tcon->unix_ext && cap_unix(tcon->ses) && |
| 754 | 817 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
| 755 | 818 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
| @@ -773,6 +836,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) · 17 unmodified lines | ||
| 773 | 836 | * in the reconnect path it is important to retry hard |
| 774 | 837 | */ |
| 775 | 838 | } |
| 839 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 776 | 840 | |
| 777 | 841 | desired_access = cifs_convert_flags(cfile->f_flags); |
| 778 | 842 | |
| @@ -817,7 +881,9 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) · 38 unmodified lines | ||
| 817 | 881 | goto reopen_error_exit; |
| 818 | 882 | } |
| 819 | 883 | |
| 884 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 820 | 885 | reopen_success: |
| 886 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 821 | 887 | cfile->invalidHandle = false; |
| 822 | 888 | mutex_unlock(&cfile->fh_mutex); |
| 823 | 889 | cinode = CIFS_I(inode); |
| @@ -928,9 +994,7 @@ int cifs_close(struct inode *inode, struct file *file) · 104 unmodified lines | ||
| 928 | 994 | void |
| 929 | 995 | cifs_reopen_persistent_handles(struct cifs_tcon *tcon) |
| 930 | 996 | { |
| 931 | − struct cifsFileInfo *open_file; | |
| 932 | − struct list_head *tmp; | |
| 933 | − struct list_head *tmp1; | |
| 997 | + struct cifsFileInfo *open_file, *tmp; | |
| 934 | 998 | struct list_head tmp_list; |
| 935 | 999 | |
| 936 | 1000 | if (!tcon->use_persistent || !tcon->need_reopen_files) |
| @@ -943,8 +1007,7 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon) · 6 unmodified lines | ||
| 943 | 1007 | |
| 944 | 1008 | /* list all files open on tree connection, reopen resilient handles */ |
| 945 | 1009 | spin_lock(&tcon->open_file_lock); |
| 946 | − list_for_each(tmp, &tcon->openFileList) { | |
| 947 | − open_file = list_entry(tmp, struct cifsFileInfo, tlist); | |
| 1010 | + list_for_each_entry(open_file, &tcon->openFileList, tlist) { | |
| 948 | 1011 | if (!open_file->invalidHandle) |
| 949 | 1012 | continue; |
| 950 | 1013 | cifsFileInfo_get(open_file); |
| @@ -952,8 +1015,7 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon) · 1 unmodified line | ||
| 952 | 1015 | } |
| 953 | 1016 | spin_unlock(&tcon->open_file_lock); |
| 954 | 1017 | |
| 955 | − list_for_each_safe(tmp, tmp1, &tmp_list) { | |
| 956 | − open_file = list_entry(tmp, struct cifsFileInfo, rlist); | |
| 1018 | + list_for_each_entry_safe(open_file, tmp, &tmp_list, rlist) { | |
| 957 | 1019 | if (cifs_reopen_file(open_file, false /* do not flush */)) |
| 958 | 1020 | tcon->need_reopen_files = true; |
| 959 | 1021 | list_del_init(&open_file->rlist); |
| @@ -1196,6 +1258,7 @@ try_again: · 236 unmodified lines | ||
| 1196 | 1258 | return rc; |
| 1197 | 1259 | } |
| 1198 | 1260 | |
| 1261 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1199 | 1262 | /* |
| 1200 | 1263 | * Check if there is another lock that prevents us to set the lock (posix |
| 1201 | 1264 | * style). If such a lock exists, update the flock structure with its |
| @@ -1334,6 +1397,7 @@ hash_lockowner(fl_owner_t owner) · 132 unmodified lines | ||
| 1334 | 1397 | { |
| 1335 | 1398 | return cifs_lock_secret ^ hash32_ptr((const void *)owner); |
| 1336 | 1399 | } |
| 1400 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1337 | 1401 | |
| 1338 | 1402 | struct lock_to_push { |
| 1339 | 1403 | struct list_head llist; |
| @@ -1344,6 +1408,7 @@ struct lock_to_push { · 4 unmodified lines | ||
| 1344 | 1408 | __u8 type; |
| 1345 | 1409 | }; |
| 1346 | 1410 | |
| 1411 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1347 | 1412 | static int |
| 1348 | 1413 | cifs_push_posix_locks(struct cifsFileInfo *cfile) |
| 1349 | 1414 | { |
| @@ -1431,14 +1496,17 @@ err_out: · 81 unmodified lines | ||
| 1431 | 1496 | } |
| 1432 | 1497 | goto out; |
| 1433 | 1498 | } |
| 1499 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1434 | 1500 | |
| 1435 | 1501 | static int |
| 1436 | 1502 | cifs_push_locks(struct cifsFileInfo *cfile) |
| 1437 | 1503 | { |
| 1438 | − struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb); | |
| 1439 | 1504 | struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); |
| 1440 | 1505 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
| 1441 | 1506 | int rc = 0; |
| 1507 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1508 | + struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb); | |
| 1509 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1442 | 1510 | |
| 1443 | 1511 | /* we are going to update can_cache_brlcks here - need a write access */ |
| 1444 | 1512 | cifs_down_write(&cinode->lock_sem); |
| @@ -1447,11 +1515,13 @@ cifs_push_locks(struct cifsFileInfo *cfile) · 2 unmodified lines | ||
| 1447 | 1515 | return rc; |
| 1448 | 1516 | } |
| 1449 | 1517 | |
| 1518 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1450 | 1519 | if (cap_unix(tcon->ses) && |
| 1451 | 1520 | (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && |
| 1452 | 1521 | ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) |
| 1453 | 1522 | rc = cifs_push_posix_locks(cfile); |
| 1454 | 1523 | else |
| 1524 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1455 | 1525 | rc = tcon->ses->server->ops->push_mand_locks(cfile); |
| 1456 | 1526 | |
| 1457 | 1527 | cinode->can_cache_brlcks = false; |
| @@ -1515,6 +1585,7 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type, · 57 unmodified lines | ||
| 1515 | 1585 | struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; |
| 1516 | 1586 | struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); |
| 1517 | 1587 | struct TCP_Server_Info *server = tcon->ses->server; |
| 1588 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1518 | 1589 | __u16 netfid = cfile->fid.netfid; |
| 1519 | 1590 | |
| 1520 | 1591 | if (posix_lck) { |
| @@ -1534,6 +1605,7 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type, · 13 unmodified lines | ||
| 1534 | 1605 | posix_lock_type, wait_flag); |
| 1535 | 1606 | return rc; |
| 1536 | 1607 | } |
| 1608 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1537 | 1609 | |
| 1538 | 1610 | rc = cifs_lock_test(cfile, flock->fl_start, length, type, flock); |
| 1539 | 1611 | if (!rc) |
| @@ -1594,6 +1666,7 @@ cifs_free_llist(struct list_head *llist) · 54 unmodified lines | ||
| 1594 | 1666 | } |
| 1595 | 1667 | } |
| 1596 | 1668 | |
| 1669 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1597 | 1670 | int |
| 1598 | 1671 | cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, |
| 1599 | 1672 | unsigned int xid) |
| @@ -1706,6 +1779,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, · 106 unmodified lines | ||
| 1706 | 1779 | kfree(buf); |
| 1707 | 1780 | return rc; |
| 1708 | 1781 | } |
| 1782 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1709 | 1783 | |
| 1710 | 1784 | static int |
| 1711 | 1785 | cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, |
| @@ -1719,6 +1793,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, · 7 unmodified lines | ||
| 1719 | 1793 | struct TCP_Server_Info *server = tcon->ses->server; |
| 1720 | 1794 | struct inode *inode = d_inode(cfile->dentry); |
| 1721 | 1795 | |
| 1796 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1722 | 1797 | if (posix_lck) { |
| 1723 | 1798 | int posix_lock_type; |
| 1724 | 1799 | |
| @@ -1740,7 +1815,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, · 15 unmodified lines | ||
| 1740 | 1815 | NULL, posix_lock_type, wait_flag); |
| 1741 | 1816 | goto out; |
| 1742 | 1817 | } |
| 1743 | − | |
| 1818 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1744 | 1819 | if (lock) { |
| 1745 | 1820 | struct cifsLockInfo *lock; |
| 1746 | 1821 | |
| @@ -2204,6 +2279,185 @@ cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, · 457 unmodified lines | ||
| 2204 | 2279 | return -ENOENT; |
| 2205 | 2280 | } |
| 2206 | 2281 | |
| 2282 | +void | |
| 2283 | +cifs_writedata_release(struct kref *refcount) | |
| 2284 | +{ | |
| 2285 | + struct cifs_writedata *wdata = container_of(refcount, | |
| 2286 | + struct cifs_writedata, refcount); | |
| 2287 | +#ifdef CONFIG_CIFS_SMB_DIRECT | |
| 2288 | + if (wdata->mr) { | |
| 2289 | + smbd_deregister_mr(wdata->mr); | |
| 2290 | + wdata->mr = NULL; | |
| 2291 | + } | |
| 2292 | +#endif | |
| 2293 | + | |
| 2294 | + if (wdata->cfile) | |
| 2295 | + cifsFileInfo_put(wdata->cfile); | |
| 2296 | + | |
| 2297 | + kvfree(wdata->pages); | |
| 2298 | + kfree(wdata); | |
| 2299 | +} | |
| 2300 | + | |
| 2301 | +/* | |
| 2302 | + * Write failed with a retryable error. Resend the write request. It's also | |
| 2303 | + * possible that the page was redirtied so re-clean the page. | |
| 2304 | + */ | |
| 2305 | +static void | |
| 2306 | +cifs_writev_requeue(struct cifs_writedata *wdata) | |
| 2307 | +{ | |
| 2308 | + int i, rc = 0; | |
| 2309 | + struct inode *inode = d_inode(wdata->cfile->dentry); | |
| 2310 | + struct TCP_Server_Info *server; | |
| 2311 | + unsigned int rest_len; | |
| 2312 | + | |
| 2313 | + server = tlink_tcon(wdata->cfile->tlink)->ses->server; | |
| 2314 | + i = 0; | |
| 2315 | + rest_len = wdata->bytes; | |
| 2316 | + do { | |
| 2317 | + struct cifs_writedata *wdata2; | |
| 2318 | + unsigned int j, nr_pages, wsize, tailsz, cur_len; | |
| 2319 | + | |
| 2320 | + wsize = server->ops->wp_retry_size(inode); | |
| 2321 | + if (wsize < rest_len) { | |
| 2322 | + nr_pages = wsize / PAGE_SIZE; | |
| 2323 | + if (!nr_pages) { | |
| 2324 | + rc = -EOPNOTSUPP; | |
| 2325 | + break; | |
| 2326 | + } | |
| 2327 | + cur_len = nr_pages * PAGE_SIZE; | |
| 2328 | + tailsz = PAGE_SIZE; | |
| 2329 | + } else { | |
| 2330 | + nr_pages = DIV_ROUND_UP(rest_len, PAGE_SIZE); | |
| 2331 | + cur_len = rest_len; | |
| 2332 | + tailsz = rest_len - (nr_pages - 1) * PAGE_SIZE; | |
| 2333 | + } | |
| 2334 | + | |
| 2335 | + wdata2 = cifs_writedata_alloc(nr_pages, cifs_writev_complete); | |
| 2336 | + if (!wdata2) { | |
| 2337 | + rc = -ENOMEM; | |
| 2338 | + break; | |
| 2339 | + } | |
| 2340 | + | |
| 2341 | + for (j = 0; j < nr_pages; j++) { | |
| 2342 | + wdata2->pages[j] = wdata->pages[i + j]; | |
| 2343 | + lock_page(wdata2->pages[j]); | |
| 2344 | + clear_page_dirty_for_io(wdata2->pages[j]); | |
| 2345 | + } | |
| 2346 | + | |
| 2347 | + wdata2->sync_mode = wdata->sync_mode; | |
| 2348 | + wdata2->nr_pages = nr_pages; | |
| 2349 | + wdata2->offset = page_offset(wdata2->pages[0]); | |
| 2350 | + wdata2->pagesz = PAGE_SIZE; | |
| 2351 | + wdata2->tailsz = tailsz; | |
| 2352 | + wdata2->bytes = cur_len; | |
| 2353 | + | |
| 2354 | + rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, | |
| 2355 | + &wdata2->cfile); | |
| 2356 | + if (!wdata2->cfile) { | |
| 2357 | + cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n", | |
| 2358 | + rc); | |
| 2359 | + if (!is_retryable_error(rc)) | |
| 2360 | + rc = -EBADF; | |
| 2361 | + } else { | |
| 2362 | + wdata2->pid = wdata2->cfile->pid; | |
| 2363 | + rc = server->ops->async_writev(wdata2, | |
| 2364 | + cifs_writedata_release); | |
| 2365 | + } | |
| 2366 | + | |
| 2367 | + for (j = 0; j < nr_pages; j++) { | |
| 2368 | + unlock_page(wdata2->pages[j]); | |
| 2369 | + if (rc != 0 && !is_retryable_error(rc)) { | |
| 2370 | + SetPageError(wdata2->pages[j]); | |
| 2371 | + end_page_writeback(wdata2->pages[j]); | |
| 2372 | + put_page(wdata2->pages[j]); | |
| 2373 | + } | |
| 2374 | + } | |
| 2375 | + | |
| 2376 | + kref_put(&wdata2->refcount, cifs_writedata_release); | |
| 2377 | + if (rc) { | |
| 2378 | + if (is_retryable_error(rc)) | |
| 2379 | + continue; | |
| 2380 | + i += nr_pages; | |
| 2381 | + break; | |
| 2382 | + } | |
| 2383 | + | |
| 2384 | + rest_len -= cur_len; | |
| 2385 | + i += nr_pages; | |
| 2386 | + } while (i < wdata->nr_pages); | |
| 2387 | + | |
| 2388 | + /* cleanup remaining pages from the original wdata */ | |
| 2389 | + for (; i < wdata->nr_pages; i++) { | |
| 2390 | + SetPageError(wdata->pages[i]); | |
| 2391 | + end_page_writeback(wdata->pages[i]); | |
| 2392 | + put_page(wdata->pages[i]); | |
| 2393 | + } | |
| 2394 | + | |
| 2395 | + if (rc != 0 && !is_retryable_error(rc)) | |
| 2396 | + mapping_set_error(inode->i_mapping, rc); | |
| 2397 | + kref_put(&wdata->refcount, cifs_writedata_release); | |
| 2398 | +} | |
| 2399 | + | |
| 2400 | +void | |
| 2401 | +cifs_writev_complete(struct work_struct *work) | |
| 2402 | +{ | |
| 2403 | + struct cifs_writedata *wdata = container_of(work, | |
| 2404 | + struct cifs_writedata, work); | |
| 2405 | + struct inode *inode = d_inode(wdata->cfile->dentry); | |
| 2406 | + int i = 0; | |
| 2407 | + | |
| 2408 | + if (wdata->result == 0) { | |
| 2409 | + spin_lock(&inode->i_lock); | |
| 2410 | + cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes); | |
| 2411 | + spin_unlock(&inode->i_lock); | |
| 2412 | + cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink), | |
| 2413 | + wdata->bytes); | |
| 2414 | + } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN) | |
| 2415 | + return cifs_writev_requeue(wdata); | |
| 2416 | + | |
| 2417 | + for (i = 0; i < wdata->nr_pages; i++) { | |
| 2418 | + struct page *page = wdata->pages[i]; | |
| 2419 | + | |
| 2420 | + if (wdata->result == -EAGAIN) | |
| 2421 | + __set_page_dirty_nobuffers(page); | |
| 2422 | + else if (wdata->result < 0) | |
| 2423 | + SetPageError(page); | |
| 2424 | + end_page_writeback(page); | |
| 2425 | + cifs_readpage_to_fscache(inode, page); | |
| 2426 | + put_page(page); | |
| 2427 | + } | |
| 2428 | + if (wdata->result != -EAGAIN) | |
| 2429 | + mapping_set_error(inode->i_mapping, wdata->result); | |
| 2430 | + kref_put(&wdata->refcount, cifs_writedata_release); | |
| 2431 | +} | |
| 2432 | + | |
| 2433 | +struct cifs_writedata * | |
| 2434 | +cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete) | |
| 2435 | +{ | |
| 2436 | + struct page **pages = | |
| 2437 | + kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS); | |
| 2438 | + if (pages) | |
| 2439 | + return cifs_writedata_direct_alloc(pages, complete); | |
| 2440 | + | |
| 2441 | + return NULL; | |
| 2442 | +} | |
| 2443 | + | |
| 2444 | +struct cifs_writedata * | |
| 2445 | +cifs_writedata_direct_alloc(struct page **pages, work_func_t complete) | |
| 2446 | +{ | |
| 2447 | + struct cifs_writedata *wdata; | |
| 2448 | + | |
| 2449 | + wdata = kzalloc(sizeof(*wdata), GFP_NOFS); | |
| 2450 | + if (wdata != NULL) { | |
| 2451 | + wdata->pages = pages; | |
| 2452 | + kref_init(&wdata->refcount); | |
| 2453 | + INIT_LIST_HEAD(&wdata->list); | |
| 2454 | + init_completion(&wdata->done); | |
| 2455 | + INIT_WORK(&wdata->work, complete); | |
| 2456 | + } | |
| 2457 | + return wdata; | |
| 2458 | +} | |
| 2459 | + | |
| 2460 | + | |
| 2207 | 2461 | static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) |
| 2208 | 2462 | { |
| 2209 | 2463 | struct address_space *mapping = page->mapping; |
| @@ -4459,10 +4713,11 @@ static void cifs_readahead(struct readahead_control *ractl) · 2249 unmodified lines | ||
| 4459 | 4713 | * TODO: Send a whole batch of pages to be read |
| 4460 | 4714 | * by the cache. |
| 4461 | 4715 | */ |
| 4462 | − page = readahead_page(ractl); | |
| 4463 | − last_batch_size = 1 << thp_order(page); | |
| 4716 | + struct folio *folio = readahead_folio(ractl); | |
| 4717 | + | |
| 4718 | + last_batch_size = folio_nr_pages(folio); | |
| 4464 | 4719 | if (cifs_readpage_from_fscache(ractl->mapping->host, |
| 4465 | − page) < 0) { | |
| 4720 | + &folio->page) < 0) { | |
| 4466 | 4721 | /* |
| 4467 | 4722 | * TODO: Deal with cache read failure |
| 4468 | 4723 | * here, but for the moment, delegate |
| @@ -4470,7 +4725,7 @@ static void cifs_readahead(struct readahead_control *ractl) · 1 unmodified line | ||
| 4470 | 4725 | */ |
| 4471 | 4726 | caching = false; |
| 4472 | 4727 | } |
| 4473 | − unlock_page(page); | |
| 4728 | + folio_unlock(folio); | |
| 4474 | 4729 | next_cached++; |
| 4475 | 4730 | cache_nr_pages--; |
| 4476 | 4731 | if (cache_nr_pages == 0) |
| @@ -339,6 +339,7 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) · 338 unmodified lines | ||
| 339 | 339 | fattr->cf_flags = CIFS_FATTR_DFS_REFERRAL; |
| 340 | 340 | } |
| 341 | 341 | |
| 342 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 342 | 343 | static int |
| 343 | 344 | cifs_get_file_info_unix(struct file *filp) |
| 344 | 345 | { |
| @@ -432,6 +433,14 @@ int cifs_get_inode_info_unix(struct inode **pinode, · 87 unmodified lines | ||
| 432 | 433 | cgiiu_exit: |
| 433 | 434 | return rc; |
| 434 | 435 | } |
| 436 | +#else | |
| 437 | +int cifs_get_inode_info_unix(struct inode **pinode, | |
| 438 | + const unsigned char *full_path, | |
| 439 | + struct super_block *sb, unsigned int xid) | |
| 440 | +{ | |
| 441 | + return -EOPNOTSUPP; | |
| 442 | +} | |
| 443 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 435 | 444 | |
| 436 | 445 | static int |
| 437 | 446 | cifs_sfu_type(struct cifs_fattr *fattr, const char *path, |
| @@ -795,6 +804,7 @@ static __u64 simple_hashstr(const char *str) · 357 unmodified lines | ||
| 795 | 804 | return hash; |
| 796 | 805 | } |
| 797 | 806 | |
| 807 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 798 | 808 | /** |
| 799 | 809 | * cifs_backup_query_path_info - SMB1 fallback code to get ino |
| 800 | 810 | * |
| @@ -847,6 +857,7 @@ cifs_backup_query_path_info(int xid, · 46 unmodified lines | ||
| 847 | 857 | *data = (FILE_ALL_INFO *)info.srch_entries_start; |
| 848 | 858 | return 0; |
| 849 | 859 | } |
| 860 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 850 | 861 | |
| 851 | 862 | static void |
| 852 | 863 | cifs_set_fattr_ino(int xid, |
| @@ -991,6 +1002,7 @@ cifs_get_inode_info(struct inode **inode, · 138 unmodified lines | ||
| 991 | 1002 | rc = 0; |
| 992 | 1003 | break; |
| 993 | 1004 | case -EACCES: |
| 1005 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 994 | 1006 | /* |
| 995 | 1007 | * perm errors, try again with backup flags if possible |
| 996 | 1008 | * |
| @@ -1022,6 +1034,9 @@ cifs_get_inode_info(struct inode **inode, · 25 unmodified lines | ||
| 1022 | 1034 | /* nothing we can do, bail out */ |
| 1023 | 1035 | goto out; |
| 1024 | 1036 | } |
| 1037 | +#else | |
| 1038 | + goto out; | |
| 1039 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1025 | 1040 | break; |
| 1026 | 1041 | default: |
| 1027 | 1042 | cifs_dbg(FYI, "%s: unhandled err rc %d\n", __func__, rc); |
| @@ -1037,8 +1052,9 @@ cifs_get_inode_info(struct inode **inode, · 9 unmodified lines | ||
| 1037 | 1052 | /* |
| 1038 | 1053 | * 4. Tweak fattr based on mount options |
| 1039 | 1054 | */ |
| 1040 | − | |
| 1055 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1041 | 1056 | handle_mnt_opt: |
| 1057 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1042 | 1058 | /* query for SFU type info if supported and needed */ |
| 1043 | 1059 | if (fattr.cf_cifsattrs & ATTR_SYSTEM && |
| 1044 | 1060 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
| @@ -1223,7 +1239,7 @@ static const struct inode_operations cifs_ipc_inode_ops = { · 178 unmodified lines | ||
| 1223 | 1239 | static int |
| 1224 | 1240 | cifs_find_inode(struct inode *inode, void *opaque) |
| 1225 | 1241 | { |
| 1226 | − struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | |
| 1242 | + struct cifs_fattr *fattr = opaque; | |
| 1227 | 1243 | |
| 1228 | 1244 | /* don't match inode with different uniqueid */ |
| 1229 | 1245 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) |
| @@ -1247,7 +1263,7 @@ cifs_find_inode(struct inode *inode, void *opaque) · 17 unmodified lines | ||
| 1247 | 1263 | static int |
| 1248 | 1264 | cifs_init_inode(struct inode *inode, void *opaque) |
| 1249 | 1265 | { |
| 1250 | − struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | |
| 1266 | + struct cifs_fattr *fattr = opaque; | |
| 1251 | 1267 | |
| 1252 | 1268 | CIFS_I(inode)->uniqueid = fattr->cf_uniqueid; |
| 1253 | 1269 | CIFS_I(inode)->createtime = fattr->cf_createtime; |
| @@ -1435,6 +1451,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid, · 181 unmodified lines | ||
| 1435 | 1451 | return server->ops->set_file_info(inode, full_path, &info_buf, xid); |
| 1436 | 1452 | } |
| 1437 | 1453 | |
| 1454 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1438 | 1455 | /* |
| 1439 | 1456 | * Open the given file (if it isn't already), set the DELETE_ON_CLOSE bit |
| 1440 | 1457 | * and rename it to a random name that hopefully won't conflict with |
| @@ -1565,6 +1582,7 @@ undo_setattr: · 124 unmodified lines | ||
| 1565 | 1582 | |
| 1566 | 1583 | goto out_close; |
| 1567 | 1584 | } |
| 1585 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1568 | 1586 | |
| 1569 | 1587 | /* copied from fs/nfs/dir.c with small changes */ |
| 1570 | 1588 | static void |
| @@ -1627,6 +1645,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) · 56 unmodified lines | ||
| 1627 | 1645 | } |
| 1628 | 1646 | |
| 1629 | 1647 | cifs_close_deferred_file_under_dentry(tcon, full_path); |
| 1648 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1630 | 1649 | if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
| 1631 | 1650 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
| 1632 | 1651 | rc = CIFSPOSIXDelFile(xid, tcon, full_path, |
| @@ -1636,6 +1655,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) · 3 unmodified lines | ||
| 1636 | 1655 | if ((rc == 0) || (rc == -ENOENT)) |
| 1637 | 1656 | goto psx_del_no_retry; |
| 1638 | 1657 | } |
| 1658 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1639 | 1659 | |
| 1640 | 1660 | retry_std_delete: |
| 1641 | 1661 | if (!server->ops->unlink) { |
| @@ -1714,9 +1734,11 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, · 72 unmodified lines | ||
| 1714 | 1734 | |
| 1715 | 1735 | if (tcon->posix_extensions) |
| 1716 | 1736 | rc = smb311_posix_get_inode_info(&inode, full_path, parent->i_sb, xid); |
| 1737 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1717 | 1738 | else if (tcon->unix_ext) |
| 1718 | 1739 | rc = cifs_get_inode_info_unix(&inode, full_path, parent->i_sb, |
| 1719 | 1740 | xid); |
| 1741 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1720 | 1742 | else |
| 1721 | 1743 | rc = cifs_get_inode_info(&inode, full_path, NULL, parent->i_sb, |
| 1722 | 1744 | xid, NULL); |
| @@ -1746,6 +1768,7 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, · 23 unmodified lines | ||
| 1746 | 1768 | if (parent->i_mode & S_ISGID) |
| 1747 | 1769 | mode |= S_ISGID; |
| 1748 | 1770 | |
| 1771 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1749 | 1772 | if (tcon->unix_ext) { |
| 1750 | 1773 | struct cifs_unix_set_info_args args = { |
| 1751 | 1774 | .mode = mode, |
| @@ -1768,6 +1791,9 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, · 16 unmodified lines | ||
| 1768 | 1791 | cifs_sb->local_nls, |
| 1769 | 1792 | cifs_remap(cifs_sb)); |
| 1770 | 1793 | } else { |
| 1794 | +#else | |
| 1795 | + { | |
| 1796 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1771 | 1797 | struct TCP_Server_Info *server = tcon->ses->server; |
| 1772 | 1798 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && |
| 1773 | 1799 | (mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo) |
| @@ -1788,6 +1814,7 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, · 14 unmodified lines | ||
| 1788 | 1814 | return 0; |
| 1789 | 1815 | } |
| 1790 | 1816 | |
| 1817 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1791 | 1818 | static int |
| 1792 | 1819 | cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode, |
| 1793 | 1820 | const char *full_path, struct cifs_sb_info *cifs_sb, |
| @@ -1850,6 +1877,7 @@ posix_mkdir_get_info: · 56 unmodified lines | ||
| 1850 | 1877 | xid); |
| 1851 | 1878 | goto posix_mkdir_out; |
| 1852 | 1879 | } |
| 1880 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1853 | 1881 | |
| 1854 | 1882 | int cifs_mkdir(struct user_namespace *mnt_userns, struct inode *inode, |
| 1855 | 1883 | struct dentry *direntry, umode_t mode) |
| @@ -1892,6 +1920,7 @@ int cifs_mkdir(struct user_namespace *mnt_userns, struct inode *inode, · 36 unmodified lines | ||
| 1892 | 1920 | goto mkdir_out; |
| 1893 | 1921 | } |
| 1894 | 1922 | |
| 1923 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1895 | 1924 | if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
| 1896 | 1925 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
| 1897 | 1926 | rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb, |
| @@ -1899,6 +1928,7 @@ int cifs_mkdir(struct user_namespace *mnt_userns, struct inode *inode, · 1 unmodified line | ||
| 1899 | 1928 | if (rc != -EOPNOTSUPP) |
| 1900 | 1929 | goto mkdir_out; |
| 1901 | 1930 | } |
| 1931 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 1902 | 1932 | |
| 1903 | 1933 | if (!server->ops->mkdir) { |
| 1904 | 1934 | rc = -ENOSYS; |
| @@ -2015,9 +2045,12 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, · 110 unmodified lines | ||
| 2015 | 2045 | struct tcon_link *tlink; |
| 2016 | 2046 | struct cifs_tcon *tcon; |
| 2017 | 2047 | struct TCP_Server_Info *server; |
| 2048 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 2018 | 2049 | struct cifs_fid fid; |
| 2019 | 2050 | struct cifs_open_parms oparms; |
| 2020 | − int oplock, rc; | |
| 2051 | + int oplock; | |
| 2052 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 2053 | + int rc; | |
| 2021 | 2054 | |
| 2022 | 2055 | tlink = cifs_sb_tlink(cifs_sb); |
| 2023 | 2056 | if (IS_ERR(tlink)) |
| @@ -2043,6 +2076,7 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, · 19 unmodified lines | ||
| 2043 | 2076 | if (server->vals->protocol_id != 0) |
| 2044 | 2077 | goto do_rename_exit; |
| 2045 | 2078 | |
| 2079 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 2046 | 2080 | /* open-file renames don't work across directories */ |
| 2047 | 2081 | if (to_dentry->d_parent != from_dentry->d_parent) |
| 2048 | 2082 | goto do_rename_exit; |
| @@ -2064,6 +2098,7 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, · 15 unmodified lines | ||
| 2064 | 2098 | cifs_sb->local_nls, cifs_remap(cifs_sb)); |
| 2065 | 2099 | CIFSSMBClose(xid, tcon, fid.netfid); |
| 2066 | 2100 | } |
| 2101 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 2067 | 2102 | do_rename_exit: |
| 2068 | 2103 | if (rc == 0) |
| 2069 | 2104 | d_move(from_dentry, to_dentry); |
| @@ -2081,11 +2116,13 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir, · 11 unmodified lines | ||
| 2081 | 2116 | struct cifs_sb_info *cifs_sb; |
| 2082 | 2117 | struct tcon_link *tlink; |
| 2083 | 2118 | struct cifs_tcon *tcon; |
| 2084 | − FILE_UNIX_BASIC_INFO *info_buf_source = NULL; | |
| 2085 | − FILE_UNIX_BASIC_INFO *info_buf_target; | |
| 2086 | 2119 | unsigned int xid; |
| 2087 | 2120 | int rc, tmprc; |
| 2088 | 2121 | int retry_count = 0; |
| 2122 | + FILE_UNIX_BASIC_INFO *info_buf_source = NULL; | |
| 2123 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 2124 | + FILE_UNIX_BASIC_INFO *info_buf_target; | |
| 2125 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 2089 | 2126 | |
| 2090 | 2127 | if (flags & ~RENAME_NOREPLACE) |
| 2091 | 2128 | return -EINVAL; |
| @@ -2139,6 +2176,7 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir, · 47 unmodified lines | ||
| 2139 | 2176 | if (flags & RENAME_NOREPLACE) |
| 2140 | 2177 | goto cifs_rename_exit; |
| 2141 | 2178 | |
| 2179 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 2142 | 2180 | if (rc == -EEXIST && tcon->unix_ext) { |
| 2143 | 2181 | /* |
| 2144 | 2182 | * Are src and dst hardlinks of same inode? We can only tell |
| @@ -2178,6 +2216,8 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir, · 33 unmodified lines | ||
| 2178 | 2216 | */ |
| 2179 | 2217 | |
| 2180 | 2218 | unlink_target: |
| 2219 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 2220 | + | |
| 2181 | 2221 | /* Try unlinking the target dentry if it's not negative */ |
| 2182 | 2222 | if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) { |
| 2183 | 2223 | if (d_is_dir(target_dentry)) |
| @@ -2337,14 +2377,18 @@ int cifs_revalidate_file_attr(struct file *filp) · 153 unmodified lines | ||
| 2337 | 2377 | { |
| 2338 | 2378 | int rc = 0; |
| 2339 | 2379 | struct dentry *dentry = file_dentry(filp); |
| 2380 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 2340 | 2381 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; |
| 2382 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 2341 | 2383 | |
| 2342 | 2384 | if (!cifs_dentry_needs_reval(dentry)) |
| 2343 | 2385 | return rc; |
| 2344 | 2386 | |
| 2387 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 2345 | 2388 | if (tlink_tcon(cfile->tlink)->unix_ext) |
| 2346 | 2389 | rc = cifs_get_file_info_unix(filp); |
| 2347 | 2390 | else |
| 2391 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 2348 | 2392 | rc = cifs_get_file_info(filp); |
| 2349 | 2393 | |
| 2350 | 2394 | return rc; |
| @@ -2653,6 +2697,7 @@ set_size_out: · 302 unmodified lines | ||
| 2653 | 2697 | return rc; |
| 2654 | 2698 | } |
| 2655 | 2699 | |
| 2700 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 2656 | 2701 | static int |
| 2657 | 2702 | cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) |
| 2658 | 2703 | { |
| @@ -2800,6 +2845,7 @@ out: · 141 unmodified lines | ||
| 2800 | 2845 | free_xid(xid); |
| 2801 | 2846 | return rc; |
| 2802 | 2847 | } |
| 2848 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 2803 | 2849 | |
| 2804 | 2850 | static int |
| 2805 | 2851 | cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) |
| @@ -2995,16 +3041,20 @@ cifs_setattr(struct user_namespace *mnt_userns, struct dentry *direntry, · 189 unmodified lines | ||
| 2995 | 3041 | struct iattr *attrs) |
| 2996 | 3042 | { |
| 2997 | 3043 | struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); |
| 2998 | − struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb); | |
| 2999 | 3044 | int rc, retries = 0; |
| 3045 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 3046 | + struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb); | |
| 3047 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 3000 | 3048 | |
| 3001 | 3049 | if (unlikely(cifs_forced_shutdown(cifs_sb))) |
| 3002 | 3050 | return -EIO; |
| 3003 | 3051 | |
| 3004 | 3052 | do { |
| 3053 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 3005 | 3054 | if (pTcon->unix_ext) |
| 3006 | 3055 | rc = cifs_setattr_unix(direntry, attrs); |
| 3007 | 3056 | else |
| 3057 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 3008 | 3058 | rc = cifs_setattr_nounix(direntry, attrs); |
| 3009 | 3059 | retries++; |
| 3010 | 3060 | } while (is_retryable_error(rc) && retries < 2); |
| @@ -333,6 +333,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) · 332 unmodified lines | ||
| 333 | 333 | tcon = tlink_tcon(pSMBFile->tlink); |
| 334 | 334 | caps = le64_to_cpu(tcon->fsUnixInfo.Capability); |
| 335 | 335 | #ifdef CONFIG_CIFS_POSIX |
| 336 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 336 | 337 | if (CIFS_UNIX_EXTATTR_CAP & caps) { |
| 337 | 338 | __u64 ExtAttrMask = 0; |
| 338 | 339 | rc = CIFSGetExtAttr(xid, tcon, |
| @@ -345,6 +346,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) · 6 unmodified lines | ||
| 345 | 346 | if (rc != EOPNOTSUPP) |
| 346 | 347 | break; |
| 347 | 348 | } |
| 349 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 348 | 350 | #endif /* CONFIG_CIFS_POSIX */ |
| 349 | 351 | rc = 0; |
| 350 | 352 | if (CIFS_I(inode)->cifsAttrs & ATTR_COMPRESSED) { |
| @@ -286,6 +286,7 @@ out: · 285 unmodified lines | ||
| 286 | 286 | return rc; |
| 287 | 287 | } |
| 288 | 288 | |
| 289 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 289 | 290 | /* |
| 290 | 291 | * SMB 1.0 Protocol specific functions |
| 291 | 292 | */ |
| @@ -368,6 +369,7 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, · 76 unmodified lines | ||
| 368 | 369 | CIFSSMBClose(xid, tcon, fid.netfid); |
| 369 | 370 | return rc; |
| 370 | 371 | } |
| 372 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 371 | 373 | |
| 372 | 374 | /* |
| 373 | 375 | * SMB 2.1/SMB3 Protocol specific functions |
| @@ -532,11 +534,15 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, · 158 unmodified lines | ||
| 532 | 534 | goto cifs_hl_exit; |
| 533 | 535 | } |
| 534 | 536 | |
| 537 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 535 | 538 | if (tcon->unix_ext) |
| 536 | 539 | rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name, |
| 537 | 540 | cifs_sb->local_nls, |
| 538 | 541 | cifs_remap(cifs_sb)); |
| 539 | 542 | else { |
| 543 | +#else | |
| 544 | + { | |
| 545 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 540 | 546 | server = tcon->ses->server; |
| 541 | 547 | if (!server->ops->create_hardlink) { |
| 542 | 548 | rc = -ENOSYS; |
| @@ -704,10 +710,12 @@ cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode, · 161 unmodified lines | ||
| 704 | 710 | /* BB what if DFS and this volume is on different share? BB */ |
| 705 | 711 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) |
| 706 | 712 | rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname); |
| 713 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 707 | 714 | else if (pTcon->unix_ext) |
| 708 | 715 | rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, |
| 709 | 716 | cifs_sb->local_nls, |
| 710 | 717 | cifs_remap(cifs_sb)); |
| 718 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 711 | 719 | /* else |
| 712 | 720 | rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName, |
| 713 | 721 | cifs_sb_target->local_nls); */ |
| @@ -69,6 +69,7 @@ sesInfoAlloc(void) · 68 unmodified lines | ||
| 69 | 69 | ret_buf = kzalloc(sizeof(struct cifs_ses), GFP_KERNEL); |
| 70 | 70 | if (ret_buf) { |
| 71 | 71 | atomic_inc(&sesInfoAllocCount); |
| 72 | + spin_lock_init(&ret_buf->ses_lock); | |
| 72 | 73 | ret_buf->ses_status = SES_NEW; |
| 73 | 74 | ++ret_buf->ses_count; |
| 74 | 75 | INIT_LIST_HEAD(&ret_buf->smb_ses_list); |
| @@ -126,6 +127,7 @@ tconInfoAlloc(void) · 51 unmodified lines | ||
| 126 | 127 | atomic_inc(&tconInfoAllocCount); |
| 127 | 128 | ret_buf->status = TID_NEW; |
| 128 | 129 | ++ret_buf->tc_count; |
| 130 | + spin_lock_init(&ret_buf->tc_lock); | |
| 129 | 131 | INIT_LIST_HEAD(&ret_buf->openFileList); |
| 130 | 132 | INIT_LIST_HEAD(&ret_buf->tcon_list); |
| 131 | 133 | spin_lock_init(&ret_buf->open_file_lock); |
| @@ -172,9 +174,9 @@ cifs_buf_get(void) · 40 unmodified lines | ||
| 172 | 174 | /* clear the first few header bytes */ |
| 173 | 175 | /* for most paths, more is cleared in header_assemble */ |
| 174 | 176 | memset(ret_buf, 0, buf_size + 3); |
| 175 | − atomic_inc(&bufAllocCount); | |
| 177 | + atomic_inc(&buf_alloc_count); | |
| 176 | 178 | #ifdef CONFIG_CIFS_STATS2 |
| 177 | − atomic_inc(&totBufAllocCount); | |
| 179 | + atomic_inc(&total_buf_alloc_count); | |
| 178 | 180 | #endif /* CONFIG_CIFS_STATS2 */ |
| 179 | 181 | |
| 180 | 182 | return ret_buf; |
| @@ -189,7 +191,7 @@ cifs_buf_release(void *buf_to_free) · 8 unmodified lines | ||
| 189 | 191 | } |
| 190 | 192 | mempool_free(buf_to_free, cifs_req_poolp); |
| 191 | 193 | |
| 192 | − atomic_dec(&bufAllocCount); | |
| 194 | + atomic_dec(&buf_alloc_count); | |
| 193 | 195 | return; |
| 194 | 196 | } |
| 195 | 197 | |
| @@ -205,9 +207,9 @@ cifs_small_buf_get(void) · 9 unmodified lines | ||
| 205 | 207 | ret_buf = mempool_alloc(cifs_sm_req_poolp, GFP_NOFS); |
| 206 | 208 | /* No need to clear memory here, cleared in header assemble */ |
| 207 | 209 | /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/ |
| 208 | − atomic_inc(&smBufAllocCount); | |
| 210 | + atomic_inc(&small_buf_alloc_count); | |
| 209 | 211 | #ifdef CONFIG_CIFS_STATS2 |
| 210 | − atomic_inc(&totSmBufAllocCount); | |
| 212 | + atomic_inc(&total_small_buf_alloc_count); | |
| 211 | 213 | #endif /* CONFIG_CIFS_STATS2 */ |
| 212 | 214 | |
| 213 | 215 | return ret_buf; |
| @@ -223,7 +225,7 @@ cifs_small_buf_release(void *buf_to_free) · 9 unmodified lines | ||
| 223 | 225 | } |
| 224 | 226 | mempool_free(buf_to_free, cifs_sm_req_poolp); |
| 225 | 227 | |
| 226 | − atomic_dec(&smBufAllocCount); | |
| 228 | + atomic_dec(&small_buf_alloc_count); | |
| 227 | 229 | return; |
| 228 | 230 | } |
| 229 | 231 | |
| @@ -400,7 +402,6 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) · 170 unmodified lines | ||
| 400 | 402 | { |
| 401 | 403 | struct smb_hdr *buf = (struct smb_hdr *)buffer; |
| 402 | 404 | struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf; |
| 403 | − struct list_head *tmp, *tmp1, *tmp2; | |
| 404 | 405 | struct cifs_ses *ses; |
| 405 | 406 | struct cifs_tcon *tcon; |
| 406 | 407 | struct cifsInodeInfo *pCifsInode; |
| @@ -467,18 +468,14 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) · 60 unmodified lines | ||
| 467 | 468 | |
| 468 | 469 | /* look up tcon based on tid & uid */ |
| 469 | 470 | spin_lock(&cifs_tcp_ses_lock); |
| 470 | − list_for_each(tmp, &srv->smb_ses_list) { | |
| 471 | − ses = list_entry(tmp, struct cifs_ses, smb_ses_list); | |
| 472 | − list_for_each(tmp1, &ses->tcon_list) { | |
| 473 | − tcon = list_entry(tmp1, struct cifs_tcon, tcon_list); | |
| 471 | + list_for_each_entry(ses, &srv->smb_ses_list, smb_ses_list) { | |
| 472 | + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { | |
| 474 | 473 | if (tcon->tid != buf->Tid) |
| 475 | 474 | continue; |
| 476 | 475 | |
| 477 | 476 | cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks); |
| 478 | 477 | spin_lock(&tcon->open_file_lock); |
| 479 | − list_for_each(tmp2, &tcon->openFileList) { | |
| 480 | − netfile = list_entry(tmp2, struct cifsFileInfo, | |
| 481 | − tlist); | |
| 478 | + list_for_each_entry(netfile, &tcon->openFileList, tlist) { | |
| 482 | 479 | if (pSMB->Fid != netfile->fid.netfid) |
| 483 | 480 | continue; |
| 484 | 481 | |
| @@ -763,14 +760,12 @@ void · 278 unmodified lines | ||
| 763 | 760 | cifs_close_all_deferred_files(struct cifs_tcon *tcon) |
| 764 | 761 | { |
| 765 | 762 | struct cifsFileInfo *cfile; |
| 766 | − struct list_head *tmp; | |
| 767 | 763 | struct file_list *tmp_list, *tmp_next_list; |
| 768 | 764 | struct list_head file_head; |
| 769 | 765 | |
| 770 | 766 | INIT_LIST_HEAD(&file_head); |
| 771 | 767 | spin_lock(&tcon->open_file_lock); |
| 772 | − list_for_each(tmp, &tcon->openFileList) { | |
| 773 | − cfile = list_entry(tmp, struct cifsFileInfo, tlist); | |
| 768 | + list_for_each_entry(cfile, &tcon->openFileList, tlist) { | |
| 774 | 769 | if (delayed_work_pending(&cfile->deferred)) { |
| 775 | 770 | if (cancel_delayed_work(&cfile->deferred)) { |
| 776 | 771 | tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); |
| @@ -793,7 +788,6 @@ void · 16 unmodified lines | ||
| 793 | 788 | cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path) |
| 794 | 789 | { |
| 795 | 790 | struct cifsFileInfo *cfile; |
| 796 | − struct list_head *tmp; | |
| 797 | 791 | struct file_list *tmp_list, *tmp_next_list; |
| 798 | 792 | struct list_head file_head; |
| 799 | 793 | void *page; |
| @@ -802,8 +796,7 @@ cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path) · 2 unmodified lines | ||
| 802 | 796 | INIT_LIST_HEAD(&file_head); |
| 803 | 797 | page = alloc_dentry_path(); |
| 804 | 798 | spin_lock(&tcon->open_file_lock); |
| 805 | − list_for_each(tmp, &tcon->openFileList) { | |
| 806 | − cfile = list_entry(tmp, struct cifsFileInfo, tlist); | |
| 799 | + list_for_each_entry(cfile, &tcon->openFileList, tlist) { | |
| 807 | 800 | full_path = build_path_from_dentry(cfile->dentry, page); |
| 808 | 801 | if (strstr(full_path, path)) { |
| 809 | 802 | if (delayed_work_pending(&cfile->deferred)) { |
| @@ -911,7 +911,7 @@ map_and_check_smb_error(struct mid_q_entry *mid, bool logErr) · 910 unmodified lines | ||
| 911 | 911 | unsigned int |
| 912 | 912 | smbCalcSize(void *buf, struct TCP_Server_Info *server) |
| 913 | 913 | { |
| 914 | − struct smb_hdr *ptr = (struct smb_hdr *)buf; | |
| 914 | + struct smb_hdr *ptr = buf; | |
| 915 | 915 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + |
| 916 | 916 | 2 /* size of the bcc field */ + get_bcc(ptr)); |
| 917 | 917 | } |
| @@ -499,6 +499,7 @@ out: · 498 unmodified lines | ||
| 499 | 499 | return rc; |
| 500 | 500 | } |
| 501 | 501 | |
| 502 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 502 | 503 | static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, |
| 503 | 504 | struct TCP_Server_Info *server, |
| 504 | 505 | SESSION_SETUP_ANDX *pSMB) |
| @@ -591,7 +592,6 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses, · 86 unmodified lines | ||
| 591 | 592 | *pbcc_area = bcc_ptr; |
| 592 | 593 | } |
| 593 | 594 | |
| 594 | − | |
| 595 | 595 | static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, |
| 596 | 596 | const struct nls_table *nls_cp) |
| 597 | 597 | { |
| @@ -753,6 +753,7 @@ static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft, · 155 unmodified lines | ||
| 753 | 753 | for it later, but it is not very important */ |
| 754 | 754 | cifs_dbg(FYI, "ascii: bytes left %d\n", bleft); |
| 755 | 755 | } |
| 756 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 756 | 757 | |
| 757 | 758 | int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, |
| 758 | 759 | struct cifs_ses *ses) |
| @@ -1170,6 +1171,7 @@ struct sess_data { · 411 unmodified lines | ||
| 1170 | 1171 | struct kvec iov[3]; |
| 1171 | 1172 | }; |
| 1172 | 1173 | |
| 1174 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 1173 | 1175 | static int |
| 1174 | 1176 | sess_alloc_buffer(struct sess_data *sess_data, int wct) |
| 1175 | 1177 | { |
| @@ -1846,3 +1848,4 @@ out: · 670 unmodified lines | ||
| 1846 | 1848 | kfree(sess_data); |
| 1847 | 1849 | return rc; |
| 1848 | 1850 | } |
| 1851 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| @@ -92,17 +92,17 @@ cifs_find_mid(struct TCP_Server_Info *server, char *buffer) · 91 unmodified lines | ||
| 92 | 92 | struct smb_hdr *buf = (struct smb_hdr *)buffer; |
| 93 | 93 | struct mid_q_entry *mid; |
| 94 | 94 | |
| 95 | − spin_lock(&GlobalMid_Lock); | |
| 95 | + spin_lock(&server->mid_lock); | |
| 96 | 96 | list_for_each_entry(mid, &server->pending_mid_q, qhead) { |
| 97 | 97 | if (compare_mid(mid->mid, buf) && |
| 98 | 98 | mid->mid_state == MID_REQUEST_SUBMITTED && |
| 99 | 99 | le16_to_cpu(mid->command) == buf->Command) { |
| 100 | 100 | kref_get(&mid->refcount); |
| 101 | − spin_unlock(&GlobalMid_Lock); | |
| 101 | + spin_unlock(&server->mid_lock); | |
| 102 | 102 | return mid; |
| 103 | 103 | } |
| 104 | 104 | } |
| 105 | − spin_unlock(&GlobalMid_Lock); | |
| 105 | + spin_unlock(&server->mid_lock); | |
| 106 | 106 | return NULL; |
| 107 | 107 | } |
| 108 | 108 | |
| @@ -166,7 +166,7 @@ cifs_get_next_mid(struct TCP_Server_Info *server) · 57 unmodified lines | ||
| 166 | 166 | __u16 last_mid, cur_mid; |
| 167 | 167 | bool collision, reconnect = false; |
| 168 | 168 | |
| 169 | − spin_lock(&GlobalMid_Lock); | |
| 169 | + spin_lock(&server->mid_lock); | |
| 170 | 170 | |
| 171 | 171 | /* mid is 16 bit only for CIFS/SMB */ |
| 172 | 172 | cur_mid = (__u16)((server->CurrentMid) & 0xffff); |
| @@ -225,7 +225,7 @@ cifs_get_next_mid(struct TCP_Server_Info *server) · 52 unmodified lines | ||
| 225 | 225 | } |
| 226 | 226 | cur_mid++; |
| 227 | 227 | } |
| 228 | − spin_unlock(&GlobalMid_Lock); | |
| 228 | + spin_unlock(&server->mid_lock); | |
| 229 | 229 | |
| 230 | 230 | if (reconnect) { |
| 231 | 231 | cifs_signal_cifsd_for_reconnect(server, false); |
| @@ -132,15 +132,15 @@ static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, · 131 unmodified lines | ||
| 132 | 132 | } |
| 133 | 133 | |
| 134 | 134 | int |
| 135 | −smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) | |
| 135 | +smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server) | |
| 136 | 136 | { |
| 137 | 137 | struct smb2_hdr *shdr = (struct smb2_hdr *)buf; |
| 138 | 138 | struct smb2_pdu *pdu = (struct smb2_pdu *)shdr; |
| 139 | − __u64 mid; | |
| 140 | − __u32 clc_len; /* calculated length */ | |
| 141 | − int command; | |
| 142 | − int pdu_size = sizeof(struct smb2_pdu); | |
| 143 | 139 | int hdr_size = sizeof(struct smb2_hdr); |
| 140 | + int pdu_size = sizeof(struct smb2_pdu); | |
| 141 | + int command; | |
| 142 | + __u32 calc_len; /* calculated length */ | |
| 143 | + __u64 mid; | |
| 144 | 144 | |
| 145 | 145 | /* |
| 146 | 146 | * Add function to do table lookup of StructureSize by command |
| @@ -154,7 +154,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) · 7 unmodified lines | ||
| 154 | 154 | |
| 155 | 155 | /* decrypt frame now that it is completely read in */ |
| 156 | 156 | spin_lock(&cifs_tcp_ses_lock); |
| 157 | − list_for_each_entry(iter, &srvr->smb_ses_list, smb_ses_list) { | |
| 157 | + list_for_each_entry(iter, &server->smb_ses_list, smb_ses_list) { | |
| 158 | 158 | if (iter->Suid == le64_to_cpu(thdr->SessionId)) { |
| 159 | 159 | ses = iter; |
| 160 | 160 | break; |
| @@ -221,30 +221,33 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) · 60 unmodified lines | ||
| 221 | 221 | } |
| 222 | 222 | } |
| 223 | 223 | |
| 224 | − clc_len = smb2_calc_size(buf, srvr); | |
| 224 | + calc_len = smb2_calc_size(buf, server); | |
| 225 | + | |
| 226 | + /* For SMB2_IOCTL, OutputOffset and OutputLength are optional, so might | |
| 227 | + * be 0, and not a real miscalculation */ | |
| 228 | + if (command == SMB2_IOCTL_HE && calc_len == 0) | |
| 229 | + return 0; | |
| 225 | 230 | |
| 226 | − if (shdr->Command == SMB2_NEGOTIATE) | |
| 227 | − clc_len += get_neg_ctxt_len(shdr, len, clc_len); | |
| 231 | + if (command == SMB2_NEGOTIATE_HE) | |
| 232 | + calc_len += get_neg_ctxt_len(shdr, len, calc_len); | |
| 228 | 233 | |
| 229 | − if (len != clc_len) { | |
| 230 | − cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n", | |
| 231 | − clc_len, len, mid); | |
| 234 | + if (len != calc_len) { | |
| 232 | 235 | /* create failed on symlink */ |
| 233 | 236 | if (command == SMB2_CREATE_HE && |
| 234 | 237 | shdr->Status == STATUS_STOPPED_ON_SYMLINK) |
| 235 | 238 | return 0; |
| 236 | 239 | /* Windows 7 server returns 24 bytes more */ |
| 237 | − if (clc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE) | |
| 240 | + if (calc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE) | |
| 238 | 241 | return 0; |
| 239 | 242 | /* server can return one byte more due to implied bcc[0] */ |
| 240 | − if (clc_len == len + 1) | |
| 243 | + if (calc_len == len + 1) | |
| 241 | 244 | return 0; |
| 242 | 245 | |
| 243 | 246 | /* |
| 244 | 247 | * Some windows servers (win2016) will pad also the final |
| 245 | 248 | * PDU in a compound to 8 bytes. |
| 246 | 249 | */ |
| 247 | − if (((clc_len + 7) & ~7) == len) | |
| 250 | + if (((calc_len + 7) & ~7) == len) | |
| 248 | 251 | return 0; |
| 249 | 252 | |
| 250 | 253 | /* |
| @@ -253,12 +256,18 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr) · 2 unmodified lines | ||
| 253 | 256 | * SMB2/SMB3 frame length (header + smb2 response specific data) |
| 254 | 257 | * Some windows servers also pad up to 8 bytes when compounding. |
| 255 | 258 | */ |
| 256 | − if (clc_len < len) | |
| 259 | + if (calc_len < len) | |
| 257 | 260 | return 0; |
| 258 | 261 | |
| 259 | − pr_warn_once( | |
| 260 | − "srv rsp too short, len %d not %d. cmd:%d mid:%llu\n", | |
| 261 | − len, clc_len, command, mid); | |
| 262 | + /* Only log a message if len was really miscalculated */ | |
| 263 | + if (unlikely(cifsFYI)) | |
| 264 | + cifs_dbg(FYI, "Server response too short: calculated " | |
| 265 | + "length %u doesn't match read length %u (cmd=%d, mid=%llu)\n", | |
| 266 | + calc_len, len, command, mid); | |
| 267 | + else | |
| 268 | + pr_warn("Server response too short: calculated length " | |
| 269 | + "%u doesn't match read length %u (cmd=%d, mid=%llu)\n", | |
| 270 | + calc_len, len, command, mid); | |
| 262 | 271 | |
| 263 | 272 | return 1; |
| 264 | 273 | } |
| @@ -402,7 +411,7 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *shdr) · 137 unmodified lines | ||
| 402 | 411 | unsigned int |
| 403 | 412 | smb2_calc_size(void *buf, struct TCP_Server_Info *srvr) |
| 404 | 413 | { |
| 405 | − struct smb2_pdu *pdu = (struct smb2_pdu *)buf; | |
| 414 | + struct smb2_pdu *pdu = buf; | |
| 406 | 415 | struct smb2_hdr *shdr = &pdu->hdr; |
| 407 | 416 | int offset; /* the offset from the beginning of SMB to data area */ |
| 408 | 417 | int data_length; /* the length of the variable length data area */ |
| @@ -126,13 +126,13 @@ smb2_add_credits(struct TCP_Server_Info *server, · 125 unmodified lines | ||
| 126 | 126 | optype, scredits, add); |
| 127 | 127 | } |
| 128 | 128 | |
| 129 | − spin_lock(&cifs_tcp_ses_lock); | |
| 129 | + spin_lock(&server->srv_lock); | |
| 130 | 130 | if (server->tcpStatus == CifsNeedReconnect |
| 131 | 131 | || server->tcpStatus == CifsExiting) { |
| 132 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 132 | + spin_unlock(&server->srv_lock); | |
| 133 | 133 | return; |
| 134 | 134 | } |
| 135 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 135 | + spin_unlock(&server->srv_lock); | |
| 136 | 136 | |
| 137 | 137 | switch (rc) { |
| 138 | 138 | case -1: |
| @@ -218,12 +218,12 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size, · 79 unmodified lines | ||
| 218 | 218 | spin_lock(&server->req_lock); |
| 219 | 219 | } else { |
| 220 | 220 | spin_unlock(&server->req_lock); |
| 221 | − spin_lock(&cifs_tcp_ses_lock); | |
| 221 | + spin_lock(&server->srv_lock); | |
| 222 | 222 | if (server->tcpStatus == CifsExiting) { |
| 223 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 223 | + spin_unlock(&server->srv_lock); | |
| 224 | 224 | return -ENOENT; |
| 225 | 225 | } |
| 226 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 226 | + spin_unlock(&server->srv_lock); | |
| 227 | 227 | |
| 228 | 228 | spin_lock(&server->req_lock); |
| 229 | 229 | scredits = server->credits; |
| @@ -319,19 +319,19 @@ smb2_get_next_mid(struct TCP_Server_Info *server) · 89 unmodified lines | ||
| 319 | 319 | { |
| 320 | 320 | __u64 mid; |
| 321 | 321 | /* for SMB2 we need the current value */ |
| 322 | − spin_lock(&GlobalMid_Lock); | |
| 322 | + spin_lock(&server->mid_lock); | |
| 323 | 323 | mid = server->CurrentMid++; |
| 324 | − spin_unlock(&GlobalMid_Lock); | |
| 324 | + spin_unlock(&server->mid_lock); | |
| 325 | 325 | return mid; |
| 326 | 326 | } |
| 327 | 327 | |
| 328 | 328 | static void |
| 329 | 329 | smb2_revert_current_mid(struct TCP_Server_Info *server, const unsigned int val) |
| 330 | 330 | { |
| 331 | − spin_lock(&GlobalMid_Lock); | |
| 331 | + spin_lock(&server->mid_lock); | |
| 332 | 332 | if (server->CurrentMid >= val) |
| 333 | 333 | server->CurrentMid -= val; |
| 334 | − spin_unlock(&GlobalMid_Lock); | |
| 334 | + spin_unlock(&server->mid_lock); | |
| 335 | 335 | } |
| 336 | 336 | |
| 337 | 337 | static struct mid_q_entry * |
| @@ -346,7 +346,7 @@ __smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue) · 8 unmodified lines | ||
| 346 | 346 | return NULL; |
| 347 | 347 | } |
| 348 | 348 | |
| 349 | − spin_lock(&GlobalMid_Lock); | |
| 349 | + spin_lock(&server->mid_lock); | |
| 350 | 350 | list_for_each_entry(mid, &server->pending_mid_q, qhead) { |
| 351 | 351 | if ((mid->mid == wire_mid) && |
| 352 | 352 | (mid->mid_state == MID_REQUEST_SUBMITTED) && |
| @@ -356,11 +356,11 @@ __smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue) · 3 unmodified lines | ||
| 356 | 356 | list_del_init(&mid->qhead); |
| 357 | 357 | mid->mid_flags |= MID_DELETED; |
| 358 | 358 | } |
| 359 | − spin_unlock(&GlobalMid_Lock); | |
| 359 | + spin_unlock(&server->mid_lock); | |
| 360 | 360 | return mid; |
| 361 | 361 | } |
| 362 | 362 | } |
| 363 | − spin_unlock(&GlobalMid_Lock); | |
| 363 | + spin_unlock(&server->mid_lock); | |
| 364 | 364 | return NULL; |
| 365 | 365 | } |
| 366 | 366 | |
| @@ -403,9 +403,9 @@ smb2_negotiate(const unsigned int xid, · 36 unmodified lines | ||
| 403 | 403 | { |
| 404 | 404 | int rc; |
| 405 | 405 | |
| 406 | − spin_lock(&GlobalMid_Lock); | |
| 406 | + spin_lock(&server->mid_lock); | |
| 407 | 407 | server->CurrentMid = 0; |
| 408 | − spin_unlock(&GlobalMid_Lock); | |
| 408 | + spin_unlock(&server->mid_lock); | |
| 409 | 409 | rc = SMB2_negotiate(xid, ses, server); |
| 410 | 410 | /* BB we probably don't need to retry with modern servers */ |
| 411 | 411 | if (rc == -EAGAIN) |
| @@ -1145,9 +1145,7 @@ move_smb2_ea_to_cifs(char *dst, size_t dst_size, · 733 unmodified lines | ||
| 1145 | 1145 | size_t name_len, value_len, user_name_len; |
| 1146 | 1146 | |
| 1147 | 1147 | while (src_size > 0) { |
| 1148 | − name = &src->ea_data[0]; | |
| 1149 | 1148 | name_len = (size_t)src->ea_name_length; |
| 1150 | − value = &src->ea_data[src->ea_name_length + 1]; | |
| 1151 | 1149 | value_len = (size_t)le16_to_cpu(src->ea_value_length); |
| 1152 | 1150 | |
| 1153 | 1151 | if (name_len == 0) |
| @@ -1159,6 +1157,9 @@ move_smb2_ea_to_cifs(char *dst, size_t dst_size, · 5 unmodified lines | ||
| 1159 | 1157 | goto out; |
| 1160 | 1158 | } |
| 1161 | 1159 | |
| 1160 | + name = &src->ea_data[0]; | |
| 1161 | + value = &src->ea_data[src->ea_name_length + 1]; | |
| 1162 | + | |
| 1162 | 1163 | if (ea_name) { |
| 1163 | 1164 | if (ea_name_len == name_len && |
| 1164 | 1165 | memcmp(ea_name, name, name_len) == 0) { |
| @@ -2574,7 +2575,6 @@ static void · 1409 unmodified lines | ||
| 2574 | 2575 | smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server) |
| 2575 | 2576 | { |
| 2576 | 2577 | struct smb2_hdr *shdr = (struct smb2_hdr *)buf; |
| 2577 | − struct list_head *tmp, *tmp1; | |
| 2578 | 2578 | struct cifs_ses *ses; |
| 2579 | 2579 | struct cifs_tcon *tcon; |
| 2580 | 2580 | |
| @@ -2582,12 +2582,12 @@ smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server) · 1 unmodified line | ||
| 2582 | 2582 | return; |
| 2583 | 2583 | |
| 2584 | 2584 | spin_lock(&cifs_tcp_ses_lock); |
| 2585 | − list_for_each(tmp, &server->smb_ses_list) { | |
| 2586 | − ses = list_entry(tmp, struct cifs_ses, smb_ses_list); | |
| 2587 | − list_for_each(tmp1, &ses->tcon_list) { | |
| 2588 | − tcon = list_entry(tmp1, struct cifs_tcon, tcon_list); | |
| 2585 | + list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { | |
| 2586 | + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { | |
| 2589 | 2587 | if (tcon->tid == le32_to_cpu(shdr->Id.SyncId.TreeId)) { |
| 2588 | + spin_lock(&tcon->tc_lock); | |
| 2590 | 2589 | tcon->need_reconnect = true; |
| 2590 | + spin_unlock(&tcon->tc_lock); | |
| 2591 | 2591 | spin_unlock(&cifs_tcp_ses_lock); |
| 2592 | 2592 | pr_warn_once("Server share %s deleted.\n", |
| 2593 | 2593 | tcon->treeName); |
| @@ -4563,9 +4563,11 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key) · 1969 unmodified lines | ||
| 4563 | 4563 | list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { |
| 4564 | 4564 | list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { |
| 4565 | 4565 | if (ses->Suid == ses_id) { |
| 4566 | + spin_lock(&ses->ses_lock); | |
| 4566 | 4567 | ses_enc_key = enc ? ses->smb3encryptionkey : |
| 4567 | 4568 | ses->smb3decryptionkey; |
| 4568 | 4569 | memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE); |
| 4570 | + spin_unlock(&ses->ses_lock); | |
| 4569 | 4571 | spin_unlock(&cifs_tcp_ses_lock); |
| 4570 | 4572 | return 0; |
| 4571 | 4573 | } |
| @@ -5080,23 +5082,24 @@ static void smb2_decrypt_offload(struct work_struct *work) · 508 unmodified lines | ||
| 5080 | 5082 | |
| 5081 | 5083 | mid->callback(mid); |
| 5082 | 5084 | } else { |
| 5083 | − spin_lock(&cifs_tcp_ses_lock); | |
| 5084 | − spin_lock(&GlobalMid_Lock); | |
| 5085 | + spin_lock(&dw->server->srv_lock); | |
| 5085 | 5086 | if (dw->server->tcpStatus == CifsNeedReconnect) { |
| 5087 | + spin_lock(&dw->server->mid_lock); | |
| 5086 | 5088 | mid->mid_state = MID_RETRY_NEEDED; |
| 5087 | − spin_unlock(&GlobalMid_Lock); | |
| 5088 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 5089 | + spin_unlock(&dw->server->mid_lock); | |
| 5090 | + spin_unlock(&dw->server->srv_lock); | |
| 5089 | 5091 | mid->callback(mid); |
| 5090 | 5092 | } else { |
| 5093 | + spin_lock(&dw->server->mid_lock); | |
| 5091 | 5094 | mid->mid_state = MID_REQUEST_SUBMITTED; |
| 5092 | 5095 | mid->mid_flags &= ~(MID_DELETED); |
| 5093 | 5096 | list_add_tail(&mid->qhead, |
| 5094 | 5097 | &dw->server->pending_mid_q); |
| 5095 | − spin_unlock(&GlobalMid_Lock); | |
| 5096 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 5098 | + spin_unlock(&dw->server->mid_lock); | |
| 5099 | + spin_unlock(&dw->server->srv_lock); | |
| 5097 | 5100 | } |
| 5098 | 5101 | } |
| 5099 | − cifs_mid_q_entry_release(mid); | |
| 5102 | + release_mid(mid); | |
| 5100 | 5103 | } |
| 5101 | 5104 | |
| 5102 | 5105 | free_pages: |
| @@ -162,7 +162,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, · 161 unmodified lines | ||
| 162 | 162 | if (smb2_command == SMB2_TREE_CONNECT || smb2_command == SMB2_IOCTL) |
| 163 | 163 | return 0; |
| 164 | 164 | |
| 165 | − spin_lock(&cifs_tcp_ses_lock); | |
| 165 | + spin_lock(&tcon->tc_lock); | |
| 166 | 166 | if (tcon->status == TID_EXITING) { |
| 167 | 167 | /* |
| 168 | 168 | * only tree disconnect, open, and write, |
| @@ -172,13 +172,13 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, · 3 unmodified lines | ||
| 172 | 172 | if ((smb2_command != SMB2_WRITE) && |
| 173 | 173 | (smb2_command != SMB2_CREATE) && |
| 174 | 174 | (smb2_command != SMB2_TREE_DISCONNECT)) { |
| 175 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 175 | + spin_unlock(&tcon->tc_lock); | |
| 176 | 176 | cifs_dbg(FYI, "can not send cmd %d while umounting\n", |
| 177 | 177 | smb2_command); |
| 178 | 178 | return -ENODEV; |
| 179 | 179 | } |
| 180 | 180 | } |
| 181 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 181 | + spin_unlock(&tcon->tc_lock); | |
| 182 | 182 | if ((!tcon->ses) || (tcon->ses->ses_status == SES_EXITING) || |
| 183 | 183 | (!tcon->ses->server) || !server) |
| 184 | 184 | return -EIO; |
| @@ -217,12 +217,12 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, · 32 unmodified lines | ||
| 217 | 217 | } |
| 218 | 218 | |
| 219 | 219 | /* are we still trying to reconnect? */ |
| 220 | − spin_lock(&cifs_tcp_ses_lock); | |
| 220 | + spin_lock(&server->srv_lock); | |
| 221 | 221 | if (server->tcpStatus != CifsNeedReconnect) { |
| 222 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 222 | + spin_unlock(&server->srv_lock); | |
| 223 | 223 | break; |
| 224 | 224 | } |
| 225 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 225 | + spin_unlock(&server->srv_lock); | |
| 226 | 226 | |
| 227 | 227 | if (retries && --retries) |
| 228 | 228 | continue; |
| @@ -256,13 +256,13 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, · 27 unmodified lines | ||
| 256 | 256 | * and the server never sends an answer the socket will be closed |
| 257 | 257 | * and tcpStatus set to reconnect. |
| 258 | 258 | */ |
| 259 | − spin_lock(&cifs_tcp_ses_lock); | |
| 259 | + spin_lock(&server->srv_lock); | |
| 260 | 260 | if (server->tcpStatus == CifsNeedReconnect) { |
| 261 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 261 | + spin_unlock(&server->srv_lock); | |
| 262 | 262 | rc = -EHOSTDOWN; |
| 263 | 263 | goto out; |
| 264 | 264 | } |
| 265 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 265 | + spin_unlock(&server->srv_lock); | |
| 266 | 266 | |
| 267 | 267 | /* |
| 268 | 268 | * need to prevent multiple threads trying to simultaneously |
| @@ -354,7 +354,7 @@ fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, · 85 unmodified lines | ||
| 354 | 354 | void *buf, |
| 355 | 355 | unsigned int *total_len) |
| 356 | 356 | { |
| 357 | − struct smb2_pdu *spdu = (struct smb2_pdu *)buf; | |
| 357 | + struct smb2_pdu *spdu = buf; | |
| 358 | 358 | /* lookup word count ie StructureSize from table */ |
| 359 | 359 | __u16 parmsize = smb2_req_struct_sizes[le16_to_cpu(smb2_command)]; |
| 360 | 360 | |
| @@ -3776,7 +3776,7 @@ smb2_echo_callback(struct mid_q_entry *mid) · 3415 unmodified lines | ||
| 3776 | 3776 | credits.instance = server->reconnect_instance; |
| 3777 | 3777 | } |
| 3778 | 3778 | |
| 3779 | − DeleteMidQEntry(mid); | |
| 3779 | + release_mid(mid); | |
| 3780 | 3780 | add_credits(server, &credits, CIFS_ECHO_OP); |
| 3781 | 3781 | } |
| 3782 | 3782 | |
| @@ -3911,15 +3911,15 @@ SMB2_echo(struct TCP_Server_Info *server) · 128 unmodified lines | ||
| 3911 | 3911 | |
| 3912 | 3912 | cifs_dbg(FYI, "In echo request for conn_id %lld\n", server->conn_id); |
| 3913 | 3913 | |
| 3914 | − spin_lock(&cifs_tcp_ses_lock); | |
| 3914 | + spin_lock(&server->srv_lock); | |
| 3915 | 3915 | if (server->ops->need_neg && |
| 3916 | 3916 | server->ops->need_neg(server)) { |
| 3917 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 3917 | + spin_unlock(&server->srv_lock); | |
| 3918 | 3918 | /* No need to send echo on newly established connections */ |
| 3919 | 3919 | mod_delayed_work(cifsiod_wq, &server->reconnect, 0); |
| 3920 | 3920 | return rc; |
| 3921 | 3921 | } |
| 3922 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 3922 | + spin_unlock(&server->srv_lock); | |
| 3923 | 3923 | |
| 3924 | 3924 | rc = smb2_plain_req_init(SMB2_ECHO, NULL, server, |
| 3925 | 3925 | (void **)&req, &total_len); |
| @@ -4201,7 +4201,7 @@ smb2_readv_callback(struct mid_q_entry *mid) · 275 unmodified lines | ||
| 4201 | 4201 | rdata->offset, rdata->got_bytes); |
| 4202 | 4202 | |
| 4203 | 4203 | queue_work(cifsiod_wq, &rdata->work); |
| 4204 | − DeleteMidQEntry(mid); | |
| 4204 | + release_mid(mid); | |
| 4205 | 4205 | add_credits(server, &credits, 0); |
| 4206 | 4206 | } |
| 4207 | 4207 | |
| @@ -4440,7 +4440,7 @@ smb2_writev_callback(struct mid_q_entry *mid) · 232 unmodified lines | ||
| 4440 | 4440 | wdata->offset, wdata->bytes); |
| 4441 | 4441 | |
| 4442 | 4442 | queue_work(cifsiod_wq, &wdata->work); |
| 4443 | − DeleteMidQEntry(mid); | |
| 4443 | + release_mid(mid); | |
| 4444 | 4444 | add_credits(server, &credits, 0); |
| 4445 | 4445 | } |
| 4446 | 4446 | |
| @@ -640,13 +640,13 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server) · 639 unmodified lines | ||
| 640 | 640 | |
| 641 | 641 | if (!is_signed) |
| 642 | 642 | return 0; |
| 643 | − spin_lock(&cifs_tcp_ses_lock); | |
| 643 | + spin_lock(&server->srv_lock); | |
| 644 | 644 | if (server->ops->need_neg && |
| 645 | 645 | server->ops->need_neg(server)) { |
| 646 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 646 | + spin_unlock(&server->srv_lock); | |
| 647 | 647 | return 0; |
| 648 | 648 | } |
| 649 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 649 | + spin_unlock(&server->srv_lock); | |
| 650 | 650 | if (!is_binding && !server->session_estab) { |
| 651 | 651 | strncpy(shdr->Signature, "BSRSPYL", 8); |
| 652 | 652 | return 0; |
| @@ -750,7 +750,7 @@ smb2_mid_entry_alloc(const struct smb2_hdr *shdr, · 97 unmodified lines | ||
| 750 | 750 | temp->callback = cifs_wake_up_task; |
| 751 | 751 | temp->callback_data = current; |
| 752 | 752 | |
| 753 | − atomic_inc(&midCount); | |
| 753 | + atomic_inc(&mid_count); | |
| 754 | 754 | temp->mid_state = MID_REQUEST_ALLOCATED; |
| 755 | 755 | trace_smb3_cmd_enter(le32_to_cpu(shdr->Id.SyncId.TreeId), |
| 756 | 756 | le64_to_cpu(shdr->SessionId), |
| @@ -762,28 +762,30 @@ static int · 5 unmodified lines | ||
| 762 | 762 | smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Server_Info *server, |
| 763 | 763 | struct smb2_hdr *shdr, struct mid_q_entry **mid) |
| 764 | 764 | { |
| 765 | − spin_lock(&cifs_tcp_ses_lock); | |
| 765 | + spin_lock(&server->srv_lock); | |
| 766 | 766 | if (server->tcpStatus == CifsExiting) { |
| 767 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 767 | + spin_unlock(&server->srv_lock); | |
| 768 | 768 | return -ENOENT; |
| 769 | 769 | } |
| 770 | 770 | |
| 771 | 771 | if (server->tcpStatus == CifsNeedReconnect) { |
| 772 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 772 | + spin_unlock(&server->srv_lock); | |
| 773 | 773 | cifs_dbg(FYI, "tcp session dead - return to caller to retry\n"); |
| 774 | 774 | return -EAGAIN; |
| 775 | 775 | } |
| 776 | 776 | |
| 777 | 777 | if (server->tcpStatus == CifsNeedNegotiate && |
| 778 | 778 | shdr->Command != SMB2_NEGOTIATE) { |
| 779 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 779 | + spin_unlock(&server->srv_lock); | |
| 780 | 780 | return -EAGAIN; |
| 781 | 781 | } |
| 782 | + spin_unlock(&server->srv_lock); | |
| 782 | 783 | |
| 784 | + spin_lock(&ses->ses_lock); | |
| 783 | 785 | if (ses->ses_status == SES_NEW) { |
| 784 | 786 | if ((shdr->Command != SMB2_SESSION_SETUP) && |
| 785 | 787 | (shdr->Command != SMB2_NEGOTIATE)) { |
| 786 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 788 | + spin_unlock(&ses->ses_lock); | |
| 787 | 789 | return -EAGAIN; |
| 788 | 790 | } |
| 789 | 791 | /* else ok - we are setting up session */ |
| @@ -791,19 +793,19 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct TCP_Server_Info *server, · 1 unmodified line | ||
| 791 | 793 | |
| 792 | 794 | if (ses->ses_status == SES_EXITING) { |
| 793 | 795 | if (shdr->Command != SMB2_LOGOFF) { |
| 794 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 796 | + spin_unlock(&ses->ses_lock); | |
| 795 | 797 | return -EAGAIN; |
| 796 | 798 | } |
| 797 | 799 | /* else ok - we are shutting down the session */ |
| 798 | 800 | } |
| 799 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 801 | + spin_unlock(&ses->ses_lock); | |
| 800 | 802 | |
| 801 | 803 | *mid = smb2_mid_entry_alloc(shdr, server); |
| 802 | 804 | if (*mid == NULL) |
| 803 | 805 | return -ENOMEM; |
| 804 | − spin_lock(&GlobalMid_Lock); | |
| 806 | + spin_lock(&server->mid_lock); | |
| 805 | 807 | list_add_tail(&(*mid)->qhead, &server->pending_mid_q); |
| 806 | − spin_unlock(&GlobalMid_Lock); | |
| 808 | + spin_unlock(&server->mid_lock); | |
| 807 | 809 | |
| 808 | 810 | return 0; |
| 809 | 811 | } |
| @@ -854,7 +856,7 @@ smb2_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *server, · 44 unmodified lines | ||
| 854 | 856 | rc = smb2_sign_rqst(rqst, server); |
| 855 | 857 | if (rc) { |
| 856 | 858 | revert_current_mid_from_hdr(server, shdr); |
| 857 | − cifs_delete_mid(mid); | |
| 859 | + delete_mid(mid); | |
| 858 | 860 | return ERR_PTR(rc); |
| 859 | 861 | } |
| 860 | 862 | |
| @@ -869,13 +871,13 @@ smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) · 8 unmodified lines | ||
| 869 | 871 | (struct smb2_hdr *)rqst->rq_iov[0].iov_base; |
| 870 | 872 | struct mid_q_entry *mid; |
| 871 | 873 | |
| 872 | − spin_lock(&cifs_tcp_ses_lock); | |
| 874 | + spin_lock(&server->srv_lock); | |
| 873 | 875 | if (server->tcpStatus == CifsNeedNegotiate && |
| 874 | 876 | shdr->Command != SMB2_NEGOTIATE) { |
| 875 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 877 | + spin_unlock(&server->srv_lock); | |
| 876 | 878 | return ERR_PTR(-EAGAIN); |
| 877 | 879 | } |
| 878 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 880 | + spin_unlock(&server->srv_lock); | |
| 879 | 881 | |
| 880 | 882 | smb2_seq_num_into_buf(server, shdr); |
| 881 | 883 | |
| @@ -888,7 +890,7 @@ smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) · 6 unmodified lines | ||
| 888 | 890 | rc = smb2_sign_rqst(rqst, server); |
| 889 | 891 | if (rc) { |
| 890 | 892 | revert_current_mid_from_hdr(server, shdr); |
| 891 | − DeleteMidQEntry(mid); | |
| 893 | + release_mid(mid); | |
| 892 | 894 | return ERR_PTR(rc); |
| 893 | 895 | } |
| 894 | 896 | |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <asm/processor.h> |
| 22 | 22 | #include <linux/mempool.h> |
| 23 | 23 | #include <linux/sched/signal.h> |
| 24 | +#include <linux/task_io_accounting_ops.h> | |
| 24 | 25 | #include "cifspdu.h" |
| 25 | 26 | #include "cifsglob.h" |
| 26 | 27 | #include "cifsproto.h" |
| @@ -37,13 +38,13 @@ cifs_wake_up_task(struct mid_q_entry *mid) · 10 unmodified lines | ||
| 37 | 38 | wake_up_process(mid->callback_data); |
| 38 | 39 | } |
| 39 | 40 | |
| 40 | −struct mid_q_entry * | |
| 41 | −AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) | |
| 41 | +static struct mid_q_entry * | |
| 42 | +alloc_mid(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) | |
| 42 | 43 | { |
| 43 | 44 | struct mid_q_entry *temp; |
| 44 | 45 | |
| 45 | 46 | if (server == NULL) { |
| 46 | − cifs_dbg(VFS, "Null TCP session in AllocMidQEntry\n"); | |
| 47 | + cifs_dbg(VFS, "%s: null TCP session\n", __func__); | |
| 47 | 48 | return NULL; |
| 48 | 49 | } |
| 49 | 50 | |
| @@ -68,12 +69,12 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) · 18 unmodified lines | ||
| 68 | 69 | temp->callback = cifs_wake_up_task; |
| 69 | 70 | temp->callback_data = current; |
| 70 | 71 | |
| 71 | − atomic_inc(&midCount); | |
| 72 | + atomic_inc(&mid_count); | |
| 72 | 73 | temp->mid_state = MID_REQUEST_ALLOCATED; |
| 73 | 74 | return temp; |
| 74 | 75 | } |
| 75 | 76 | |
| 76 | −static void _cifs_mid_q_entry_release(struct kref *refcount) | |
| 77 | +static void __release_mid(struct kref *refcount) | |
| 77 | 78 | { |
| 78 | 79 | struct mid_q_entry *midEntry = |
| 79 | 80 | container_of(refcount, struct mid_q_entry, refcount); |
| @@ -91,7 +92,7 @@ static void _cifs_mid_q_entry_release(struct kref *refcount) · 11 unmodified lines | ||
| 91 | 92 | server->ops->handle_cancelled_mid(midEntry, server); |
| 92 | 93 | |
| 93 | 94 | midEntry->mid_state = MID_FREE; |
| 94 | − atomic_dec(&midCount); | |
| 95 | + atomic_dec(&mid_count); | |
| 95 | 96 | if (midEntry->large_buf) |
| 96 | 97 | cifs_buf_release(midEntry->resp_buf); |
| 97 | 98 | else |
| @@ -152,29 +153,26 @@ static void _cifs_mid_q_entry_release(struct kref *refcount) · 54 unmodified lines | ||
| 152 | 153 | mempool_free(midEntry, cifs_mid_poolp); |
| 153 | 154 | } |
| 154 | 155 | |
| 155 | −void cifs_mid_q_entry_release(struct mid_q_entry *midEntry) | |
| 156 | +void release_mid(struct mid_q_entry *mid) | |
| 156 | 157 | { |
| 157 | − spin_lock(&GlobalMid_Lock); | |
| 158 | − kref_put(&midEntry->refcount, _cifs_mid_q_entry_release); | |
| 159 | − spin_unlock(&GlobalMid_Lock); | |
| 160 | −} | |
| 158 | + struct TCP_Server_Info *server = mid->server; | |
| 161 | 159 | |
| 162 | −void DeleteMidQEntry(struct mid_q_entry *midEntry) | |
| 163 | −{ | |
| 164 | − cifs_mid_q_entry_release(midEntry); | |
| 160 | + spin_lock(&server->mid_lock); | |
| 161 | + kref_put(&mid->refcount, __release_mid); | |
| 162 | + spin_unlock(&server->mid_lock); | |
| 165 | 163 | } |
| 166 | 164 | |
| 167 | 165 | void |
| 168 | −cifs_delete_mid(struct mid_q_entry *mid) | |
| 166 | +delete_mid(struct mid_q_entry *mid) | |
| 169 | 167 | { |
| 170 | − spin_lock(&GlobalMid_Lock); | |
| 168 | + spin_lock(&mid->server->mid_lock); | |
| 171 | 169 | if (!(mid->mid_flags & MID_DELETED)) { |
| 172 | 170 | list_del_init(&mid->qhead); |
| 173 | 171 | mid->mid_flags |= MID_DELETED; |
| 174 | 172 | } |
| 175 | − spin_unlock(&GlobalMid_Lock); | |
| 173 | + spin_unlock(&mid->server->mid_lock); | |
| 176 | 174 | |
| 177 | − DeleteMidQEntry(mid); | |
| 175 | + release_mid(mid); | |
| 178 | 176 | } |
| 179 | 177 | |
| 180 | 178 | /* |
| @@ -577,12 +575,12 @@ wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits, · 396 unmodified lines | ||
| 577 | 575 | } else { |
| 578 | 576 | spin_unlock(&server->req_lock); |
| 579 | 577 | |
| 580 | − spin_lock(&cifs_tcp_ses_lock); | |
| 578 | + spin_lock(&server->srv_lock); | |
| 581 | 579 | if (server->tcpStatus == CifsExiting) { |
| 582 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 580 | + spin_unlock(&server->srv_lock); | |
| 583 | 581 | return -ENOENT; |
| 584 | 582 | } |
| 585 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 583 | + spin_unlock(&server->srv_lock); | |
| 586 | 584 | |
| 587 | 585 | /* |
| 588 | 586 | * For normal commands, reserve the last MAX_COMPOUND |
| @@ -725,11 +723,11 @@ cifs_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size, · 136 unmodified lines | ||
| 725 | 723 | static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, |
| 726 | 724 | struct mid_q_entry **ppmidQ) |
| 727 | 725 | { |
| 728 | − spin_lock(&cifs_tcp_ses_lock); | |
| 726 | + spin_lock(&ses->ses_lock); | |
| 729 | 727 | if (ses->ses_status == SES_NEW) { |
| 730 | 728 | if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && |
| 731 | 729 | (in_buf->Command != SMB_COM_NEGOTIATE)) { |
| 732 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 730 | + spin_unlock(&ses->ses_lock); | |
| 733 | 731 | return -EAGAIN; |
| 734 | 732 | } |
| 735 | 733 | /* else ok - we are setting up session */ |
| @@ -738,19 +736,19 @@ static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, · 2 unmodified lines | ||
| 738 | 736 | if (ses->ses_status == SES_EXITING) { |
| 739 | 737 | /* check if SMB session is bad because we are setting it up */ |
| 740 | 738 | if (in_buf->Command != SMB_COM_LOGOFF_ANDX) { |
| 741 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 739 | + spin_unlock(&ses->ses_lock); | |
| 742 | 740 | return -EAGAIN; |
| 743 | 741 | } |
| 744 | 742 | /* else ok - we are shutting down session */ |
| 745 | 743 | } |
| 746 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 744 | + spin_unlock(&ses->ses_lock); | |
| 747 | 745 | |
| 748 | − *ppmidQ = AllocMidQEntry(in_buf, ses->server); | |
| 746 | + *ppmidQ = alloc_mid(in_buf, ses->server); | |
| 749 | 747 | if (*ppmidQ == NULL) |
| 750 | 748 | return -ENOMEM; |
| 751 | − spin_lock(&GlobalMid_Lock); | |
| 749 | + spin_lock(&ses->server->mid_lock); | |
| 752 | 750 | list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q); |
| 753 | − spin_unlock(&GlobalMid_Lock); | |
| 751 | + spin_unlock(&ses->server->mid_lock); | |
| 754 | 752 | return 0; |
| 755 | 753 | } |
| 756 | 754 | |
| @@ -782,13 +780,13 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) · 25 unmodified lines | ||
| 782 | 780 | if (server->sign) |
| 783 | 781 | hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
| 784 | 782 | |
| 785 | − mid = AllocMidQEntry(hdr, server); | |
| 783 | + mid = alloc_mid(hdr, server); | |
| 786 | 784 | if (mid == NULL) |
| 787 | 785 | return ERR_PTR(-ENOMEM); |
| 788 | 786 | |
| 789 | 787 | rc = cifs_sign_rqst(rqst, server, &mid->sequence_number); |
| 790 | 788 | if (rc) { |
| 791 | − DeleteMidQEntry(mid); | |
| 789 | + release_mid(mid); | |
| 792 | 790 | return ERR_PTR(rc); |
| 793 | 791 | } |
| 794 | 792 | |
| @@ -849,9 +847,9 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, · 54 unmodified lines | ||
| 849 | 847 | mid->mid_state = MID_REQUEST_SUBMITTED; |
| 850 | 848 | |
| 851 | 849 | /* put it on the pending_mid_q */ |
| 852 | − spin_lock(&GlobalMid_Lock); | |
| 850 | + spin_lock(&server->mid_lock); | |
| 853 | 851 | list_add_tail(&mid->qhead, &server->pending_mid_q); |
| 854 | − spin_unlock(&GlobalMid_Lock); | |
| 852 | + spin_unlock(&server->mid_lock); | |
| 855 | 853 | |
| 856 | 854 | /* |
| 857 | 855 | * Need to store the time in mid before calling I/O. For call_async, |
| @@ -865,7 +863,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, · 7 unmodified lines | ||
| 865 | 863 | if (rc < 0) { |
| 866 | 864 | revert_current_mid(server, mid->credits); |
| 867 | 865 | server->sequence_number -= 2; |
| 868 | − cifs_delete_mid(mid); | |
| 866 | + delete_mid(mid); | |
| 869 | 867 | } |
| 870 | 868 | |
| 871 | 869 | cifs_server_unlock(server); |
| @@ -912,10 +910,10 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) · 40 unmodified lines | ||
| 912 | 910 | cifs_dbg(FYI, "%s: cmd=%d mid=%llu state=%d\n", |
| 913 | 911 | __func__, le16_to_cpu(mid->command), mid->mid, mid->mid_state); |
| 914 | 912 | |
| 915 | − spin_lock(&GlobalMid_Lock); | |
| 913 | + spin_lock(&server->mid_lock); | |
| 916 | 914 | switch (mid->mid_state) { |
| 917 | 915 | case MID_RESPONSE_RECEIVED: |
| 918 | − spin_unlock(&GlobalMid_Lock); | |
| 916 | + spin_unlock(&server->mid_lock); | |
| 919 | 917 | return rc; |
| 920 | 918 | case MID_RETRY_NEEDED: |
| 921 | 919 | rc = -EAGAIN; |
| @@ -935,9 +933,9 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) · 13 unmodified lines | ||
| 935 | 933 | __func__, mid->mid, mid->mid_state); |
| 936 | 934 | rc = -EIO; |
| 937 | 935 | } |
| 938 | − spin_unlock(&GlobalMid_Lock); | |
| 936 | + spin_unlock(&server->mid_lock); | |
| 939 | 937 | |
| 940 | − DeleteMidQEntry(mid); | |
| 938 | + release_mid(mid); | |
| 941 | 939 | return rc; |
| 942 | 940 | } |
| 943 | 941 | |
| @@ -997,7 +995,7 @@ cifs_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *ignored, · 53 unmodified lines | ||
| 997 | 995 | return ERR_PTR(rc); |
| 998 | 996 | rc = cifs_sign_rqst(rqst, ses->server, &mid->sequence_number); |
| 999 | 997 | if (rc) { |
| 1000 | − cifs_delete_mid(mid); | |
| 998 | + delete_mid(mid); | |
| 1001 | 999 | return ERR_PTR(rc); |
| 1002 | 1000 | } |
| 1003 | 1001 | return mid; |
| @@ -1026,7 +1024,7 @@ static void · 22 unmodified lines | ||
| 1026 | 1024 | cifs_cancelled_callback(struct mid_q_entry *mid) |
| 1027 | 1025 | { |
| 1028 | 1026 | cifs_compound_callback(mid); |
| 1029 | − DeleteMidQEntry(mid); | |
| 1027 | + release_mid(mid); | |
| 1030 | 1028 | } |
| 1031 | 1029 | |
| 1032 | 1030 | /* |
| @@ -1078,12 +1076,12 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, · 45 unmodified lines | ||
| 1078 | 1076 | return -EIO; |
| 1079 | 1077 | } |
| 1080 | 1078 | |
| 1081 | − spin_lock(&cifs_tcp_ses_lock); | |
| 1079 | + spin_lock(&server->srv_lock); | |
| 1082 | 1080 | if (server->tcpStatus == CifsExiting) { |
| 1083 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1081 | + spin_unlock(&server->srv_lock); | |
| 1084 | 1082 | return -ENOENT; |
| 1085 | 1083 | } |
| 1086 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1084 | + spin_unlock(&server->srv_lock); | |
| 1087 | 1085 | |
| 1088 | 1086 | /* |
| 1089 | 1087 | * Wait for all the requests to become available. |
| @@ -1130,7 +1128,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, · 40 unmodified lines | ||
| 1130 | 1128 | if (IS_ERR(midQ[i])) { |
| 1131 | 1129 | revert_current_mid(server, i); |
| 1132 | 1130 | for (j = 0; j < i; j++) |
| 1133 | − cifs_delete_mid(midQ[j]); | |
| 1131 | + delete_mid(midQ[j]); | |
| 1134 | 1132 | cifs_server_unlock(server); |
| 1135 | 1133 | |
| 1136 | 1134 | /* Update # of requests on wire to server */ |
| @@ -1186,17 +1184,17 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, · 49 unmodified lines | ||
| 1186 | 1184 | /* |
| 1187 | 1185 | * Compounding is never used during session establish. |
| 1188 | 1186 | */ |
| 1189 | − spin_lock(&cifs_tcp_ses_lock); | |
| 1187 | + spin_lock(&ses->ses_lock); | |
| 1190 | 1188 | if ((ses->ses_status == SES_NEW) || (optype & CIFS_NEG_OP) || (optype & CIFS_SESS_OP)) { |
| 1191 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1189 | + spin_unlock(&ses->ses_lock); | |
| 1192 | 1190 | |
| 1193 | 1191 | cifs_server_lock(server); |
| 1194 | 1192 | smb311_update_preauth_hash(ses, server, rqst[0].rq_iov, rqst[0].rq_nvec); |
| 1195 | 1193 | cifs_server_unlock(server); |
| 1196 | 1194 | |
| 1197 | − spin_lock(&cifs_tcp_ses_lock); | |
| 1195 | + spin_lock(&ses->ses_lock); | |
| 1198 | 1196 | } |
| 1199 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1197 | + spin_unlock(&ses->ses_lock); | |
| 1200 | 1198 | |
| 1201 | 1199 | for (i = 0; i < num_rqst; i++) { |
| 1202 | 1200 | rc = wait_for_response(server, midQ[i]); |
| @@ -1208,14 +1206,14 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, · 5 unmodified lines | ||
| 1208 | 1206 | cifs_server_dbg(FYI, "Cancelling wait for mid %llu cmd: %d\n", |
| 1209 | 1207 | midQ[i]->mid, le16_to_cpu(midQ[i]->command)); |
| 1210 | 1208 | send_cancel(server, &rqst[i], midQ[i]); |
| 1211 | − spin_lock(&GlobalMid_Lock); | |
| 1209 | + spin_lock(&server->mid_lock); | |
| 1212 | 1210 | midQ[i]->mid_flags |= MID_WAIT_CANCELLED; |
| 1213 | 1211 | if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) { |
| 1214 | 1212 | midQ[i]->callback = cifs_cancelled_callback; |
| 1215 | 1213 | cancelled_mid[i] = true; |
| 1216 | 1214 | credits[i].value = 0; |
| 1217 | 1215 | } |
| 1218 | − spin_unlock(&GlobalMid_Lock); | |
| 1216 | + spin_unlock(&server->mid_lock); | |
| 1219 | 1217 | } |
| 1220 | 1218 | } |
| 1221 | 1219 | |
| @@ -1250,7 +1248,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, · 28 unmodified lines | ||
| 1250 | 1248 | rc = server->ops->check_receive(midQ[i], server, |
| 1251 | 1249 | flags & CIFS_LOG_ERROR); |
| 1252 | 1250 | |
| 1253 | − /* mark it so buf will not be freed by cifs_delete_mid */ | |
| 1251 | + /* mark it so buf will not be freed by delete_mid */ | |
| 1254 | 1252 | if ((flags & CIFS_NO_RSP_BUF) == 0) |
| 1255 | 1253 | midQ[i]->resp_buf = NULL; |
| 1256 | 1254 | |
| @@ -1259,19 +1257,19 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, · 2 unmodified lines | ||
| 1259 | 1257 | /* |
| 1260 | 1258 | * Compounding is never used during session establish. |
| 1261 | 1259 | */ |
| 1262 | − spin_lock(&cifs_tcp_ses_lock); | |
| 1260 | + spin_lock(&ses->ses_lock); | |
| 1263 | 1261 | if ((ses->ses_status == SES_NEW) || (optype & CIFS_NEG_OP) || (optype & CIFS_SESS_OP)) { |
| 1264 | 1262 | struct kvec iov = { |
| 1265 | 1263 | .iov_base = resp_iov[0].iov_base, |
| 1266 | 1264 | .iov_len = resp_iov[0].iov_len |
| 1267 | 1265 | }; |
| 1268 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1266 | + spin_unlock(&ses->ses_lock); | |
| 1269 | 1267 | cifs_server_lock(server); |
| 1270 | 1268 | smb311_update_preauth_hash(ses, server, &iov, 1); |
| 1271 | 1269 | cifs_server_unlock(server); |
| 1272 | − spin_lock(&cifs_tcp_ses_lock); | |
| 1270 | + spin_lock(&ses->ses_lock); | |
| 1273 | 1271 | } |
| 1274 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1272 | + spin_unlock(&ses->ses_lock); | |
| 1275 | 1273 | |
| 1276 | 1274 | out: |
| 1277 | 1275 | /* |
| @@ -1282,7 +1280,7 @@ out: · 4 unmodified lines | ||
| 1282 | 1280 | */ |
| 1283 | 1281 | for (i = 0; i < num_rqst; i++) { |
| 1284 | 1282 | if (!cancelled_mid[i]) |
| 1285 | − cifs_delete_mid(midQ[i]); | |
| 1283 | + delete_mid(midQ[i]); | |
| 1286 | 1284 | } |
| 1287 | 1285 | |
| 1288 | 1286 | return rc; |
| @@ -1360,12 +1358,12 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, · 71 unmodified lines | ||
| 1360 | 1358 | return -EIO; |
| 1361 | 1359 | } |
| 1362 | 1360 | |
| 1363 | − spin_lock(&cifs_tcp_ses_lock); | |
| 1361 | + spin_lock(&server->srv_lock); | |
| 1364 | 1362 | if (server->tcpStatus == CifsExiting) { |
| 1365 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1363 | + spin_unlock(&server->srv_lock); | |
| 1366 | 1364 | return -ENOENT; |
| 1367 | 1365 | } |
| 1368 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1366 | + spin_unlock(&server->srv_lock); | |
| 1369 | 1367 | |
| 1370 | 1368 | /* Ensure that we do not send more than 50 overlapping requests |
| 1371 | 1369 | to the same server. We may make this configurable later or |
| @@ -1419,15 +1417,15 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, · 47 unmodified lines | ||
| 1419 | 1417 | rc = wait_for_response(server, midQ); |
| 1420 | 1418 | if (rc != 0) { |
| 1421 | 1419 | send_cancel(server, &rqst, midQ); |
| 1422 | − spin_lock(&GlobalMid_Lock); | |
| 1420 | + spin_lock(&server->mid_lock); | |
| 1423 | 1421 | if (midQ->mid_state == MID_REQUEST_SUBMITTED) { |
| 1424 | 1422 | /* no longer considered to be "in-flight" */ |
| 1425 | − midQ->callback = DeleteMidQEntry; | |
| 1426 | − spin_unlock(&GlobalMid_Lock); | |
| 1423 | + midQ->callback = release_mid; | |
| 1424 | + spin_unlock(&server->mid_lock); | |
| 1427 | 1425 | add_credits(server, &credits, 0); |
| 1428 | 1426 | return rc; |
| 1429 | 1427 | } |
| 1430 | − spin_unlock(&GlobalMid_Lock); | |
| 1428 | + spin_unlock(&server->mid_lock); | |
| 1431 | 1429 | } |
| 1432 | 1430 | |
| 1433 | 1431 | rc = cifs_sync_mid_result(midQ, server); |
| @@ -1447,7 +1445,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, · 13 unmodified lines | ||
| 1447 | 1445 | memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); |
| 1448 | 1446 | rc = cifs_check_receive(midQ, server, 0); |
| 1449 | 1447 | out: |
| 1450 | − cifs_delete_mid(midQ); | |
| 1448 | + delete_mid(midQ); | |
| 1451 | 1449 | add_credits(server, &credits, 0); |
| 1452 | 1450 | |
| 1453 | 1451 | return rc; |
| @@ -1505,12 +1503,12 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, · 51 unmodified lines | ||
| 1505 | 1503 | return -EIO; |
| 1506 | 1504 | } |
| 1507 | 1505 | |
| 1508 | − spin_lock(&cifs_tcp_ses_lock); | |
| 1506 | + spin_lock(&server->srv_lock); | |
| 1509 | 1507 | if (server->tcpStatus == CifsExiting) { |
| 1510 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1508 | + spin_unlock(&server->srv_lock); | |
| 1511 | 1509 | return -ENOENT; |
| 1512 | 1510 | } |
| 1513 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1511 | + spin_unlock(&server->srv_lock); | |
| 1514 | 1512 | |
| 1515 | 1513 | /* Ensure that we do not send more than 50 overlapping requests |
| 1516 | 1514 | to the same server. We may make this configurable later or |
| @@ -1540,7 +1538,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, · 23 unmodified lines | ||
| 1540 | 1538 | |
| 1541 | 1539 | rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number); |
| 1542 | 1540 | if (rc) { |
| 1543 | − cifs_delete_mid(midQ); | |
| 1541 | + delete_mid(midQ); | |
| 1544 | 1542 | cifs_server_unlock(server); |
| 1545 | 1543 | return rc; |
| 1546 | 1544 | } |
| @@ -1557,7 +1555,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, · 10 unmodified lines | ||
| 1557 | 1555 | cifs_server_unlock(server); |
| 1558 | 1556 | |
| 1559 | 1557 | if (rc < 0) { |
| 1560 | − cifs_delete_mid(midQ); | |
| 1558 | + delete_mid(midQ); | |
| 1561 | 1559 | return rc; |
| 1562 | 1560 | } |
| 1563 | 1561 | |
| @@ -1568,19 +1566,19 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, · 4 unmodified lines | ||
| 1568 | 1566 | (server->tcpStatus != CifsNew))); |
| 1569 | 1567 | |
| 1570 | 1568 | /* Were we interrupted by a signal ? */ |
| 1571 | − spin_lock(&cifs_tcp_ses_lock); | |
| 1569 | + spin_lock(&server->srv_lock); | |
| 1572 | 1570 | if ((rc == -ERESTARTSYS) && |
| 1573 | 1571 | (midQ->mid_state == MID_REQUEST_SUBMITTED) && |
| 1574 | 1572 | ((server->tcpStatus == CifsGood) || |
| 1575 | 1573 | (server->tcpStatus == CifsNew))) { |
| 1576 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1574 | + spin_unlock(&server->srv_lock); | |
| 1577 | 1575 | |
| 1578 | 1576 | if (in_buf->Command == SMB_COM_TRANSACTION2) { |
| 1579 | 1577 | /* POSIX lock. We send a NT_CANCEL SMB to cause the |
| 1580 | 1578 | blocking lock to return. */ |
| 1581 | 1579 | rc = send_cancel(server, &rqst, midQ); |
| 1582 | 1580 | if (rc) { |
| 1583 | − cifs_delete_mid(midQ); | |
| 1581 | + delete_mid(midQ); | |
| 1584 | 1582 | return rc; |
| 1585 | 1583 | } |
| 1586 | 1584 | } else { |
| @@ -1592,7 +1590,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, · 5 unmodified lines | ||
| 1592 | 1590 | /* If we get -ENOLCK back the lock may have |
| 1593 | 1591 | already been removed. Don't exit in this case. */ |
| 1594 | 1592 | if (rc && rc != -ENOLCK) { |
| 1595 | − cifs_delete_mid(midQ); | |
| 1593 | + delete_mid(midQ); | |
| 1596 | 1594 | return rc; |
| 1597 | 1595 | } |
| 1598 | 1596 | } |
| @@ -1600,21 +1598,21 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, · 1 unmodified line | ||
| 1600 | 1598 | rc = wait_for_response(server, midQ); |
| 1601 | 1599 | if (rc) { |
| 1602 | 1600 | send_cancel(server, &rqst, midQ); |
| 1603 | − spin_lock(&GlobalMid_Lock); | |
| 1601 | + spin_lock(&server->mid_lock); | |
| 1604 | 1602 | if (midQ->mid_state == MID_REQUEST_SUBMITTED) { |
| 1605 | 1603 | /* no longer considered to be "in-flight" */ |
| 1606 | − midQ->callback = DeleteMidQEntry; | |
| 1607 | − spin_unlock(&GlobalMid_Lock); | |
| 1604 | + midQ->callback = release_mid; | |
| 1605 | + spin_unlock(&server->mid_lock); | |
| 1608 | 1606 | return rc; |
| 1609 | 1607 | } |
| 1610 | − spin_unlock(&GlobalMid_Lock); | |
| 1608 | + spin_unlock(&server->mid_lock); | |
| 1611 | 1609 | } |
| 1612 | 1610 | |
| 1613 | 1611 | /* We got the response - restart system call. */ |
| 1614 | 1612 | rstart = 1; |
| 1615 | − spin_lock(&cifs_tcp_ses_lock); | |
| 1613 | + spin_lock(&server->srv_lock); | |
| 1616 | 1614 | } |
| 1617 | − spin_unlock(&cifs_tcp_ses_lock); | |
| 1615 | + spin_unlock(&server->srv_lock); | |
| 1618 | 1616 | |
| 1619 | 1617 | rc = cifs_sync_mid_result(midQ, server); |
| 1620 | 1618 | if (rc != 0) |
| @@ -1631,8 +1629,186 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, · 10 unmodified lines | ||
| 1631 | 1629 | memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); |
| 1632 | 1630 | rc = cifs_check_receive(midQ, server, 0); |
| 1633 | 1631 | out: |
| 1634 | − cifs_delete_mid(midQ); | |
| 1632 | + delete_mid(midQ); | |
| 1635 | 1633 | if (rstart && rc == -EACCES) |
| 1636 | 1634 | return -ERESTARTSYS; |
| 1637 | 1635 | return rc; |
| 1638 | 1636 | } |
| 1637 | + | |
| 1638 | +/* | |
| 1639 | + * Discard any remaining data in the current SMB. To do this, we borrow the | |
| 1640 | + * current bigbuf. | |
| 1641 | + */ | |
| 1642 | +int | |
| 1643 | +cifs_discard_remaining_data(struct TCP_Server_Info *server) | |
| 1644 | +{ | |
| 1645 | + unsigned int rfclen = server->pdu_size; | |
| 1646 | + int remaining = rfclen + server->vals->header_preamble_size - | |
| 1647 | + server->total_read; | |
| 1648 | + | |
| 1649 | + while (remaining > 0) { | |
| 1650 | + int length; | |
| 1651 | + | |
| 1652 | + length = cifs_discard_from_socket(server, | |
| 1653 | + min_t(size_t, remaining, | |
| 1654 | + CIFSMaxBufSize + MAX_HEADER_SIZE(server))); | |
| 1655 | + if (length < 0) | |
| 1656 | + return length; | |
| 1657 | + server->total_read += length; | |
| 1658 | + remaining -= length; | |
| 1659 | + } | |
| 1660 | + | |
| 1661 | + return 0; | |
| 1662 | +} | |
| 1663 | + | |
| 1664 | +static int | |
| 1665 | +__cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid, | |
| 1666 | + bool malformed) | |
| 1667 | +{ | |
| 1668 | + int length; | |
| 1669 | + | |
| 1670 | + length = cifs_discard_remaining_data(server); | |
| 1671 | + dequeue_mid(mid, malformed); | |
| 1672 | + mid->resp_buf = server->smallbuf; | |
| 1673 | + server->smallbuf = NULL; | |
| 1674 | + return length; | |
| 1675 | +} | |
| 1676 | + | |
| 1677 | +static int | |
| 1678 | +cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |
| 1679 | +{ | |
| 1680 | + struct cifs_readdata *rdata = mid->callback_data; | |
| 1681 | + | |
| 1682 | + return __cifs_readv_discard(server, mid, rdata->result); | |
| 1683 | +} | |
| 1684 | + | |
| 1685 | +int | |
| 1686 | +cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |
| 1687 | +{ | |
| 1688 | + int length, len; | |
| 1689 | + unsigned int data_offset, data_len; | |
| 1690 | + struct cifs_readdata *rdata = mid->callback_data; | |
| 1691 | + char *buf = server->smallbuf; | |
| 1692 | + unsigned int buflen = server->pdu_size + | |
| 1693 | + server->vals->header_preamble_size; | |
| 1694 | + bool use_rdma_mr = false; | |
| 1695 | + | |
| 1696 | + cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n", | |
| 1697 | + __func__, mid->mid, rdata->offset, rdata->bytes); | |
| 1698 | + | |
| 1699 | + /* | |
| 1700 | + * read the rest of READ_RSP header (sans Data array), or whatever we | |
| 1701 | + * can if there's not enough data. At this point, we've read down to | |
| 1702 | + * the Mid. | |
| 1703 | + */ | |
| 1704 | + len = min_t(unsigned int, buflen, server->vals->read_rsp_size) - | |
| 1705 | + HEADER_SIZE(server) + 1; | |
| 1706 | + | |
| 1707 | + length = cifs_read_from_socket(server, | |
| 1708 | + buf + HEADER_SIZE(server) - 1, len); | |
| 1709 | + if (length < 0) | |
| 1710 | + return length; | |
| 1711 | + server->total_read += length; | |
| 1712 | + | |
| 1713 | + if (server->ops->is_session_expired && | |
| 1714 | + server->ops->is_session_expired(buf)) { | |
| 1715 | + cifs_reconnect(server, true); | |
| 1716 | + return -1; | |
| 1717 | + } | |
| 1718 | + | |
| 1719 | + if (server->ops->is_status_pending && | |
| 1720 | + server->ops->is_status_pending(buf, server)) { | |
| 1721 | + cifs_discard_remaining_data(server); | |
| 1722 | + return -1; | |
| 1723 | + } | |
| 1724 | + | |
| 1725 | + /* set up first two iov for signature check and to get credits */ | |
| 1726 | + rdata->iov[0].iov_base = buf; | |
| 1727 | + rdata->iov[0].iov_len = server->vals->header_preamble_size; | |
| 1728 | + rdata->iov[1].iov_base = buf + server->vals->header_preamble_size; | |
| 1729 | + rdata->iov[1].iov_len = | |
| 1730 | + server->total_read - server->vals->header_preamble_size; | |
| 1731 | + cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n", | |
| 1732 | + rdata->iov[0].iov_base, rdata->iov[0].iov_len); | |
| 1733 | + cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n", | |
| 1734 | + rdata->iov[1].iov_base, rdata->iov[1].iov_len); | |
| 1735 | + | |
| 1736 | + /* Was the SMB read successful? */ | |
| 1737 | + rdata->result = server->ops->map_error(buf, false); | |
| 1738 | + if (rdata->result != 0) { | |
| 1739 | + cifs_dbg(FYI, "%s: server returned error %d\n", | |
| 1740 | + __func__, rdata->result); | |
| 1741 | + /* normal error on read response */ | |
| 1742 | + return __cifs_readv_discard(server, mid, false); | |
| 1743 | + } | |
| 1744 | + | |
| 1745 | + /* Is there enough to get to the rest of the READ_RSP header? */ | |
| 1746 | + if (server->total_read < server->vals->read_rsp_size) { | |
| 1747 | + cifs_dbg(FYI, "%s: server returned short header. got=%u expected=%zu\n", | |
| 1748 | + __func__, server->total_read, | |
| 1749 | + server->vals->read_rsp_size); | |
| 1750 | + rdata->result = -EIO; | |
| 1751 | + return cifs_readv_discard(server, mid); | |
| 1752 | + } | |
| 1753 | + | |
| 1754 | + data_offset = server->ops->read_data_offset(buf) + | |
| 1755 | + server->vals->header_preamble_size; | |
| 1756 | + if (data_offset < server->total_read) { | |
| 1757 | + /* | |
| 1758 | + * win2k8 sometimes sends an offset of 0 when the read | |
| 1759 | + * is beyond the EOF. Treat it as if the data starts just after | |
| 1760 | + * the header. | |
| 1761 | + */ | |
| 1762 | + cifs_dbg(FYI, "%s: data offset (%u) inside read response header\n", | |
| 1763 | + __func__, data_offset); | |
| 1764 | + data_offset = server->total_read; | |
| 1765 | + } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) { | |
| 1766 | + /* data_offset is beyond the end of smallbuf */ | |
| 1767 | + cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n", | |
| 1768 | + __func__, data_offset); | |
| 1769 | + rdata->result = -EIO; | |
| 1770 | + return cifs_readv_discard(server, mid); | |
| 1771 | + } | |
| 1772 | + | |
| 1773 | + cifs_dbg(FYI, "%s: total_read=%u data_offset=%u\n", | |
| 1774 | + __func__, server->total_read, data_offset); | |
| 1775 | + | |
| 1776 | + len = data_offset - server->total_read; | |
| 1777 | + if (len > 0) { | |
| 1778 | + /* read any junk before data into the rest of smallbuf */ | |
| 1779 | + length = cifs_read_from_socket(server, | |
| 1780 | + buf + server->total_read, len); | |
| 1781 | + if (length < 0) | |
| 1782 | + return length; | |
| 1783 | + server->total_read += length; | |
| 1784 | + } | |
| 1785 | + | |
| 1786 | + /* how much data is in the response? */ | |
| 1787 | +#ifdef CONFIG_CIFS_SMB_DIRECT | |
| 1788 | + use_rdma_mr = rdata->mr; | |
| 1789 | +#endif | |
| 1790 | + data_len = server->ops->read_data_length(buf, use_rdma_mr); | |
| 1791 | + if (!use_rdma_mr && (data_offset + data_len > buflen)) { | |
| 1792 | + /* data_len is corrupt -- discard frame */ | |
| 1793 | + rdata->result = -EIO; | |
| 1794 | + return cifs_readv_discard(server, mid); | |
| 1795 | + } | |
| 1796 | + | |
| 1797 | + length = rdata->read_into_pages(server, rdata, data_len); | |
| 1798 | + if (length < 0) | |
| 1799 | + return length; | |
| 1800 | + | |
| 1801 | + server->total_read += length; | |
| 1802 | + | |
| 1803 | + cifs_dbg(FYI, "total_read=%u buflen=%u remaining=%u\n", | |
| 1804 | + server->total_read, buflen, data_len); | |
| 1805 | + | |
| 1806 | + /* discard anything left over */ | |
| 1807 | + if (server->total_read < buflen) | |
| 1808 | + return cifs_readv_discard(server, mid); | |
| 1809 | + | |
| 1810 | + dequeue_mid(mid, false); | |
| 1811 | + mid->resp_buf = server->smallbuf; | |
| 1812 | + server->smallbuf = NULL; | |
| 1813 | + return length; | |
| 1814 | +} | |
| @@ -201,6 +201,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler, · 200 unmodified lines | ||
| 201 | 201 | break; |
| 202 | 202 | } |
| 203 | 203 | |
| 204 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 204 | 205 | case XATTR_ACL_ACCESS: |
| 205 | 206 | #ifdef CONFIG_CIFS_POSIX |
| 206 | 207 | if (!value) |
| @@ -224,6 +225,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler, · 17 unmodified lines | ||
| 224 | 225 | cifs_remap(cifs_sb)); |
| 225 | 226 | #endif /* CONFIG_CIFS_POSIX */ |
| 226 | 227 | break; |
| 228 | +#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 227 | 229 | } |
| 228 | 230 | |
| 229 | 231 | out: |
| @@ -364,7 +366,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler, · 134 unmodified lines | ||
| 364 | 366 | } |
| 365 | 367 | break; |
| 366 | 368 | } |
| 367 | − | |
| 369 | +#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | |
| 368 | 370 | case XATTR_ACL_ACCESS: |
| 369 | 371 | #ifdef CONFIG_CIFS_POSIX |
| 370 | 372 | if (sb->s_flags & SB_POSIXACL) |
| @@ -384,6 +386,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler, · 13 unmodified lines | ||
| 384 | 386 | cifs_remap(cifs_sb)); |
| 385 | 387 | #endif /* CONFIG_CIFS_POSIX */ |
| 386 | 388 | break; |
| 389 | +#endif /* ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | |
| 387 | 390 | } |
| 388 | 391 | |
| 389 | 392 | /* We could add an additional check for streams ie |