Merge branch 'nvme-4.19' of git://git.infradead.org/nvme into for-linus

Pull single NVMe fix from Christoph.

* 'nvme-4.19' of git://git.infradead.org/nvme:
  nvmet-rdma: fix possible bogus dereference under heavy load
This commit is contained in:
Jens Axboe 2018-09-10 08:16:56 -06:00
commit bf93585ee1

View File

@ -66,6 +66,7 @@ struct nvmet_rdma_rsp {
struct nvmet_req req;
bool allocated;
u8 n_rdma;
u32 flags;
u32 invalidate_rkey;
@ -174,11 +175,19 @@ nvmet_rdma_get_rsp(struct nvmet_rdma_queue *queue)
unsigned long flags;
spin_lock_irqsave(&queue->rsps_lock, flags);
rsp = list_first_entry(&queue->free_rsps,
rsp = list_first_entry_or_null(&queue->free_rsps,
struct nvmet_rdma_rsp, free_list);
list_del(&rsp->free_list);
if (likely(rsp))
list_del(&rsp->free_list);
spin_unlock_irqrestore(&queue->rsps_lock, flags);
if (unlikely(!rsp)) {
rsp = kmalloc(sizeof(*rsp), GFP_KERNEL);
if (unlikely(!rsp))
return NULL;
rsp->allocated = true;
}
return rsp;
}
@ -187,6 +196,11 @@ nvmet_rdma_put_rsp(struct nvmet_rdma_rsp *rsp)
{
unsigned long flags;
if (rsp->allocated) {
kfree(rsp);
return;
}
spin_lock_irqsave(&rsp->queue->rsps_lock, flags);
list_add_tail(&rsp->free_list, &rsp->queue->free_rsps);
spin_unlock_irqrestore(&rsp->queue->rsps_lock, flags);
@ -776,6 +790,15 @@ static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc)
cmd->queue = queue;
rsp = nvmet_rdma_get_rsp(queue);
if (unlikely(!rsp)) {
/*
* we get here only under memory pressure,
* silently drop and have the host retry
* as we can't even fail it.
*/
nvmet_rdma_post_recv(queue->dev, cmd);
return;
}
rsp->queue = queue;
rsp->cmd = cmd;
rsp->flags = 0;