Skip to content

Commit ee32f32

Browse files
committed
xen: don't use page->lru for ZONE_DEVICE memory
Commit 9e2369c ("xen: add helpers to allocate unpopulated memory") introduced usage of ZONE_DEVICE memory for foreign memory mappings. Unfortunately this collides with using page->lru for Xen backend private page caches. Fix that by using page->zone_device_data instead. Cc: <[email protected]> # 5.9 Fixes: 9e2369c ("xen: add helpers to allocate unpopulated memory") Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Boris Ostrovsky <[email protected]> Reviewed-by: Jason Andryuk <[email protected]> Signed-off-by: Juergen Gross <[email protected]>
1 parent ca33479 commit ee32f32

File tree

3 files changed

+73
-16
lines changed

3 files changed

+73
-16
lines changed

drivers/xen/grant-table.c

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -813,10 +813,63 @@ int gnttab_alloc_pages(int nr_pages, struct page **pages)
813813
}
814814
EXPORT_SYMBOL_GPL(gnttab_alloc_pages);
815815

816+
#ifdef CONFIG_XEN_UNPOPULATED_ALLOC
817+
static inline void cache_init(struct gnttab_page_cache *cache)
818+
{
819+
cache->pages = NULL;
820+
}
821+
822+
static inline bool cache_empty(struct gnttab_page_cache *cache)
823+
{
824+
return !cache->pages;
825+
}
826+
827+
static inline struct page *cache_deq(struct gnttab_page_cache *cache)
828+
{
829+
struct page *page;
830+
831+
page = cache->pages;
832+
cache->pages = page->zone_device_data;
833+
834+
return page;
835+
}
836+
837+
static inline void cache_enq(struct gnttab_page_cache *cache, struct page *page)
838+
{
839+
page->zone_device_data = cache->pages;
840+
cache->pages = page;
841+
}
842+
#else
843+
static inline void cache_init(struct gnttab_page_cache *cache)
844+
{
845+
INIT_LIST_HEAD(&cache->pages);
846+
}
847+
848+
static inline bool cache_empty(struct gnttab_page_cache *cache)
849+
{
850+
return list_empty(&cache->pages);
851+
}
852+
853+
static inline struct page *cache_deq(struct gnttab_page_cache *cache)
854+
{
855+
struct page *page;
856+
857+
page = list_first_entry(&cache->pages, struct page, lru);
858+
list_del(&page->lru);
859+
860+
return page;
861+
}
862+
863+
static inline void cache_enq(struct gnttab_page_cache *cache, struct page *page)
864+
{
865+
list_add(&page->lru, &cache->pages);
866+
}
867+
#endif
868+
816869
void gnttab_page_cache_init(struct gnttab_page_cache *cache)
817870
{
818871
spin_lock_init(&cache->lock);
819-
INIT_LIST_HEAD(&cache->pages);
872+
cache_init(cache);
820873
cache->num_pages = 0;
821874
}
822875
EXPORT_SYMBOL_GPL(gnttab_page_cache_init);
@@ -827,13 +880,12 @@ int gnttab_page_cache_get(struct gnttab_page_cache *cache, struct page **page)
827880

828881
spin_lock_irqsave(&cache->lock, flags);
829882

830-
if (list_empty(&cache->pages)) {
883+
if (cache_empty(cache)) {
831884
spin_unlock_irqrestore(&cache->lock, flags);
832885
return gnttab_alloc_pages(1, page);
833886
}
834887

835-
page[0] = list_first_entry(&cache->pages, struct page, lru);
836-
list_del(&page[0]->lru);
888+
page[0] = cache_deq(cache);
837889
cache->num_pages--;
838890

839891
spin_unlock_irqrestore(&cache->lock, flags);
@@ -851,7 +903,7 @@ void gnttab_page_cache_put(struct gnttab_page_cache *cache, struct page **page,
851903
spin_lock_irqsave(&cache->lock, flags);
852904

853905
for (i = 0; i < num; i++)
854-
list_add(&page[i]->lru, &cache->pages);
906+
cache_enq(cache, page[i]);
855907
cache->num_pages += num;
856908

857909
spin_unlock_irqrestore(&cache->lock, flags);
@@ -867,8 +919,7 @@ void gnttab_page_cache_shrink(struct gnttab_page_cache *cache, unsigned int num)
867919
spin_lock_irqsave(&cache->lock, flags);
868920

869921
while (cache->num_pages > num) {
870-
page[i] = list_first_entry(&cache->pages, struct page, lru);
871-
list_del(&page[i]->lru);
922+
page[i] = cache_deq(cache);
872923
cache->num_pages--;
873924
if (++i == ARRAY_SIZE(page)) {
874925
spin_unlock_irqrestore(&cache->lock, flags);

drivers/xen/unpopulated-alloc.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include <xen/xen.h>
1313

1414
static DEFINE_MUTEX(list_lock);
15-
static LIST_HEAD(page_list);
15+
static struct page *page_list;
1616
static unsigned int list_count;
1717

1818
static int fill_list(unsigned int nr_pages)
@@ -84,7 +84,8 @@ static int fill_list(unsigned int nr_pages)
8484
struct page *pg = virt_to_page(vaddr + PAGE_SIZE * i);
8585

8686
BUG_ON(!virt_addr_valid(vaddr + PAGE_SIZE * i));
87-
list_add(&pg->lru, &page_list);
87+
pg->zone_device_data = page_list;
88+
page_list = pg;
8889
list_count++;
8990
}
9091

@@ -118,12 +119,10 @@ int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page **pages)
118119
}
119120

120121
for (i = 0; i < nr_pages; i++) {
121-
struct page *pg = list_first_entry_or_null(&page_list,
122-
struct page,
123-
lru);
122+
struct page *pg = page_list;
124123

125124
BUG_ON(!pg);
126-
list_del(&pg->lru);
125+
page_list = pg->zone_device_data;
127126
list_count--;
128127
pages[i] = pg;
129128

@@ -134,7 +133,8 @@ int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page **pages)
134133
unsigned int j;
135134

136135
for (j = 0; j <= i; j++) {
137-
list_add(&pages[j]->lru, &page_list);
136+
pages[j]->zone_device_data = page_list;
137+
page_list = pages[j];
138138
list_count++;
139139
}
140140
goto out;
@@ -160,7 +160,8 @@ void xen_free_unpopulated_pages(unsigned int nr_pages, struct page **pages)
160160

161161
mutex_lock(&list_lock);
162162
for (i = 0; i < nr_pages; i++) {
163-
list_add(&pages[i]->lru, &page_list);
163+
pages[i]->zone_device_data = page_list;
164+
page_list = pages[i];
164165
list_count++;
165166
}
166167
mutex_unlock(&list_lock);
@@ -189,7 +190,8 @@ static int __init init(void)
189190
struct page *pg =
190191
pfn_to_page(xen_extra_mem[i].start_pfn + j);
191192

192-
list_add(&pg->lru, &page_list);
193+
pg->zone_device_data = page_list;
194+
page_list = pg;
193195
list_count++;
194196
}
195197
}

include/xen/grant_table.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,11 @@ void gnttab_free_pages(int nr_pages, struct page **pages);
200200

201201
struct gnttab_page_cache {
202202
spinlock_t lock;
203+
#ifdef CONFIG_XEN_UNPOPULATED_ALLOC
204+
struct page *pages;
205+
#else
203206
struct list_head pages;
207+
#endif
204208
unsigned int num_pages;
205209
};
206210

0 commit comments

Comments
 (0)