static int restore_shmem_content(void *addr, struct shmem_info *si) { int ret = 0; struct page_read pr; unsigned long off_real; ret = open_page_read(si->shmid, &pr, opts.auto_dedup ? O_RDWR : O_RSTR, true); if (ret) goto err_unmap; while (1) { unsigned long vaddr; unsigned nr_pages; struct iovec iov; ret = pr.get_pagemap(&pr, &iov); if (ret <= 0) break; vaddr = (unsigned long)iov.iov_base; nr_pages = iov.iov_len / PAGE_SIZE; if (vaddr + nr_pages * PAGE_SIZE > si->size) break; off_real = lseek(pr.fd_pg, 0, SEEK_CUR); ret = read(pr.fd_pg, addr + vaddr, nr_pages * PAGE_SIZE); if (ret != nr_pages * PAGE_SIZE) { ret = -1; break; } if (opts.auto_dedup) { ret = punch_hole(&pr, off_real, nr_pages * PAGE_SIZE, false); if (ret == -1) { break; } } if (pr.put_pagemap) pr.put_pagemap(&pr); } pr.close(&pr); return ret; err_unmap: munmap(addr, si->size); return -1; }
static int cr_dedup_one_pagemap(int pid) { int ret; struct page_read pr; struct page_read * prp; struct iovec iov; ret = open_page_read(pid, &pr, O_RDWR, false); if (ret) { ret = -1; goto exit; } prp = pr.parent; if (!prp) goto exit; ret = pr.get_pagemap(&pr, &iov); if (ret <= 0) goto exit; while (1) { pr_debug("dedup iovec base=%p, len=%zu\n", iov.iov_base, iov.iov_len); if (!pr.pe->in_parent) { ret = dedup_one_iovec(prp, &iov); if (ret) goto exit; } pr.put_pagemap(&pr); ret = pr.get_pagemap(&pr, &iov); if (ret <= 0) goto exit; } exit: pr.close(&pr); if (ret < 0) return ret; return 0; }