virtio: serialize the unplugging of virtio memblocks

The below scenario can cause plugging of memory block enter into oom
path thus can cause the dead lock scenario:
1) Plug 'm' memory blocks. Happens sequentially under qvm_lock +
flush(work).
2) Unplug 'n' memory blocks, that can happen once for a bunch as this
get triggered in close(fd) and asynchronously.
3) some blocks from step2 are failed thus the final updated plugged size
is much larger than 'qvm_hint_total'(which effects the requested size
for the next block to be plugged)
4) Now memory pressure triggered the below:
acquire(oom_lock)->qvm_oom_notify->plug memory block. The expectation
here is to plug the memory block but because of step 3, the requested
size will be still below the plugged size thus it takes the unplug
path which again enters into reclaim and stuck on oom_lock.

This can be avoided by serializing the step2 which happens under
qvm_lock and flush(vm->wq). For the blocks that are failed to unplug
will not lead into changing the 'qvm_hint_total' thus not effect the
requested size calculation for the next block.

Change-Id: I14bd05ef21ada9d183f00f30806b1556eb967099
Signed-off-by: Charan Teja Kalla <quic_charante@quicinc.com>
This commit is contained in:
Charan Teja Kalla 2024-01-05 19:11:32 +05:30
parent 07ae530480
commit 52b5629ec5

View File

@ -71,10 +71,13 @@ static int qti_virtio_mem_hint_update(struct qti_virtio_mem_hint *hint,
static void qti_virtio_mem_hint_kref_release(struct kref *kref)
{
struct qti_virtio_mem_hint *hint;
int rc;
mutex_lock(&qvm_lock);
hint = container_of(kref, struct qti_virtio_mem_hint, kref);
WARN_ON(qti_virtio_mem_hint_update(hint, 0, false));
rc = qti_virtio_mem_hint_update(hint, 0, true);
if (rc)
pr_err("Possible permanent plug of memory to vm\n");
list_del(&hint->list);
mutex_unlock(&qvm_lock);