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

SUNRPC: Add rpc_auth::au_ralign field

Currently rpc_inline_rcv_pages() uses au_rslack to estimate the
size of the upper layer reply header. This is fine for auth flavors
where au_verfsize == au_rslack.

However, some auth flavors have more going on. krb5i for example has
two more words after the verifier, and another blob following the
RPC message. The calculation involving au_rslack pushes the upper
layer reply header too far into the rcv_buf.

au_rslack is still valuable: it's the amount of buffer space needed
for the reply, and is used when allocating the reply buffer. We'll
keep that.

But, add a new field that can be used to properly estimate the
location of the upper layer header in each RPC reply, based on the
auth flavor in use.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>

authored by

Chuck Lever and committed by
Anna Schumaker
35e77d21 a00275ba

+20 -11
+4 -5
include/linux/sunrpc/auth.h
··· 74 74 struct rpc_authops; 75 75 struct rpc_auth { 76 76 unsigned int au_cslack; /* call cred size estimate */ 77 - /* guess at number of u32's auth adds before 78 - * reply data; normally the verifier size: */ 79 - unsigned int au_rslack; 77 + unsigned int au_rslack; /* reply cred size estimate */ 80 78 unsigned int au_verfsize; /* size of reply verifier */ 79 + unsigned int au_ralign; /* words before UL header */ 81 80 82 - unsigned int au_flags; /* various flags */ 83 - const struct rpc_authops *au_ops; /* operations */ 81 + unsigned int au_flags; 82 + const struct rpc_authops *au_ops; 84 83 rpc_authflavor_t au_flavor; /* pseudoflavor (note may 85 84 * differ from the flavor in 86 85 * au_ops->au_flavor in gss
+13 -5
net/sunrpc/auth_gss/auth_gss.c
··· 1017 1017 auth->au_cslack = GSS_CRED_SLACK >> 2; 1018 1018 auth->au_rslack = GSS_VERF_SLACK >> 2; 1019 1019 auth->au_verfsize = GSS_VERF_SLACK >> 2; 1020 + auth->au_ralign = GSS_VERF_SLACK >> 2; 1020 1021 auth->au_flags = 0; 1021 1022 auth->au_ops = &authgss_ops; 1022 1023 auth->au_flavor = flavor; ··· 1892 1891 static int 1893 1892 gss_unwrap_resp_auth(struct rpc_cred *cred) 1894 1893 { 1895 - cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize; 1894 + struct rpc_auth *auth = cred->cr_auth; 1895 + 1896 + auth->au_rslack = auth->au_verfsize; 1897 + auth->au_ralign = auth->au_verfsize; 1896 1898 return 0; 1897 1899 } 1898 1900 ··· 1906 1902 { 1907 1903 struct xdr_buf integ_buf, *rcv_buf = &rqstp->rq_rcv_buf; 1908 1904 u32 data_offset, mic_offset, integ_len, maj_stat; 1905 + struct rpc_auth *auth = cred->cr_auth; 1909 1906 struct xdr_netobj mic; 1910 1907 __be32 *p; 1911 1908 ··· 1933 1928 if (maj_stat != GSS_S_COMPLETE) 1934 1929 goto bad_mic; 1935 1930 1936 - cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + 2 + 1937 - 1 + XDR_QUADLEN(mic.len); 1931 + auth->au_rslack = auth->au_verfsize + 2 + 1 + XDR_QUADLEN(mic.len); 1932 + auth->au_ralign = auth->au_verfsize + 2; 1938 1933 return 0; 1939 1934 unwrap_failed: 1940 1935 trace_rpcgss_unwrap_failed(task); ··· 1954 1949 { 1955 1950 struct xdr_buf *rcv_buf = &rqstp->rq_rcv_buf; 1956 1951 struct kvec *head = rqstp->rq_rcv_buf.head; 1952 + struct rpc_auth *auth = cred->cr_auth; 1957 1953 unsigned int savedlen = rcv_buf->len; 1958 1954 u32 offset, opaque_len, maj_stat; 1959 1955 __be32 *p; ··· 1982 1976 */ 1983 1977 xdr_init_decode(xdr, rcv_buf, p, rqstp); 1984 1978 1985 - cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + 2 + 1986 - XDR_QUADLEN(savedlen - rcv_buf->len); 1979 + auth->au_rslack = auth->au_verfsize + 2 + 1980 + XDR_QUADLEN(savedlen - rcv_buf->len); 1981 + auth->au_ralign = auth->au_verfsize + 2 + 1982 + XDR_QUADLEN(savedlen - rcv_buf->len); 1987 1983 return 0; 1988 1984 unwrap_failed: 1989 1985 trace_rpcgss_unwrap_failed(task);
+1
net/sunrpc/auth_null.c
··· 115 115 .au_cslack = NUL_CALLSLACK, 116 116 .au_rslack = NUL_REPLYSLACK, 117 117 .au_verfsize = NUL_REPLYSLACK, 118 + .au_ralign = NUL_REPLYSLACK, 118 119 .au_ops = &authnull_ops, 119 120 .au_flavor = RPC_AUTH_NULL, 120 121 .au_count = REFCOUNT_INIT(1),
+1
net/sunrpc/auth_unix.c
··· 187 187 188 188 auth->au_verfsize = XDR_QUADLEN(size) + 2; 189 189 auth->au_rslack = XDR_QUADLEN(size) + 2; 190 + auth->au_ralign = XDR_QUADLEN(size) + 2; 190 191 return 0; 191 192 } 192 193
+1 -1
net/sunrpc/clnt.c
··· 1180 1180 /* Subtract one to force an extra word of buffer space for the 1181 1181 * payload's XDR pad to fall into the rcv_buf's tail iovec. 1182 1182 */ 1183 - hdrsize += RPC_REPHDRSIZE + req->rq_cred->cr_auth->au_rslack - 1; 1183 + hdrsize += RPC_REPHDRSIZE + req->rq_cred->cr_auth->au_ralign - 1; 1184 1184 1185 1185 xdr_inline_pages(&req->rq_rcv_buf, hdrsize << 2, pages, base, len); 1186 1186 trace_rpc_reply_pages(req);