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:
commit
bf93585ee1
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user