1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /* Rolling buffer of folios
3 *
4 * Copyright (C) 2024 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
6 */
7
8 #ifndef _ROLLING_BUFFER_H
9 #define _ROLLING_BUFFER_H
10
11 #include <linux/folio_queue.h>
12 #include <linux/uio.h>
13
14 /*
15 * Rolling buffer. Whilst the buffer is live and in use, folios and folio
16 * queue segments can be added to one end by one thread and removed from the
17 * other end by another thread. The buffer isn't allowed to be empty; it must
18 * always have at least one folio_queue in it so that neither side has to
19 * modify both queue pointers.
20 *
21 * The iterator in the buffer is extended as buffers are inserted. It can be
22 * snapshotted to use a segment of the buffer.
23 */
24 struct rolling_buffer {
25 struct folio_queue *head; /* Producer's insertion point */
26 struct folio_queue *tail; /* Consumer's removal point */
27 struct iov_iter iter; /* Iterator tracking what's left in the buffer */
28 u8 next_head_slot; /* Next slot in ->head */
29 u8 first_tail_slot; /* First slot in ->tail */
30 };
31
32 /*
33 * Snapshot of a rolling buffer.
34 */
35 struct rolling_buffer_snapshot {
36 struct folio_queue *curr_folioq; /* Queue segment in which current folio resides */
37 unsigned char curr_slot; /* Folio currently being read */
38 unsigned char curr_order; /* Order of folio */
39 };
40
41 /* Marks to store per-folio in the internal folio_queue structs. */
42 #define ROLLBUF_MARK_1 BIT(0)
43 #define ROLLBUF_MARK_2 BIT(1)
44
45 int rolling_buffer_init(struct rolling_buffer *roll, unsigned int rreq_id,
46 unsigned int direction);
47 int rolling_buffer_make_space(struct rolling_buffer *roll);
48 ssize_t rolling_buffer_load_from_ra(struct rolling_buffer *roll,
49 struct readahead_control *ractl,
50 struct folio_batch *put_batch);
51 ssize_t rolling_buffer_append(struct rolling_buffer *roll, struct folio *folio,
52 unsigned int flags);
53 struct folio_queue *rolling_buffer_delete_spent(struct rolling_buffer *roll);
54 void rolling_buffer_clear(struct rolling_buffer *roll);
55
rolling_buffer_advance(struct rolling_buffer * roll,size_t amount)56 static inline void rolling_buffer_advance(struct rolling_buffer *roll, size_t amount)
57 {
58 iov_iter_advance(&roll->iter, amount);
59 }
60
61 #endif /* _ROLLING_BUFFER_H */
62