mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									14db31814a
								
							
						
					
					
						commit
						ac4812c5ff
					
				
					 2 changed files with 84 additions and 11 deletions
				
			
		| 
						 | 
					@ -19,6 +19,18 @@ config ANDROID_BINDER_IPC
 | 
				
			||||||
	  Android process, using Binder to identify, invoke and pass arguments
 | 
						  Android process, using Binder to identify, invoke and pass arguments
 | 
				
			||||||
	  between said processes.
 | 
						  between said processes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config ANDROID_BINDER_DEVICES
 | 
				
			||||||
 | 
						string "Android Binder devices"
 | 
				
			||||||
 | 
						depends on ANDROID_BINDER_IPC
 | 
				
			||||||
 | 
						default "binder"
 | 
				
			||||||
 | 
						---help---
 | 
				
			||||||
 | 
						  Default value for the binder.devices parameter.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  The binder.devices parameter is a comma-separated list of strings
 | 
				
			||||||
 | 
						  that specifies the names of the binder device nodes that will be
 | 
				
			||||||
 | 
						  created. Each binder device has its own context manager, and is
 | 
				
			||||||
 | 
						  therefore logically separated from the other devices.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config ANDROID_BINDER_IPC_32BIT
 | 
					config ANDROID_BINDER_IPC_32BIT
 | 
				
			||||||
	bool
 | 
						bool
 | 
				
			||||||
	depends on !64BIT && ANDROID_BINDER_IPC
 | 
						depends on !64BIT && ANDROID_BINDER_IPC
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,6 +50,7 @@ static DEFINE_MUTEX(binder_main_lock);
 | 
				
			||||||
static DEFINE_MUTEX(binder_deferred_lock);
 | 
					static DEFINE_MUTEX(binder_deferred_lock);
 | 
				
			||||||
static DEFINE_MUTEX(binder_mmap_lock);
 | 
					static DEFINE_MUTEX(binder_mmap_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static HLIST_HEAD(binder_devices);
 | 
				
			||||||
static HLIST_HEAD(binder_procs);
 | 
					static HLIST_HEAD(binder_procs);
 | 
				
			||||||
static HLIST_HEAD(binder_deferred_list);
 | 
					static HLIST_HEAD(binder_deferred_list);
 | 
				
			||||||
static HLIST_HEAD(binder_dead_nodes);
 | 
					static HLIST_HEAD(binder_dead_nodes);
 | 
				
			||||||
| 
						 | 
					@ -113,6 +114,9 @@ module_param_named(debug_mask, binder_debug_mask, uint, S_IWUSR | S_IRUGO);
 | 
				
			||||||
static bool binder_debug_no_lock;
 | 
					static bool binder_debug_no_lock;
 | 
				
			||||||
module_param_named(proc_no_lock, binder_debug_no_lock, bool, S_IWUSR | S_IRUGO);
 | 
					module_param_named(proc_no_lock, binder_debug_no_lock, bool, S_IWUSR | S_IRUGO);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char *binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES;
 | 
				
			||||||
 | 
					module_param_named(devices, binder_devices_param, charp, 0444);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait);
 | 
					static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait);
 | 
				
			||||||
