[PATCH] merge locate_fd() and get_unused_fd()

New primitive: alloc_fd(start, flags).  get_unused_fd() and
get_unused_fd_flags() become wrappers on top of it.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2008-07-30 04:13:04 -04:00
parent a1bc6eb4b4
commit 1027abe882
4 changed files with 76 additions and 129 deletions

View file

@ -49,73 +49,6 @@ static int get_close_on_exec(unsigned int fd)
return res;
}
/*
* locate_fd finds a free file descriptor in the open_fds fdset,
* expanding the fd arrays if necessary. Must be called with the
* file_lock held for write.
*/
static int locate_fd(unsigned int orig_start, int cloexec)
{
struct files_struct *files = current->files;
unsigned int newfd;
unsigned int start;
int error;
struct fdtable *fdt;
spin_lock(&files->file_lock);
repeat:
fdt = files_fdtable(files);
/*
* Someone might have closed fd's in the range
* orig_start..fdt->next_fd
*/
start = orig_start;
if (start < files->next_fd)
start = files->next_fd;
newfd = start;
if (start < fdt->max_fds)
newfd = find_next_zero_bit(fdt->open_fds->fds_bits,
fdt->max_fds, start);
error = expand_files(files, newfd);
if (error < 0)
goto out;
/*
* If we needed to expand the fs array we
* might have blocked - try again.
*/
if (error)
goto repeat;
if (start <= files->next_fd)
files->next_fd = newfd + 1;
FD_SET(newfd, fdt->open_fds);
if (cloexec)
FD_SET(newfd, fdt->close_on_exec);
else
FD_CLR(newfd, fdt->close_on_exec);
error = newfd;
out:
spin_unlock(&files->file_lock);
return error;
}
static int dupfd(struct file *file, unsigned int start, int cloexec)
{
int fd = locate_fd(start, cloexec);
if (fd >= 0)
fd_install(fd, file);
else
fput(file);
return fd;
}
asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
{
int err = -EBADF;
@ -194,10 +127,15 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
asmlinkage long sys_dup(unsigned int fildes)
{
int ret = -EBADF;
struct file * file = fget(fildes);
struct file *file = fget(fildes);
if (file)
ret = dupfd(file, 0, 0);
if (file) {
ret = get_unused_fd();
if (ret >= 0)
fd_install(ret, file);
else
fput(file);
}
return ret;
}
@ -322,8 +260,11 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
case F_DUPFD_CLOEXEC:
if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
break;
get_file(filp);
err = dupfd(filp, arg, cmd == F_DUPFD_CLOEXEC);
err = alloc_fd(arg, cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0);
if (err >= 0) {
get_file(filp);
fd_install(err, filp);
}
break;
case F_GETFD:
err = get_close_on_exec(fd) ? FD_CLOEXEC : 0;