Skip to content

Commit

Permalink
zram: Fixes for lookup_swap_cache()
Browse files Browse the repository at this point in the history
Fix the following three issues:
(1) swap cache missing page tree offset
    The radix or xarray start at an offset inside struct address_space.
(2) swap cache entries are pointer to struct page
    The entries in radix, xarray (swap cache) are address to struct page.
(3) exclude shadow entries from swap cache lookup
    radix or xarray can contain shadow entries from previous page
    entries. These should be ignored when looking for a page pointer.

Without the patch,
- lookup_swap_cache() returns NULL since do_xarray() call returns FALSE,
- in try_zram_decompress(), since 'entry' is NULL, page is filled with 0,
    if (!entry || (flags & ZRAM_FLAG_SAME_BIT)) {
and pages in swap cache will be seen to be a 'zero' page.

Signed-off-by: Johan Erlandsson <[email protected]>
Signed-off-by: Kazuhito Hagio <[email protected]>
  • Loading branch information
Johan Erlandsson authored and liutgnu committed Dec 1, 2024
1 parent 228e7b6 commit 78cbdcc
Showing 1 changed file with 14 additions and 5 deletions.
19 changes: 14 additions & 5 deletions diskdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "diskdump.h"
#include "xen_dom0.h"
#include "vmcore.h"
#include "maple_tree.h"

#define BITMAP_SECT_LEN 4096

Expand Down Expand Up @@ -2877,11 +2878,16 @@ zram_object_addr(ulong pool, ulong handle, unsigned char *zram_buf)
return zram_buf;
}

static inline bool radix_tree_exceptional_entry(ulong entry)
{
return entry & RADIX_TREE_EXCEPTIONAL_ENTRY;
}

static unsigned char *
lookup_swap_cache(ulonglong pte_val, unsigned char *zram_buf)
{
ulonglong swp_offset;
ulong swp_type, swp_space, page;
ulong swp_type, swp_space;
struct list_pair lp;
physaddr_t paddr;
static int is_xarray = -1;
Expand All @@ -2907,10 +2913,13 @@ lookup_swap_cache(ulonglong pte_val, unsigned char *zram_buf)
swp_space += (swp_offset >> SWAP_ADDRESS_SPACE_SHIFT) * SIZE(address_space);

lp.index = swp_offset;
if ((is_xarray ? do_xarray : do_radix_tree)(swp_space, RADIX_TREE_SEARCH, &lp)) {
readmem((ulong)lp.value, KVADDR, &page, sizeof(void *),
"swap_cache page", FAULT_ON_ERROR);
if (!is_page_ptr(page, &paddr)) {
if ((is_xarray ? do_xarray : do_radix_tree)
(swp_space+OFFSET(address_space_page_tree), RADIX_TREE_SEARCH, &lp)) {
if ((is_xarray ? xa_is_value : radix_tree_exceptional_entry)((ulong)lp.value)) {
/* ignore shadow values */
return NULL;
}
if (!is_page_ptr((ulong)lp.value, &paddr)) {
error(WARNING, "radix page: %lx: not a page pointer\n", lp.value);
return NULL;
}
Expand Down

0 comments on commit 78cbdcc

Please sign in to comment.