static int binder_stop_on_user_error;
 | 
					static int binder_stop_on_user_error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -220,9 +224,10 @@ struct binder_context {
 | 
				
			||||||
	const char *name;
 | 
						const char *name;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct binder_context global_context = {
 | 
					struct binder_device {
 | 
				
			||||||
	.binder_context_mgr_uid = INVALID_UID,
 | 
						struct hlist_node hlist;
 | 
				
			||||||
	.name = "binder",
 | 
						struct miscdevice miscdev;
 | 
				
			||||||
 | 
						struct binder_context context;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct binder_work {
 | 
					struct binder_work {
 | 
				
			||||||
| 
						 | 
					@ -3047,6 +3052,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
 | 
				
			||||||
static int binder_open(struct inode *nodp, struct file *filp)
 | 
					static int binder_open(struct inode *nodp, struct file *filp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct binder_proc *proc;
 | 
						struct binder_proc *proc;
 | 
				
			||||||
 | 
						struct binder_device *binder_dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n",
 | 
						binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n",
 | 
				
			||||||
		     current->group_leader->pid, current->pid);
 | 
							     current->group_leader->pid, current->pid);
 | 
				
			||||||
| 
						 | 
					@ -3057,10 +3063,12 @@ static int binder_open(struct inode *nodp, struct file *filp)
 | 
				
			||||||
	get_task_struct(current);
 | 
						get_task_struct(current);
 | 
				
			||||||
	proc->tsk = current;
 | 
						proc->tsk = current;
 | 
				
			||||||
	proc->vma_vm_mm = current->mm;
 | 
						proc->vma_vm_mm = current->mm;
 | 
				
			||||||
	proc->context = &global_context;
 | 
					 | 
				
			||||||
	INIT_LIST_HEAD(&proc->todo);
 | 
						INIT_LIST_HEAD(&proc->todo);
 | 
				
			||||||
	init_waitqueue_head(&proc->wait);
 | 
						init_waitqueue_head(&proc->wait);
 | 
				
			||||||
	proc->default_priority = task_nice(current);
 | 
						proc->default_priority = task_nice(current);
 | 
				
			||||||
 | 
						binder_dev = container_of(filp->private_data, struct binder_device,
 | 
				
			||||||
 | 
									  miscdev);
 | 
				
			||||||
 | 
						proc->context = &binder_dev->context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	binder_lock(__func__);
 | 
						binder_lock(__func__);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3767,26 +3775,50 @@ static const struct file_operations binder_fops = {
 | 
				
			||||||
	.release = binder_release,
 | 
						.release = binder_release,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct miscdevice binder_miscdev = {
 | 
					 | 
				
			||||||
	.minor = MISC_DYNAMIC_MINOR,
 | 
					 | 
				
			||||||
	.name = "binder",
 | 
					 | 
				
			||||||
	.fops = &binder_fops
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BINDER_DEBUG_ENTRY(state);
 | 
					BINDER_DEBUG_ENTRY(state);
 | 
				
			||||||
BINDER_DEBUG_ENTRY(stats);
 | 
					BINDER_DEBUG_ENTRY(stats);
 | 
				
			||||||
BINDER_DEBUG_ENTRY(transactions);
 | 
					BINDER_DEBUG_ENTRY(transactions);
 | 
				
			||||||
BINDER_DEBUG_ENTRY(transaction_log);
 | 
					BINDER_DEBUG_ENTRY(transaction_log);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __init init_binder_device(const char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
						struct binder_device *binder_device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						binder_device = kzalloc(sizeof(*binder_device), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!binder_device)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						binder_device->miscdev.fops = &binder_fops;
 | 
				
			||||||
 | 
						binder_device->miscdev.minor = MISC_DYNAMIC_MINOR;
 | 
				
			||||||
 | 
						binder_device->miscdev.name = name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						binder_device->context.binder_context_mgr_uid = INVALID_UID;
 | 
				
			||||||
 | 
						binder_device->context.name = name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = misc_register(&binder_device->miscdev);
 | 
				
			||||||
 | 
						if (ret < 0) {
 | 
				
			||||||
 | 
							kfree(binder_device);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hlist_add_head(&binder_device->hlist, &binder_devices);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init binder_init(void)
 | 
					static int __init binder_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
						char *device_name, *device_names;
 | 
				
			||||||
 | 
						struct binder_device *device;
 | 
				
			||||||
 | 
						struct hlist_node *tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL);
 | 
						binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL);
 | 
				
			||||||
	if (binder_debugfs_dir_entry_root)
 | 
						if (binder_debugfs_dir_entry_root)
 | 
				
			||||||
		binder_debugfs_dir_entry_proc = debugfs_create_dir("proc",
 | 
							binder_debugfs_dir_entry_proc = debugfs_create_dir("proc",
 | 
				
			||||||
						 binder_debugfs_dir_entry_root);
 | 
											 binder_debugfs_dir_entry_root);
 | 
				
			||||||
	ret = misc_register(&binder_miscdev);
 | 
					
 | 
				
			||||||
	if (binder_debugfs_dir_entry_root) {
 | 
						if (binder_debugfs_dir_entry_root) {
 | 
				
			||||||
		debugfs_create_file("state",
 | 
							debugfs_create_file("state",
 | 
				
			||||||
				    S_IRUGO,
 | 
									    S_IRUGO,
 | 
				
			||||||
| 
						 | 
					@ -3814,6 +3846,35 @@ static int __init binder_init(void)
 | 
				
			||||||
				    &binder_transaction_log_failed,
 | 
									    &binder_transaction_log_failed,
 | 
				
			||||||
				    &binder_transaction_log_fops);
 | 
									    &binder_transaction_log_fops);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Copy the module_parameter string, because we don't want to
 | 
				
			||||||
 | 
						 * tokenize it in-place.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						device_names = kzalloc(strlen(binder_devices_param) + 1, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!device_names) {
 | 
				
			||||||
 | 
							ret = -ENOMEM;
 | 
				
			||||||
 | 
							goto err_alloc_device_names_failed;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						strcpy(device_names, binder_devices_param);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while ((device_name = strsep(&device_names, ","))) {
 | 
				
			||||||
 | 
							ret = init_binder_device(device_name);
 | 
				
			||||||
 | 
							if (ret)
 | 
				
			||||||
 | 
								goto err_init_binder_device_failed;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_init_binder_device_failed:
 | 
				
			||||||
 | 
						hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) {
 | 
				
			||||||
 | 
							misc_deregister(&device->miscdev);
 | 
				
			||||||
 | 
							hlist_del(&device->hlist);
 | 
				
			||||||
 | 
							kfree(device);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					err_alloc_device_names_failed:
 | 
				
			||||||
 | 
						debugfs_remove_recursive(binder_debugfs_dir_entry_root);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue