mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	new helper: __alloc_fd()
Essentially, alloc_fd() in a files_struct we own a reference to. Most of the time wanting to use it is a sign of lousy API design (such as android/binder). It's *not* a general-purpose interface; better that than open-coding its guts, but again, playing with other process' descriptor table is a sign of bad design. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									f33ff9927f
								
							
						
					
					
						commit
						dcfadfa4ec
					
				
					 3 changed files with 16 additions and 58 deletions
				
			
		|  | @ -362,71 +362,22 @@ struct binder_transaction { | |||
| static void | ||||
| binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer); | ||||
| 
 | ||||
| /*
 | ||||
|  * copied from get_unused_fd_flags | ||||
|  */ | ||||
| int task_get_unused_fd_flags(struct binder_proc *proc, int flags) | ||||
| { | ||||
| 	struct files_struct *files = proc->files; | ||||
| 	int fd, error; | ||||
| 	struct fdtable *fdt; | ||||
| 	unsigned long rlim_cur; | ||||
| 	unsigned long irqs; | ||||
| 
 | ||||
| 	if (files == NULL) | ||||
| 		return -ESRCH; | ||||
| 
 | ||||
| 	error = -EMFILE; | ||||
| 	spin_lock(&files->file_lock); | ||||
| 	if (!lock_task_sighand(proc->tsk, &irqs)) | ||||
| 		return -EMFILE; | ||||
| 
 | ||||
| repeat: | ||||
| 	fdt = files_fdtable(files); | ||||
| 	fd = find_next_zero_bit(fdt->open_fds, fdt->max_fds, files->next_fd); | ||||
| 	rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE); | ||||
| 	unlock_task_sighand(proc->tsk, &irqs); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * N.B. For clone tasks sharing a files structure, this test | ||||
| 	 * will limit the total number of files that can be opened. | ||||
| 	 */ | ||||
| 	rlim_cur = 0; | ||||
| 	if (lock_task_sighand(proc->tsk, &irqs)) { | ||||
| 		rlim_cur = proc->tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur; | ||||
| 		unlock_task_sighand(proc->tsk, &irqs); | ||||
| 	} | ||||
| 	if (fd >= rlim_cur) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	/* Do we need to expand the fd array or fd set?  */ | ||||
| 	error = expand_files(files, fd); | ||||
| 	if (error < 0) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	if (error) { | ||||
| 		/*
 | ||||
| 		 * If we needed to expand the fs array we | ||||
| 		 * might have blocked - try again. | ||||
| 		 */ | ||||
| 		error = -EMFILE; | ||||
| 		goto repeat; | ||||
| 	} | ||||
| 
 | ||||
| 	__set_open_fd(fd, fdt); | ||||
| 	if (flags & O_CLOEXEC) | ||||
| 		__set_close_on_exec(fd, fdt); | ||||
| 	else | ||||
| 		__clear_close_on_exec(fd, fdt); | ||||
| 	files->next_fd = fd + 1; | ||||
| #if 1 | ||||
| 	/* Sanity check */ | ||||
| 	if (fdt->fd[fd] != NULL) { | ||||
| 		pr_warn("get_unused_fd: slot %d not NULL!\n", fd); | ||||
| 		fdt->fd[fd] = NULL; | ||||
| 	} | ||||
| #endif | ||||
| 	error = fd; | ||||
| 
 | ||||
| out: | ||||
| 	spin_unlock(&files->file_lock); | ||||
| 	return error; | ||||
| 	return __alloc_fd(files, 0, rlim_cur, flags); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  |  | |||
							
								
								
									
										12
									
								
								fs/file.c
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								fs/file.c
									
										
									
									
									
								
							|  | @ -420,11 +420,10 @@ struct files_struct init_files = { | |||
| /*
 | ||||
|  * allocate a file descriptor, mark it busy. | ||||
|  */ | ||||
| int alloc_fd(unsigned start, unsigned flags) | ||||
| int __alloc_fd(struct files_struct *files, | ||||
| 	       unsigned start, unsigned end, unsigned flags) | ||||
| { | ||||
| 	struct files_struct *files = current->files; | ||||
| 	unsigned int fd; | ||||
| 	unsigned end = rlimit(RLIMIT_NOFILE); | ||||
| 	int error; | ||||
| 	struct fdtable *fdt; | ||||
| 
 | ||||
|  | @ -479,8 +478,13 @@ out: | |||
| 	return error; | ||||
| } | ||||
| 
 | ||||
| int alloc_fd(unsigned start, unsigned flags) | ||||
| { | ||||
| 	return __alloc_fd(current->files, start, rlimit(RLIMIT_NOFILE), flags); | ||||
| } | ||||
| 
 | ||||
| int get_unused_fd_flags(unsigned flags) | ||||
| { | ||||
| 	return alloc_fd(0, flags); | ||||
| 	return __alloc_fd(current->files, 0, rlimit(RLIMIT_NOFILE), flags); | ||||
| } | ||||
| EXPORT_SYMBOL(get_unused_fd_flags); | ||||
|  |  | |||
|  | @ -125,6 +125,9 @@ void reset_files_struct(struct files_struct *); | |||
| int unshare_files(struct files_struct **); | ||||
| struct files_struct *dup_fd(struct files_struct *, int *); | ||||
| 
 | ||||
| extern int __alloc_fd(struct files_struct *files, | ||||
| 		      unsigned start, unsigned end, unsigned flags); | ||||
| 
 | ||||
| extern struct kmem_cache *files_cachep; | ||||
| 
 | ||||
| #endif /* __LINUX_FDTABLE_H */ | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Al Viro
						Al Viro