Commit 9700fda4 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Jeff Garzik

Make dupfd() locking more clear.

Walter Harms pointed out the locking was rather obtuse in dupfd. This
patch makes it much clearer.  Present code acquires a lock in dupfd()
callee locate_fd(), and releases it in allocate_fd() OR dupfd() itself.

This changes cleans this up to acquire and release the lock entirely
within dupfd(), which moves locking completely out of locate_fd()
and allows the manual inlining of allocate_fd() into its only caller,
dupfd().

This change is functionally equivalent to the current code
[well, dupfd might run a cycle or two faster if the compiler optimizes well...]
parent c447c456
...@@ -75,8 +75,8 @@ static int expand_files(struct files_struct *files, int nr) ...@@ -75,8 +75,8 @@ static int expand_files(struct files_struct *files, int nr)
/* /*
* locate_fd finds a free file descriptor in the open_fds fdset, * locate_fd finds a free file descriptor in the open_fds fdset,
* expanding the fd arrays if necessary. The files write lock will be * expanding the fd arrays if necessary. Must be called with the
* held on exit to ensure that the fd can be entered atomically. * file_lock held for write.
*/ */
static int locate_fd(struct files_struct *files, static int locate_fd(struct files_struct *files,
...@@ -86,8 +86,6 @@ static int locate_fd(struct files_struct *files, ...@@ -86,8 +86,6 @@ static int locate_fd(struct files_struct *files,
int error; int error;
int start; int start;
write_lock(&files->file_lock);
error = -EINVAL; error = -EINVAL;
if (orig_start >= current->rlim[RLIMIT_NOFILE].rlim_cur) if (orig_start >= current->rlim[RLIMIT_NOFILE].rlim_cur)
goto out; goto out;
...@@ -131,30 +129,24 @@ static int locate_fd(struct files_struct *files, ...@@ -131,30 +129,24 @@ static int locate_fd(struct files_struct *files,
return error; return error;
} }
static inline void allocate_fd(struct files_struct *files, static int dupfd(struct file *file, int start)
struct file *file, int fd)
{ {
struct files_struct * files = current->files;
int fd;
write_lock(&files->file_lock);
fd = locate_fd(files, file, start);
if (fd >= 0) {
FD_SET(fd, files->open_fds); FD_SET(fd, files->open_fds);
FD_CLR(fd, files->close_on_exec); FD_CLR(fd, files->close_on_exec);
write_unlock(&files->file_lock); write_unlock(&files->file_lock);
fd_install(fd, file); fd_install(fd, file);
} } else {
static int dupfd(struct file *file, int start)
{
struct files_struct * files = current->files;
int ret;
ret = locate_fd(files, file, start);
if (ret < 0)
goto out_putf;
allocate_fd(files, file, ret);
return ret;
out_putf:
write_unlock(&files->file_lock); write_unlock(&files->file_lock);
fput(file); fput(file);
return ret; }
return fd;
} }
asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
......
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