- patches.apparmor/remove_suid_new_case_in_2.6.22.diff: Merge fix.
[linux-flexiantxendom0-3.2.10.git] / arch / powerpc / lib / rheap.c
index 6c5c5dd..180ee29 100644 (file)
@@ -133,7 +133,7 @@ static rh_block_t *get_slot(rh_info_t * info)
        info->empty_slots--;
 
        /* Initialize */
-       blk->start = NULL;
+       blk->start = 0;
        blk->size = 0;
        blk->owner = NULL;
 
@@ -158,7 +158,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
 
        /* We assume that they are aligned properly */
        size = blkn->size;
-       s = (unsigned long)blkn->start;
+       s = blkn->start;
        e = s + size;
 
        /* Find the blocks immediately before and after the given one
@@ -170,7 +170,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
        list_for_each(l, &info->free_list) {
                blk = list_entry(l, rh_block_t, list);
 
-               bs = (unsigned long)blk->start;
+               bs = blk->start;
                be = bs + blk->size;
 
                if (next == NULL && s >= bs)
@@ -188,10 +188,10 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
        }
 
        /* Now check if they are really adjacent */
-       if (before != NULL && s != (unsigned long)before->start + before->size)
+       if (before && s != (before->start + before->size))
                before = NULL;
 
-       if (after != NULL && e != (unsigned long)after->start)
+       if (after && e != after->start)
                after = NULL;
 
        /* No coalescing; list insert and return */
@@ -216,7 +216,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
 
        /* Grow the after block backwards */
        if (before == NULL && after != NULL) {
-               after->start = (int8_t *)after->start - size;
+               after->start -= size;
                after->size += size;
                return;
        }
@@ -321,14 +321,14 @@ void rh_init(rh_info_t * info, unsigned int alignment, int max_blocks,
 }
 
 /* Attach a free memory region, coalesces regions if adjuscent */
-int rh_attach_region(rh_info_t * info, void *start, int size)
+int rh_attach_region(rh_info_t * info, unsigned long start, int size)
 {
        rh_block_t *blk;
        unsigned long s, e, m;
        int r;
 
        /* The region must be aligned */
-       s = (unsigned long)start;
+       s = start;
        e = s + size;
        m = info->alignment - 1;
 
@@ -338,9 +338,12 @@ int rh_attach_region(rh_info_t * info, void *start, int size)
        /* Round end down */
        e = e & ~m;
 
+       if (IS_ERR_VALUE(e) || (e < s))
+               return -ERANGE;
+
        /* Take final values */
-       start = (void *)s;
-       size = (int)(e - s);
+       start = s;
+       size = e - s;
 
        /* Grow the blocks, if needed */
        r = assure_empty(info, 1);
@@ -358,7 +361,7 @@ int rh_attach_region(rh_info_t * info, void *start, int size)
 }
 
 /* Detatch given address range, splits free block if needed. */
-void *rh_detach_region(rh_info_t * info, void *start, int size)
+unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size)
 {
        struct list_head *l;
        rh_block_t *blk, *newblk;
@@ -366,10 +369,10 @@ void *rh_detach_region(rh_info_t * info, void *start, int size)
 
        /* Validate size */
        if (size <= 0)
-               return ERR_PTR(-EINVAL);
+               return (unsigned long) -EINVAL;
 
        /* The region must be aligned */
-       s = (unsigned long)start;
+       s = start;
        e = s + size;
        m = info->alignment - 1;
 
@@ -380,34 +383,34 @@ void *rh_detach_region(rh_info_t * info, void *start, int size)
        e = e & ~m;
 
        if (assure_empty(info, 1) < 0)
-               return ERR_PTR(-ENOMEM);
+               return (unsigned long) -ENOMEM;
 
        blk = NULL;
        list_for_each(l, &info->free_list) {
                blk = list_entry(l, rh_block_t, list);
                /* The range must lie entirely inside one free block */
-               bs = (unsigned long)blk->start;
-               be = (unsigned long)blk->start + blk->size;
+               bs = blk->start;
+               be = blk->start + blk->size;
                if (s >= bs && e <= be)
                        break;
                blk = NULL;
        }
 
        if (blk == NULL)
-               return ERR_PTR(-ENOMEM);
+               return (unsigned long) -ENOMEM;
 
        /* Perfect fit */
        if (bs == s && be == e) {
                /* Delete from free list, release slot */
                list_del(&blk->list);
                release_slot(info, blk);
-               return (void *)s;
+               return s;
        }
 
        /* blk still in free list, with updated start and/or size */
        if (bs == s || be == e) {
                if (bs == s)
-                       blk->start = (int8_t *)blk->start + size;
+                       blk->start += size;
                blk->size -= size;
 
        } else {
@@ -416,25 +419,29 @@ void *rh_detach_region(rh_info_t * info, void *start, int size)
 
                /* the back free fragment */
                newblk = get_slot(info);
-               newblk->start = (void *)e;
+               newblk->start = e;
                newblk->size = be - e;
 
                list_add(&newblk->list, &blk->list);
        }
 
-       return (void *)s;
+       return s;
 }
 
