]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/android/binder_alloc.c
net: phy: adin: const-ify static data
[linux.git] / drivers / android / binder_alloc.c
index d42a8b2f636a5bbdcd43bcfee43b24d820e1e745..2d8b9b91dee0ce29549968c5c6def1d89cb9601b 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/cacheflush.h>
 #include <linux/uaccess.h>
 #include <linux/highmem.h>
+#include <linux/sizes.h>
 #include "binder_alloc.h"
 #include "binder_trace.h"
 
@@ -267,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);
@@ -276,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;
 
@@ -290,6 +289,8 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
                WARN_ON(!ret);
 
                trace_binder_free_lru_end(alloc, index);
+               if (page_addr == start)
+                       break;
                continue;
 
 err_vm_insert_page_failed:
@@ -297,7 +298,8 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
                page->page_ptr = NULL;
 err_alloc_page_failed:
 err_page_ptr_cleared:
-               ;
+               if (page_addr == start)
+                       break;
        }
 err_no_vma:
        if (mm) {
@@ -680,16 +682,18 @@ 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->pages = kcalloc((vma->vm_end - vma->vm_start) / PAGE_SIZE,
+       alloc->pages = kcalloc(alloc->buffer_size / PAGE_SIZE,
                               sizeof(alloc->pages[0]),
                               GFP_KERNEL);
        if (alloc->pages == NULL) {
@@ -697,7 +701,6 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
                failure_string = "alloc page array";
                goto err_alloc_pages_failed;
        }
-       alloc->buffer_size = vma->vm_end - vma->vm_start;
 
        buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
        if (!buffer) {
@@ -720,8 +723,9 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
        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,
@@ -839,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);