aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/fcntl.c40
1 files changed, 14 insertions, 26 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c
index e632da761fc1..3f3ac630ccde 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -55,14 +55,16 @@ static int get_close_on_exec(unsigned int fd)
55 * file_lock held for write. 55 * file_lock held for write.
56 */ 56 */
57 57
58static int locate_fd(struct files_struct *files, 58static int locate_fd(unsigned int orig_start, int cloexec)
59 struct file *file, unsigned int orig_start)
60{ 59{
60 struct files_struct *files = current->files;
61 unsigned int newfd; 61 unsigned int newfd;
62 unsigned int start; 62 unsigned int start;
63 int error; 63 int error;
64 struct fdtable *fdt; 64 struct fdtable *fdt;
65 65
66 spin_lock(&files->file_lock);
67
66 error = -EINVAL; 68 error = -EINVAL;
67 if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) 69 if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
68 goto out; 70 goto out;
@@ -97,42 +99,28 @@ repeat:
97 if (error) 99 if (error)
98 goto repeat; 100 goto repeat;
99 101
100 /*
101 * We reacquired files_lock, so we are safe as long as
102 * we reacquire the fdtable pointer and use it while holding
103 * the lock, no one can free it during that time.
104 */
105 if (start <= files->next_fd) 102 if (start <= files->next_fd)
106 files->next_fd = newfd + 1; 103 files->next_fd = newfd + 1;
107 104
105 FD_SET(newfd, fdt->open_fds);
106 if (cloexec)
107 FD_SET(newfd, fdt->close_on_exec);
108 else
109 FD_CLR(newfd, fdt->close_on_exec);
108 error = newfd; 110 error = newfd;
109 111
110out: 112out:
113 spin_unlock(&files->file_lock);
111 return error; 114 return error;
112} 115}
113 116
114static int dupfd(struct file *file, unsigned int start, int cloexec) 117static int dupfd(struct file *file, unsigned int start, int cloexec)
115{ 118{
116 struct files_struct * files = current->files; 119 int fd = locate_fd(start, cloexec);
117 struct fdtable *fdt; 120 if (fd >= 0)
118 int fd;
119
120 spin_lock(&files->file_lock);
121 fd = locate_fd(files, file, start);
122 if (fd >= 0) {
123 /* locate_fd() may have expanded fdtable, load the ptr */
124 fdt = files_fdtable(files);
125 FD_SET(fd, fdt->open_fds);
126 if (cloexec)
127 FD_SET(fd, fdt->close_on_exec);
128 else
129 FD_CLR(fd, fdt->close_on_exec);
130 spin_unlock(&files->file_lock);
131 fd_install(fd, file); 121 fd_install(fd, file);
132 } else { 122 else
133 spin_unlock(&files->file_lock);
134 fput(file); 123 fput(file);
135 }
136 124
137 return fd; 125 return fd;
138} 126}