From: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> When we have both a pmd_entry() and a pte_entry() callback, in some siutaions it is desirable not to traverse the pte level. Reserve positive callback return values for walk control and define a return value PAGE_WALK_CONTINUE that means skip lower level traversal and continue the walk. Co-developed-by: Thomas Hellstrom <thellstrom@xxxxxxxxxx> Signed-off-by: Thomas Hellstrom <thellstrom@xxxxxxxxxx> --- include/linux/pagewalk.h | 6 ++++++ mm/pagewalk.c | 9 ++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/linux/pagewalk.h b/include/linux/pagewalk.h index 6ec82e92c87f..d9e5d1927315 100644 --- a/include/linux/pagewalk.h +++ b/include/linux/pagewalk.h @@ -4,6 +4,12 @@ #include <linux/mm.h> +/* + * pmd_entry() Return code meaning skip to next entry. + * Don't look for lower levels + */ +#define PAGE_WALK_CONTINUE 1 + struct mm_walk; /** diff --git a/mm/pagewalk.c b/mm/pagewalk.c index ea0b9e606ad1..d2483d432fda 100644 --- a/mm/pagewalk.c +++ b/mm/pagewalk.c @@ -52,8 +52,12 @@ static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end, */ if (ops->pmd_entry) err = ops->pmd_entry(pmd, addr, next, walk); - if (err) + if (err < 0) break; + if (err == PAGE_WALK_CONTINUE) { + err = 0; + continue; + } /* * Check this here so we only break down trans_huge @@ -291,8 +295,7 @@ static int __walk_page_range(unsigned long start, unsigned long end, * * - 0 : succeeded to handle the current entry, and if you don't reach the * end address yet, continue to walk. - * - >0 : succeeded to handle the current entry, and return to the caller - * with caller specific value. + * - >0 : Reserved for walk control. Use only PAGE_WALK_XX values. * - <0 : failed to handle the current entry, and return to the caller * with error code. * -- 2.21.0