Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Several cases of bug fixes in 'net' overlapping other changes in 'net-next-. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -1616,7 +1616,7 @@ gss_validate(struct rpc_task *task, __be32 *p)
|
||||
{
|
||||
struct rpc_cred *cred = task->tk_rqstp->rq_cred;
|
||||
struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
|
||||
__be32 seq;
|
||||
__be32 *seq = NULL;
|
||||
struct kvec iov;
|
||||
struct xdr_buf verf_buf;
|
||||
struct xdr_netobj mic;
|
||||
@@ -1631,9 +1631,12 @@ gss_validate(struct rpc_task *task, __be32 *p)
|
||||
goto out_bad;
|
||||
if (flav != RPC_AUTH_GSS)
|
||||
goto out_bad;
|
||||
seq = htonl(task->tk_rqstp->rq_seqno);
|
||||
iov.iov_base = &seq;
|
||||
iov.iov_len = sizeof(seq);
|
||||
seq = kmalloc(4, GFP_NOFS);
|
||||
if (!seq)
|
||||
goto out_bad;
|
||||
*seq = htonl(task->tk_rqstp->rq_seqno);
|
||||
iov.iov_base = seq;
|
||||
iov.iov_len = 4;
|
||||
xdr_buf_from_iov(&iov, &verf_buf);
|
||||
mic.data = (u8 *)p;
|
||||
mic.len = len;
|
||||
@@ -1653,11 +1656,13 @@ gss_validate(struct rpc_task *task, __be32 *p)
|
||||
gss_put_ctx(ctx);
|
||||
dprintk("RPC: %5u %s: gss_verify_mic succeeded.\n",
|
||||
task->tk_pid, __func__);
|
||||
kfree(seq);
|
||||
return p + XDR_QUADLEN(len);
|
||||
out_bad:
|
||||
gss_put_ctx(ctx);
|
||||
dprintk("RPC: %5u %s failed ret %ld.\n", task->tk_pid, __func__,
|
||||
PTR_ERR(ret));
|
||||
kfree(seq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -166,8 +166,8 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen,
|
||||
unsigned int usage, struct xdr_netobj *cksumout)
|
||||
{
|
||||
struct scatterlist sg[1];
|
||||
int err;
|
||||
u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN];
|
||||
int err = -1;
|
||||
u8 *checksumdata;
|
||||
u8 rc4salt[4];
|
||||
struct crypto_ahash *md5;
|
||||
struct crypto_ahash *hmac_md5;
|
||||
@@ -187,23 +187,22 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen,
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS);
|
||||
if (!checksumdata)
|
||||
return GSS_S_FAILURE;
|
||||
|
||||
md5 = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(md5))
|
||||
return GSS_S_FAILURE;
|
||||
goto out_free_cksum;
|
||||
|
||||
hmac_md5 = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0,
|
||||
CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(hmac_md5)) {
|
||||
crypto_free_ahash(md5);
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
if (IS_ERR(hmac_md5))
|
||||
goto out_free_md5;
|
||||
|
||||
req = ahash_request_alloc(md5, GFP_KERNEL);
|
||||
if (!req) {
|
||||
crypto_free_ahash(hmac_md5);
|
||||
crypto_free_ahash(md5);
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
if (!req)
|
||||
goto out_free_hmac_md5;
|
||||
|
||||
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
|
||||
|
||||
@@ -232,11 +231,8 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen,
|
||||
|
||||
ahash_request_free(req);
|
||||
req = ahash_request_alloc(hmac_md5, GFP_KERNEL);
|
||||
if (!req) {
|
||||
crypto_free_ahash(hmac_md5);
|
||||
crypto_free_ahash(md5);
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
if (!req)
|
||||
goto out_free_hmac_md5;
|
||||
|
||||
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
|
||||
|
||||
@@ -258,8 +254,12 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen,
|
||||
cksumout->len = kctx->gk5e->cksumlength;
|
||||
out:
|
||||
ahash_request_free(req);
|
||||
crypto_free_ahash(md5);
|
||||
out_free_hmac_md5:
|
||||
crypto_free_ahash(hmac_md5);
|
||||
out_free_md5:
|
||||
crypto_free_ahash(md5);
|
||||
out_free_cksum:
|
||||
kfree(checksumdata);
|
||||
return err ? GSS_S_FAILURE : 0;
|
||||
}
|
||||
|
||||
@@ -276,8 +276,8 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
|
||||
struct crypto_ahash *tfm;
|
||||
struct ahash_request *req;
|
||||
struct scatterlist sg[1];
|
||||
int err;
|
||||
u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN];
|
||||
int err = -1;
|
||||
u8 *checksumdata;
|
||||
unsigned int checksumlen;
|
||||
|
||||
if (kctx->gk5e->ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR)
|
||||
@@ -291,15 +291,17 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(tfm))
|
||||
checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS);
|
||||
if (checksumdata == NULL)
|
||||
return GSS_S_FAILURE;
|
||||
|
||||
tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(tfm))
|
||||
goto out_free_cksum;
|
||||
|
||||
req = ahash_request_alloc(tfm, GFP_KERNEL);
|
||||
if (!req) {
|
||||
crypto_free_ahash(tfm);
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
if (!req)
|
||||
goto out_free_ahash;
|
||||
|
||||
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
|
||||
|
||||
@@ -349,7 +351,10 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
|
||||
cksumout->len = kctx->gk5e->cksumlength;
|
||||
out:
|
||||
ahash_request_free(req);
|
||||
out_free_ahash:
|
||||
crypto_free_ahash(tfm);
|
||||
out_free_cksum:
|
||||
kfree(checksumdata);
|
||||
return err ? GSS_S_FAILURE : 0;
|
||||
}
|
||||
|
||||
@@ -368,8 +373,8 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,
|
||||
struct crypto_ahash *tfm;
|
||||
struct ahash_request *req;
|
||||
struct scatterlist sg[1];
|
||||
int err;
|
||||
u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN];
|
||||
int err = -1;
|
||||
u8 *checksumdata;
|
||||
unsigned int checksumlen;
|
||||
|
||||
if (kctx->gk5e->keyed_cksum == 0) {
|
||||
@@ -383,16 +388,18 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
|
||||
checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS);
|
||||
if (!checksumdata)
|
||||
return GSS_S_FAILURE;
|
||||
|
||||
tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(tfm))
|
||||
return GSS_S_FAILURE;
|
||||
goto out_free_cksum;
|
||||
checksumlen = crypto_ahash_digestsize(tfm);
|
||||
|
||||
req = ahash_request_alloc(tfm, GFP_KERNEL);
|
||||
if (!req) {
|
||||
crypto_free_ahash(tfm);
|
||||
return GSS_S_FAILURE;
|
||||
}
|
||||
if (!req)
|
||||
goto out_free_ahash;
|
||||
|
||||
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
|
||||
|
||||
@@ -433,7 +440,10 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,
|
||||
}
|
||||
out:
|
||||
ahash_request_free(req);
|
||||
out_free_ahash:
|
||||
crypto_free_ahash(tfm);
|
||||
out_free_cksum:
|
||||
kfree(checksumdata);
|
||||
return err ? GSS_S_FAILURE : 0;
|
||||
}
|
||||
|
||||
@@ -666,14 +676,17 @@ gss_krb5_cts_crypt(struct crypto_skcipher *cipher, struct xdr_buf *buf,
|
||||
u32 ret;
|
||||
struct scatterlist sg[1];
|
||||
SKCIPHER_REQUEST_ON_STACK(req, cipher);
|
||||
u8 data[GSS_KRB5_MAX_BLOCKSIZE * 2];
|
||||
u8 *data;
|
||||
struct page **save_pages;
|
||||
u32 len = buf->len - offset;
|
||||
|
||||
if (len > ARRAY_SIZE(data)) {
|
||||
if (len > GSS_KRB5_MAX_BLOCKSIZE * 2) {
|
||||
WARN_ON(0);
|
||||
return -ENOMEM;
|
||||
}
|
||||
data = kmalloc(GSS_KRB5_MAX_BLOCKSIZE * 2, GFP_NOFS);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* For encryption, we want to read from the cleartext
|
||||
@@ -708,6 +721,7 @@ gss_krb5_cts_crypt(struct crypto_skcipher *cipher, struct xdr_buf *buf,
|
||||
ret = write_bytes_to_xdr_buf(buf, offset, data, len);
|
||||
|
||||
out:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -718,30 +718,37 @@ gss_write_null_verf(struct svc_rqst *rqstp)
|
||||
static int
|
||||
gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
|
||||
{
|
||||
__be32 xdr_seq;
|
||||
__be32 *xdr_seq;
|
||||
u32 maj_stat;
|
||||
struct xdr_buf verf_data;
|
||||
struct xdr_netobj mic;
|
||||
__be32 *p;
|
||||
struct kvec iov;
|
||||
int err = -1;
|
||||
|
||||
svc_putnl(rqstp->rq_res.head, RPC_AUTH_GSS);
|
||||
xdr_seq = htonl(seq);
|
||||
xdr_seq = kmalloc(4, GFP_KERNEL);
|
||||
if (!xdr_seq)
|
||||
return -1;
|
||||
*xdr_seq = htonl(seq);
|
||||
|
||||
iov.iov_base = &xdr_seq;
|
||||
iov.iov_len = sizeof(xdr_seq);
|
||||
iov.iov_base = xdr_seq;
|
||||
iov.iov_len = 4;
|
||||
xdr_buf_from_iov(&iov, &verf_data);
|
||||
p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
|
||||
mic.data = (u8 *)(p + 1);
|
||||
maj_stat = gss_get_mic(ctx_id, &verf_data, &mic);
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
return -1;
|
||||
goto out;
|
||||
*p++ = htonl(mic.len);
|
||||
memset((u8 *)p + mic.len, 0, round_up_to_quad(mic.len) - mic.len);
|
||||
p += XDR_QUADLEN(mic.len);
|
||||
if (!xdr_ressize_check(rqstp, p))
|
||||
return -1;
|
||||
return 0;
|
||||
goto out;
|
||||
err = 0;
|
||||
out:
|
||||
kfree(xdr_seq);
|
||||
return err;
|
||||
}
|
||||
|
||||
struct gss_domain {
|
||||
|
@@ -2753,14 +2753,18 @@ EXPORT_SYMBOL_GPL(rpc_cap_max_reconnect_timeout);
|
||||
|
||||
void rpc_clnt_xprt_switch_put(struct rpc_clnt *clnt)
|
||||
{
|
||||
rcu_read_lock();
|
||||
xprt_switch_put(rcu_dereference(clnt->cl_xpi.xpi_xpswitch));
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_put);
|
||||
|
||||
void rpc_clnt_xprt_switch_add_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
|
||||
{
|
||||
rcu_read_lock();
|
||||
rpc_xprt_switch_add_xprt(rcu_dereference(clnt->cl_xpi.xpi_xpswitch),
|
||||
xprt);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpc_clnt_xprt_switch_add_xprt);
|
||||
|
||||
@@ -2770,9 +2774,8 @@ bool rpc_clnt_xprt_switch_has_addr(struct rpc_clnt *clnt,
|
||||
struct rpc_xprt_switch *xps;
|
||||
bool ret;
|
||||
|
||||
xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
|
||||
|
||||
rcu_read_lock();
|
||||
xps = rcu_dereference(clnt->cl_xpi.xpi_xpswitch);
|
||||
ret = rpc_xprt_switch_has_addr(xps, sap);
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
|
@@ -44,18 +44,20 @@
|
||||
* being done.
|
||||
*
|
||||
* When the underlying transport disconnects, MRs are left in one of
|
||||
* three states:
|
||||
* four states:
|
||||
*
|
||||
* INVALID: The MR was not in use before the QP entered ERROR state.
|
||||
* (Or, the LOCAL_INV WR has not completed or flushed yet).
|
||||
*
|
||||
* STALE: The MR was being registered or unregistered when the QP
|
||||
* entered ERROR state, and the pending WR was flushed.
|
||||
*
|
||||
* VALID: The MR was registered before the QP entered ERROR state.
|
||||
*
|
||||
* When frwr_op_map encounters STALE and VALID MRs, they are recovered
|
||||
* with ib_dereg_mr and then are re-initialized. Beause MR recovery
|
||||
* FLUSHED_FR: The MR was being registered when the QP entered ERROR
|
||||
* state, and the pending WR was flushed.
|
||||
*
|
||||
* FLUSHED_LI: The MR was being invalidated when the QP entered ERROR
|
||||
* state, and the pending WR was flushed.
|
||||
*
|
||||
* When frwr_op_map encounters FLUSHED and VALID MRs, they are recovered
|
||||
* with ib_dereg_mr and then are re-initialized. Because MR recovery
|
||||
* allocates fresh resources, it is deferred to a workqueue, and the
|
||||
* recovered MRs are placed back on the rb_mws list when recovery is
|
||||
* complete. frwr_op_map allocates another MR for the current RPC while
|
||||
@@ -177,12 +179,15 @@ __frwr_reset_mr(struct rpcrdma_ia *ia, struct rpcrdma_mw *r)
|
||||
static void
|
||||
frwr_op_recover_mr(struct rpcrdma_mw *mw)
|
||||
{
|
||||
enum rpcrdma_frmr_state state = mw->frmr.fr_state;
|
||||
struct rpcrdma_xprt *r_xprt = mw->mw_xprt;
|
||||
struct rpcrdma_ia *ia = &r_xprt->rx_ia;
|
||||
int rc;
|
||||
|
||||
rc = __frwr_reset_mr(ia, mw);
|
||||
ib_dma_unmap_sg(ia->ri_device, mw->mw_sg, mw->mw_nents, mw->mw_dir);
|
||||
if (state != FRMR_FLUSHED_LI)
|
||||
ib_dma_unmap_sg(ia->ri_device,
|
||||
mw->mw_sg, mw->mw_nents, mw->mw_dir);
|
||||
if (rc)
|
||||
goto out_release;
|
||||
|
||||
@@ -262,10 +267,8 @@ frwr_op_maxpages(struct rpcrdma_xprt *r_xprt)
|
||||
}
|
||||
|
||||
static void
|
||||
__frwr_sendcompletion_flush(struct ib_wc *wc, struct rpcrdma_frmr *frmr,
|
||||
const char *wr)
|
||||
__frwr_sendcompletion_flush(struct ib_wc *wc, const char *wr)
|
||||
{
|
||||
frmr->fr_state = FRMR_IS_STALE;
|
||||
if (wc->status != IB_WC_WR_FLUSH_ERR)
|
||||
pr_err("rpcrdma: %s: %s (%u/0x%x)\n",
|
||||
wr, ib_wc_status_msg(wc->status),
|
||||
@@ -288,7 +291,8 @@ frwr_wc_fastreg(struct ib_cq *cq, struct ib_wc *wc)
|
||||
if (wc->status != IB_WC_SUCCESS) {
|
||||
cqe = wc->wr_cqe;
|
||||
frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe);
|
||||
__frwr_sendcompletion_flush(wc, frmr, "fastreg");
|
||||
frmr->fr_state = FRMR_FLUSHED_FR;
|
||||
__frwr_sendcompletion_flush(wc, "fastreg");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,7 +312,8 @@ frwr_wc_localinv(struct ib_cq *cq, struct ib_wc *wc)
|
||||
if (wc->status != IB_WC_SUCCESS) {
|
||||
cqe = wc->wr_cqe;
|
||||
frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe);
|
||||
__frwr_sendcompletion_flush(wc, frmr, "localinv");
|
||||
frmr->fr_state = FRMR_FLUSHED_LI;
|
||||
__frwr_sendcompletion_flush(wc, "localinv");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,8 +333,10 @@ frwr_wc_localinv_wake(struct ib_cq *cq, struct ib_wc *wc)
|
||||
/* WARNING: Only wr_cqe and status are reliable at this point */
|
||||
cqe = wc->wr_cqe;
|
||||
frmr = container_of(cqe, struct rpcrdma_frmr, fr_cqe);
|
||||
if (wc->status != IB_WC_SUCCESS)
|
||||
__frwr_sendcompletion_flush(wc, frmr, "localinv");
|
||||
if (wc->status != IB_WC_SUCCESS) {
|
||||
frmr->fr_state = FRMR_FLUSHED_LI;
|
||||
__frwr_sendcompletion_flush(wc, "localinv");
|
||||
}
|
||||
complete(&frmr->fr_linv_done);
|
||||
}
|
||||
|
||||
|
@@ -177,18 +177,26 @@ xprt_rdma_bc_allocate(struct rpc_task *task)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* svc_rdma_sendto releases this page */
|
||||
page = alloc_page(RPCRDMA_DEF_GFP);
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
|
||||
rqst->rq_buffer = page_address(page);
|
||||
|
||||
rqst->rq_rbuffer = kmalloc(rqst->rq_rcvsize, RPCRDMA_DEF_GFP);
|
||||
if (!rqst->rq_rbuffer) {
|
||||
put_page(page);
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
xprt_rdma_bc_free(struct rpc_task *task)
|
||||
{
|
||||
/* No-op: ctxt and page have already been freed. */
|
||||
struct rpc_rqst *rqst = task->tk_rqstp;
|
||||
|
||||
kfree(rqst->rq_rbuffer);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@@ -216,7 +216,8 @@ struct rpcrdma_rep {
|
||||
enum rpcrdma_frmr_state {
|
||||
FRMR_IS_INVALID, /* ready to be used */
|
||||
FRMR_IS_VALID, /* in use */
|
||||
FRMR_IS_STALE, /* failed completion */
|
||||
FRMR_FLUSHED_FR, /* flushed FASTREG WR */
|
||||
FRMR_FLUSHED_LI, /* flushed LOCALINV WR */
|
||||
};
|
||||
|
||||
struct rpcrdma_frmr {
|
||||
|
@@ -2563,6 +2563,7 @@ static int bc_malloc(struct rpc_task *task)
|
||||
buf->len = PAGE_SIZE;
|
||||
|
||||
rqst->rq_buffer = buf->data;
|
||||
rqst->rq_rbuffer = (char *)rqst->rq_buffer + rqst->rq_callsize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user