Make smalloc redzone pointer properly aligned

It would SIGBUS on archs that require proper alignment, and work
suboptimally on others. Real fix is pending, making sure that
we always return naturally aligned pointers. But this at least
makes it work on sparc64.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
diff --git a/smalloc.c b/smalloc.c
index e82ef1d..e0bc498 100644
--- a/smalloc.c
+++ b/smalloc.c
@@ -268,9 +268,20 @@
 }
 
 #ifdef SMALLOC_REDZONE
+static void *postred_ptr(struct block_hdr *hdr)
+{
+	const int int_mask = sizeof(unsigned int) - 1;
+	unsigned long ptr;
+
+	ptr = (unsigned long) hdr + hdr->size - sizeof(unsigned int);
+	ptr = (ptr + int_mask) & ~int_mask;
+
+	return (void *) ptr;
+}
+
 static void fill_redzone(struct block_hdr *hdr)
 {
-	unsigned int *postred = (void *) hdr + hdr->size - sizeof(unsigned int);
+	unsigned int *postred = postred_ptr(hdr);
 
 	hdr->prered = SMALLOC_PRE_RED;
 	*postred = SMALLOC_POST_RED;
@@ -278,7 +289,7 @@
 
 static void sfree_check_redzone(struct block_hdr *hdr)
 {
-	unsigned int *postred = (void *) hdr + hdr->size - sizeof(unsigned int);
+	unsigned int *postred = postred_ptr(hdr);
 
 	if (hdr->prered != SMALLOC_PRE_RED) {
 		fprintf(stderr, "smalloc pre redzone destroyed!\n");
@@ -414,8 +425,12 @@
 	unsigned int alloc_size = size + sizeof(struct block_hdr);
 	void *ptr;
 
+	/*
+	 * Use twice the size for good luck, we may need to adjust
+	 * alignment.
+	 */
 #ifdef SMALLOC_REDZONE
-	alloc_size += sizeof(unsigned int);
+	alloc_size += 2 * sizeof(unsigned int);
 #endif
 
 	ptr = __smalloc_pool(pool, alloc_size);