[RFC PATCH 3/3] mm: Implement for_each_valid_pfn() for CONFIG_SPARSEMEM

Mike Rapoport rppt at kernel.org
Wed Apr 2 23:24:04 PDT 2025


On Wed, Apr 02, 2025 at 09:18:41PM +0100, David Woodhouse wrote:
> From: David Woodhouse <dwmw at amazon.co.uk>
> 
> Introduce a pfn_first_valid() helper which takes a pointer to the PFN and
> updates it to point to the first valid PFN starting from that point, and
> returns true if a valid PFN was found.
> 
> This largely mirrors pfn_valid(), calling into a pfn_section_first_valid()
> helper which is trivial for the !CONFIG_SPARSEMEM_VMEMMAP case, and in
> the VMEMMAP case will skip to the next subsection as needed.
> 
> Signed-off-by: David Woodhouse <dwmw at amazon.co.uk>

Reviewed-by: Mike Rapoport (Microsoft) <rppt at kernel.org>

with a small nit below

> +static inline bool first_valid_pfn(unsigned long *p_pfn)
> +{
> +	unsigned long pfn = *p_pfn;
> +	unsigned long nr = pfn_to_section_nr(pfn);
> +	struct mem_section *ms;
> +	bool ret = false;
> +
> +	ms = __pfn_to_section(pfn);
> +
> +	rcu_read_lock_sched();
> +
> +	while (!ret && nr <= __highest_present_section_nr) {

This could be just for(;;), we anyway break when ret becomes true or we get
past last present section.

> +		if (valid_section(ms) &&
> +		    (early_section(ms) || pfn_section_first_valid(ms, &pfn))) {
> +			ret = true;
> +			break;
> +		}
> +
> +		nr++;
> +		if (nr > __highest_present_section_nr)
> +			break;
> +
> +		pfn = section_nr_to_pfn(nr);
> +		ms = __pfn_to_section(pfn);
> +	}
> +
> +	rcu_read_unlock_sched();
> +
> +	*p_pfn = pfn;
> +
> +	return ret;
> +}
> +
> +#define for_each_valid_pfn(_pfn, _start_pfn, _end_pfn)	       \
> +	for ((_pfn) = (_start_pfn);			       \
> +	     first_valid_pfn(&(_pfn)) && (_pfn) < (_end_pfn);  \
> +	     (_pfn)++)
> +
>  #endif
>  
>  static inline int pfn_in_present_section(unsigned long pfn)
> -- 
> 2.49.0
> 

-- 
Sincerely yours,
Mike.



More information about the linux-arm-kernel mailing list