diff options
Diffstat (limited to 'drivers/android/binder_alloc.c')
-rw-r--r-- | drivers/android/binder_alloc.c | 74 |
1 files changed, 32 insertions, 42 deletions
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 1014beb12802..1c39cfce32fa 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -208,8 +208,8 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, } } - if (need_mm && mmget_not_zero(alloc->vma_vm_mm)) - mm = alloc->vma_vm_mm; + if (need_mm && mmget_not_zero(alloc->mm)) + mm = alloc->mm; if (mm) { mmap_read_lock(mm); @@ -309,35 +309,13 @@ err_no_vma: return vma ? -ENOMEM : -ESRCH; } - -static inline void binder_alloc_set_vma(struct binder_alloc *alloc, - struct vm_area_struct *vma) -{ - unsigned long vm_start = 0; - - /* - * Allow clearing the vma with holding just the read lock to allow - * munmapping downgrade of the write lock before freeing and closing the - * file using binder_alloc_vma_close(). - */ - if (vma) { - vm_start = vma->vm_start; - alloc->vma_vm_mm = vma->vm_mm; - mmap_assert_write_locked(alloc->vma_vm_mm); - } else { - mmap_assert_locked(alloc->vma_vm_mm); - } - - alloc->vma_addr = vm_start; -} - static inline struct vm_area_struct *binder_alloc_get_vma( struct binder_alloc *alloc) { struct vm_area_struct *vma = NULL; if (alloc->vma_addr) - vma = vma_lookup(alloc->vma_vm_mm, alloc->vma_addr); + vma = vma_lookup(alloc->mm, alloc->vma_addr); return vma; } @@ -402,12 +380,15 @@ static struct binder_buffer *binder_alloc_new_buf_locked( size_t size, data_offsets_size; int ret; + mmap_read_lock(alloc->mm); if (!binder_alloc_get_vma(alloc)) { + mmap_read_unlock(alloc->mm); binder_alloc_debug(BINDER_DEBUG_USER_ERROR, "%d: binder_alloc_buf, no vma\n", alloc->pid); return ERR_PTR(-ESRCH); } + mmap_read_unlock(alloc->mm); data_offsets_size = ALIGN(data_size, sizeof(void *)) + ALIGN(offsets_size, sizeof(void *)); @@ -791,8 +772,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, buffer->free = 1; binder_insert_free_buffer(alloc, buffer); alloc->free_async_space = alloc->buffer_size / 2; - binder_alloc_set_vma(alloc, vma); - mmgrab(alloc->vma_vm_mm); + alloc->vma_addr = vma->vm_start; return 0; @@ -822,7 +802,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) buffers = 0; mutex_lock(&alloc->mutex); BUG_ON(alloc->vma_addr && - vma_lookup(alloc->vma_vm_mm, alloc->vma_addr)); + vma_lookup(alloc->mm, alloc->vma_addr)); while ((n = rb_first(&alloc->allocated_buffers))) { buffer = rb_entry(n, struct binder_buffer, rb_node); @@ -872,8 +852,8 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) kfree(alloc->pages); } mutex_unlock(&alloc->mutex); - if (alloc->vma_vm_mm) - mmdrop(alloc->vma_vm_mm); + if (alloc->mm) + mmdrop(alloc->mm); binder_alloc_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d buffers %d, pages %d\n", @@ -929,17 +909,25 @@ void binder_alloc_print_pages(struct seq_file *m, * 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++; - } + + mmap_read_lock(alloc->mm); + if (binder_alloc_get_vma(alloc) == NULL) { + mmap_read_unlock(alloc->mm); + goto uninitialized; } + + mmap_read_unlock(alloc->mm); + 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++; + } + +uninitialized: mutex_unlock(&alloc->mutex); seq_printf(m, " pages: %d:%d:%d\n", active, lru, free); seq_printf(m, " pages high watermark: %zu\n", alloc->pages_high); @@ -974,7 +962,7 @@ int binder_alloc_get_allocated_count(struct binder_alloc *alloc) */ void binder_alloc_vma_close(struct binder_alloc *alloc) { - binder_alloc_set_vma(alloc, NULL); + alloc->vma_addr = 0; } /** @@ -1011,7 +999,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item, index = page - alloc->pages; page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE; - mm = alloc->vma_vm_mm; + mm = alloc->mm; if (!mmget_not_zero(mm)) goto err_mmget; if (!mmap_read_trylock(mm)) @@ -1080,6 +1068,8 @@ static struct shrinker binder_shrinker = { void binder_alloc_init(struct binder_alloc *alloc) { alloc->pid = current->group_leader->pid; + alloc->mm = current->mm; + mmgrab(alloc->mm); mutex_init(&alloc->mutex); INIT_LIST_HEAD(&alloc->buffers); } |