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 ([email protected]) 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 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