On 12/10/21 03:02, Liam Howlett wrote: > > vma_find() uses mas_find() which was created to implement find_vma(). > As a replacement, the search looks for an entry at the address and if > nothing exists, it will continue the search upwards. The result is that > the first entry can be found at the address passed. Every subsequent > call to vma_find() would search from the end of the previous range - as > saved in the maple state, or the vma iterator in this case. > > mas_next(), however is more of a traditional linked list operation that > finds the next entry _after_ the one containing the index in the maple > state. The only difference is on the start when the maple state is not > currently pointing at an entry at all (the node is set to MAS_START). > > mas_find() can be thought of as: > > entry = mas_walk(); > if (!entry) > entry = mas_next_entry(); > > return entry; > > > mas_next can be though to as: > > if (mas_is_start()) > mas_walk(); > > return mas_next_entry(); > > > Matthew uses mas_find() for his implementation of the vma iterator so > that the first entry is not skipped. Yeah, but if vma_next() is going to replace the cases where we already have a vma and use vma->vm_next to get the next one, then mas_next() would be a better fit? Do I understand correctly that e.g. after a mas_pause(), vma_next() done via max_next() might return the same vma again, while vma_prev() will not, and vma_next() implemented by mas_next() also wouldn't? Isn't that unexpected semantics? >> >> > +} >> > + >> > +static inline struct vm_area_struct *vma_prev(struct vma_iterator *vmi) >> > +{ >> > + return mas_prev(&vmi->mas, 0); >> > +} >> > + >> > +static inline unsigned long vma_iter_addr(struct vma_iterator *vmi) >> > +{ >> > + return vmi->mas.index; >> > +} >> > + >> > +#define for_each_vma(vmi, vma) while ((vma = vma_next(&vmi)) != NULL) >> > +