diff options
Diffstat (limited to 'drivers/android/binder_alloc.c')
| -rw-r--r-- | drivers/android/binder_alloc.c | 42 | 
1 files changed, 25 insertions, 17 deletions
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index eb76a823fbb2..2d8b9b91dee0 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -268,7 +268,6 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,  			alloc->pages_high = index + 1;  		trace_binder_alloc_page_end(alloc, index); -		/* vm_insert_page does not seem to increment the refcount */  	}  	if (mm) {  		up_read(&mm->mmap_sem); @@ -277,8 +276,7 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,  	return 0;  free_range: -	for (page_addr = end - PAGE_SIZE; page_addr >= start; -	     page_addr -= PAGE_SIZE) { +	for (page_addr = end - PAGE_SIZE; 1; page_addr -= PAGE_SIZE) {  		bool ret;  		size_t index; @@ -291,6 +289,8 @@ free_range:  		WARN_ON(!ret);  		trace_binder_free_lru_end(alloc, index); +		if (page_addr == start) +			break;  		continue;  err_vm_insert_page_failed: @@ -298,7 +298,8 @@ err_vm_insert_page_failed:  		page->page_ptr = NULL;  err_alloc_page_failed:  err_page_ptr_cleared: -		; +		if (page_addr == start) +			break;  	}  err_no_vma:  	if (mm) { @@ -681,17 +682,17 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,  	struct binder_buffer *buffer;  	mutex_lock(&binder_alloc_mmap_lock); -	if (alloc->buffer) { +	if (alloc->buffer_size) {  		ret = -EBUSY;  		failure_string = "already mapped";  		goto err_already_mapped;  	} +	alloc->buffer_size = min_t(unsigned long, vma->vm_end - vma->vm_start, +				   SZ_4M); +	mutex_unlock(&binder_alloc_mmap_lock);  	alloc->buffer = (void __user *)vma->vm_start; -	mutex_unlock(&binder_alloc_mmap_lock); -	alloc->buffer_size = min_t(unsigned long, vma->vm_end - vma->vm_start, -				   SZ_4M);  	alloc->pages = kcalloc(alloc->buffer_size / PAGE_SIZE,  			       sizeof(alloc->pages[0]),  			       GFP_KERNEL); @@ -722,8 +723,9 @@ err_alloc_buf_struct_failed:  	kfree(alloc->pages);  	alloc->pages = NULL;  err_alloc_pages_failed: -	mutex_lock(&binder_alloc_mmap_lock);  	alloc->buffer = NULL; +	mutex_lock(&binder_alloc_mmap_lock); +	alloc->buffer_size = 0;  err_already_mapped:  	mutex_unlock(&binder_alloc_mmap_lock);  	binder_alloc_debug(BINDER_DEBUG_USER_ERROR, @@ -841,14 +843,20 @@ void binder_alloc_print_pages(struct seq_file *m,  	int free = 0;  	mutex_lock(&alloc->mutex); -	for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { -		page = &alloc->pages[i]; -		if (!page->page_ptr) -			free++; -		else if (list_empty(&page->lru)) -			active++; -		else -			lru++; +	/* +	 * Make sure the binder_alloc is fully initialized, otherwise we might +	 * read inconsistent state. +	 */ +	if (binder_alloc_get_vma(alloc) != NULL) { +		for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { +			page = &alloc->pages[i]; +			if (!page->page_ptr) +				free++; +			else if (list_empty(&page->lru)) +				active++; +			else +				lru++; +		}  	}  	mutex_unlock(&alloc->mutex);  	seq_printf(m, "  pages: %d:%d:%d\n", active, lru, free);  | 
