enum lru_status binder_alloc_free_page()

in binder_alloc.c [984:1047]


enum lru_status binder_alloc_free_page(struct list_head *item,
				       struct list_lru_one *lru,
				       spinlock_t *lock,
				       void *cb_arg)
	__must_hold(lock)
{
	struct mm_struct *mm = NULL;
	struct binder_lru_page *page = container_of(item,
						    struct binder_lru_page,
						    lru);
	struct binder_alloc *alloc;
	uintptr_t page_addr;
	size_t index;
	struct vm_area_struct *vma;

	alloc = page->alloc;
	if (!mutex_trylock(&alloc->mutex))
		goto err_get_alloc_mutex_failed;

	if (!page->page_ptr)
		goto err_page_already_freed;

	index = page - alloc->pages;
	page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE;

	mm = alloc->vma_vm_mm;
	if (!mmget_not_zero(mm))
		goto err_mmget;
	if (!mmap_read_trylock(mm))
		goto err_mmap_read_lock_failed;
	vma = binder_alloc_get_vma(alloc);

	list_lru_isolate(lru, item);
	spin_unlock(lock);

	if (vma) {
		trace_binder_unmap_user_start(alloc, index);

		zap_page_range(vma, page_addr, PAGE_SIZE);

		trace_binder_unmap_user_end(alloc, index);
	}
	mmap_read_unlock(mm);
	mmput_async(mm);

	trace_binder_unmap_kernel_start(alloc, index);

	__free_page(page->page_ptr);
	page->page_ptr = NULL;

	trace_binder_unmap_kernel_end(alloc, index);

	spin_lock(lock);
	mutex_unlock(&alloc->mutex);
	return LRU_REMOVED_RETRY;

err_mmap_read_lock_failed:
	mmput_async(mm);
err_mmget:
err_page_already_freed:
	mutex_unlock(&alloc->mutex);
err_get_alloc_mutex_failed:
	return LRU_SKIP;
}