[PATCH v17 7/8] netfs: Remove the rolling_buffer implementation

David Howells dhowells at redhat.com
Thu Oct 8 03:22:51 PDT 2026


Remove the rolling_buffer implementation as it has been replaced with the
use of bvecq_pos.

Signed-off-by: David Howells <dhowells at redhat.com>
Reviewed-by: Paulo Alcantara <pc at manguebit.org>
cc: Matthew Wilcox <willy at infradead.org>
cc: netfs at lists.linux.dev
cc: linux-fsdevel at vger.kernel.org
---
 fs/netfs/rolling_buffer.c      | 182 ---------------------------------
 include/linux/rolling_buffer.h |  47 ---------
 2 files changed, 229 deletions(-)
 delete mode 100644 fs/netfs/rolling_buffer.c
 delete mode 100644 include/linux/rolling_buffer.h

diff --git a/fs/netfs/rolling_buffer.c b/fs/netfs/rolling_buffer.c
deleted file mode 100644
index 66ce9add4012..000000000000
--- a/fs/netfs/rolling_buffer.c
+++ /dev/null
@@ -1,182 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/* Rolling buffer helpers
- *
- * Copyright (C) 2024 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells at redhat.com)
- */
-
-#include <linux/bitops.h>
-#include <linux/mempool.h>
-#include <linux/pagemap.h>
-#include <linux/rolling_buffer.h>
-#include <linux/slab.h>
-#include "internal.h"
-
-/*
- * Initialise a rolling buffer.  We allocate an empty folio queue struct to so
- * that the pointers can be independently driven by the producer and the
- * consumer.
- */
-int rolling_buffer_init(struct rolling_buffer *roll, unsigned int direction,
-			gfp_t gfp, bool for_writeback)
-{
-	struct bvecq *bq;
-
-	roll->for_writeback = for_writeback;
-
-	bq = bvecq_alloc_one(BVECQ_POOL_SLOTS, gfp, for_writeback);
-	if (!bq)
-		return -ENOMEM;
-
-	roll->head = bq;
-	roll->tail = bq;
-	iov_iter_bvec_queue(&roll->iter, direction, bq, 0, 0, 0);
-	return 0;
-}
-
-/*
- * Add another bvecq to a rolling buffer if there's no space left.
- */
-int rolling_buffer_make_space(struct rolling_buffer *roll, gfp_t gfp)
-{
-	struct bvecq *bq, *head = roll->head;
-
-	if (!bvecq_is_full(head))
-		return 0;
-
-	bq = bvecq_alloc_one(BVECQ_POOL_SLOTS, gfp, roll->for_writeback);
-	if (!bq)
-		return -ENOMEM;
-
-	roll->head = bq;
-	if (bvecq_is_full(head)) {
-		/* Make sure we don't leave the master iterator pointing to a
-		 * block that might get immediately consumed.
-		 */
-		if (roll->iter.bvecq == head &&
-		    roll->iter.bvecq_slot == head->nr_slots) {
-			roll->iter.bvecq = bq;
-			roll->iter.bvecq_slot = 0;
-		}
-	}
-
-	/* Make sure the initialisation is stored before the next pointer.
-	 *
-	 * [!] NOTE: After we set head->next, the consumer is at liberty to
-	 * immediately delete the old head.
-	 */
-	bvecq_append(head, bq);
-	return 0;
-}
-
-/*
- * Decant the entire list of folios to read into a rolling buffer.
- */
-ssize_t rolling_buffer_bulk_load_from_ra(struct rolling_buffer *roll,
-					 struct readahead_control *ractl,
-					 gfp_t gfp)
-{
-	struct bvecq *bq;
-	size_t loaded = 0;
-
-	while (ractl->_nr_pages - ractl->_batch_count > 0) {
-		struct page **pages;
-		unsigned int nr;
-
-		/* Allocate a bvecq to put some folios into and attach it to
-		 * the rolling buffer.
-		 */
-		bq = bvecq_alloc_one(BVECQ_POOL_SLOTS, gfp, false);
-		if (!bq)
-			goto nomem_unlock;
-		bq->mem_type = BVECQ_MEM_EXTERNAL; /* Folio cleanup handled separately. */
-
-		if (!roll->tail)
-			roll->tail = bq;
-		else
-			bvecq_append(roll->head, bq);
-		roll->head = bq;
-
-		/* Get a bunch of folios and note their sizes. */
-		pages = (struct page **)(bq->bv + bq->max_slots);
-		pages -= bq->max_slots;
-		nr = __readahead_batch(ractl, pages, bq->max_slots);
-		if (WARN_ON_ONCE(!nr))
-			break;
-
-		for (int slot = 0; slot < nr; slot++) {
-			struct folio *folio = page_folio(pages[slot]);
-			size_t len = folio_size(folio);
-
-			bvec_set_folio(&bq->bv[slot], folio, len, 0);
-			loaded += len;
-			trace_netfs_folio(folio, netfs_folio_trace_read);
-		}
-
-		bvecq_filled_to(bq, nr);
-	}
-
-	WRITE_ONCE(roll->iter.count, loaded);
-	iov_iter_bvec_queue(&roll->iter, ITER_DEST, roll->tail, 0, 0, loaded);
-	return loaded;
-
-nomem_unlock:
-	for (bq = roll->tail; bq; bq = bq->next) {
-		for (int slot = 0; slot < bq->nr_slots; slot++) {
-			struct folio *folio = bvec_folio(&bq->bv[slot]);
-
-			folio_unlock(folio);
-			folio_put(folio);
-		}
-	}
-	rolling_buffer_clear(roll);
-	roll->head = NULL;
-	roll->tail = NULL;
-	return -ENOMEM;
-}
-
-/*
- * Append a folio to the rolling buffer.
- */
-ssize_t rolling_buffer_append(struct rolling_buffer *roll, struct folio *folio,
-			      gfp_t gfp)
-{
-	ssize_t size = folio_size(folio);
-	int slot;
-
-	if (rolling_buffer_make_space(roll, gfp) < 0)
-		return -ENOMEM;
-
-	slot = roll->head->nr_slots;
-	bvec_set_folio(&roll->head->bv[slot], folio, size, 0);
-	bvecq_filled_to(roll->head, slot + 1);
-
-	WRITE_ONCE(roll->iter.count, roll->iter.count + size);
-	return size;
-}
-
-/*
- * Delete a spent buffer from a rolling queue and return the next in line.  We
- * don't return the last buffer to keep the pointers independent, but return
- * NULL instead.
- */
-struct bvecq *rolling_buffer_delete_spent(struct rolling_buffer *roll)
-{
-	struct bvecq *spent = roll->tail, *next = bvecq_next(spent);
-
-	if (!next)
-		return NULL;
-	next->prev = NULL;
-	roll->tail = next;
-	spent->next = NULL;
-	bvecq_put(spent);
-	return next;
-}
-
-/*
- * Clear out a rolling queue.
- */
-void rolling_buffer_clear(struct rolling_buffer *roll)
-{
-	bvecq_put(roll->tail);
-}
diff --git a/include/linux/rolling_buffer.h b/include/linux/rolling_buffer.h
deleted file mode 100644
index 5c0bc4221f01..000000000000
--- a/include/linux/rolling_buffer.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Rolling buffer of folios
- *
- * Copyright (C) 2024 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells at redhat.com)
- */
-
-#ifndef _ROLLING_BUFFER_H
-#define _ROLLING_BUFFER_H
-
-#include <linux/bvecq.h>
-#include <linux/uio.h>
-
-/*
- * Rolling buffer.  Whilst the buffer is live and in use, folios and bvecq
- * segments can be added to one end by one thread and removed from the other
- * end by another thread.  The buffer isn't allowed to be empty; it must always
- * have at least one bvecq in it so that neither side has to modify both queue
- * pointers.
- *
- * The iterator in the buffer is extended as buffers are inserted.  It can be
- * snapshotted to use a segment of the buffer.
- */
-struct rolling_buffer {
-	struct bvecq		*head;		/* Producer's insertion point */
-	struct bvecq		*tail;		/* Consumer's removal point */
-	struct iov_iter		iter;		/* Iterator tracking what's left in the buffer */
-	u8			first_tail_slot; /* First slot in ->tail */
-	bool			for_writeback;	/* T if being used for writeback */
-};
-
-int rolling_buffer_init(struct rolling_buffer *roll, unsigned int direction,
-			gfp_t gfp, bool for_writeback);
-int rolling_buffer_make_space(struct rolling_buffer *roll, gfp_t gfp);
-ssize_t rolling_buffer_bulk_load_from_ra(struct rolling_buffer *roll,
-					 struct readahead_control *ractl,
-					 gfp_t gfp);
-ssize_t rolling_buffer_append(struct rolling_buffer *roll, struct folio *folio, gfp_t gfp);
-struct bvecq *rolling_buffer_delete_spent(struct rolling_buffer *roll);
-void rolling_buffer_clear(struct rolling_buffer *roll);
-
-static inline void rolling_buffer_advance(struct rolling_buffer *roll, size_t amount)
-{
-	iov_iter_advance(&roll->iter, amount);
-}
-
-#endif /* _ROLLING_BUFFER_H */




More information about the linux-afs mailing list