[..] > > > > /* > > * Return the number of contiguous zeromap entries started from entry; > > * If all entries have consistent zeromap, *consistent will be true; > > * otherwise, false; > > */ > > static inline unsigned int swap_zeromap_entries_count(swp_entry_t entry, > > int nr, bool *consistent) > > { > > struct swap_info_struct *sis = swp_swap_info(entry); > > unsigned long start = swp_offset(entry); > > unsigned long end = start + nr; > > unsigned long s_idx, c_idx; > > > > s_idx = find_next_bit(sis->zeromap, end, start); > > if (s_idx == end) { > > *consistent = true; > > return 0; > > } > > > > c_idx = find_next_zero_bit(sis->zeromap, end, start); > > if (c_idx == end) { > > *consistent = true; > > return nr; > > } > > > > *consistent = false; > > if (s_idx == start) > > return 0; > > return c_idx - s_idx; > > } > > > > I can actually switch the places of the "consistent" and returned > > number if that looks > > better. > > I'd rather make it simpler by: > > /* > * Check if all entries have consistent zeromap status, return true if > * all entries are zeromap or non-zeromap, else return false; > */ > static inline bool swap_zeromap_entries_check(swp_entry_t entry, int nr) > { > struct swap_info_struct *sis = swp_swap_info(entry); > unsigned long start = swp_offset(entry); > unsigned long end = start + *nr; > > if (find_next_bit(sis->zeromap, end, start) == end) > return true; > if (find_next_zero_bit(sis->zeromap, end, start) == end) > return true; > > return false; > } We can start with a simple version like this, and when the time comes to implement the logic below we can decide if it's worth the complexity to return an exact number/order rather than a boolean to decide the swapin order. I think it will also depend on whether we can do the same for other backends (e.g. swapcache, zswap, etc). We can note that in the commit log or something. > > mm/page_io.c can combine this with reading the zeromap of first entry to > decide if it will read folio from zeromap; mm/memory.c only needs the bool > to fallback to the largest possible order. > > static inline unsigned long thp_swap_suitable_orders(...) > { > int order, nr; > > order = highest_order(orders); > > while (orders) { > nr = 1 << order; > if ((addr >> PAGE_SHIFT) % nr == swp_offset % nr && > swap_zeromap_entries_check(entry, nr)) > break; > order = next_order(&orders, order); > } > > return orders; > } >