28
28
#include <linux/slab.h>
29
29
#include <linux/module.h>
30
30
31
+ /*
32
+ * Balloon device works in 4K page units. So each page is pointed to by
33
+ * multiple balloon pages. All memory counters in this driver are in balloon
34
+ * page units.
35
+ */
36
+ #define VIRTIO_BALLOON_PAGES_PER_PAGE (PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
37
+
31
38
struct virtio_balloon
32
39
{
33
40
struct virtio_device * vdev ;
@@ -42,8 +49,13 @@ struct virtio_balloon
42
49
/* Waiting for host to ack the pages we released. */
43
50
struct completion acked ;
44
51
45
- /* The pages we've told the Host we're not using. */
52
+ /* Number of balloon pages we've told the Host we're not using. */
46
53
unsigned int num_pages ;
54
+ /*
55
+ * The pages we've told the Host we're not using.
56
+ * Each page on this list adds VIRTIO_BALLOON_PAGES_PER_PAGE
57
+ * to num_pages above.
58
+ */
47
59
struct list_head pages ;
48
60
49
61
/* The array of pfns we tell the Host about. */
@@ -66,7 +78,13 @@ static u32 page_to_balloon_pfn(struct page *page)
66
78
67
79
BUILD_BUG_ON (PAGE_SHIFT < VIRTIO_BALLOON_PFN_SHIFT );
68
80
/* Convert pfn from Linux page size to balloon page size. */
69
- return pfn >> (PAGE_SHIFT - VIRTIO_BALLOON_PFN_SHIFT );
81
+ return pfn * VIRTIO_BALLOON_PAGES_PER_PAGE ;
82
+ }
83
+
84
+ static struct page * balloon_pfn_to_page (u32 pfn )
85
+ {
86
+ BUG_ON (pfn % VIRTIO_BALLOON_PAGES_PER_PAGE );
87
+ return pfn_to_page (pfn / VIRTIO_BALLOON_PAGES_PER_PAGE );
70
88
}
71
89
72
90
static void balloon_ack (struct virtqueue * vq )
@@ -96,12 +114,23 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
96
114
wait_for_completion (& vb -> acked );
97
115
}
98
116
117
+ static void set_page_pfns (u32 pfns [], struct page * page )
118
+ {
119
+ unsigned int i ;
120
+
121
+ /* Set balloon pfns pointing at this page.
122
+ * Note that the first pfn points at start of the page. */
123
+ for (i = 0 ; i < VIRTIO_BALLOON_PAGES_PER_PAGE ; i ++ )
124
+ pfns [i ] = page_to_balloon_pfn (page ) + i ;
125
+ }
126
+
99
127
static void fill_balloon (struct virtio_balloon * vb , size_t num )
100
128
{
101
129
/* We can only do one array worth at a time. */
102
130
num = min (num , ARRAY_SIZE (vb -> pfns ));
103
131
104
- for (vb -> num_pfns = 0 ; vb -> num_pfns < num ; vb -> num_pfns ++ ) {
132
+ for (vb -> num_pfns = 0 ; vb -> num_pfns < num ;
133
+ vb -> num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE ) {
105
134
struct page * page = alloc_page (GFP_HIGHUSER | __GFP_NORETRY |
106
135
__GFP_NOMEMALLOC | __GFP_NOWARN );
107
136
if (!page ) {
@@ -113,9 +142,9 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num)
113
142
msleep (200 );
114
143
break ;
115
144
}
116
- vb -> pfns [vb -> num_pfns ] = page_to_balloon_pfn (page );
145
+ set_page_pfns (vb -> pfns + vb -> num_pfns , page );
146
+ vb -> num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE ;
117
147
totalram_pages -- ;
118
- vb -> num_pages ++ ;
119
148
list_add (& page -> lru , & vb -> pages );
120
149
}
121
150
@@ -130,8 +159,9 @@ static void release_pages_by_pfn(const u32 pfns[], unsigned int num)
130
159
{
131
160
unsigned int i ;
132
161
133
- for (i = 0 ; i < num ; i ++ ) {
134
- __free_page (pfn_to_page (pfns [i ]));
162
+ /* Find pfns pointing at start of each page, get pages and free them. */
163
+ for (i = 0 ; i < num ; i += VIRTIO_BALLOON_PAGES_PER_PAGE ) {
164
+ __free_page (balloon_pfn_to_page (pfns [i ]));
135
165
totalram_pages ++ ;
136
166
}
137
167
}
@@ -143,11 +173,12 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num)
143
173
/* We can only do one array worth at a time. */
144
174
num = min (num , ARRAY_SIZE (vb -> pfns ));
145
175
146
- for (vb -> num_pfns = 0 ; vb -> num_pfns < num ; vb -> num_pfns ++ ) {
176
+ for (vb -> num_pfns = 0 ; vb -> num_pfns < num ;
177
+ vb -> num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE ) {
147
178
page = list_first_entry (& vb -> pages , struct page , lru );
148
179
list_del (& page -> lru );
149
- vb -> pfns [ vb -> num_pfns ] = page_to_balloon_pfn ( page );
150
- vb -> num_pages -- ;
180
+ set_page_pfns ( vb -> pfns + vb -> num_pfns , page );
181
+ vb -> num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE ;
151
182
}
152
183
153
184
/*
0 commit comments