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

xprtrdma: No direct data placement with krb5i and krb5p

Direct data placement is not allowed when using flavors that
guarantee integrity or privacy. When such security flavors are in
effect, don't allow the use of Read and Write chunks for moving
individual data items. All messages larger than the inline threshold
are sent via Long Call or Long Reply.

On my systems (CX-3 Pro on FDR), for small I/O operations, the use
of Long messages adds only around 5 usecs of latency in each
direction.

Note that when integrity or encryption is used, the host CPU touches
every byte in these messages. Even if it could be used, data
movement offload doesn't buy much in this case.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Tested-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>

authored by

Chuck Lever and committed by
Anna Schumaker
65b80179 64695bde

+31 -2
+3
include/linux/sunrpc/auth.h
··· 107 107 /* per-flavor data */ 108 108 }; 109 109 110 + /* rpc_auth au_flags */ 111 + #define RPCAUTH_AUTH_DATATOUCH 0x00000002 112 + 110 113 struct rpc_auth_create_args { 111 114 rpc_authflavor_t pseudoflavor; 112 115 const char *target_name;
+2
include/linux/sunrpc/gss_api.h
··· 73 73 rpc_authflavor_t gss_svc_to_pseudoflavor(struct gss_api_mech *, u32 qop, 74 74 u32 service); 75 75 u32 gss_pseudoflavor_to_service(struct gss_api_mech *, u32 pseudoflavor); 76 + bool gss_pseudoflavor_to_datatouch(struct gss_api_mech *, u32 pseudoflavor); 76 77 char *gss_service_to_auth_domain_name(struct gss_api_mech *, u32 service); 77 78 78 79 struct pf_desc { ··· 82 81 u32 service; 83 82 char *name; 84 83 char *auth_domain_name; 84 + bool datatouch; 85 85 }; 86 86 87 87 /* Different mechanisms (e.g., krb5 or spkm3) may implement gss-api, and
+2
net/sunrpc/auth_gss/auth_gss.c
··· 1017 1017 auth->au_rslack = GSS_VERF_SLACK >> 2; 1018 1018 auth->au_ops = &authgss_ops; 1019 1019 auth->au_flavor = flavor; 1020 + if (gss_pseudoflavor_to_datatouch(gss_auth->mech, flavor)) 1021 + auth->au_flags |= RPCAUTH_AUTH_DATATOUCH; 1020 1022 atomic_set(&auth->au_count, 1); 1021 1023 kref_init(&gss_auth->kref); 1022 1024
+2
net/sunrpc/auth_gss/gss_krb5_mech.c
··· 745 745 .qop = GSS_C_QOP_DEFAULT, 746 746 .service = RPC_GSS_SVC_INTEGRITY, 747 747 .name = "krb5i", 748 + .datatouch = true, 748 749 }, 749 750 [2] = { 750 751 .pseudoflavor = RPC_AUTH_GSS_KRB5P, 751 752 .qop = GSS_C_QOP_DEFAULT, 752 753 .service = RPC_GSS_SVC_PRIVACY, 753 754 .name = "krb5p", 755 + .datatouch = true, 754 756 }, 755 757 }; 756 758
+12
net/sunrpc/auth_gss/gss_mech_switch.c
··· 361 361 } 362 362 EXPORT_SYMBOL(gss_pseudoflavor_to_service); 363 363 364 + bool 365 + gss_pseudoflavor_to_datatouch(struct gss_api_mech *gm, u32 pseudoflavor) 366 + { 367 + int i; 368 + 369 + for (i = 0; i < gm->gm_pf_num; i++) { 370 + if (gm->gm_pfs[i].pseudoflavor == pseudoflavor) 371 + return gm->gm_pfs[i].datatouch; 372 + } 373 + return false; 374 + } 375 + 364 376 char * 365 377 gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service) 366 378 {
+10 -2
net/sunrpc/xprtrdma/rpc_rdma.c
··· 570 570 struct rpcrdma_req *req = rpcr_to_rdmar(rqst); 571 571 enum rpcrdma_chunktype rtype, wtype; 572 572 struct rpcrdma_msg *headerp; 573 + bool ddp_allowed; 573 574 ssize_t hdrlen; 574 575 size_t rpclen; 575 576 __be32 *iptr; ··· 587 586 headerp->rm_credit = cpu_to_be32(r_xprt->rx_buf.rb_max_requests); 588 587 headerp->rm_type = rdma_msg; 589 588 589 + /* When the ULP employs a GSS flavor that guarantees integrity 590 + * or privacy, direct data placement of individual data items 591 + * is not allowed. 592 + */ 593 + ddp_allowed = !(rqst->rq_cred->cr_auth->au_flags & 594 + RPCAUTH_AUTH_DATATOUCH); 595 + 590 596 /* 591 597 * Chunks needed for results? 592 598 * ··· 605 597 */ 606 598 if (rpcrdma_results_inline(r_xprt, rqst)) 607 599 wtype = rpcrdma_noch; 608 - else if (rqst->rq_rcv_buf.flags & XDRBUF_READ) 600 + else if (ddp_allowed && rqst->rq_rcv_buf.flags & XDRBUF_READ) 609 601 wtype = rpcrdma_writech; 610 602 else 611 603 wtype = rpcrdma_replych; ··· 628 620 rtype = rpcrdma_noch; 629 621 rpcrdma_inline_pullup(rqst); 630 622 rpclen = rqst->rq_svec[0].iov_len; 631 - } else if (rqst->rq_snd_buf.flags & XDRBUF_WRITE) { 623 + } else if (ddp_allowed && rqst->rq_snd_buf.flags & XDRBUF_WRITE) { 632 624 rtype = rpcrdma_readch; 633 625 rpclen = rqst->rq_svec[0].iov_len; 634 626 rpclen += rpcrdma_tail_pullup(&rqst->rq_snd_buf);