On Sat, Jun 19, 2021 at 02:20:02AM -0700, Peter Collingbourne wrote: > +void prep_refpage_private_data(struct refpage_private_data *priv) > +{ > + u8 *addr = page_address(priv->refpage); > + u8 pattern = addr[0]; > + int i; > + > + for (i = 1; i != PAGE_SIZE; ++i) > + if (addr[i] != pattern) > + return; > + > + priv->optzn_kind = REFPAGE_OPTZN_PATTERN; > + priv->optzn_info = pattern; > +} > + > +void copy_refpage(struct page *page, unsigned long addr, > + struct vm_area_struct *vma) > +{ > + struct refpage_private_data *priv = vma->vm_private_data; > + > + if (priv->optzn_kind == REFPAGE_OPTZN_PATTERN) > + memset(page_address(page), priv->optzn_info, PAGE_SIZE); > + else > + copy_user_highpage(page, priv->refpage, addr, vma); > +} I wonder if single-byte captures enough of the useful possibilities. In the kernel we have memset32() and memset64() [1] so we could support a larger pattern than just an 8-bit byte. It all depends what userspace would find useful. [1] Along with memset_p(), memset_l() and memset16() that aren't terribly relevant to this use case. Although maybe memset_l() would be the right one to use since there probably aren't too many 32-bit apps that want a 64-bit pattern and memset64() might not be the fastest on a 32-bit kernel).