summaryrefslogtreecommitdiff
path: root/include/linux/rolling_buffer.h
blob: 5c0bc4221f010c52c1fe2e55d2d09c2b74a26104 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/* 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@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 */