mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-22 09:58:09 +00:00
121 lines
2.6 KiB
C
121 lines
2.6 KiB
C
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include "vma.h"
|
|
#include "xmalloc.h"
|
|
#include "aio.h"
|
|
#include "parasite.h"
|
|
#include "parasite-syscall.h"
|
|
#include "protobuf/mm.pb-c.h"
|
|
|
|
int dump_aio_ring(MmEntry *mme, struct vma_area *vma)
|
|
{
|
|
int nr = mme->n_aios;
|
|
AioRingEntry *re;
|
|
|
|
pr_info("Dumping AIO ring @%"PRIx64", %u reqs\n",
|
|
vma->e->start, vma->aio_nr_req);
|
|
|
|
mme->aios = xrealloc(mme->aios, (nr + 1) * sizeof(re));
|
|
if (!mme->aios)
|
|
return -1;
|
|
|
|
re = xmalloc(sizeof(*re));
|
|
if (!re)
|
|
return -1;
|
|
|
|
aio_ring_entry__init(re);
|
|
re->id = vma->e->start;
|
|
re->nr_req = vma->aio_nr_req;
|
|
re->ring_len = vma->e->end - vma->e->start;
|
|
mme->aios[nr] = re;
|
|
mme->n_aios = nr + 1;
|
|
return 0;
|
|
}
|
|
|
|
void free_aios(MmEntry *mme)
|
|
{
|
|
int i;
|
|
|
|
if (mme->aios) {
|
|
for (i = 0; i < mme->n_aios; i++)
|
|
xfree(mme->aios[i]);
|
|
xfree(mme->aios);
|
|
}
|
|
}
|
|
|
|
static unsigned int aio_estimate_nr_reqs(unsigned int k_max_reqs)
|
|
{
|
|
/*
|
|
* Kernel does
|
|
*
|
|
* nr_reqs = max(nr_reqs, nr_cpus * 4)
|
|
* nr_reqs *= 2
|
|
* nr_reqs += 2
|
|
* ring = roundup(sizeof(head) + nr_reqs * sizeof(req))
|
|
* nr_reqs = (ring - sizeof(head)) / sizeof(req)
|
|
*
|
|
* And the k_max_reqs here is the resulting value.
|
|
*
|
|
* We need to get the initial nr_reqs that would grow
|
|
* up back to the k_max_reqs.
|
|
*/
|
|
|
|
return (k_max_reqs - 2) / 2;
|
|
}
|
|
|
|
unsigned long aio_rings_args_size(struct vm_area_list *vmas)
|
|
{
|
|
return sizeof(struct parasite_check_aios_args) +
|
|
vmas->nr_aios * sizeof(struct parasite_aio);
|
|
}
|
|
|
|
int parasite_check_aios(struct parasite_ctl *ctl, struct vm_area_list *vmas)
|
|
{
|
|
struct vma_area *vma;
|
|
struct parasite_check_aios_args *aa;
|
|
struct parasite_aio *pa;
|
|
int i;
|
|
|
|
if (!vmas->nr_aios)
|
|
return 0;
|
|
|
|
pr_info("Checking AIO rings\n");
|
|
|
|
/*
|
|
* Go to parasite and
|
|
* a) check that no requests are currently pengind
|
|
* b) get the maximum number of requests kernel handles
|
|
* to estimate what was the user request on ring
|
|
* creation.
|
|
*/
|
|
|
|
aa = parasite_args_s(ctl, aio_rings_args_size(vmas));
|
|
pa = &aa->ring[0];
|
|
list_for_each_entry(vma, &vmas->h, list) {
|
|
if (!vma_area_is(vma, VMA_AREA_AIORING))
|
|
continue;
|
|
|
|
pr_debug(" `- Ring #%ld @%"PRIx64"\n",
|
|
(long)(pa - &aa->ring[0]), vma->e->start);
|
|
pa->ctx = vma->e->start;
|
|
pa->max_reqs = 0;
|
|
pa->vma_nr_reqs = &vma->aio_nr_req;
|
|
pa++;
|
|
}
|
|
aa->nr_rings = vmas->nr_aios;
|
|
|
|
if (parasite_execute_daemon(PARASITE_CMD_CHECK_AIOS, ctl))
|
|
return -1;
|
|
|
|
pa = &aa->ring[0];
|
|
for (i = 0; i < vmas->nr_aios; i++) {
|
|
pa = &aa->ring[i];
|
|
*pa->vma_nr_reqs = aio_estimate_nr_reqs(pa->max_reqs);
|
|
pr_debug(" `- Ring #%d has %u reqs, estimated to %u\n", i,
|
|
pa->max_reqs, *pa->vma_nr_reqs);
|
|
}
|
|
|
|
return 0;
|
|
}
|