[PATCH] sanitize locate_fd()

* 'file' argument is unused; lose it.
* move setting flags from the caller (dupfd()) to locate_fd();
  pass cloexec flag as new argument.  Note that files_fdtable()
  that used to be in dupfd() isn't needed in the place in
  locate_fd() where the moved code ends up - we know that ->file_lock
  hadn't been dropped since the last time we calculated fdt because
  we can get there only if expand_files() returns 0 and it doesn't
  drop/reacquire in that case.
* move getting/dropping ->file_lock into locate_fd().  Now the caller
  doesn't need to do anything with files_struct *files anymore and
  we can move that inside locate_fd() as well, killing the
  struct files_struct * argument.

At that point locate_fd() is extremely similar to get_unused_fd_flags()
and the next patches will merge those two.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2008-04-23 20:38:10 -04:00
parent 3b1253880b
commit f8f95702f0

View file

@ -55,14 +55,16 @@ static int get_close_on_exec(unsigned int fd)
* file_lock held for write.
*/
static int locate_fd(struct files_struct *files,
struct file *file, unsigned int orig_start)
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);
error = -EINVAL;
if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
goto out;
@ -97,42 +99,28 @@ repeat:
if (error)
goto repeat;
/*
* We reacquired files_lock, so we are safe as long as
* we reacquire the fdtable pointer and use it while holding
* the lock, no one can free it during that time.
*/
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)
{
struct files_struct * files = current->files;
struct fdtable *fdt;
int fd;
spin_lock(&files->file_lock);
fd = locate_fd(files, file, start);
if (fd >= 0) {
/* locate_fd() may have expanded fdtable, load the ptr */
fdt = files_fdtable(files);
FD_SET(fd, fdt->open_fds);
if (cloexec)
FD_SET(fd, fdt->close_on_exec);
else
FD_CLR(fd, fdt->close_on_exec);
spin_unlock(&files->file_lock);
int fd = locate_fd(start, cloexec);
if (fd >= 0)
fd_install(fd, file);
} else {
spin_unlock(&files->file_lock);
else
fput(file);
}
return fd;
}