diff options
| author | Neil Zhang <neilzhang1123@hotmail.com> | 2016-01-26 17:39:06 +0800 |
|---|---|---|
| committer | Mister Oyster <oysterized@gmail.com> | 2017-04-16 15:03:43 +0200 |
| commit | 48e1ef0d95ba7b05bf1b25f3b5860e73eb784aa7 (patch) | |
| tree | 338470967c2c159ab8c18eca565401a245fde110 | |
| parent | b4dd6a3a7ac317146c73b03118f8721c48e6eb5b (diff) | |
| download | android_kernel_m2note-48e1ef0d95ba7b05bf1b25f3b5860e73eb784aa7.tar.gz | |
BACKPORT: ion:synchronize debugfs callback and ion_client_destroy
(cherry picked from commit 948c4db4ee10d85fe78ed3755dcaeb85cd37a148)
There are race condition B/T ion_client_destroy and debugfs callbacks.
Let's use a mutex to synchronize them.
Change-Id: I4d73b258ac1fb67604b62f237da0e004275fd3da
Signed-off-by: Neil Zhang <neilzhang1123@hotmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rwxr-xr-x | drivers/staging/android/ion/ion.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index d8dfe66e2..d6fa9f639 100755 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -881,6 +881,34 @@ void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle) } EXPORT_SYMBOL(ion_unmap_kernel); +static struct mutex debugfs_mutex; +static struct rb_root *ion_root_client; +static int is_client_alive(struct ion_client *client) +{ + struct rb_node *node; + struct ion_client *tmp; + struct ion_device *dev; + + node = ion_root_client->rb_node; + dev = container_of(ion_root_client, struct ion_device, clients); + + down_read(&dev->lock); + while (node) { + tmp = rb_entry(node, struct ion_client, node); + if (client < tmp) { + node = node->rb_left; + } else if (client > tmp) { + node = node->rb_right; + } else { + up_read(&dev->lock); + return 1; + } + } + + up_read(&dev->lock); + return 0; +} + static int ion_client_validate(struct ion_device *dev, struct ion_client *client) { @@ -915,6 +943,14 @@ static int ion_debug_client_show(struct seq_file *s, void *unused) seq_printf(s, "%16.s %8.s %8.s %8.s %8.s %8.s\n", "heap_name","pid", "size", "handle_count","handle","buffer"); + mutex_lock(&debugfs_mutex); + if (!is_client_alive(client)) { + seq_printf(s, "ion_client 0x%p dead, can't dump its buffers\n", + client); + mutex_unlock(&debugfs_mutex); + return 0; + } + mutex_lock(&client->lock); for (n = rb_first(&client->handles); n; n = rb_next(n)) { struct ion_handle *handle = rb_entry(n, struct ion_handle, @@ -930,6 +966,7 @@ static int ion_debug_client_show(struct seq_file *s, void *unused) client->pid, buffer->size, buffer->handle_count, handle, buffer); } mutex_unlock(&client->lock); + mutex_unlock(&debugfs_mutex); seq_printf(s, "----------------------------------------------------\n"); @@ -1086,6 +1123,7 @@ void __ion_client_destroy(struct ion_client *client, int from_kern) struct rb_node *n; pr_debug("%s: %d\n", __func__, __LINE__); + mutex_lock(&debugfs_mutex); while ((n = rb_first(&client->handles))) { struct ion_handle *handle = rb_entry(n, struct ion_handle, node); @@ -1114,6 +1152,7 @@ void __ion_client_destroy(struct ion_client *client, int from_kern) #endif kfree(client); + mutex_unlock(&debugfs_mutex); } void ion_client_destroy(struct ion_client *client) @@ -1750,6 +1789,7 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) seq_puts(s, "----------------------------------------------------\n"); down_read(&dev->lock); + mutex_lock(&debugfs_mutex); for (n = rb_first(&dev->clients); n; n = rb_next(n)) { struct ion_client *client = rb_entry(n, struct ion_client, node); @@ -1768,6 +1808,7 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) } } up_read(&dev->lock); + mutex_unlock(&debugfs_mutex); seq_puts(s, "----------------------------------------------------\n"); seq_puts(s, "orphaned allocations (info is from last known client):\n"); @@ -2001,6 +2042,8 @@ debugfs_done: /* Create ION Debug DB Root */ ion_debug_create_db(idev->debug_root); #endif + ion_root_client = &idev->clients; + mutex_init(&debugfs_mutex); return idev; } |
