forked from mirrors/linux
		
	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 | ||||
| 	  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 | ||||
| 	bool | ||||
| 	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_mmap_lock); | ||||
| 
 | ||||
| static HLIST_HEAD(binder_devices); | ||||
| static HLIST_HEAD(binder_procs); | ||||
| static HLIST_HEAD(binder_deferred_list); | ||||
| 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; | ||||
| 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 int binder_stop_on_user_error; | ||||
| 
 | ||||
|  | @ -220,9 +224,10 @@ struct binder_context { | |||
| 	const char *name; | ||||
| }; | ||||
| 
 | ||||
| static struct binder_context global_context = { | ||||
| 	.binder_context_mgr_uid = INVALID_UID, | ||||
| 	.name = "binder", | ||||
| struct binder_device { | ||||
| 	struct hlist_node hlist; | ||||
| 	struct miscdevice miscdev; | ||||
| 	struct binder_context context; | ||||
| }; | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
| 	struct binder_proc *proc; | ||||
| 	struct binder_device *binder_dev; | ||||
| 
 | ||||
| 	binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n", | ||||
| 		     current->group_leader->pid, current->pid); | ||||
|  | @ -3057,10 +3063,12 @@ static int binder_open(struct inode *nodp, struct file *filp) | |||
| 	get_task_struct(current); | ||||
| 	proc->tsk = current; | ||||
| 	proc->vma_vm_mm = current->mm; | ||||
| 	proc->context = &global_context; | ||||
| 	INIT_LIST_HEAD(&proc->todo); | ||||
| 	init_waitqueue_head(&proc->wait); | ||||
| 	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__); | ||||
| 
 | ||||
|  | @ -3767,26 +3775,50 @@ static const struct file_operations binder_fops = { | |||
| 	.release = binder_release, | ||||
| }; | ||||
| 
 | ||||
| static struct miscdevice binder_miscdev = { | ||||
| 	.minor = MISC_DYNAMIC_MINOR, | ||||
| 	.name = "binder", | ||||
| 	.fops = &binder_fops | ||||
| }; | ||||
| 
 | ||||
| BINDER_DEBUG_ENTRY(state); | ||||
| BINDER_DEBUG_ENTRY(stats); | ||||
| BINDER_DEBUG_ENTRY(transactions); | ||||
| 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) | ||||
| { | ||||
| 	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); | ||||
| 	if (binder_debugfs_dir_entry_root) | ||||
| 		binder_debugfs_dir_entry_proc = debugfs_create_dir("proc", | ||||
| 						 binder_debugfs_dir_entry_root); | ||||
| 	ret = misc_register(&binder_miscdev); | ||||
| 
 | ||||
| 	if (binder_debugfs_dir_entry_root) { | ||||
| 		debugfs_create_file("state", | ||||
| 				    S_IRUGO, | ||||
|  | @ -3814,6 +3846,35 @@ static int __init binder_init(void) | |||
| 				    &binder_transaction_log_failed, | ||||
| 				    &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; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Martijn Coenen
						Martijn Coenen