void cephsan_pagefrag_deinit(struct cephsan_pagefrag *pf);
void cephsan_pagefrag_reset(struct cephsan_pagefrag *pf);
void *cephsan_pagefrag_get_ptr(struct cephsan_pagefrag *pf, u64 val);
+bool cephsan_pagefrag_is_wraparound(u64 val);
/* Get allocation size from pagefrag allocation result */
u64 cephsan_pagefrag_get_alloc_size(u64 val);
BUG_ON(entry->len == 0);
cephsan_pagefrag_free(&ctx->pf, entry->len);
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->line = line;
entry->file = file;
entry->func = func;
- entry->buffer = (char *)(entry + 1);
+ if (unlikely(cephsan_pagefrag_is_wraparound(alloc))) {
+ entry->buffer = cephsan_pagefrag_get_ptr(&ctx->pf, 0);
+ } else {
+ entry->buffer = (char *)(entry + 1);
+ }
entry->len = cephsan_pagefrag_get_alloc_size(alloc);
spin_unlock(&ctx->pf.lock);
pf->head += n;
return ((u64)n << 32) | prev_head;
} else {
- /* Need to wrap around return a partial allocation*/
- pf->head = 0;
- return ((u64)delta << 32) | prev_head;
+ if (pf->tail > n) {
+ /* Need to wrap around return a partial allocation*/
+ pf->head = n;
+ return ((u64)(delta + n) << 32) | prev_head;
+ } else {
+ return 0;
+ }
}
}
EXPORT_SYMBOL(cephsan_pagefrag_alloc);
}
EXPORT_SYMBOL(cephsan_pagefrag_get_alloc_size);
+/**
+ * cephsan_pagefrag_is_wraparound - Check if allocation wraps around buffer end
+ * @val: Return value from cephsan_pagefrag_alloc
+ *
+ * Checks if the allocation represented by @val wraps around the end of the
+ * pagefrag buffer by verifying if alloc_size + address > CEPHSAN_PAGEFRAG_SIZE.
+ *
+ * Return: true if allocation wraps around, false otherwise
+ */
+bool cephsan_pagefrag_is_wraparound(u64 val)
+{
+ u32 addr = val & 0xFFFFFFFF;
+ u32 size = val >> 32;
+ return (addr + size) > CEPHSAN_PAGEFRAG_SIZE;
+}
+EXPORT_SYMBOL(cephsan_pagefrag_is_wraparound);
+
/**
* cephsan_pagefrag_get_ptr_from_tail - Get buffer pointer from pagefrag tail
* @pf: pagefrag allocator