linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Yang Shi <shy828301@gmail.com>
To: kernel test robot <lkp@intel.com>
Cc: Yang Shi <yang@os.amperecomputing.com>,
	oe-kbuild-all@lists.linux.dev,
	 Linux Memory Management List <linux-mm@kvack.org>,
	Andrew Morton <akpm@linux-foundation.org>
Subject: Re: [linux-next:master 9137/9689] mm/gup.c:476:25: error: implicit declaration of function 'try_grab_folio_fast'; did you mean 'try_grab_folio'?
Date: Fri, 28 Jun 2024 18:58:14 -0700	[thread overview]
Message-ID: <CAHbLzkowMSso-4Nufc9hcMehQsK9PNz3OSu-+eniU-2Mm-xjhA@mail.gmail.com> (raw)
In-Reply-To: <202406290729.21FzkVlI-lkp@intel.com>

[-- Attachment #1: Type: text/plain, Size: 4914 bytes --]

On Fri, Jun 28, 2024 at 5:01 PM kernel test robot <lkp@intel.com> wrote:
>
> tree:   https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
> head:   1eb586a9782cde8e5091b9de74603e0a8386b09e
> commit: ee3fe497bdf0c7cb6fbec346f36aa1f9b1dfe6dd [9137/9689] mm: gup: do not call try_grab_folio() in slow path
> config: powerpc-randconfig-r005-20221108
> compiler: powerpc-linux-gcc (GCC) 13.2.0
> reproduce (this is a W=1 build):
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202406290729.21FzkVlI-lkp@intel.com/
>
> All error/warnings (new ones prefixed by >>):
>
>    mm/gup.c: In function 'gup_hugepte':
> >> mm/gup.c:476:25: error: implicit declaration of function 'try_grab_folio_fast'; did you mean 'try_grab_folio'? [-Werror=implicit-function-declaration]

The definition of try_grab_folio_fast() should be protected by
CONFIG_ARCH_HAS_HUGEPD || CONFIG_HAVE_GUP_FAST.

Andrew,

Please apply the attached fix on top of it. The reproducer requires
x86 machine since the cross build tool is on x86, but I don't have a
x86 machine by hand right now. But I think the patch should fix it.

>      476 |                 folio = try_grab_folio_fast(page, refs, flags);
>          |                         ^~~~~~~~~~~~~~~~~~~
>          |                         try_grab_folio
> >> mm/gup.c:476:23: warning: assignment to 'struct folio *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
>      476 |                 folio = try_grab_folio_fast(page, refs, flags);
>          |                       ^
>    mm/gup.c: At top level:
> >> mm/gup.c:2748:22: error: conflicting types for 'try_grab_folio_fast'; have 'struct folio *(struct page *, int,  unsigned int)'
>     2748 | static struct folio *try_grab_folio_fast(struct page *page, int refs,
>          |                      ^~~~~~~~~~~~~~~~~~~
>    mm/gup.c:476:25: note: previous implicit declaration of 'try_grab_folio_fast' with type 'int()'
>      476 |                 folio = try_grab_folio_fast(page, refs, flags);
>          |                         ^~~~~~~~~~~~~~~~~~~
>    cc1: some warnings being treated as errors
>
>
> vim +476 mm/gup.c
>
>    441
>    442  /*
>    443   * Returns 1 if succeeded, 0 if failed, -EMLINK if unshare needed.
>    444   *
>    445   * NOTE: for the same entry, gup-fast and gup-slow can return different
>    446   * results (0 v.s. -EMLINK) depending on whether vma is available.  This is
>    447   * the expected behavior, where we simply want gup-fast to fallback to
>    448   * gup-slow to take the vma reference first.
>    449   */
>    450  static int gup_hugepte(struct vm_area_struct *vma, pte_t *ptep, unsigned long sz,
>    451                         unsigned long addr, unsigned long end, unsigned int flags,
>    452                         struct page **pages, int *nr, bool fast)
>    453  {
>    454          unsigned long pte_end;
>    455          struct page *page;
>    456          struct folio *folio;
>    457          pte_t pte;
>    458          int refs;
>    459
>    460          pte_end = (addr + sz) & ~(sz-1);
>    461          if (pte_end < end)
>    462                  end = pte_end;
>    463
>    464          pte = huge_ptep_get(ptep);
>    465
>    466          if (!pte_access_permitted(pte, flags & FOLL_WRITE))
>    467                  return 0;
>    468
>    469          /* hugepages are never "special" */
>    470          VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
>    471
>    472          page = pte_page(pte);
>    473          refs = record_subpages(page, sz, addr, end, pages + *nr);
>    474
>    475          if (fast) {
>  > 476                  folio = try_grab_folio_fast(page, refs, flags);
>    477                  if (!folio)
>    478                          return 0;
>    479          } else {
>    480                  folio = page_folio(page);
>    481                  if (try_grab_folio(folio, refs, flags))
>    482                          return 0;
>    483          }
>    484
>    485          if (unlikely(pte_val(pte) != pte_val(ptep_get(ptep)))) {
>    486                  gup_put_folio(folio, refs, flags);
>    487                  return 0;
>    488          }
>    489
>    490          if (!pte_write(pte) && gup_must_unshare(vma, flags, &folio->page)) {
>    491                  gup_put_folio(folio, refs, flags);
>    492                  return -EMLINK;
>    493          }
>    494
>    495          *nr += refs;
>    496          folio_set_referenced(folio);
>    497          return 1;
>    498  }
>    499
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki

[-- Attachment #2: mm-gup-stop-abusing-try_grab_folio-fix.patch --]
[-- Type: application/octet-stream, Size: 6771 bytes --]

diff --git a/mm/gup.c b/mm/gup.c
index e65773ce4622..fdd3b2719f33 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -427,6 +427,102 @@ static int record_subpages(struct page *page, unsigned long sz,
 
 	return nr;
 }
+
+/**
+ * try_grab_folio_fast() - Attempt to get or pin a folio in fast path.
+ * @page:  pointer to page to be grabbed
+ * @refs:  the value to (effectively) add to the folio's refcount
+ * @flags: gup flags: these are the FOLL_* flag values.
+ *
+ * "grab" names in this file mean, "look at flags to decide whether to use
+ * FOLL_PIN or FOLL_GET behavior, when incrementing the folio's refcount.
+ *
+ * Either FOLL_PIN or FOLL_GET (or neither) must be set, but not both at the
+ * same time. (That's true throughout the get_user_pages*() and
+ * pin_user_pages*() APIs.) Cases:
+ *
+ *    FOLL_GET: folio's refcount will be incremented by @refs.
+ *
+ *    FOLL_PIN on large folios: folio's refcount will be incremented by
+ *    @refs, and its pincount will be incremented by @refs.
+ *
+ *    FOLL_PIN on single-page folios: folio's refcount will be incremented by
+ *    @refs * GUP_PIN_COUNTING_BIAS.
+ *
+ * Return: The folio containing @page (with refcount appropriately
+ * incremented) for success, or NULL upon failure. If neither FOLL_GET
+ * nor FOLL_PIN was set, that's considered failure, and furthermore,
+ * a likely bug in the caller, so a warning is also emitted.
+ *
+ * It uses add ref unless zero to elevate the folio refcount and must be called
+ * in fast path only.
+ */
+static struct folio *try_grab_folio_fast(struct page *page, int refs,
+					 unsigned int flags)
+{
+	struct folio *folio;
+
+	/* Raise warn if it is not called in fast GUP */
+	VM_WARN_ON_ONCE(!irqs_disabled());
+
+	if (WARN_ON_ONCE((flags & (FOLL_GET | FOLL_PIN)) == 0))
+		return NULL;
+
+	if (unlikely(!(flags & FOLL_PCI_P2PDMA) && is_pci_p2pdma_page(page)))
+		return NULL;
+
+	if (flags & FOLL_GET)
+		return try_get_folio(page, refs);
+
+	/* FOLL_PIN is set */
+
+	/*
+	 * Don't take a pin on the zero page - it's not going anywhere
+	 * and it is used in a *lot* of places.
+	 */
+	if (is_zero_page(page))
+		return page_folio(page);
+
+	folio = try_get_folio(page, refs);
+	if (!folio)
+		return NULL;
+
+	/*
+	 * Can't do FOLL_LONGTERM + FOLL_PIN gup fast path if not in a
+	 * right zone, so fail and let the caller fall back to the slow
+	 * path.
+	 */
+	if (unlikely((flags & FOLL_LONGTERM) &&
+		     !folio_is_longterm_pinnable(folio))) {
+		if (!put_devmap_managed_folio_refs(folio, refs))
+			folio_put_refs(folio, refs);
+		return NULL;
+	}
+
+	/*
+	 * When pinning a large folio, use an exact count to track it.
+	 *
+	 * However, be sure to *also* increment the normal folio
+	 * refcount field at least once, so that the folio really
+	 * is pinned.  That's why the refcount from the earlier
+	 * try_get_folio() is left intact.
+	 */
+	if (folio_test_large(folio))
+		atomic_add(refs, &folio->_pincount);
+	else
+		folio_ref_add(folio,
+				refs * (GUP_PIN_COUNTING_BIAS - 1));
+	/*
+	 * Adjust the pincount before re-checking the PTE for changes.
+	 * This is essentially a smp_mb() and is paired with a memory
+	 * barrier in folio_try_share_anon_rmap_*().
+	 */
+	smp_mb__after_atomic();
+
+	node_stat_mod_folio(folio, NR_FOLL_PIN_ACQUIRED, refs);
+
+	return folio;
+}
 #endif	/* CONFIG_ARCH_HAS_HUGEPD || CONFIG_HAVE_GUP_FAST */
 
 #ifdef CONFIG_ARCH_HAS_HUGEPD
@@ -2715,102 +2811,6 @@ EXPORT_SYMBOL(get_user_pages_unlocked);
  * This code is based heavily on the PowerPC implementation by Nick Piggin.
  */
 #ifdef CONFIG_HAVE_GUP_FAST
-/**
- * try_grab_folio_fast() - Attempt to get or pin a folio in fast path.
- * @page:  pointer to page to be grabbed
- * @refs:  the value to (effectively) add to the folio's refcount
- * @flags: gup flags: these are the FOLL_* flag values.
- *
- * "grab" names in this file mean, "look at flags to decide whether to use
- * FOLL_PIN or FOLL_GET behavior, when incrementing the folio's refcount.
- *
- * Either FOLL_PIN or FOLL_GET (or neither) must be set, but not both at the
- * same time. (That's true throughout the get_user_pages*() and
- * pin_user_pages*() APIs.) Cases:
- *
- *    FOLL_GET: folio's refcount will be incremented by @refs.
- *
- *    FOLL_PIN on large folios: folio's refcount will be incremented by
- *    @refs, and its pincount will be incremented by @refs.
- *
- *    FOLL_PIN on single-page folios: folio's refcount will be incremented by
- *    @refs * GUP_PIN_COUNTING_BIAS.
- *
- * Return: The folio containing @page (with refcount appropriately
- * incremented) for success, or NULL upon failure. If neither FOLL_GET
- * nor FOLL_PIN was set, that's considered failure, and furthermore,
- * a likely bug in the caller, so a warning is also emitted.
- *
- * It uses add ref unless zero to elevate the folio refcount and must be called
- * in fast path only.
- */
-static struct folio *try_grab_folio_fast(struct page *page, int refs,
-					 unsigned int flags)
-{
-	struct folio *folio;
-
-	/* Raise warn if it is not called in fast GUP */
-	VM_WARN_ON_ONCE(!irqs_disabled());
-
-	if (WARN_ON_ONCE((flags & (FOLL_GET | FOLL_PIN)) == 0))
-		return NULL;
-
-	if (unlikely(!(flags & FOLL_PCI_P2PDMA) && is_pci_p2pdma_page(page)))
-		return NULL;
-
-	if (flags & FOLL_GET)
-		return try_get_folio(page, refs);
-
-	/* FOLL_PIN is set */
-
-	/*
-	 * Don't take a pin on the zero page - it's not going anywhere
-	 * and it is used in a *lot* of places.
-	 */
-	if (is_zero_page(page))
-		return page_folio(page);
-
-	folio = try_get_folio(page, refs);
-	if (!folio)
-		return NULL;
-
-	/*
-	 * Can't do FOLL_LONGTERM + FOLL_PIN gup fast path if not in a
-	 * right zone, so fail and let the caller fall back to the slow
-	 * path.
-	 */
-	if (unlikely((flags & FOLL_LONGTERM) &&
-		     !folio_is_longterm_pinnable(folio))) {
-		if (!put_devmap_managed_folio_refs(folio, refs))
-			folio_put_refs(folio, refs);
-		return NULL;
-	}
-
-	/*
-	 * When pinning a large folio, use an exact count to track it.
-	 *
-	 * However, be sure to *also* increment the normal folio
-	 * refcount field at least once, so that the folio really
-	 * is pinned.  That's why the refcount from the earlier
-	 * try_get_folio() is left intact.
-	 */
-	if (folio_test_large(folio))
-		atomic_add(refs, &folio->_pincount);
-	else
-		folio_ref_add(folio,
-				refs * (GUP_PIN_COUNTING_BIAS - 1));
-	/*
-	 * Adjust the pincount before re-checking the PTE for changes.
-	 * This is essentially a smp_mb() and is paired with a memory
-	 * barrier in folio_try_share_anon_rmap_*().
-	 */
-	smp_mb__after_atomic();
-
-	node_stat_mod_folio(folio, NR_FOLL_PIN_ACQUIRED, refs);
-
-	return folio;
-}
-
 /*
  * Used in the GUP-fast path to determine whether GUP is permitted to work on
  * a specific folio.

      reply	other threads:[~2024-06-29  1:58 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-28 23:56 [linux-next:master 9137/9689] mm/gup.c:476:25: error: implicit declaration of function 'try_grab_folio_fast'; did you mean 'try_grab_folio'? kernel test robot
2024-06-29  1:58 ` Yang Shi [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAHbLzkowMSso-4Nufc9hcMehQsK9PNz3OSu-+eniU-2Mm-xjhA@mail.gmail.com \
    --to=shy828301@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=linux-mm@kvack.org \
    --cc=lkp@intel.com \
    --cc=oe-kbuild-all@lists.linux.dev \
    --cc=yang@os.amperecomputing.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).