-void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owner)
+/* Allocate a block of memory at the specified alignment.  The value returned
+ * is an offset into the buffer initialized by rh_init(), or a negative number
+ * if there is an error.
+ */
+unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owner)
 {
        struct list_head *l;
        rh_block_t *blk;
        rh_block_t *newblk;
-       void *start;
+       unsigned long start;
 
-       /* Validate size, (must be power of two) */
+       /* Validate size, and alignment must be power of two */
        if (size <= 0 || (alignment & (alignment - 1)) != 0)
-               return ERR_PTR(-EINVAL);
+               return (unsigned long) -EINVAL;
 
        /* given alignment larger that default rheap alignment */
        if (alignment > info->alignment)
@@ -444,7 +451,7 @@ void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owne
        size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
 
        if (assure_empty(info, 1) < 0)
-               return ERR_PTR(-ENOMEM);
+               return (unsigned long) -ENOMEM;
 
        blk = NULL;
        list_for_each(l, &info->free_list) {
@@ -455,50 +462,50 @@ void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owne
        }
 
        if (blk == NULL)
-               return ERR_PTR(-ENOMEM);
+               return (unsigned long) -ENOMEM;
 
        /* Just fits */
        if (blk->size == size) {
                /* Move from free list to taken list */
                list_del(&blk->list);
-               blk->owner = owner;
-               start = blk->start;
-
-               attach_taken_block(info, blk);
+               newblk = blk;
+       } else {
+               newblk = get_slot(info);
+               newblk->start = blk->start;
+               newblk->size = size;
 
-               return start;
+               /* blk still in free list, with updated start, size */
+               blk->start += size;
+               blk->size -= size;
        }
 
-       newblk = get_slot(info);
-       newblk->start = blk->start;
-       newblk->size = size;
        newblk->owner = owner;
-
-       /* blk still in free list, with updated start, size */
-       blk->start = (int8_t *)blk->start + size;
-       blk->size -= size;
-
        start = newblk->start;
-
        attach_taken_block(info, newblk);
 
        /* for larger alignment return fixed up pointer  */
        /* this is no problem with the deallocator since */
        /* we scan for pointers that lie in the blocks   */
        if (alignment > info->alignment)
-               start = (void *)(((unsigned long)start + alignment - 1) &
-                               ~(alignment - 1));
+               start = (start + alignment - 1) & ~(alignment - 1);
 
        return start;
 }
 
-void *rh_alloc(rh_info_t * info, int size, const char *owner)
+/* Allocate a block of memory at the default alignment.  The value returned is
+ * an offset into the buffer initialized by rh_init(), or a negative number if
+ * there is an error.
+ */
+unsigned long rh_alloc(rh_info_t * info, int size, const char *owner)
 {
        return rh_alloc_align(info, size, info->alignment, owner);
 }
 
