aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fcntl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r--fs/fcntl.c47
1 files changed, 29 insertions, 18 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 6fbc9d8fcc36..bfecc6238083 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -24,20 +24,24 @@
24void fastcall set_close_on_exec(unsigned int fd, int flag) 24void fastcall set_close_on_exec(unsigned int fd, int flag)
25{ 25{
26 struct files_struct *files = current->files; 26 struct files_struct *files = current->files;
27 struct fdtable *fdt;
27 spin_lock(&files->file_lock); 28 spin_lock(&files->file_lock);
29 fdt = files_fdtable(files);
28 if (flag) 30 if (flag)
29 FD_SET(fd, files->close_on_exec); 31 FD_SET(fd, fdt->close_on_exec);
30 else 32 else
31 FD_CLR(fd, files->close_on_exec); 33 FD_CLR(fd, fdt->close_on_exec);
32 spin_unlock(&files->file_lock); 34 spin_unlock(&files->file_lock);
33} 35}
34 36
35static inline int get_close_on_exec(unsigned int fd) 37static inline int get_close_on_exec(unsigned int fd)
36{ 38{
37 struct files_struct *files = current->files; 39 struct files_struct *files = current->files;
40 struct fdtable *fdt;
38 int res; 41 int res;
39 spin_lock(&files->file_lock); 42 spin_lock(&files->file_lock);
40 res = FD_ISSET(fd, files->close_on_exec); 43 fdt = files_fdtable(files);
44 res = FD_ISSET(fd, fdt->close_on_exec);
41 spin_unlock(&files->file_lock); 45 spin_unlock(&files->file_lock);
42 return res; 46 return res;
43} 47}
@@ -54,24 +58,26 @@ static int locate_fd(struct files_struct *files,
54 unsigned int newfd; 58 unsigned int newfd;
55 unsigned int start; 59 unsigned int start;
56 int error; 60 int error;
61 struct fdtable *fdt;
57 62
58 error = -EINVAL; 63 error = -EINVAL;
59 if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) 64 if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
60 goto out; 65 goto out;
61 66
67 fdt = files_fdtable(files);
62repeat: 68repeat:
63 /* 69 /*
64 * Someone might have closed fd's in the range 70 * Someone might have closed fd's in the range
65 * orig_start..files->next_fd 71 * orig_start..fdt->next_fd
66 */ 72 */
67 start = orig_start; 73 start = orig_start;
68 if (start < files->next_fd) 74 if (start < fdt->next_fd)
69 start = files->next_fd; 75 start = fdt->next_fd;
70 76
71 newfd = start; 77 newfd = start;
72 if (start < files->max_fdset) { 78 if (start < fdt->max_fdset) {
73 newfd = find_next_zero_bit(files->open_fds->fds_bits, 79 newfd = find_next_zero_bit(fdt->open_fds->fds_bits,
74 files->max_fdset, start); 80 fdt->max_fdset, start);
75 } 81 }
76 82
77 error = -EMFILE; 83 error = -EMFILE;
@@ -89,8 +95,8 @@ repeat:
89 if (error) 95 if (error)
90 goto repeat; 96 goto repeat;
91 97
92 if (start <= files->next_fd) 98 if (start <= fdt->next_fd)
93 files->next_fd = newfd + 1; 99 fdt->next_fd = newfd + 1;
94 100
95 error = newfd; 101 error = newfd;
96 102
@@ -101,13 +107,16 @@ out:
101static int dupfd(struct file *file, unsigned int start) 107static int dupfd(struct file *file, unsigned int start)
102{ 108{
103 struct files_struct * files = current->files; 109 struct files_struct * files = current->files;
110 struct fdtable *fdt;
104 int fd; 111 int fd;
105 112
106 spin_lock(&files->file_lock); 113 spin_lock(&files->file_lock);
107 fd = locate_fd(files, file, start); 114 fd = locate_fd(files, file, start);
108 if (fd >= 0) { 115 if (fd >= 0) {
109 FD_SET(fd, files->open_fds); 116 /* locate_fd() may have expanded fdtable, load the ptr */
110 FD_CLR(fd, files->close_on_exec); 117 fdt = files_fdtable(files);
118 FD_SET(fd, fdt->open_fds);
119 FD_CLR(fd, fdt->close_on_exec);
111 spin_unlock(&files->file_lock); 120 spin_unlock(&files->file_lock);
112 fd_install(fd, file); 121 fd_install(fd, file);
113 } else { 122 } else {
@@ -123,6 +132,7 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
123 int err = -EBADF; 132 int err = -EBADF;
124 struct file * file, *tofree; 133 struct file * file, *tofree;
125 struct files_struct * files = current->files; 134 struct files_struct * files = current->files;
135 struct fdtable *fdt;
126 136
127 spin_lock(&files->file_lock); 137 spin_lock(&files->file_lock);
128 if (!(file = fcheck(oldfd))) 138 if (!(file = fcheck(oldfd)))
@@ -148,13 +158,14 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
148 158
149 /* Yes. It's a race. In user space. Nothing sane to do */ 159 /* Yes. It's a race. In user space. Nothing sane to do */
150 err = -EBUSY; 160 err = -EBUSY;
151 tofree = files->fd[newfd]; 161 fdt = files_fdtable(files);
152 if (!tofree && FD_ISSET(newfd, files->open_fds)) 162 tofree = fdt->fd[newfd];
163 if (!tofree && FD_ISSET(newfd, fdt->open_fds))
153 goto out_fput; 164 goto out_fput;
154 165
155 files->fd[newfd] = file; 166 fdt->fd[newfd] = file;
156 FD_SET(newfd, files->open_fds); 167 FD_SET(newfd, fdt->open_fds);
157 FD_CLR(newfd, files->close_on_exec); 168 FD_CLR(newfd, fdt->close_on_exec);
158 spin_unlock(&files->file_lock); 169 spin_unlock(&files->file_lock);
159 170
160 if (tofree) 171 if (tofree)