Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag '5.7-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
"Ten cifs/smb fixes:

- five RDMA (smbdirect) related fixes

- add experimental support for swap over SMB3 mounts

- also a fix which improves performance of signed connections"

* tag '5.7-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6:
smb3: enable swap on SMB3 mounts
smb3: change noisy error message to FYI
smb3: smbdirect support can be configured by default
cifs: smbd: Do not schedule work to send immediate packet on every receive
cifs: smbd: Properly process errors on ib_post_send
cifs: Allocate crypto structures on the fly for calculating signatures of incoming packets
cifs: smbd: Update receive credits before sending and deal with credits roll back on failure before sending
cifs: smbd: Check send queue size before posting a send
cifs: smbd: Merge code to track pending packets
cifs: ignore cached share root handle closing errors

+284 -250
+1 -1
fs/cifs/Kconfig
··· 202 202 help 203 203 Enables SMB Direct support for SMB 3.0, 3.02 and 3.1.1. 204 204 SMB Direct allows transferring SMB packets over RDMA. If unsure, 205 - say N. 205 + say Y. 206 206 207 207 config CIFS_FSCACHE 208 208 bool "Provide CIFS client caching support"
+2 -4
fs/cifs/cifs_debug.c
··· 323 323 atomic_read(&server->smbd_conn->send_credits), 324 324 atomic_read(&server->smbd_conn->receive_credits), 325 325 server->smbd_conn->receive_credit_target); 326 - seq_printf(m, "\nPending send_pending: %x " 327 - "send_payload_pending: %x", 328 - atomic_read(&server->smbd_conn->send_pending), 329 - atomic_read(&server->smbd_conn->send_payload_pending)); 326 + seq_printf(m, "\nPending send_pending: %x ", 327 + atomic_read(&server->smbd_conn->send_pending)); 330 328 seq_printf(m, "\nReceive buffers count_receive_queue: %x " 331 329 "count_empty_packet_queue: %x", 332 330 server->smbd_conn->count_receive_queue,
+4
fs/cifs/cifsfs.c
··· 1208 1208 { 1209 1209 unsigned int xid = get_xid(); 1210 1210 ssize_t rc; 1211 + struct cifsFileInfo *cfile = dst_file->private_data; 1212 + 1213 + if (cfile->swapfile) 1214 + return -EOPNOTSUPP; 1211 1215 1212 1216 rc = cifs_file_copychunk_range(xid, src_file, off, dst_file, destoff, 1213 1217 len, flags);
+3 -1
fs/cifs/cifsglob.h
··· 426 426 /* generate new lease key */ 427 427 void (*new_lease_key)(struct cifs_fid *); 428 428 int (*generate_signingkey)(struct cifs_ses *); 429 - int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *); 429 + int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *, 430 + bool allocate_crypto); 430 431 int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon, 431 432 struct cifsFileInfo *src_file); 432 433 int (*enum_snapshots)(const unsigned int xid, struct cifs_tcon *tcon, ··· 1313 1312 struct tcon_link *tlink; 1314 1313 unsigned int f_flags; 1315 1314 bool invalidHandle:1; /* file closed via session abend */ 1315 + bool swapfile:1; 1316 1316 bool oplock_break_cancelled:1; 1317 1317 unsigned int oplock_epoch; /* epoch from the lease break */ 1318 1318 __u32 oplock_level; /* oplock/lease level from the lease break */
+61
fs/cifs/file.c
··· 4808 4808 return -EINVAL; 4809 4809 } 4810 4810 4811 + static int cifs_swap_activate(struct swap_info_struct *sis, 4812 + struct file *swap_file, sector_t *span) 4813 + { 4814 + struct cifsFileInfo *cfile = swap_file->private_data; 4815 + struct inode *inode = swap_file->f_mapping->host; 4816 + unsigned long blocks; 4817 + long long isize; 4818 + 4819 + cifs_dbg(FYI, "swap activate\n"); 4820 + 4821 + spin_lock(&inode->i_lock); 4822 + blocks = inode->i_blocks; 4823 + isize = inode->i_size; 4824 + spin_unlock(&inode->i_lock); 4825 + if (blocks*512 < isize) { 4826 + pr_warn("swap activate: swapfile has holes\n"); 4827 + return -EINVAL; 4828 + } 4829 + *span = sis->pages; 4830 + 4831 + printk_once(KERN_WARNING "Swap support over SMB3 is experimental\n"); 4832 + 4833 + /* 4834 + * TODO: consider adding ACL (or documenting how) to prevent other 4835 + * users (on this or other systems) from reading it 4836 + */ 4837 + 4838 + 4839 + /* TODO: add sk_set_memalloc(inet) or similar */ 4840 + 4841 + if (cfile) 4842 + cfile->swapfile = true; 4843 + /* 4844 + * TODO: Since file already open, we can't open with DENY_ALL here 4845 + * but we could add call to grab a byte range lock to prevent others 4846 + * from reading or writing the file 4847 + */ 4848 + 4849 + return 0; 4850 + } 4851 + 4852 + static void cifs_swap_deactivate(struct file *file) 4853 + { 4854 + struct cifsFileInfo *cfile = file->private_data; 4855 + 4856 + cifs_dbg(FYI, "swap deactivate\n"); 4857 + 4858 + /* TODO: undo sk_set_memalloc(inet) will eventually be needed */ 4859 + 4860 + if (cfile) 4861 + cfile->swapfile = false; 4862 + 4863 + /* do we need to unpin (or unlock) the file */ 4864 + } 4811 4865 4812 4866 const struct address_space_operations cifs_addr_ops = { 4813 4867 .readpage = cifs_readpage, ··· 4875 4821 .direct_IO = cifs_direct_io, 4876 4822 .invalidatepage = cifs_invalidate_page, 4877 4823 .launder_page = cifs_launder_page, 4824 + /* 4825 + * TODO: investigate and if useful we could add an cifs_migratePage 4826 + * helper (under an CONFIG_MIGRATION) in the future, and also 4827 + * investigate and add an is_dirty_writeback helper if needed 4828 + */ 4829 + .swap_activate = cifs_swap_activate, 4830 + .swap_deactivate = cifs_swap_deactivate, 4878 4831 }; 4879 4832 4880 4833 /*
+4
fs/cifs/inode.c
··· 2026 2026 int rc; 2027 2027 unsigned long *flags = &CIFS_I(inode)->flags; 2028 2028 2029 + /* swapfiles are not supposed to be shared */ 2030 + if (IS_SWAPFILE(inode)) 2031 + return 0; 2032 + 2029 2033 rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable, 2030 2034 TASK_KILLABLE); 2031 2035 if (rc)
+1 -1
fs/cifs/readdir.c
··· 246 246 */ 247 247 fattr->cf_mode = le32_to_cpu(info->Mode) & ~S_IFMT; 248 248 249 - cifs_dbg(VFS, "XXX dev %d, reparse %d, mode %o", 249 + cifs_dbg(FYI, "posix fattr: dev %d, reparse %d, mode %o", 250 250 le32_to_cpu(info->DeviceId), 251 251 le32_to_cpu(info->ReparseTag), 252 252 le32_to_cpu(info->Mode));
+14
fs/cifs/smb2misc.c
··· 766 766 767 767 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count); 768 768 spin_lock(&cifs_tcp_ses_lock); 769 + if (tcon->tc_count <= 0) { 770 + struct TCP_Server_Info *server = NULL; 771 + 772 + WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative"); 773 + spin_unlock(&cifs_tcp_ses_lock); 774 + 775 + if (tcon->ses) 776 + server = tcon->ses->server; 777 + 778 + cifs_server_dbg(FYI, "tid=%u: tcon is closing, skipping async close retry of fid %llu %llu\n", 779 + tcon->tid, persistent_fid, volatile_fid); 780 + 781 + return 0; 782 + } 769 783 tcon->tc_count++; 770 784 spin_unlock(&cifs_tcp_ses_lock); 771 785
+4 -2
fs/cifs/smb2proto.h
··· 55 55 extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server, 56 56 __u64 ses_id, __u32 tid); 57 57 extern int smb2_calc_signature(struct smb_rqst *rqst, 58 - struct TCP_Server_Info *server); 58 + struct TCP_Server_Info *server, 59 + bool allocate_crypto); 59 60 extern int smb3_calc_signature(struct smb_rqst *rqst, 60 - struct TCP_Server_Info *server); 61 + struct TCP_Server_Info *server, 62 + bool allocate_crypto); 61 63 extern void smb2_echo_request(struct work_struct *work); 62 64 extern __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode); 63 65 extern bool smb2_is_valid_oplock_break(char *buffer,
+54 -33
fs/cifs/smb2transport.c
··· 41 41 #include "smb2glob.h" 42 42 43 43 static int 44 - smb2_crypto_shash_allocate(struct TCP_Server_Info *server) 45 - { 46 - return cifs_alloc_hash("hmac(sha256)", 47 - &server->secmech.hmacsha256, 48 - &server->secmech.sdeschmacsha256); 49 - } 50 - 51 - static int 52 44 smb3_crypto_shash_allocate(struct TCP_Server_Info *server) 53 45 { 54 46 struct cifs_secmech *p = &server->secmech; ··· 211 219 } 212 220 213 221 int 214 - smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) 222 + smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, 223 + bool allocate_crypto) 215 224 { 216 225 int rc; 217 226 unsigned char smb2_signature[SMB2_HMACSHA256_SIZE]; ··· 221 228 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base; 222 229 struct cifs_ses *ses; 223 230 struct shash_desc *shash; 231 + struct crypto_shash *hash; 232 + struct sdesc *sdesc = NULL; 224 233 struct smb_rqst drqst; 225 234 226 235 ses = smb2_find_smb_ses(server, shdr->SessionId); ··· 234 239 memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE); 235 240 memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE); 236 241 237 - rc = smb2_crypto_shash_allocate(server); 238 - if (rc) { 239 - cifs_server_dbg(VFS, "%s: sha256 alloc failed\n", __func__); 240 - return rc; 242 + if (allocate_crypto) { 243 + rc = cifs_alloc_hash("hmac(sha256)", &hash, &sdesc); 244 + if (rc) { 245 + cifs_server_dbg(VFS, 246 + "%s: sha256 alloc failed\n", __func__); 247 + return rc; 248 + } 249 + shash = &sdesc->shash; 250 + } else { 251 + hash = server->secmech.hmacsha256; 252 + shash = &server->secmech.sdeschmacsha256->shash; 241 253 } 242 254 243 - rc = crypto_shash_setkey(server->secmech.hmacsha256, 244 - ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE); 255 + rc = crypto_shash_setkey(hash, ses->auth_key.response, 256 + SMB2_NTLMV2_SESSKEY_SIZE); 245 257 if (rc) { 246 - cifs_server_dbg(VFS, "%s: Could not update with response\n", __func__); 247 - return rc; 258 + cifs_server_dbg(VFS, 259 + "%s: Could not update with response\n", 260 + __func__); 261 + goto out; 248 262 } 249 263 250 - shash = &server->secmech.sdeschmacsha256->shash; 251 264 rc = crypto_shash_init(shash); 252 265 if (rc) { 253 266 cifs_server_dbg(VFS, "%s: Could not init sha256", __func__); 254 - return rc; 267 + goto out; 255 268 } 256 269 257 270 /* ··· 274 271 rc = crypto_shash_update(shash, iov[0].iov_base, 275 272 iov[0].iov_len); 276 273 if (rc) { 277 - cifs_server_dbg(VFS, "%s: Could not update with payload\n", 278 - __func__); 279 - return rc; 274 + cifs_server_dbg(VFS, 275 + "%s: Could not update with payload\n", 276 + __func__); 277 + goto out; 280 278 } 281 279 drqst.rq_iov++; 282 280 drqst.rq_nvec--; ··· 287 283 if (!rc) 288 284 memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE); 289 285 286 + out: 287 + if (allocate_crypto) 288 + cifs_free_hash(&hash, &sdesc); 290 289 return rc; 291 290 } 292 291 ··· 511 504 } 512 505 513 506 int 514 - smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) 507 + smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, 508 + bool allocate_crypto) 515 509 { 516 510 int rc; 517 511 unsigned char smb3_signature[SMB2_CMACAES_SIZE]; 518 512 unsigned char *sigptr = smb3_signature; 519 513 struct kvec *iov = rqst->rq_iov; 520 514 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base; 521 - struct shash_desc *shash = &server->secmech.sdesccmacaes->shash; 515 + struct shash_desc *shash; 516 + struct crypto_shash *hash; 517 + struct sdesc *sdesc = NULL; 522 518 struct smb_rqst drqst; 523 519 u8 key[SMB3_SIGN_KEY_SIZE]; 524 520 ··· 529 519 if (rc) 530 520 return 0; 531 521 522 + if (allocate_crypto) { 523 + rc = cifs_alloc_hash("cmac(aes)", &hash, &sdesc); 524 + if (rc) 525 + return rc; 526 + 527 + shash = &sdesc->shash; 528 + } else { 529 + hash = server->secmech.cmacaes; 530 + shash = &server->secmech.sdesccmacaes->shash; 531 + } 532 + 532 533 memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE); 533 534 memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE); 534 535 535 - rc = crypto_shash_setkey(server->secmech.cmacaes, 536 - key, SMB2_CMACAES_SIZE); 536 + rc = crypto_shash_setkey(hash, key, SMB2_CMACAES_SIZE); 537 537 if (rc) { 538 538 cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__); 539 - return rc; 539 + goto out; 540 540 } 541 541 542 542 /* ··· 557 537 rc = crypto_shash_init(shash); 558 538 if (rc) { 559 539 cifs_server_dbg(VFS, "%s: Could not init cmac aes\n", __func__); 560 - return rc; 540 + goto out; 561 541 } 562 542 563 543 /* ··· 574 554 if (rc) { 575 555 cifs_server_dbg(VFS, "%s: Could not update with payload\n", 576 556 __func__); 577 - return rc; 557 + goto out; 578 558 } 579 559 drqst.rq_iov++; 580 560 drqst.rq_nvec--; ··· 584 564 if (!rc) 585 565 memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE); 586 566 567 + out: 568 + if (allocate_crypto) 569 + cifs_free_hash(&hash, &sdesc); 587 570 return rc; 588 571 } 589 572 ··· 616 593 return 0; 617 594 } 618 595 619 - rc = server->ops->calc_signature(rqst, server); 596 + rc = server->ops->calc_signature(rqst, server, false); 620 597 621 598 return rc; 622 599 } ··· 654 631 655 632 memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE); 656 633 657 - mutex_lock(&server->srv_mutex); 658 - rc = server->ops->calc_signature(rqst, server); 659 - mutex_unlock(&server->srv_mutex); 634 + rc = server->ops->calc_signature(rqst, server, true); 660 635 661 636 if (rc) 662 637 return rc;
+135 -202
fs/cifs/smbdirect.c
··· 284 284 request->sge[i].length, 285 285 DMA_TO_DEVICE); 286 286 287 - if (request->has_payload) { 288 - if (atomic_dec_and_test(&request->info->send_payload_pending)) 289 - wake_up(&request->info->wait_send_payload_pending); 290 - } else { 291 - if (atomic_dec_and_test(&request->info->send_pending)) 292 - wake_up(&request->info->wait_send_pending); 293 - } 287 + if (atomic_dec_and_test(&request->info->send_pending)) 288 + wake_up(&request->info->wait_send_pending); 289 + 290 + wake_up(&request->info->wait_post_send); 294 291 295 292 mempool_free(request, request->info->request_mempool); 296 293 } ··· 380 383 return true; 381 384 } 382 385 383 - /* 384 - * Check and schedule to send an immediate packet 385 - * This is used to extend credtis to remote peer to keep the transport busy 386 - */ 387 - static void check_and_send_immediate(struct smbd_connection *info) 388 - { 389 - if (info->transport_status != SMBD_CONNECTED) 390 - return; 391 - 392 - info->send_immediate = true; 393 - 394 - /* 395 - * Promptly send a packet if our peer is running low on receive 396 - * credits 397 - */ 398 - if (atomic_read(&info->receive_credits) < 399 - info->receive_credit_target - 1) 400 - queue_delayed_work( 401 - info->workqueue, &info->send_immediate_work, 0); 402 - } 403 - 404 386 static void smbd_post_send_credits(struct work_struct *work) 405 387 { 406 388 int ret = 0; ··· 429 453 info->new_credits_offered += ret; 430 454 spin_unlock(&info->lock_new_credits_offered); 431 455 432 - atomic_add(ret, &info->receive_credits); 433 - 434 - /* Check if we can post new receive and grant credits to peer */ 435 - check_and_send_immediate(info); 456 + /* Promptly send an immediate packet as defined in [MS-SMBD] 3.1.1.1 */ 457 + info->send_immediate = true; 458 + if (atomic_read(&info->receive_credits) < 459 + info->receive_credit_target - 1) { 460 + if (info->keep_alive_requested == KEEP_ALIVE_PENDING || 461 + info->send_immediate) { 462 + log_keep_alive(INFO, "send an empty message\n"); 463 + smbd_post_send_empty(info); 464 + } 465 + } 436 466 } 437 467 438 468 /* Called from softirq, when recv is done */ ··· 532 550 SMB_DIRECT_RESPONSE_REQUESTED) { 533 551 info->keep_alive_requested = KEEP_ALIVE_PENDING; 534 552 } 535 - 536 - /* 537 - * Check if we need to send something to remote peer to 538 - * grant more credits or respond to KEEP_ALIVE packet 539 - */ 540 - check_and_send_immediate(info); 541 553 542 554 return; 543 555 ··· 725 749 request->sge[0].addr, 726 750 request->sge[0].length, request->sge[0].lkey); 727 751 728 - request->has_payload = false; 729 752 atomic_inc(&info->send_pending); 730 753 rc = ib_post_send(info->id->qp, &send_wr, NULL); 731 754 if (!rc) ··· 781 806 return 0; 782 807 } 783 808 784 - /* 785 - * Build and prepare the SMBD packet header 786 - * This function waits for avaialbe send credits and build a SMBD packet 787 - * header. The caller then optional append payload to the packet after 788 - * the header 789 - * intput values 790 - * size: the size of the payload 791 - * remaining_data_length: remaining data to send if this is part of a 792 - * fragmented packet 793 - * output values 794 - * request_out: the request allocated from this function 795 - * return values: 0 on success, otherwise actual error code returned 796 - */ 797 - static int smbd_create_header(struct smbd_connection *info, 798 - int size, int remaining_data_length, 799 - struct smbd_request **request_out) 800 - { 801 - struct smbd_request *request; 802 - struct smbd_data_transfer *packet; 803 - int header_length; 804 - int rc; 805 - 806 - /* Wait for send credits. A SMBD packet needs one credit */ 807 - rc = wait_event_interruptible(info->wait_send_queue, 808 - atomic_read(&info->send_credits) > 0 || 809 - info->transport_status != SMBD_CONNECTED); 810 - if (rc) 811 - return rc; 812 - 813 - if (info->transport_status != SMBD_CONNECTED) { 814 - log_outgoing(ERR, "disconnected not sending\n"); 815 - return -EAGAIN; 816 - } 817 - atomic_dec(&info->send_credits); 818 - 819 - request = mempool_alloc(info->request_mempool, GFP_KERNEL); 820 - if (!request) { 821 - rc = -ENOMEM; 822 - goto err; 823 - } 824 - 825 - request->info = info; 826 - 827 - /* Fill in the packet header */ 828 - packet = smbd_request_payload(request); 829 - packet->credits_requested = cpu_to_le16(info->send_credit_target); 830 - packet->credits_granted = 831 - cpu_to_le16(manage_credits_prior_sending(info)); 832 - info->send_immediate = false; 833 - 834 - packet->flags = 0; 835 - if (manage_keep_alive_before_sending(info)) 836 - packet->flags |= cpu_to_le16(SMB_DIRECT_RESPONSE_REQUESTED); 837 - 838 - packet->reserved = 0; 839 - if (!size) 840 - packet->data_offset = 0; 841 - else 842 - packet->data_offset = cpu_to_le32(24); 843 - packet->data_length = cpu_to_le32(size); 844 - packet->remaining_data_length = cpu_to_le32(remaining_data_length); 845 - packet->padding = 0; 846 - 847 - log_outgoing(INFO, "credits_requested=%d credits_granted=%d " 848 - "data_offset=%d data_length=%d remaining_data_length=%d\n", 849 - le16_to_cpu(packet->credits_requested), 850 - le16_to_cpu(packet->credits_granted), 851 - le32_to_cpu(packet->data_offset), 852 - le32_to_cpu(packet->data_length), 853 - le32_to_cpu(packet->remaining_data_length)); 854 - 855 - /* Map the packet to DMA */ 856 - header_length = sizeof(struct smbd_data_transfer); 857 - /* If this is a packet without payload, don't send padding */ 858 - if (!size) 859 - header_length = offsetof(struct smbd_data_transfer, padding); 860 - 861 - request->num_sge = 1; 862 - request->sge[0].addr = ib_dma_map_single(info->id->device, 863 - (void *)packet, 864 - header_length, 865 - DMA_TO_DEVICE); 866 - if (ib_dma_mapping_error(info->id->device, request->sge[0].addr)) { 867 - mempool_free(request, info->request_mempool); 868 - rc = -EIO; 869 - goto err; 870 - } 871 - 872 - request->sge[0].length = header_length; 873 - request->sge[0].lkey = info->pd->local_dma_lkey; 874 - 875 - *request_out = request; 876 - return 0; 877 - 878 - err: 879 - atomic_inc(&info->send_credits); 880 - return rc; 881 - } 882 - 883 - static void smbd_destroy_header(struct smbd_connection *info, 884 - struct smbd_request *request) 885 - { 886 - 887 - ib_dma_unmap_single(info->id->device, 888 - request->sge[0].addr, 889 - request->sge[0].length, 890 - DMA_TO_DEVICE); 891 - mempool_free(request, info->request_mempool); 892 - atomic_inc(&info->send_credits); 893 - } 894 - 895 809 /* Post the send request */ 896 810 static int smbd_post_send(struct smbd_connection *info, 897 - struct smbd_request *request, bool has_payload) 811 + struct smbd_request *request) 898 812 { 899 813 struct ib_send_wr send_wr; 900 814 int rc, i; ··· 808 944 send_wr.opcode = IB_WR_SEND; 809 945 send_wr.send_flags = IB_SEND_SIGNALED; 810 946 811 - if (has_payload) { 812 - request->has_payload = true; 813 - atomic_inc(&info->send_payload_pending); 814 - } else { 815 - request->has_payload = false; 816 - atomic_inc(&info->send_pending); 817 - } 818 - 819 947 rc = ib_post_send(info->id->qp, &send_wr, NULL); 820 948 if (rc) { 821 949 log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc); 822 - if (has_payload) { 823 - if (atomic_dec_and_test(&info->send_payload_pending)) 824 - wake_up(&info->wait_send_payload_pending); 825 - } else { 826 - if (atomic_dec_and_test(&info->send_pending)) 827 - wake_up(&info->wait_send_pending); 828 - } 829 950 smbd_disconnect_rdma_connection(info); 830 951 rc = -EAGAIN; 831 952 } else ··· 826 977 { 827 978 int num_sgs; 828 979 int i, rc; 980 + int header_length; 829 981 struct smbd_request *request; 982 + struct smbd_data_transfer *packet; 983 + int new_credits; 830 984 struct scatterlist *sg; 831 985 832 - rc = smbd_create_header( 833 - info, data_length, remaining_data_length, &request); 986 + wait_credit: 987 + /* Wait for send credits. A SMBD packet needs one credit */ 988 + rc = wait_event_interruptible(info->wait_send_queue, 989 + atomic_read(&info->send_credits) > 0 || 990 + info->transport_status != SMBD_CONNECTED); 834 991 if (rc) 835 - return rc; 992 + goto err_wait_credit; 836 993 994 + if (info->transport_status != SMBD_CONNECTED) { 995 + log_outgoing(ERR, "disconnected not sending on wait_credit\n"); 996 + rc = -EAGAIN; 997 + goto err_wait_credit; 998 + } 999 + if (unlikely(atomic_dec_return(&info->send_credits) < 0)) { 1000 + atomic_inc(&info->send_credits); 1001 + goto wait_credit; 1002 + } 1003 + 1004 + wait_send_queue: 1005 + wait_event(info->wait_post_send, 1006 + atomic_read(&info->send_pending) < info->send_credit_target || 1007 + info->transport_status != SMBD_CONNECTED); 1008 + 1009 + if (info->transport_status != SMBD_CONNECTED) { 1010 + log_outgoing(ERR, "disconnected not sending on wait_send_queue\n"); 1011 + rc = -EAGAIN; 1012 + goto err_wait_send_queue; 1013 + } 1014 + 1015 + if (unlikely(atomic_inc_return(&info->send_pending) > 1016 + info->send_credit_target)) { 1017 + atomic_dec(&info->send_pending); 1018 + goto wait_send_queue; 1019 + } 1020 + 1021 + request = mempool_alloc(info->request_mempool, GFP_KERNEL); 1022 + if (!request) { 1023 + rc = -ENOMEM; 1024 + goto err_alloc; 1025 + } 1026 + 1027 + request->info = info; 1028 + 1029 + /* Fill in the packet header */ 1030 + packet = smbd_request_payload(request); 1031 + packet->credits_requested = cpu_to_le16(info->send_credit_target); 1032 + 1033 + new_credits = manage_credits_prior_sending(info); 1034 + atomic_add(new_credits, &info->receive_credits); 1035 + packet->credits_granted = cpu_to_le16(new_credits); 1036 + 1037 + info->send_immediate = false; 1038 + 1039 + packet->flags = 0; 1040 + if (manage_keep_alive_before_sending(info)) 1041 + packet->flags |= cpu_to_le16(SMB_DIRECT_RESPONSE_REQUESTED); 1042 + 1043 + packet->reserved = 0; 1044 + if (!data_length) 1045 + packet->data_offset = 0; 1046 + else 1047 + packet->data_offset = cpu_to_le32(24); 1048 + packet->data_length = cpu_to_le32(data_length); 1049 + packet->remaining_data_length = cpu_to_le32(remaining_data_length); 1050 + packet->padding = 0; 1051 + 1052 + log_outgoing(INFO, "credits_requested=%d credits_granted=%d " 1053 + "data_offset=%d data_length=%d remaining_data_length=%d\n", 1054 + le16_to_cpu(packet->credits_requested), 1055 + le16_to_cpu(packet->credits_granted), 1056 + le32_to_cpu(packet->data_offset), 1057 + le32_to_cpu(packet->data_length), 1058 + le32_to_cpu(packet->remaining_data_length)); 1059 + 1060 + /* Map the packet to DMA */ 1061 + header_length = sizeof(struct smbd_data_transfer); 1062 + /* If this is a packet without payload, don't send padding */ 1063 + if (!data_length) 1064 + header_length = offsetof(struct smbd_data_transfer, padding); 1065 + 1066 + request->num_sge = 1; 1067 + request->sge[0].addr = ib_dma_map_single(info->id->device, 1068 + (void *)packet, 1069 + header_length, 1070 + DMA_TO_DEVICE); 1071 + if (ib_dma_mapping_error(info->id->device, request->sge[0].addr)) { 1072 + rc = -EIO; 1073 + request->sge[0].addr = 0; 1074 + goto err_dma; 1075 + } 1076 + 1077 + request->sge[0].length = header_length; 1078 + request->sge[0].lkey = info->pd->local_dma_lkey; 1079 + 1080 + /* Fill in the packet data payload */ 837 1081 num_sgs = sgl ? sg_nents(sgl) : 0; 838 1082 for_each_sg(sgl, sg, num_sgs, i) { 839 1083 request->sge[i+1].addr = ··· 936 994 info->id->device, request->sge[i+1].addr)) { 937 995 rc = -EIO; 938 996 request->sge[i+1].addr = 0; 939 - goto dma_mapping_failure; 997 + goto err_dma; 940 998 } 941 999 request->sge[i+1].length = sg->length; 942 1000 request->sge[i+1].lkey = info->pd->local_dma_lkey; 943 1001 request->num_sge++; 944 1002 } 945 1003 946 - rc = smbd_post_send(info, request, data_length); 1004 + rc = smbd_post_send(info, request); 947 1005 if (!rc) 948 1006 return 0; 949 1007 950 - dma_mapping_failure: 951 - for (i = 1; i < request->num_sge; i++) 1008 + err_dma: 1009 + for (i = 0; i < request->num_sge; i++) 952 1010 if (request->sge[i].addr) 953 1011 ib_dma_unmap_single(info->id->device, 954 1012 request->sge[i].addr, 955 1013 request->sge[i].length, 956 1014 DMA_TO_DEVICE); 957 - smbd_destroy_header(info, request); 1015 + mempool_free(request, info->request_mempool); 1016 + 1017 + /* roll back receive credits and credits to be offered */ 1018 + spin_lock(&info->lock_new_credits_offered); 1019 + info->new_credits_offered += new_credits; 1020 + spin_unlock(&info->lock_new_credits_offered); 1021 + atomic_sub(new_credits, &info->receive_credits); 1022 + 1023 + err_alloc: 1024 + if (atomic_dec_and_test(&info->send_pending)) 1025 + wake_up(&info->wait_send_pending); 1026 + 1027 + err_wait_send_queue: 1028 + /* roll back send credits and pending */ 1029 + atomic_inc(&info->send_credits); 1030 + 1031 + err_wait_credit: 958 1032 return rc; 959 1033 } 960 1034 ··· 1292 1334 mempool_free(response, info->response_mempool); 1293 1335 } 1294 1336 1295 - /* 1296 - * Check and send an immediate or keep alive packet 1297 - * The condition to send those packets are defined in [MS-SMBD] 3.1.1.1 1298 - * Connection.KeepaliveRequested and Connection.SendImmediate 1299 - * The idea is to extend credits to server as soon as it becomes available 1300 - */ 1301 - static void send_immediate_work(struct work_struct *work) 1302 - { 1303 - struct smbd_connection *info = container_of( 1304 - work, struct smbd_connection, 1305 - send_immediate_work.work); 1306 - 1307 - if (info->keep_alive_requested == KEEP_ALIVE_PENDING || 1308 - info->send_immediate) { 1309 - log_keep_alive(INFO, "send an empty message\n"); 1310 - smbd_post_send_empty(info); 1311 - } 1312 - } 1313 - 1314 1337 /* Implement idle connection timer [MS-SMBD] 3.1.6.2 */ 1315 1338 static void idle_connection_timer(struct work_struct *work) 1316 1339 { ··· 1346 1407 1347 1408 log_rdma_event(INFO, "cancelling idle timer\n"); 1348 1409 cancel_delayed_work_sync(&info->idle_timer_work); 1349 - log_rdma_event(INFO, "cancelling send immediate work\n"); 1350 - cancel_delayed_work_sync(&info->send_immediate_work); 1351 1410 1352 1411 log_rdma_event(INFO, "wait for all send posted to IB to finish\n"); 1353 1412 wait_event(info->wait_send_pending, 1354 1413 atomic_read(&info->send_pending) == 0); 1355 - wait_event(info->wait_send_payload_pending, 1356 - atomic_read(&info->send_payload_pending) == 0); 1357 1414 1358 1415 /* It's not posssible for upper layer to get to reassembly */ 1359 1416 log_rdma_event(INFO, "drain the reassembly queue\n"); ··· 1679 1744 1680 1745 init_waitqueue_head(&info->wait_send_queue); 1681 1746 INIT_DELAYED_WORK(&info->idle_timer_work, idle_connection_timer); 1682 - INIT_DELAYED_WORK(&info->send_immediate_work, send_immediate_work); 1683 1747 queue_delayed_work(info->workqueue, &info->idle_timer_work, 1684 1748 info->keep_alive_interval*HZ); 1685 1749 1686 1750 init_waitqueue_head(&info->wait_send_pending); 1687 1751 atomic_set(&info->send_pending, 0); 1688 1752 1689 - init_waitqueue_head(&info->wait_send_payload_pending); 1690 - atomic_set(&info->send_payload_pending, 0); 1753 + init_waitqueue_head(&info->wait_post_send); 1691 1754 1692 1755 INIT_WORK(&info->disconnect_work, smbd_disconnect_rdma_work); 1693 1756 INIT_WORK(&info->post_send_credits_work, smbd_post_send_credits); ··· 2159 2226 * that means all the I/Os have been out and we are good to return 2160 2227 */ 2161 2228 2162 - wait_event(info->wait_send_payload_pending, 2163 - atomic_read(&info->send_payload_pending) == 0); 2229 + wait_event(info->wait_send_pending, 2230 + atomic_read(&info->send_pending) == 0); 2164 2231 2165 2232 return rc; 2166 2233 }
+1 -6
fs/cifs/smbdirect.h
··· 114 114 /* Activity accoutning */ 115 115 atomic_t send_pending; 116 116 wait_queue_head_t wait_send_pending; 117 - atomic_t send_payload_pending; 118 - wait_queue_head_t wait_send_payload_pending; 117 + wait_queue_head_t wait_post_send; 119 118 120 119 /* Receive queue */ 121 120 struct list_head receive_queue; ··· 153 154 154 155 struct workqueue_struct *workqueue; 155 156 struct delayed_work idle_timer_work; 156 - struct delayed_work send_immediate_work; 157 157 158 158 /* Memory pool for preallocating buffers */ 159 159 /* request pool for RDMA send */ ··· 231 233 struct smbd_request { 232 234 struct smbd_connection *info; 233 235 struct ib_cqe cqe; 234 - 235 - /* true if this request carries upper layer payload */ 236 - bool has_payload; 237 236 238 237 /* the SGE entries for this packet */ 239 238 struct ib_sge sge[SMBDIRECT_MAX_SGE];