On 2025-08-07 01:44:35, Pasha Tatashin wrote: > From: Pratyush Yadav <ptyadav@xxxxxxxxx> > +static void memfd_luo_unpreserve_folios(const struct memfd_luo_preserved_folio *pfolios, > + unsigned int nr_folios) > +{ > + unsigned int i; > + > + for (i = 0; i < nr_folios; i++) { > + const struct memfd_luo_preserved_folio *pfolio = &pfolios[i]; > + struct folio *folio; > + > + if (!pfolio->foliodesc) > + continue; > + > + folio = pfn_folio(PRESERVED_FOLIO_PFN(pfolio->foliodesc)); > + > + kho_unpreserve_folio(folio); This one is missing WARN_ON_ONCE() similar to the one in memfd_luo_preserve_folios(). > + unpin_folio(folio); > + } > +} > + > +static void *memfd_luo_create_fdt(unsigned long size) > +{ > + unsigned int order = get_order(size); > + struct folio *fdt_folio; > + int err = 0; > + void *fdt; > + > + if (order > MAX_PAGE_ORDER) > + return NULL; > + > + fdt_folio = folio_alloc(GFP_KERNEL, order); __GFP_ZERO should also be used here. Otherwise this can lead to unintentional passing of old kernel memory. > +static int memfd_luo_prepare(struct liveupdate_file_handler *handler, > + struct file *file, u64 *data) > +{ > + struct memfd_luo_preserved_folio *preserved_folios; > + struct inode *inode = file_inode(file); > + unsigned int max_folios, nr_folios = 0; > + int err = 0, preserved_size; > + struct folio **folios; > + long size, nr_pinned; > + pgoff_t offset; > + void *fdt; > + u64 pos; > + > + if (WARN_ON_ONCE(!shmem_file(file))) > + return -EINVAL; This one is only check for shmem_file, whereas in memfd_luo_can_preserve() there is check for inode->i_nlink also. Is that not needed here? > + > + inode_lock(inode); > + shmem_i_mapping_freeze(inode, true); > + > + size = i_size_read(inode); > + if ((PAGE_ALIGN(size) / PAGE_SIZE) > UINT_MAX) { > + err = -E2BIG; > + goto err_unlock; > + } > + > + /* > + * Guess the number of folios based on inode size. Real number might end > + * up being smaller if there are higher order folios. > + */ > + max_folios = PAGE_ALIGN(size) / PAGE_SIZE; > + folios = kvmalloc_array(max_folios, sizeof(*folios), GFP_KERNEL); __GFP_ZERO? > +static int memfd_luo_freeze(struct liveupdate_file_handler *handler, > + struct file *file, u64 *data) > +{ > + u64 pos = file->f_pos; > + void *fdt; > + int err; > + > + if (WARN_ON_ONCE(!*data)) > + return -EINVAL; > + > + fdt = phys_to_virt(*data); > + > + /* > + * The pos or size might have changed since prepare. Everything else > + * stays the same. > + */ > + err = fdt_setprop(fdt, 0, "pos", &pos, sizeof(pos)); > + if (err) > + return err; Comment is talking about pos and size but code is only updating pos. > +static int memfd_luo_retrieve(struct liveupdate_file_handler *handler, u64 data, > + struct file **file_p) > +{ > + const struct memfd_luo_preserved_folio *pfolios; > + int nr_pfolios, len, ret = 0, i = 0; > + struct address_space *mapping; > + struct folio *folio, *fdt_folio; > + const u64 *pos, *size; > + struct inode *inode; > + struct file *file; > + const void *fdt; > + > + fdt_folio = memfd_luo_get_fdt(data); > + if (!fdt_folio) > + return -ENOENT; > + > + fdt = page_to_virt(folio_page(fdt_folio, 0)); > + > + pfolios = fdt_getprop(fdt, 0, "folios", &len); > + if (!pfolios || len % sizeof(*pfolios)) { > + pr_err("invalid 'folios' property\n"); Print should clearly state that error is because fields is not found or len is not multiple of sizeof(*pfolios).