forked from checkpoint-restore/criu
-
Notifications
You must be signed in to change notification settings - Fork 0
/
aio.c
120 lines (101 loc) · 2.59 KB
/
aio.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#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;
}