Commit dcfadfa4 authored by Al Viro's avatar Al Viro

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent f33ff992
...@@ -362,71 +362,22 @@ struct binder_transaction { ...@@ -362,71 +362,22 @@ struct binder_transaction {
static void static void
binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer); 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) int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
{ {
struct files_struct *files = proc->files; struct files_struct *files = proc->files;
int fd, error;
struct fdtable *fdt;
unsigned long rlim_cur; unsigned long rlim_cur;
unsigned long irqs; unsigned long irqs;
if (files == NULL) if (files == NULL)
return -ESRCH; return -ESRCH;
error = -EMFILE; if (!lock_task_sighand(proc->tsk, &irqs))
spin_lock(&files->file_lock); return -EMFILE;
repeat: rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE);
fdt = files_fdtable(files); unlock_task_sighand(proc->tsk, &irqs);
fd = find_next_zero_bit(fdt->open_fds, fdt->max_fds, files->next_fd);
/*
* 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: return __alloc_fd(files, 0, rlim_cur, flags);
spin_unlock(&files->file_lock);
return error;
} }
/* /*
......
...@@ -420,11 +420,10 @@ struct files_struct init_files = { ...@@ -420,11 +420,10 @@ struct files_struct init_files = {
/* /*
* allocate a file descriptor, mark it busy. * 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 int fd;
unsigned end = rlimit(RLIMIT_NOFILE);
int error; int error;
struct fdtable *fdt; struct fdtable *fdt;
...@@ -479,8 +478,13 @@ int alloc_fd(unsigned start, unsigned flags) ...@@ -479,8 +478,13 @@ int alloc_fd(unsigned start, unsigned flags)
return error; 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) 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); EXPORT_SYMBOL(get_unused_fd_flags);
...@@ -125,6 +125,9 @@ void reset_files_struct(struct files_struct *); ...@@ -125,6 +125,9 @@ void reset_files_struct(struct files_struct *);
int unshare_files(struct files_struct **); int unshare_files(struct files_struct **);
struct files_struct *dup_fd(struct files_struct *, int *); 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; extern struct kmem_cache *files_cachep;
#endif /* __LINUX_FDTABLE_H */ #endif /* __LINUX_FDTABLE_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment