[dhowells-fs:netfs-next 7/25] fs/netfs/bvecq.c:67:24: error: incomplete definition of type 'mempool_t' (aka 'struct mempool')

kernel test robot <[email protected]> Tue, 04 Aug 2026 12:07:32 +0800
Newsgroups dev.linux.lists.oe-kbuild-all,dev.linux.lists.llvm
Message-ID <[email protected]>
tree:   https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git netfs-next
head:   aaa4a525c627a60047b4d6b0d90ae8ea6a4bbdd4
commit: 2839f517bfb007fbfccafb1e6ac2b7d858e72fb4 [7/25] netfs: Make mempool available for bvecq
config: hexagon-randconfig-002-20260804 (https://download.01.org/0day-ci/archive/20260804/[email protected]/config)
compiler: clang version 24.0.0git (https://github.com/llvm/llvm-project bacfe2950f8218268fcc0a8765644ea0c15f0360)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260804/[email protected]/reproduce)

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 <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All errors (new ones prefixed by >>):

>> fs/netfs/bvecq.c:67:24: error: incomplete definition of type 'mempool_t' (aka 'struct mempool')
      67 |                 bq = netfs_bvecq_pool.alloc(gfp, netfs_bvecq_pool.pool_data);
         |                      ~~~~~~~~~~~~~~~~^
   include/linux/netfs.h:25:16: note: forward declaration of 'struct mempool'
      25 | typedef struct mempool mempool_t;
         |                ^
   fs/netfs/bvecq.c:67:52: error: incomplete definition of type 'mempool_t' (aka 'struct mempool')
      67 |                 bq = netfs_bvecq_pool.alloc(gfp, netfs_bvecq_pool.pool_data);
         |                                                  ~~~~~~~~~~~~~~~~^
   include/linux/netfs.h:25:16: note: forward declaration of 'struct mempool'
      25 | typedef struct mempool mempool_t;
         |                ^
>> fs/netfs/bvecq.c:71:8: error: call to undeclared function 'mempool_alloc'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
      71 |                 bq = mempool_alloc(&netfs_bvecq_pool, gfp);
         |                      ^
>> fs/netfs/bvecq.c:71:6: error: incompatible integer to pointer conversion assigning to 'struct bvecq *' from 'int' [-Wint-conversion]
      71 |                 bq = mempool_alloc(&netfs_bvecq_pool, gfp);
         |                    ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> fs/netfs/bvecq.c:260:4: error: call to undeclared function 'mempool_free'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
     260 |                         mempool_free(bq, &netfs_bvecq_pool);
         |                         ^
   5 errors generated.


vim +67 fs/netfs/bvecq.c

    40	
    41	/**
    42	 * bvecq_alloc_one - Allocate a single bvecq node with unpopulated slots
    43	 * @nr_slots: Number of slots to allocate
    44	 * @gfp: The allocation constraints.
    45	 *
    46	 * Allocate a single bvecq node and initialise the header.  A number of inline
    47	 * slots are also allocated, rounded up to fit after the header in a power-of-2
    48	 * slab object of up to 512 bytes (up to 29 slots on a 64-bit cpu).  The caller
    49	 * should be aware that the number of slots allocated may be more or less than
    50	 * the number requested.  The slot array is not initialised.
    51	 *
    52	 * Return: The node pointer or NULL on allocation failure.
    53	 */
    54	struct bvecq *bvecq_alloc_one(size_t nr_slots, gfp_t gfp)
    55	{
    56		struct bvecq *bq;
    57		const size_t max_size = 512;
    58		const size_t max_slots = (max_size - sizeof(*bq)) / sizeof(bq->__bv[0]);
    59		size_t part = umin(nr_slots, max_slots);
    60		size_t size = roundup_pow_of_two(struct_size(bq, __bv, part));
    61		bool from_pool = false;
    62	
    63		gfp &= ~GFP_ZONEMASK;
    64		if (size != BVECQ_STD_SIZE) {
    65			bq = kmalloc(size, gfp);
    66		} else {
  > 67			bq = netfs_bvecq_pool.alloc(gfp, netfs_bvecq_pool.pool_data);
    68			from_pool = true;
    69		}
    70		if (!bq && gfp != GFP_KERNEL) {
  > 71			bq = mempool_alloc(&netfs_bvecq_pool, gfp);
    72			from_pool = true;
    73			size = BVECQ_STD_SIZE;
    74		}
    75		if (bq) {
    76			*bq = (struct bvecq) {
    77				.ref		= REFCOUNT_INIT(1),
    78				.bv		= bq->__bv,
    79				.inline_bv	= true,
    80				.max_slots	= (size - sizeof(*bq)) / sizeof(bq->__bv[0]),
    81				.from_pool	= from_pool,
    82			};
    83			netfs_stat(&netfs_n_bvecq);
    84		}
    85		return bq;
    86	}
    87	EXPORT_SYMBOL(bvecq_alloc_one);
    88	
    89	/**
    90	 * bvecq_alloc_chain - Allocate an unpopulated bvecq chain
    91	 * @nr_slots: Number of slots to allocate
    92	 * @gfp: The allocation constraints.
    93	 *
    94	 * Allocate a chain of bvecq nodes providing at least the requested cumulative
    95	 * number of slots.
    96	 *
    97	 * Return: The first node pointer or NULL on allocation failure.
    98	 */
    99	struct bvecq *bvecq_alloc_chain(size_t nr_slots, gfp_t gfp)
   100	{
   101		struct bvecq *head = NULL, *tail = NULL;
   102	
   103		_enter("%zu", nr_slots);
   104	
   105		for (;;) {
   106			struct bvecq *bq;
   107	
   108			bq = bvecq_alloc_one(nr_slots, gfp);
   109			if (!bq)
   110				goto oom;
   111	
   112			if (tail)
   113				bvecq_append(tail, bq);
   114			else
   115				head = bq;
   116			tail = bq;
   117			if (tail->max_slots >= nr_slots)
   118				break;
   119			nr_slots -= tail->max_slots;
   120		}
   121	
   122		return head;
   123	oom:
   124		bvecq_put(head);
   125		return NULL;
   126	}
   127	EXPORT_SYMBOL(bvecq_alloc_chain);
   128	
   129	/**
   130	 * bvecq_alloc_buffer2 - Allocate a bvecq chain and populate with buffers
   131	 * @size: Target size of the buffer (can be 0 for an empty buffer)
   132	 * @pre_slots: Number of preamble slots to set aside
   133	 * @gfp: The allocation constraints.
   134	 *
   135	 * Allocate a chain of bvecq nodes and populate the slots with sufficient pages
   136	 * to provide at least the requested amount of space, leaving the first
   137	 * @pre_slots slots unset.  The pre-slots must all fit into the the first
   138	 * bvecq.
   139	 *
   140	 * The pages allocated may be compound pages larger than PAGE_SIZE and thus
   141	 * occupy fewer slots.  The pages have their refcounts set to 1 and can be
   142	 * passed to MSG_SPLICE_PAGES.
   143	 *
   144	 * Return: The first node pointer or NULL on allocation failure.
   145	 */
   146	struct bvecq *bvecq_alloc_buffer2(size_t size, unsigned int pre_slots, gfp_t gfp)
   147	{
   148		struct bvecq *head = NULL, *p = NULL;
   149		size_t nr_per_bq = BVECQ_STD_SLOTS;
   150		size_t count = pre_slots + DIV_ROUND_UP(size, PAGE_SIZE);
   151	
   152		_enter("%zx,%zx,%u", size, count, pre_slots);
   153	
   154		if (WARN_ON_ONCE(pre_slots > nr_per_bq))
   155			return NULL;
   156	
   157		head = bvecq_alloc_chain(count, gfp);
   158		if (!head)
   159			return NULL;
   160	
   161		p = head;
   162		do {
   163			struct page **pages;
   164			size_t unused, want, got, slot;
   165	
   166			if (!count)
   167				break;
   168			if (WARN_ON_ONCE(!p))
   169				goto oom;
   170	
   171			if (p->nr_slots == 0) {
   172				/* Need to clear pre slots and pages[], so just clear all. */
   173				memset(p->bv, 0, p->max_slots * sizeof(p->bv[0]));
   174				p->mem_type = BVECQ_MEM_ALLOCED;
   175				p->nr_slots = pre_slots;
   176				count -= pre_slots;
   177				pre_slots = 0;
   178				if (!count)
   179					break;
   180			}
   181	
   182			if (p->nr_slots >= p->max_slots) {
   183				p = p->next;
   184				continue;
   185			}
   186			unused = p->max_slots - p->nr_slots;
   187	
   188			pages = (struct page **)&p->bv[p->max_slots];
   189			pages -= unused;
   190	
   191			want = min(count, unused);
   192			got = alloc_pages_bulk(gfp, want, pages);
   193			if (!got)
   194				goto oom;
   195	
   196			slot = p->nr_slots;
   197			for (int i = 0; i < got; i++) {
   198				set_page_count(pages[i], 1);
   199				bvec_set_page(&p->bv[slot++], pages[i], PAGE_SIZE, 0);
   200			}
   201	
   202			bvecq_filled_to(p, slot);
   203			count -= got;
   204		} while (count > 0);
   205	
   206		return head;
   207	oom:
   208		bvecq_put(head);
   209		return NULL;
   210	}
   211	EXPORT_SYMBOL(bvecq_alloc_buffer2);
   212	
   213	/*
   214	 * Free the page pointed to by a slot as necessary.
   215	 */
   216	static void bvecq_free_slot(struct bvecq *bq, unsigned int slot)
   217	{
   218		struct page *page = bq->bv[slot].bv_page;
   219	
   220		if (!page)
   221			return;
   222	
   223		switch (bq->mem_type) {
   224		case BVECQ_MEM_EXTERNAL:
   225			break;
   226		case BVECQ_MEM_PAGECACHE:
   227			put_page(page);
   228			break;
   229		case BVECQ_MEM_GUP:
   230			unpin_user_page(page);
   231			break;
   232		case BVECQ_MEM_ALLOCED:
   233			__free_pages(page, compound_order(page));
   234			break;
   235		default:
   236			WARN_ON_ONCE(1);
   237			break;
   238		}
   239	}
   240	
   241	/**
   242	 * bvecq_put - Put a ref on a bvec queue
   243	 * @bq: The start of the folio queue to free
   244	 *
   245	 * Put the ref(s) on the nodes in a bvec queue, freeing up the node and the
   246	 * page fragments it points to as the refcounts become zero.
   247	 */
   248	void bvecq_put(struct bvecq *bq)
   249	{
   250		struct bvecq *next;
   251	
   252		for (; bq; bq = next) {
   253			if (!refcount_dec_and_test(&bq->ref))
   254				break;
   255			for (int slot = 0; slot < bq->nr_slots; slot++)
   256				bvecq_free_slot(bq, slot);
   257			next = bq->next;
   258			netfs_stat_d(&netfs_n_bvecq);
   259			if (bq->from_pool)
 > 260				mempool_free(bq, &netfs_bvecq_pool);
   261			else
   262				kfree(bq);
   263		}
   264	}
   265	EXPORT_SYMBOL(bvecq_put);
   266	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki