Skip to content

Commit

Permalink
uffd: Disable image deduplication after fork
Browse files Browse the repository at this point in the history
After a fork, both the child and parent processes may trigger a page fault (#PF)
at the same virtual address, referencing the same position in the page image.
If deduplication is enabled, the last process to trigger the page fault will fail.

Therefore, deduplication should be disabled after a fork to prevent this issue.

Signed-off-by: Liu Hua <[email protected]>
  • Loading branch information
Liu Hua committed Oct 14, 2024
1 parent 56bc739 commit 50d1265
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 1 deletion.
5 changes: 5 additions & 0 deletions criu/include/pagemap.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ struct page_read {
/* Whether or not pages can be read in PIE code */
bool pieok;

/* Whether or not disable image deduplication*/
bool disable_dedup;

/* Private data of reader */
struct cr_img *pmi;
struct cr_img *pi;
Expand Down Expand Up @@ -112,6 +115,8 @@ int pagemap_render_iovec(struct list_head *from, struct task_restore_args *ta);
*/
extern void dup_page_read(struct page_read *src, struct page_read *dst);

extern void page_read_disable_dedup(struct page_read *pr);

extern int dedup_one_iovec(struct page_read *pr, unsigned long base, unsigned long len);

static inline unsigned long pagemap_len(PagemapEntry *pe)
Expand Down
11 changes: 10 additions & 1 deletion criu/pagemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ static int read_local_page(struct page_read *pr, unsigned long vaddr, unsigned l
break;
}

if (opts.auto_dedup) {
if (opts.auto_dedup && !pr->disable_dedup) {
ret = punch_hole(pr, pr->pi_off, len, false);
if (ret == -1)
return -1;
Expand Down Expand Up @@ -792,6 +792,7 @@ int open_page_read_at(int dfd, unsigned long img_id, struct page_read *pr, int p
pr->bunch.iov_base = NULL;
pr->pmes = NULL;
pr->pieok = false;
pr->disable_dedup = false;

pr->pmi = open_image_at(dfd, i_typ, O_RSTR, img_id);
if (!pr->pmi)
Expand Down Expand Up @@ -852,6 +853,14 @@ int open_page_read(unsigned long img_id, struct page_read *pr, int pr_flags)

#define DUP_IDS_BASE 1000

void page_read_disable_dedup(struct page_read *pr)
{
pr_debug("disable dedup, id: %d\n", pr->id);
pr->disable_dedup = true;
if (pr->parent)
page_read_disable_dedup(pr->parent);
}

void dup_page_read(struct page_read *src, struct page_read *dst)
{
static int dup_ids = 1;
Expand Down
2 changes: 2 additions & 0 deletions criu/uffd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,8 @@ static int handle_fork(struct lazy_pages_info *parent_lpi, struct uffd_msg *msg)

lpi_get(lpi->parent);

page_read_disable_dedup(&parent_lpi->pr);
page_read_disable_dedup(&lpi->pr);
return 1;

out:
Expand Down

0 comments on commit 50d1265

Please sign in to comment.