void cephsan_pagefrag_reset(struct cephsan_pagefrag *pf);
void *cephsan_pagefrag_get_ptr(struct cephsan_pagefrag *pf, u64 val);
+/* Get allocation size from pagefrag allocation result */
+u64 cephsan_pagefrag_get_alloc_size(u64 val);
+
#define CEPHSAN_PAGEFRAG_GET_N(val) ((val) >> 32)
#endif /* CEPH_SAN_PAGEFRAG_H */
struct ceph_san_log_entry *entry;
va_list args;
u64 alloc;
- int len;
+ int len, needed_size;
ctx = ceph_san_get_tls_ctx();
if (!ctx)
len = vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
+ needed_size = sizeof(*entry) + len + 1;
/* Allocate entry from pagefrag */ //We need a spinlock here to protect printing
- alloc = cephsan_pagefrag_alloc(&ctx->pf, sizeof(*entry) + len + 1);
+ alloc = cephsan_pagefrag_alloc(&ctx->pf, needed_size);
while (!alloc) {
entry = cephsan_pagefrag_get_ptr_from_tail(&ctx->pf);
BUG_ON(entry->debug_poison != CEPH_SAN_LOG_ENTRY_POISON);
BUG_ON(entry->len == 0);
cephsan_pagefrag_free(&ctx->pf, entry->len);
- alloc = cephsan_pagefrag_alloc(&ctx->pf, sizeof(*entry) + len + 1);
+ alloc = cephsan_pagefrag_alloc(&ctx->pf, needed_size);
+ //In case we hit the wrap around, we may get a partial allocation that should be marked as used
+ if (alloc && cephsan_pagefrag_get_alloc_size(alloc) < needed_size) {
+ entry = cephsan_pagefrag_get_ptr(&ctx->pf, alloc);
+ memset(entry->buffer, 0, sizeof(entry->buffer));
+ entry->len = cephsan_pagefrag_get_alloc_size(alloc);
+ alloc = 0;
+ }
}
entry = cephsan_pagefrag_get_ptr(&ctx->pf, alloc);
entry->ts = jiffies;
entry->line = line;
entry->file = file;
- entry->len = len + sizeof(*entry) + 1;
+ entry->len = cephsan_pagefrag_get_alloc_size(alloc);
}
EXPORT_SYMBOL(ceph_san_log);
*/
u64 cephsan_pagefrag_alloc(struct cephsan_pagefrag *pf, unsigned int n)
{
+ int delta = CEPHSAN_PAGEFRAG_SIZE - pf->head -n;
+ unsigned int prev_head = pf->head;
+
/* Case 1: tail > head */
if (pf->tail > pf->head) {
if (pf->tail - pf->head > n) {
- unsigned int prev_head = pf->head;
pf->head += n;
return ((u64)n << 32) | prev_head;
} else {
}
}
/* Case 2: tail <= head */
- if (pf->head + n <= CEPHSAN_PAGEFRAG_SIZE) {
+ if (delta >= 0) {
/* Normal allocation */
- unsigned int prev_head = pf->head;
+ /* make sure we have enough space to allocate next entry */
+ if (unlikely(delta < 64)) {
+ n += delta;
+ pf->head = 0;
+ return ((u64)n << 32) | prev_head;
+ }
pf->head += n;
return ((u64)n << 32) | prev_head;
} else {
- /* Need to wrap around */
- if (n < pf->tail) {
- pf->head = n;
- n += CEPHSAN_PAGEFRAG_SIZE - pf->head;
- return ((u64)n << 32) | 0;
- } else {
- return 0;
- }
+ /* Need to wrap around return a partial allocation*/
+ pf->head = 0;
+ return ((u64)delta << 32) | prev_head;
}
- pr_err("impossible: Not enough space in pagefrag buffer\n");
- return 0;
}
EXPORT_SYMBOL(cephsan_pagefrag_alloc);
}
EXPORT_SYMBOL(cephsan_pagefrag_get_ptr);
+u64 cephsan_pagefrag_get_alloc_size(u64 val)
+{
+ return val >> 32;
+}
+EXPORT_SYMBOL(cephsan_pagefrag_get_alloc_size);
+
/**
* cephsan_pagefrag_get_ptr_from_tail - Get buffer pointer from pagefrag tail
* @pf: pagefrag allocator