/* Determine how many times the data array has wrapped. */
#define DATA_WRAPS(data_ring, lpos) ((lpos) >> (data_ring)->size_bits)
+/* Determine if a logical position refers to a data-less block. */
+#define LPOS_DATALESS(lpos) ((lpos) & 1UL)
+
/* Get the logical position at index 0 of the current wrap. */
#define DATA_THIS_WRAP_START_LPOS(data_ring, lpos) \
((lpos) & ~DATA_SIZE_MASK(data_ring))
* block does not exceed the maximum possible size that could fit within the
* ringbuffer. This function provides that basic size check so that the
* assumption is safe.
- *
- * Writers are also not allowed to write 0-sized (data-less) records. Such
- * records are used only internally by the ringbuffer.
*/
static bool data_check_size(struct prb_data_ring *data_ring, unsigned int size)
{
struct prb_data_block *db = NULL;
- /*
- * Writers are not allowed to write data-less records. Such records
- * are used only internally by the ringbuffer to denote records where
- * their data failed to allocate or have been lost.
- */
if (size == 0)
- return false;
+ return true;
/*
* Ensure the alignment padded size could possibly fit in the data
unsigned long tail_lpos;
unsigned long next_lpos;
- /* If @lpos is not valid, there is nothing to do. */
- if (lpos == INVALID_LPOS)
+ /* If @lpos is from a data-less block, there is nothing to do. */
+ if (LPOS_DATALESS(lpos))
return true;
/*
if (size == 0) {
/* Specify a data-less block. */
- blk_lpos->begin = INVALID_LPOS;
- blk_lpos->next = INVALID_LPOS;
+ blk_lpos->begin = NO_LPOS;
+ blk_lpos->next = NO_LPOS;
return NULL;
}
if (!data_push_tail(rb, data_ring, next_lpos - DATA_SIZE(data_ring))) {
/* Failed to allocate, specify a data-less block. */
- blk_lpos->begin = INVALID_LPOS;
- blk_lpos->next = INVALID_LPOS;
+ blk_lpos->begin = FAILED_LPOS;
+ blk_lpos->next = FAILED_LPOS;
return NULL;
}
static unsigned int space_used(struct prb_data_ring *data_ring,
struct prb_data_blk_lpos *blk_lpos)
{
+ /* Data-less blocks take no space. */
+ if (LPOS_DATALESS(blk_lpos->begin))
+ return 0;
+
if (DATA_WRAPS(data_ring, blk_lpos->begin) == DATA_WRAPS(data_ring, blk_lpos->next)) {
/* Data block does not wrap. */
return (DATA_INDEX(data_ring, blk_lpos->next) -
if (!data_check_size(&rb->text_data_ring, r->text_buf_size))
goto fail;
- /* Records are allowed to not have dictionaries. */
- if (r->dict_buf_size) {
- if (!data_check_size(&rb->dict_data_ring, r->dict_buf_size))
- goto fail;
- }
+ if (!data_check_size(&rb->dict_data_ring, r->dict_buf_size))
+ goto fail;
/*
* Descriptors in the reserved state act as blockers to all further
* values to possibly detect bugs in the writer code. A WARN_ON_ONCE() is
* triggered if an internal error is detected.
*/
-static char *get_data(struct prb_data_ring *data_ring,
- struct prb_data_blk_lpos *blk_lpos,
- unsigned int *data_size)
+static const char *get_data(struct prb_data_ring *data_ring,
+ struct prb_data_blk_lpos *blk_lpos,
+ unsigned int *data_size)
{
struct prb_data_block *db;
/* Data-less data block description. */
- if (blk_lpos->begin == INVALID_LPOS &&
- blk_lpos->next == INVALID_LPOS) {
+ if (LPOS_DATALESS(blk_lpos->begin) && LPOS_DATALESS(blk_lpos->next)) {
+ if (blk_lpos->begin == NO_LPOS && blk_lpos->next == NO_LPOS) {
+ *data_size = 0;
+ return "";
+ }
return NULL;
}
* (even if @text_size is 0). Each '\n' processed is counted as an additional
* line.
*/
-static unsigned int count_lines(char *text, unsigned int text_size)
+static unsigned int count_lines(const char *text, unsigned int text_size)
{
unsigned int next_size = text_size;
unsigned int line_count = 1;
- char *next = text;
+ const char *next = text;
while (next_size) {
next = memchr(next, '\n', next_size);
unsigned int buf_size, unsigned int *line_count)
{
unsigned int data_size;
- char *data;
+ const char *data;
/* Caller might not want any data. */
if ((!buf || !buf_size) && !line_count)
data_size = min_t(u16, buf_size, len);
- if (!WARN_ON_ONCE(!data_size))
- memcpy(&buf[0], data, data_size); /* LMM(copy_data:A) */
+ memcpy(&buf[0], data, data_size); /* LMM(copy_data:A) */
return true;
}
/*
* A descriptor in the reusable state may no longer have its data
- * available; report it as a data-less record. Or the record may
- * actually be a data-less record.
+ * available; report it as existing but with lost data. Or the record
+ * may actually be a record with lost data.
*/
if (d_state == desc_reusable ||
- (blk_lpos->begin == INVALID_LPOS && blk_lpos->next == INVALID_LPOS)) {
+ (blk_lpos->begin == FAILED_LPOS && blk_lpos->next == FAILED_LPOS)) {
return -ENOENT;
}
descs[_DESCS_COUNT(descbits) - 1].info.seq = 0;
atomic_long_set(&(descs[_DESCS_COUNT(descbits) - 1].state_var), DESC0_SV(descbits));
- descs[_DESCS_COUNT(descbits) - 1].text_blk_lpos.begin = INVALID_LPOS;
- descs[_DESCS_COUNT(descbits) - 1].text_blk_lpos.next = INVALID_LPOS;
- descs[_DESCS_COUNT(descbits) - 1].dict_blk_lpos.begin = INVALID_LPOS;
- descs[_DESCS_COUNT(descbits) - 1].dict_blk_lpos.next = INVALID_LPOS;
+ descs[_DESCS_COUNT(descbits) - 1].text_blk_lpos.begin = FAILED_LPOS;
+ descs[_DESCS_COUNT(descbits) - 1].text_blk_lpos.next = FAILED_LPOS;
+ descs[_DESCS_COUNT(descbits) - 1].dict_blk_lpos.begin = FAILED_LPOS;
+ descs[_DESCS_COUNT(descbits) - 1].dict_blk_lpos.next = FAILED_LPOS;
}
/**
#define DESC_FLAGS_MASK (DESC_COMMITTED_MASK | DESC_REUSE_MASK)
#define DESC_ID_MASK (~DESC_FLAGS_MASK)
#define DESC_ID(sv) ((sv) & DESC_ID_MASK)
-#define INVALID_LPOS 1
+#define FAILED_LPOS 0x1
+#define NO_LPOS 0x3
-#define INVALID_BLK_LPOS \
+#define FAILED_BLK_LPOS \
{ \
- .begin = INVALID_LPOS, \
- .next = INVALID_LPOS, \
+ .begin = FAILED_LPOS, \
+ .next = FAILED_LPOS, \
}
/*
*
* To satisfy Req1, the tail initially points to a descriptor that is
* minimally initialized (having no data block, i.e. data-less with the
- * data block's lpos @begin and @next values set to INVALID_LPOS).
+ * data block's lpos @begin and @next values set to FAILED_LPOS).
*
* To satisfy Req2, the initial tail descriptor is initialized to the
* reusable state. Readers recognize reusable descriptors as existing
/* reusable */ \
.state_var = ATOMIC_INIT(DESC0_SV(descbits)), \
/* no associated data block */ \
- .text_blk_lpos = INVALID_BLK_LPOS, \
- .dict_blk_lpos = INVALID_BLK_LPOS, \
+ .text_blk_lpos = FAILED_BLK_LPOS, \
+ .dict_blk_lpos = FAILED_BLK_LPOS, \
}, \
}; \
static struct printk_ringbuffer name = { \