-/* allocate at precisely the given address */
-void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
+/* Allocate a block of memory at the given offset, rounded up to the default
+ * alignment.  The value returned is an offset into the buffer initialized by
+ * rh_init(), or a negative number if there is an error.
+ */
+unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, const char *owner)
 {
        struct list_head *l;
        rh_block_t *blk, *newblk1, *newblk2;
@@ -506,10 +513,10 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
 
        /* Validate size */
        if (size <= 0)
-               return ERR_PTR(-EINVAL);
+               return (unsigned long) -EINVAL;
 
        /* The region must be aligned */
-       s = (unsigned long)start;
+       s = start;
        e = s + size;
        m = info->alignment - 1;
 
@@ -520,20 +527,20 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
        e = e & ~m;
 
        if (assure_empty(info, 2) < 0)
-               return ERR_PTR(-ENOMEM);
+               return (unsigned long) -ENOMEM;
 
        blk = NULL;
        list_for_each(l, &info->free_list) {
                blk = list_entry(l, rh_block_t, list);
                /* The range must lie entirely inside one free block */
-               bs = (unsigned long)blk->start;
-               be = (unsigned long)blk->start + blk->size;
+               bs = blk->start;
+               be = blk->start + blk->size;
                if (s >= bs && e <= be)
                        break;
        }
 
        if (blk == NULL)
-               return ERR_PTR(-ENOMEM);
+               return (unsigned long) -ENOMEM;
 
        /* Perfect fit */
        if (bs == s && be == e) {
@@ -551,7 +558,7 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
        /* blk still in free list, with updated start and/or size */
        if (bs == s || be == e) {
                if (bs == s)
-                       blk->start = (int8_t *)blk->start + size;
+                       blk->start += size;
                blk->size -= size;
 
        } else {
@@ -560,14 +567,14 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
 
                /* The back free fragment */
                newblk2 = get_slot(info);
-               newblk2->start = (void *)e;
+               newblk2->start = e;
                newblk2->size = be - e;
 
                list_add(&newblk2->list, &blk->list);
        }
 
        newblk1 = get_slot(info);
-       newblk1->start = (void *)s;
+       newblk1->start = s;
        newblk1->size = e - s;
        newblk1->owner = owner;
 
@@ -577,7 +584,11 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
        return start;
 }
 
-int rh_free(rh_info_t * info, void *start)
+/* Deallocate the memory previously allocated by one of the rh_alloc functions.
+ * The return value is the size of the deallocated block, or a negative number
+ * if there is an error.
+ */
+int rh_free(rh_info_t * info, unsigned long start)
 {
        rh_block_t *blk, *blk2;
        struct list_head *l;
@@ -642,7 +653,7 @@ int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats)
        return nr;
 }
 
-int rh_set_owner(rh_info_t * info, void *start, const char *owner)
+int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner)
 {
        rh_block_t *blk, *blk2;
        struct list_head *l;
@@ -684,8 +695,8 @@ void rh_dump(rh_info_t * info)
                nr = maxnr;
        for (i = 0; i < nr; i++)
                printk(KERN_INFO
-                      "    0x%p-0x%p (%u)\n",
-                      st[i].start, (int8_t *) st[i].start + st[i].size,
+                      "    0x%lx-0x%lx (%u)\n",
+                      st[i].start, st[i].start + st[i].size,
                       st[i].size);
        printk(KERN_INFO "\n");
 
@@ -695,8 +706,8 @@ void rh_dump(rh_info_t * info)
                nr = maxnr;
        for (i = 0; i < nr; i++)
                printk(KERN_INFO
-                      "    0x%p-0x%p (%u) %s\n",
-                      st[i].start, (int8_t *) st[i].start + st[i].size,
+                      "    0x%lx-0x%lx (%u) %s\n",
+                      st[i].start, st[i].start + st[i].size,
                       st[i].size, st[i].owner != NULL ? st[i].owner : "");
        printk(KERN_INFO "\n");
 }
@@ -704,6 +715,6 @@ void rh_dump(rh_info_t * info)
 void rh_dump_blk(rh_info_t * info, rh_block_t * blk)
 {
        printk(KERN_INFO
-              "blk @0x%p: 0x%p-0x%p (%u)\n",
-              blk, blk->start, (int8_t *) blk->start + blk->size, blk->size);
+              "blk @0x%p: 0x%lx-0x%lx (%u)\n",
+              blk, blk->start, blk->start + blk->size, blk->size);
 }