mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-17 16:47:50 +00:00
pagemap: Read compressed page images
Existing pagemap readers derive each pages-image offset from a fixed PAGE_SIZE payload per present page. Packed compressed blocks make that calculation invalid and must be reconstructed before reaching restore destinations. Track block and intra-region cursors while advancing, skipping, and reading pagemap entries. Validate block counts, decoded sizes, totals, and aligned-payload offsets before I/O. Read per-page and region images locally, preserve ordinary parent entries, and support sequential per-page image streams. Carry block metadata with queued iovecs, coalesce only compatible regions, read each packed batch once, and rebuild its destinations block by block. Allow exactly IOV_MAX destinations and roll back iovec changes if appending metadata fails. Decompress complete regions directly into a contiguous destination and use scratch space for partial or split regions. Copy the metadata into restorer memory for the later PIE decode path. Keep compressed images on buffered I/O, avoid hole punching packed payloads, handle short reads, and keep compressed local reads out of PIE until that path can decode them. Assisted-by: Codex:GPT-5 Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This commit is contained in:
parent
b7e6e6e19e
commit
1ab35f2e5f
3 changed files with 1262 additions and 18 deletions
|
|
@ -98,6 +98,23 @@ struct page_read {
|
|||
|
||||
/* Current offset in pages file */
|
||||
off_t pi_off;
|
||||
/* Alignment bytes a sequential image-streamer reader must discard. */
|
||||
size_t stream_padding;
|
||||
|
||||
/*
|
||||
* Index into pe->compressed_size[] for the current pagemap
|
||||
* entry. Tracks which compressed block (page in per-page mode,
|
||||
* region in region mode) we are on when reading or skipping
|
||||
* compressed pages. Reset to 0 on advance().
|
||||
*/
|
||||
size_t compressed_size_index;
|
||||
|
||||
/*
|
||||
* In region mode: pages already consumed (read or skipped) from
|
||||
* the current block. Always 0 in per-page mode. Reset to 0 on
|
||||
* advance() and whenever the reader crosses a block boundary.
|
||||
*/
|
||||
unsigned int region_block_offset;
|
||||
|
||||
/* Record consequent neighbour iov-ecs to punch together */
|
||||
struct iovec bunch;
|
||||
|
|
@ -201,4 +218,12 @@ static inline bool pagemap_payload_aligned(PagemapEntry *pe)
|
|||
return !!(pe->flags & PE_PAYLOAD_ALIGNED);
|
||||
}
|
||||
|
||||
/* Keep the mask as wide as off_t so offsets above 4 GiB remain intact. */
|
||||
static inline off_t pagemap_page_align_offset(off_t offset)
|
||||
{
|
||||
off_t mask = ~((off_t)PAGE_SIZE - 1);
|
||||
|
||||
return (offset + (off_t)PAGE_SIZE - 1) & mask;
|
||||
}
|
||||
|
||||
#endif /* __CR_PAGE_READ_H__ */
|
||||
|
|
|
|||
|
|
@ -138,6 +138,20 @@ typedef long (*thread_restore_fcall_t)(struct thread_restore_args *args);
|
|||
struct restore_vma_io {
|
||||
int nr_iovs;
|
||||
loff_t off;
|
||||
uint32_t *compressed_size;
|
||||
uint64_t total_compressed_size;
|
||||
int n_compressed_size;
|
||||
/*
|
||||
* Region compression metadata. region_pages == 0 means per-page
|
||||
* compression and block_pages is unused. When region_pages > 0,
|
||||
* compressed_size[] holds n_compressed_size (== n_blocks) entries
|
||||
* and block_pages is a parallel uint16_t-per-block array giving
|
||||
* each block's page count (the last block of any pagemap entry
|
||||
* spanning this iov may be shorter than region_pages).
|
||||
*/
|
||||
uint32_t region_pages;
|
||||
int n_pages;
|
||||
uint16_t *block_pages;
|
||||
struct iovec iovs[0];
|
||||
};
|
||||
|
||||
|
|
|
|||
1241
criu/pagemap.c
1241
criu/pagemap.c
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue