/* SPDX-License-Identifier: GPL-2.0-or-later */ /* Queue of folios definitions * * Copyright (C) 2024 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * See: * * Documentation/core-api/folio_queue.rst * * for a description of the API.
*/
/* * Segment in a queue of running buffers. Each segment can hold a number of * folios and a portion of the queue can be referenced with the ITER_FOLIOQ * iterator. The possibility exists of inserting non-folio elements into the * queue (such as gaps). * * Explicit prev and next pointers are used instead of a list_head to make it * easier to add segments to tail and remove them from the head without the * need for a lock.
*/ struct folio_queue { struct folio_batch vec; /* Folios in the queue segment */
u8 orders[PAGEVEC_SIZE]; /* Order of each folio */ struct folio_queue *next; /* Next queue segment or NULL */ struct folio_queue *prev; /* Previous queue segment of NULL */ unsignedlong marks; /* 1-bit mark per folio */ unsignedlong marks2; /* Second 1-bit mark per folio */ #if PAGEVEC_SIZE > BITS_PER_LONG #error marks is not big enough #endif unsignedint rreq_id; unsignedint debug_id;
};
/** * folioq_init - Initialise a folio queue segment * @folioq: The segment to initialise * @rreq_id: The request identifier to use in tracelines. * * Initialise a folio queue segment and set an identifier to be used in traces. * * Note that the folio pointers are left uninitialised.
*/ staticinlinevoid folioq_init(struct folio_queue *folioq, unsignedint rreq_id)
{
folio_batch_init(&folioq->vec);
folioq->next = NULL;
folioq->prev = NULL;
folioq->marks = 0;
folioq->marks2 = 0;
folioq->rreq_id = rreq_id;
folioq->debug_id = 0;
}
/** * folioq_nr_slots: Query the capacity of a folio queue segment * @folioq: The segment to query * * Query the number of folios that a particular folio queue segment might hold. * [!] NOTE: This must not be assumed to be the same for every segment!
*/ staticinlineunsignedint folioq_nr_slots(conststruct folio_queue *folioq)
{ return PAGEVEC_SIZE;
}
/** * folioq_count: Query the occupancy of a folio queue segment * @folioq: The segment to query * * Query the number of folios that have been added to a folio queue segment. * Note that this is not decreased as folios are removed from a segment.
*/ staticinlineunsignedint folioq_count(struct folio_queue *folioq)
{ return folio_batch_count(&folioq->vec);
}
/** * folioq_full: Query if a folio queue segment is full * @folioq: The segment to query * * Query if a folio queue segment is fully occupied. Note that this does not * change if folios are removed from a segment.
*/ staticinlinebool folioq_full(struct folio_queue *folioq)
{ //return !folio_batch_space(&folioq->vec); return folioq_count(folioq) >= folioq_nr_slots(folioq);
}
/** * folioq_is_marked: Check first folio mark in a folio queue segment * @folioq: The segment to query * @slot: The slot number of the folio to query * * Determine if the first mark is set for the folio in the specified slot in a * folio queue segment.
*/ staticinlinebool folioq_is_marked(conststruct folio_queue *folioq, unsignedint slot)
{ return test_bit(slot, &folioq->marks);
}
/** * folioq_mark: Set the first mark on a folio in a folio queue segment * @folioq: The segment to modify * @slot: The slot number of the folio to modify * * Set the first mark for the folio in the specified slot in a folio queue * segment.
*/ staticinlinevoid folioq_mark(struct folio_queue *folioq, unsignedint slot)
{
set_bit(slot, &folioq->marks);
}
/** * folioq_unmark: Clear the first mark on a folio in a folio queue segment * @folioq: The segment to modify * @slot: The slot number of the folio to modify * * Clear the first mark for the folio in the specified slot in a folio queue * segment.
*/ staticinlinevoid folioq_unmark(struct folio_queue *folioq, unsignedint slot)
{
clear_bit(slot, &folioq->marks);
}
/** * folioq_is_marked2: Check second folio mark in a folio queue segment * @folioq: The segment to query * @slot: The slot number of the folio to query * * Determine if the second mark is set for the folio in the specified slot in a * folio queue segment.
*/ staticinlinebool folioq_is_marked2(conststruct folio_queue *folioq, unsignedint slot)
{ return test_bit(slot, &folioq->marks2);
}
/** * folioq_mark2: Set the second mark on a folio in a folio queue segment * @folioq: The segment to modify * @slot: The slot number of the folio to modify * * Set the second mark for the folio in the specified slot in a folio queue * segment.
*/ staticinlinevoid folioq_mark2(struct folio_queue *folioq, unsignedint slot)
{
set_bit(slot, &folioq->marks2);
}
/** * folioq_unmark2: Clear the second mark on a folio in a folio queue segment * @folioq: The segment to modify * @slot: The slot number of the folio to modify * * Clear the second mark for the folio in the specified slot in a folio queue * segment.
*/ staticinlinevoid folioq_unmark2(struct folio_queue *folioq, unsignedint slot)
{
clear_bit(slot, &folioq->marks2);
}
/** * folioq_append: Add a folio to a folio queue segment * @folioq: The segment to add to * @folio: The folio to add * * Add a folio to the tail of the sequence in a folio queue segment, increasing * the occupancy count and returning the slot number for the folio just added. * The folio size is extracted and stored in the queue and the marks are left * unmodified. * * Note that it's left up to the caller to check that the segment capacity will * not be exceeded and to extend the queue.
*/ staticinlineunsignedint folioq_append(struct folio_queue *folioq, struct folio *folio)
{ unsignedint slot = folioq->vec.nr++;
/** * folioq_append_mark: Add a folio to a folio queue segment * @folioq: The segment to add to * @folio: The folio to add * * Add a folio to the tail of the sequence in a folio queue segment, increasing * the occupancy count and returning the slot number for the folio just added. * The folio size is extracted and stored in the queue, the first mark is set * and and the second and third marks are left unmodified. * * Note that it's left up to the caller to check that the segment capacity will * not be exceeded and to extend the queue.
*/ staticinlineunsignedint folioq_append_mark(struct folio_queue *folioq, struct folio *folio)
{ unsignedint slot = folioq->vec.nr++;
/** * folioq_folio: Get a folio from a folio queue segment * @folioq: The segment to access * @slot: The folio slot to access * * Retrieve the folio in the specified slot from a folio queue segment. Note * that no bounds check is made and if the slot hasn't been added into yet, the * pointer will be undefined. If the slot has been cleared, NULL will be * returned.
*/ staticinlinestruct folio *folioq_folio(conststruct folio_queue *folioq, unsignedint slot)
{ return folioq->vec.folios[slot];
}
/** * folioq_folio_order: Get the order of a folio from a folio queue segment * @folioq: The segment to access * @slot: The folio slot to access * * Retrieve the order of the folio in the specified slot from a folio queue * segment. Note that no bounds check is made and if the slot hasn't been * added into yet, the order returned will be 0.
*/ staticinlineunsignedint folioq_folio_order(conststruct folio_queue *folioq, unsignedint slot)
{ return folioq->orders[slot];
}
/** * folioq_folio_size: Get the size of a folio from a folio queue segment * @folioq: The segment to access * @slot: The folio slot to access * * Retrieve the size of the folio in the specified slot from a folio queue * segment. Note that no bounds check is made and if the slot hasn't been * added into yet, the size returned will be PAGE_SIZE.
*/ staticinline size_t folioq_folio_size(conststruct folio_queue *folioq, unsignedint slot)
{ return PAGE_SIZE << folioq_folio_order(folioq, slot);
}
/** * folioq_clear: Clear a folio from a folio queue segment * @folioq: The segment to clear * @slot: The folio slot to clear * * Clear a folio from a sequence in a folio queue segment and clear its marks. * The occupancy count is left unchanged.
*/ staticinlinevoid folioq_clear(struct folio_queue *folioq, unsignedint slot)
{
folioq->vec.folios[slot] = NULL;
folioq_unmark(folioq, slot);
folioq_unmark2(folioq, slot);
}
#endif/* _LINUX_FOLIO_QUEUE_H */
¤ Dauer der Verarbeitung: 0.29 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.