Commit ac4812c5ffbb88dd3280a6dacd39fcb73e077fe4
Committed by
Greg Kroah-Hartman
1 parent
14db31814a
binder: Support multiple /dev instances
Add a new module parameter 'devices', that can be used to specify the names of the binder device nodes we want to populate in /dev. Each device node has its own context manager, and is therefore logically separated from all the other device nodes. The config option CONFIG_ANDROID_BINDER_DEVICES can be used to set the default value of the parameter. This approach was favored over using IPC namespaces, mostly because we require a single process to be a part of multiple binder contexts, which seemed harder to achieve with namespaces. Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Martijn Coenen <maco@google.com> Cc: Arve Hjønnevåg <arve@android.com> Cc: Amit Pundir <amit.pundir@linaro.org> Cc: Serban Constantinescu <serban.constantinescu@arm.com> Cc: Dmitry Shmidt <dimitrysh@google.com> Cc: Rom Lemarchand <romlem@google.com> Cc: Android Kernel Team <kernel-team@android.com> Signed-off-by: Martijn Coenen <maco@google.com> [jstultz: minor checkpatch warning fix] Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 2 changed files with 84 additions and 11 deletions Side-by-side Diff
drivers/android/Kconfig
... | ... | @@ -19,6 +19,18 @@ |
19 | 19 | Android process, using Binder to identify, invoke and pass arguments |
20 | 20 | between said processes. |
21 | 21 | |
22 | +config ANDROID_BINDER_DEVICES | |
23 | + string "Android Binder devices" | |
24 | + depends on ANDROID_BINDER_IPC | |
25 | + default "binder" | |
26 | + ---help--- | |
27 | + Default value for the binder.devices parameter. | |
28 | + | |
29 | + The binder.devices parameter is a comma-separated list of strings | |
30 | + that specifies the names of the binder device nodes that will be | |
31 | + created. Each binder device has its own context manager, and is | |
32 | + therefore logically separated from the other devices. | |
33 | + | |
22 | 34 | config ANDROID_BINDER_IPC_32BIT |
23 | 35 | bool |
24 | 36 | depends on !64BIT && ANDROID_BINDER_IPC |
drivers/android/binder.c
... | ... | @@ -50,6 +50,7 @@ |
50 | 50 | static DEFINE_MUTEX(binder_deferred_lock); |
51 | 51 | static DEFINE_MUTEX(binder_mmap_lock); |
52 | 52 | |
53 | +static HLIST_HEAD(binder_devices); | |
53 | 54 | static HLIST_HEAD(binder_procs); |
54 | 55 | static HLIST_HEAD(binder_deferred_list); |
55 | 56 | static HLIST_HEAD(binder_dead_nodes); |
... | ... | @@ -113,6 +114,9 @@ |
113 | 114 | static bool binder_debug_no_lock; |
114 | 115 | module_param_named(proc_no_lock, binder_debug_no_lock, bool, S_IWUSR | S_IRUGO); |
115 | 116 | |
117 | +static char *binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES; | |
118 | +module_param_named(devices, binder_devices_param, charp, 0444); | |
119 | + | |
116 | 120 | static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait); |
117 | 121 | static int binder_stop_on_user_error; |
118 | 122 | |
... | ... | @@ -220,9 +224,10 @@ |
220 | 224 | const char *name; |
221 | 225 | }; |
222 | 226 | |
223 | -static struct binder_context global_context = { | |
224 | - .binder_context_mgr_uid = INVALID_UID, | |
225 | - .name = "binder", | |
227 | +struct binder_device { | |
228 | + struct hlist_node hlist; | |
229 | + struct miscdevice miscdev; | |
230 | + struct binder_context context; | |
226 | 231 | }; |
227 | 232 | |
228 | 233 | struct binder_work { |
... | ... | @@ -3047,6 +3052,7 @@ |
3047 | 3052 | static int binder_open(struct inode *nodp, struct file *filp) |
3048 | 3053 | { |
3049 | 3054 | struct binder_proc *proc; |
3055 | + struct binder_device *binder_dev; | |
3050 | 3056 | |
3051 | 3057 | binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n", |
3052 | 3058 | current->group_leader->pid, current->pid); |
3053 | 3059 | |
... | ... | @@ -3057,10 +3063,12 @@ |
3057 | 3063 | get_task_struct(current); |
3058 | 3064 | proc->tsk = current; |
3059 | 3065 | proc->vma_vm_mm = current->mm; |
3060 | - proc->context = &global_context; | |
3061 | 3066 | INIT_LIST_HEAD(&proc->todo); |
3062 | 3067 | init_waitqueue_head(&proc->wait); |
3063 | 3068 | proc->default_priority = task_nice(current); |
3069 | + binder_dev = container_of(filp->private_data, struct binder_device, | |
3070 | + miscdev); | |
3071 | + proc->context = &binder_dev->context; | |
3064 | 3072 | |
3065 | 3073 | binder_lock(__func__); |
3066 | 3074 | |
3067 | 3075 | |
3068 | 3076 | |
3069 | 3077 | |
... | ... | @@ -3767,26 +3775,50 @@ |
3767 | 3775 | .release = binder_release, |
3768 | 3776 | }; |
3769 | 3777 | |
3770 | -static struct miscdevice binder_miscdev = { | |
3771 | - .minor = MISC_DYNAMIC_MINOR, | |
3772 | - .name = "binder", | |
3773 | - .fops = &binder_fops | |
3774 | -}; | |
3775 | - | |
3776 | 3778 | BINDER_DEBUG_ENTRY(state); |
3777 | 3779 | BINDER_DEBUG_ENTRY(stats); |
3778 | 3780 | BINDER_DEBUG_ENTRY(transactions); |
3779 | 3781 | BINDER_DEBUG_ENTRY(transaction_log); |
3780 | 3782 | |
3783 | +static int __init init_binder_device(const char *name) | |
3784 | +{ | |
3785 | + int ret; | |
3786 | + struct binder_device *binder_device; | |
3787 | + | |
3788 | + binder_device = kzalloc(sizeof(*binder_device), GFP_KERNEL); | |
3789 | + if (!binder_device) | |
3790 | + return -ENOMEM; | |
3791 | + | |
3792 | + binder_device->miscdev.fops = &binder_fops; | |
3793 | + binder_device->miscdev.minor = MISC_DYNAMIC_MINOR; | |
3794 | + binder_device->miscdev.name = name; | |
3795 | + | |
3796 | + binder_device->context.binder_context_mgr_uid = INVALID_UID; | |
3797 | + binder_device->context.name = name; | |
3798 | + | |
3799 | + ret = misc_register(&binder_device->miscdev); | |
3800 | + if (ret < 0) { | |
3801 | + kfree(binder_device); | |
3802 | + return ret; | |
3803 | + } | |
3804 | + | |
3805 | + hlist_add_head(&binder_device->hlist, &binder_devices); | |
3806 | + | |
3807 | + return ret; | |
3808 | +} | |
3809 | + | |
3781 | 3810 | static int __init binder_init(void) |
3782 | 3811 | { |
3783 | 3812 | int ret; |
3813 | + char *device_name, *device_names; | |
3814 | + struct binder_device *device; | |
3815 | + struct hlist_node *tmp; | |
3784 | 3816 | |
3785 | 3817 | binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL); |
3786 | 3818 | if (binder_debugfs_dir_entry_root) |
3787 | 3819 | binder_debugfs_dir_entry_proc = debugfs_create_dir("proc", |
3788 | 3820 | binder_debugfs_dir_entry_root); |
3789 | - ret = misc_register(&binder_miscdev); | |
3821 | + | |
3790 | 3822 | if (binder_debugfs_dir_entry_root) { |
3791 | 3823 | debugfs_create_file("state", |
3792 | 3824 | S_IRUGO, |
... | ... | @@ -3814,6 +3846,35 @@ |
3814 | 3846 | &binder_transaction_log_failed, |
3815 | 3847 | &binder_transaction_log_fops); |
3816 | 3848 | } |
3849 | + | |
3850 | + /* | |
3851 | + * Copy the module_parameter string, because we don't want to | |
3852 | + * tokenize it in-place. | |
3853 | + */ | |
3854 | + device_names = kzalloc(strlen(binder_devices_param) + 1, GFP_KERNEL); | |
3855 | + if (!device_names) { | |
3856 | + ret = -ENOMEM; | |
3857 | + goto err_alloc_device_names_failed; | |
3858 | + } | |
3859 | + strcpy(device_names, binder_devices_param); | |
3860 | + | |
3861 | + while ((device_name = strsep(&device_names, ","))) { | |
3862 | + ret = init_binder_device(device_name); | |
3863 | + if (ret) | |
3864 | + goto err_init_binder_device_failed; | |
3865 | + } | |
3866 | + | |
3867 | + return ret; | |
3868 | + | |
3869 | +err_init_binder_device_failed: | |
3870 | + hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) { | |
3871 | + misc_deregister(&device->miscdev); | |
3872 | + hlist_del(&device->hlist); | |
3873 | + kfree(device); | |
3874 | + } | |
3875 | +err_alloc_device_names_failed: | |
3876 | + debugfs_remove_recursive(binder_debugfs_dir_entry_root); | |
3877 | + | |
3817 | 3878 | return ret; |
3818 | 3879 | } |
3819 | 3880 |