Staging: memrar: Moved memrar_allocator struct to memrar_allocator.c
PATCH 1/2 Staging: memrar: Moved memrar_allocator struct to memrar_allocator.c
Forward declared memrar_allocator structure in memrar_allocator.h and moved the definition to memrar_allocator.c. Implemented memrar_allocator_capacity() and memrar_allocator_largest_free_area().
--- drivers/staging/memrar/memrar_allocator.c | 43 ++++++++++++++++++++++++++ drivers/staging/memrar/memrar_allocator.h | 48 ++++++++++++----------------- 2 files changed, 63 insertions(+), 28 deletions(-)
drivers/staging/memrar/memrar_allocator.c +43 -0
@@ -41,6 +41,36 @@#include <linux/kernel.h> +/** +* struct memrar_allocator - encapsulation of the memory allocator state +* @lock: Lock used to synchronize access to the memory +* allocator state. +* @base: Base (start) address of the allocator memory +* space. +* @capacity: Size of the allocator memory space in bytes. +* @block_size: The size in bytes of individual blocks within +* the allocator memory space. +* @largest_free_area: Largest free area of memory in the allocator +* in bytes. +* @allocated_list: List of allocated memory block address +* ranges. +* @free_list: List of free address ranges. +* +* This structure contains all memory allocator state, including the +* base address, capacity, free list, lock, etc. +*/ +struct memrar_allocator { +/* private: internal use only */ +struct mutex lock; +unsigned long base; +size_t capacity; +size_t block_size; +size_t largest_free_area; +struct memrar_address_ranges allocated_list; +struct memrar_address_ranges free_list; +}; + +struct memrar_allocator *memrar_create_allocator (unsigned long base,size_t capacity,size_t block_size)
@@ -423,6 +453,19 @@ exit_memrar_free:return 0 ; } +size_t memrar_allocator_largest_free_area (struct memrar_allocator *allocator) +{ +if (allocator ==NULL ) +return 0 ; +return allocator->largest_free_area; +} + +size_t memrar_allocator_capacity (struct memrar_allocator *allocator) +{ +if (allocator ==NULL ) +return 0 ; +return allocator->capacity; +}/*
drivers/staging/memrar/memrar_allocator.h +20 -28
60 lines not on this page · raw message
Signature · 1 line
1.7.1
PATCH 2/2 Staging: memrar: Fixed memrar_handler.c
Fixed memrar_handler.c to use the new memrar_allocator API. Removed the corresponding issue from TODO. Implemented locking in memrar_allocator_largest_free_area().
--- drivers/staging/memrar/TODO | 16 +--------------- drivers/staging/memrar/memrar_allocator.c | 12 +++++++++--- drivers/staging/memrar/memrar_handler.c | 13 ++++--------- 3 files changed, 14 insertions(+), 27 deletions(-)
drivers/staging/memrar/TODO +1 -15
@@ -16,21 +16,7 @@ memrar_allocator.[ch] --------------------- 1. Address potential fragmentation issues with the memrar_allocator. -2. Hide struct memrar_allocator details/fields. They need not be - exposed to the user. - a. Forward declare struct memrar_allocator. - b. Move all three struct definitions to `memrar_allocator.c' - source file. - c. Add a memrar_allocator_largest_free_area() function, or - something like that to get access to the value of the struct - memrar_allocator "largest_free_area" field. This allows the - struct memrar_allocator fields to be completely hidden from - the user. The memrar_handler code really only needs this for - statistic gathering on-demand. - d. Do the same for the "capacity" field as the - "largest_free_area" field. - -3. Move memrar_allocator.* to kernel `lib' directory since it is HW +2. Move memrar_allocator.* to kernel `lib' directory since it is HW neutral. a. Alternatively, use lib/genalloc.c instead. b. A kernel port of Doug Lea's malloc() implementation may also
drivers/staging/memrar/memrar_allocator.c +9 -3
@@ -455,9 +455,15 @@ exit_memrar_free:size_t memrar_allocator_largest_free_area (struct memrar_allocator *allocator) { -if (allocator ==NULL ) -return 0 ; -return allocator->largest_free_area; +size_t tmp =0 ; + +if (allocator !=NULL ) { +mutex_lock (&allocator->lock); + tmp = allocator->largest_free_area; +mutex_unlock (&allocator->lock); + } + +return tmp; }size_t memrar_allocator_capacity (struct memrar_allocator *allocator)
drivers/staging/memrar/memrar_handler.c +4 -9
@@ -351,7 +351,8 @@ static int memrar_init_rar_resources(int rarnum, char const *devname) devname, rarnum, (unsigned long) low, (unsigned long) high);pr_info ("%s: BRAR[%d] size = %zu KiB\n" , - devname, rarnum, rar->allocator->capacity /1024 ); + devname, rarnum, +memrar_allocator_capacity (rar->allocator) /1024 ); rar->allocated =1 ;return 0 ;
@@ -542,15 +543,9 @@ static long memrar_get_stat(struct RAR_stat *r)BUG_ON (allocator ==NULL ); -/* -* Allocator capacity doesn't change over time. No -* need to synchronize. -*/ - r->capacity = allocator->capacity; + r->capacity =memrar_allocator_capacity (allocator); + r->largest_block_size =memrar_allocator_largest_free_area (allocator); -mutex_lock (&allocator->lock); - r->largest_block_size = allocator->largest_free_area; -mutex_unlock (&allocator->lock);return 0 ; }
Signature · 1 line
1.7.1
Re: [PATCH 2/2] Staging: memrar: Fixed memrar_handler.c
drivers/staging/memrar/memrar_allocator.c exit_memrar_free: · line 463
Quoted 11 lines
size_tmemrar_allocator_largest_free_area(struct memrar_allocator *allocator){drivers/staging/memrar/memrar_allocator.c +6
-3-if (allocator ==NULL ) -return 0 ; -return allocator->largest_free_area; +size_t tmp =0 ; + +if (allocator !=NULL ) { +mutex_lock (&allocator->lock); + tmp = allocator->largest_free_area; +mutex_unlock (&allocator->lock);
This doesn't seem to make any sense (in either version). The moment you drop the lock the value in "tmp" becomes stale as the allocator could change it. ?
RE: [PATCH 2/2] Staging: memrar: Fixed memrar_handler.c
Hi Alan,
Quoted 16 lines
Quoted 1 line
size_tmemrar_allocator_largest_free_area(structmemrar_allocator*allocator)
drivers/staging/memrar/memrar_allocator.c exit_memrar_free: · line 463
Quoted 10 lines
{
drivers/staging/memrar/memrar_allocator.c +6
-3-if (allocator ==NULL ) -return 0 ; -return allocator->largest_free_area; +size_t tmp =0 ; + +if (allocator !=NULL ) { +mutex_lock (&allocator->lock); + tmp = allocator->largest_free_area; +mutex_unlock (&allocator->lock);This doesn't seem to make any sense (in either version). The moment you drop the lock the value in "tmp" becomes stale as the allocator could change it. ?
Agreed, but I don't think there's anything we can do about it with the current interface. We will always have a time-of-check-time-of-use TOCTOU race with this function as it stands. I pointed out the issue in my response to Henri as well, but I focused more on hiding the lock from the caller. The TOCTOU race exists in both versions, i.e. the old code and proposed new code. The value returned from this function in this particular case will ultimately be passed to the user when the user issues a RAR_HANDLER_STAT ioctl to the /dev/memrar device. For the most part, this function is only used for debugging. It is not needed for general operation of the memrar_allocator or the memrar_handler (/dev/memrar).
-Ossama
drivers/staging/memrar/memrar_allocator.c exit_memrar_free: · line 461
Quoted 6 lines
drivers/staging/memrar/memrar_allocator.c +6
-0+size_t memrar_allocator_largest_free_area (struct memrar_allocator *allocator) +{ +if (allocator ==NULL ) +return 0 ; +return allocator->largest_free_area; +}
static ?
Quoted 8 lines · Alan Cox
drivers/staging/memrar/memrar_allocator.c exit_memrar_free: · line 461
Quoted 6 lines
drivers/staging/memrar/memrar_allocator.c +6
-0+size_t memrar_allocator_largest_free_area (struct memrar_allocator *allocator) +{ +if (allocator ==NULL ) +return 0 ; +return allocator->largest_free_area; +}static ?
The entire point of these two patches was to hide the memrar_allocator structure by moving it to memrar_allocator.c, forward declaring it in memrar_allocator.h and then providing accessor functions memrar_allocator_largest_free_area and memrar_allocator_capacity (this was the #2 issue for memrar_allocator.[ch] in the TODO file). By defining memrar_allocator_largest_free_area function as static (this is what you mean, right?) would make no sense.