diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/exec.c | 8 | ||||
-rw-r--r-- | fs/fcntl.c | 47 | ||||
-rw-r--r-- | fs/file.c | 42 | ||||
-rw-r--r-- | fs/locks.c | 8 | ||||
-rw-r--r-- | fs/open.c | 41 | ||||
-rw-r--r-- | fs/proc/array.c | 5 | ||||
-rw-r--r-- | fs/proc/base.c | 4 | ||||
-rw-r--r-- | fs/select.c | 12 |
8 files changed, 104 insertions, 63 deletions
@@ -798,6 +798,7 @@ no_thread_group: | |||
798 | static inline void flush_old_files(struct files_struct * files) | 798 | static inline void flush_old_files(struct files_struct * files) |
799 | { | 799 | { |
800 | long j = -1; | 800 | long j = -1; |
801 | struct fdtable *fdt; | ||
801 | 802 | ||
802 | spin_lock(&files->file_lock); | 803 | spin_lock(&files->file_lock); |
803 | for (;;) { | 804 | for (;;) { |
@@ -805,12 +806,13 @@ static inline void flush_old_files(struct files_struct * files) | |||
805 | 806 | ||
806 | j++; | 807 | j++; |
807 | i = j * __NFDBITS; | 808 | i = j * __NFDBITS; |
808 | if (i >= files->max_fds || i >= files->max_fdset) | 809 | fdt = files_fdtable(files); |
810 | if (i >= fdt->max_fds || i >= fdt->max_fdset) | ||
809 | break; | 811 | break; |
810 | set = files->close_on_exec->fds_bits[j]; | 812 | set = fdt->close_on_exec->fds_bits[j]; |
811 | if (!set) | 813 | if (!set) |
812 | continue; | 814 | continue; |
813 | files->close_on_exec->fds_bits[j] = 0; | 815 | fdt->close_on_exec->fds_bits[j] = 0; |
814 | spin_unlock(&files->file_lock); | 816 | spin_unlock(&files->file_lock); |
815 | for ( ; set ; i++,set >>= 1) { | 817 | for ( ; set ; i++,set >>= 1) { |
816 | if (set & 1) { | 818 | if (set & 1) { |
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 @@ | |||
24 | void fastcall set_close_on_exec(unsigned int fd, int flag) | 24 | void 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 | ||
35 | static inline int get_close_on_exec(unsigned int fd) | 37 | static 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); | ||
62 | repeat: | 68 | repeat: |
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: | |||
101 | static int dupfd(struct file *file, unsigned int start) | 107 | static 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) |
@@ -59,13 +59,15 @@ static int expand_fd_array(struct files_struct *files, int nr) | |||
59 | { | 59 | { |
60 | struct file **new_fds; | 60 | struct file **new_fds; |
61 | int error, nfds; | 61 | int error, nfds; |
62 | struct fdtable *fdt; | ||
62 | 63 | ||
63 | 64 | ||
64 | error = -EMFILE; | 65 | error = -EMFILE; |
65 | if (files->max_fds >= NR_OPEN || nr >= NR_OPEN) | 66 | fdt = files_fdtable(files); |
67 | if (fdt->max_fds >= NR_OPEN || nr >= NR_OPEN) | ||
66 | goto out; | 68 | goto out; |
67 | 69 | ||
68 | nfds = files->max_fds; | 70 | nfds = fdt->max_fds; |
69 | spin_unlock(&files->file_lock); | 71 | spin_unlock(&files->file_lock); |
70 | 72 | ||
71 | /* | 73 | /* |
@@ -95,13 +97,14 @@ static int expand_fd_array(struct files_struct *files, int nr) | |||
95 | goto out; | 97 | goto out; |
96 | 98 | ||
97 | /* Copy the existing array and install the new pointer */ | 99 | /* Copy the existing array and install the new pointer */ |
100 | fdt = files_fdtable(files); | ||
98 | 101 | ||
99 | if (nfds > files->max_fds) { | 102 | if (nfds > fdt->max_fds) { |
100 | struct file **old_fds; | 103 | struct file **old_fds; |
101 | int i; | 104 | int i; |
102 | 105 | ||
103 | old_fds = xchg(&files->fd, new_fds); | 106 | old_fds = xchg(&fdt->fd, new_fds); |
104 | i = xchg(&files->max_fds, nfds); | 107 | i = xchg(&fdt->max_fds, nfds); |
105 | 108 | ||
106 | /* Don't copy/clear the array if we are creating a new | 109 | /* Don't copy/clear the array if we are creating a new |
107 | fd array for fork() */ | 110 | fd array for fork() */ |
@@ -164,12 +167,14 @@ static int expand_fdset(struct files_struct *files, int nr) | |||
164 | { | 167 | { |
165 | fd_set *new_openset = NULL, *new_execset = NULL; | 168 | fd_set *new_openset = NULL, *new_execset = NULL; |
166 | int error, nfds = 0; | 169 | int error, nfds = 0; |
170 | struct fdtable *fdt; | ||
167 | 171 | ||
168 | error = -EMFILE; | 172 | error = -EMFILE; |
169 | if (files->max_fdset >= NR_OPEN || nr >= NR_OPEN) | 173 | fdt = files_fdtable(files); |
174 | if (fdt->max_fdset >= NR_OPEN || nr >= NR_OPEN) | ||
170 | goto out; | 175 | goto out; |
171 | 176 | ||
172 | nfds = files->max_fdset; | 177 | nfds = fdt->max_fdset; |
173 | spin_unlock(&files->file_lock); | 178 | spin_unlock(&files->file_lock); |
174 | 179 | ||
175 | /* Expand to the max in easy steps */ | 180 | /* Expand to the max in easy steps */ |
@@ -193,24 +198,25 @@ static int expand_fdset(struct files_struct *files, int nr) | |||
193 | error = 0; | 198 | error = 0; |
194 | 199 | ||
195 | /* Copy the existing tables and install the new pointers */ | 200 | /* Copy the existing tables and install the new pointers */ |
196 | if (nfds > files->max_fdset) { | 201 | fdt = files_fdtable(files); |
197 | int i = files->max_fdset / (sizeof(unsigned long) * 8); | 202 | if (nfds > fdt->max_fdset) { |
198 | int count = (nfds - files->max_fdset) / 8; | 203 | int i = fdt->max_fdset / (sizeof(unsigned long) * 8); |
204 | int count = (nfds - fdt->max_fdset) / 8; | ||
199 | 205 | ||
200 | /* | 206 | /* |
201 | * Don't copy the entire array if the current fdset is | 207 | * Don't copy the entire array if the current fdset is |
202 | * not yet initialised. | 208 | * not yet initialised. |
203 | */ | 209 | */ |
204 | if (i) { | 210 | if (i) { |
205 | memcpy (new_openset, files->open_fds, files->max_fdset/8); | 211 | memcpy (new_openset, fdt->open_fds, fdt->max_fdset/8); |
206 | memcpy (new_execset, files->close_on_exec, files->max_fdset/8); | 212 | memcpy (new_execset, fdt->close_on_exec, fdt->max_fdset/8); |
207 | memset (&new_openset->fds_bits[i], 0, count); | 213 | memset (&new_openset->fds_bits[i], 0, count); |
208 | memset (&new_execset->fds_bits[i], 0, count); | 214 | memset (&new_execset->fds_bits[i], 0, count); |
209 | } | 215 | } |
210 | 216 | ||
211 | nfds = xchg(&files->max_fdset, nfds); | 217 | nfds = xchg(&fdt->max_fdset, nfds); |
212 | new_openset = xchg(&files->open_fds, new_openset); | 218 | new_openset = xchg(&fdt->open_fds, new_openset); |
213 | new_execset = xchg(&files->close_on_exec, new_execset); | 219 | new_execset = xchg(&fdt->close_on_exec, new_execset); |
214 | spin_unlock(&files->file_lock); | 220 | spin_unlock(&files->file_lock); |
215 | free_fdset (new_openset, nfds); | 221 | free_fdset (new_openset, nfds); |
216 | free_fdset (new_execset, nfds); | 222 | free_fdset (new_execset, nfds); |
@@ -237,13 +243,15 @@ out: | |||
237 | int expand_files(struct files_struct *files, int nr) | 243 | int expand_files(struct files_struct *files, int nr) |
238 | { | 244 | { |
239 | int err, expand = 0; | 245 | int err, expand = 0; |
246 | struct fdtable *fdt; | ||
240 | 247 | ||
241 | if (nr >= files->max_fdset) { | 248 | fdt = files_fdtable(files); |
249 | if (nr >= fdt->max_fdset) { | ||
242 | expand = 1; | 250 | expand = 1; |
243 | if ((err = expand_fdset(files, nr))) | 251 | if ((err = expand_fdset(files, nr))) |
244 | goto out; | 252 | goto out; |
245 | } | 253 | } |
246 | if (nr >= files->max_fds) { | 254 | if (nr >= fdt->max_fds) { |
247 | expand = 1; | 255 | expand = 1; |
248 | if ((err = expand_fd_array(files, nr))) | 256 | if ((err = expand_fd_array(files, nr))) |
249 | goto out; | 257 | goto out; |
diff --git a/fs/locks.c b/fs/locks.c index 11956b6179ff..c2c09b4798d6 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -2198,21 +2198,23 @@ void steal_locks(fl_owner_t from) | |||
2198 | { | 2198 | { |
2199 | struct files_struct *files = current->files; | 2199 | struct files_struct *files = current->files; |
2200 | int i, j; | 2200 | int i, j; |
2201 | struct fdtable *fdt; | ||
2201 | 2202 | ||
2202 | if (from == files) | 2203 | if (from == files) |
2203 | return; | 2204 | return; |
2204 | 2205 | ||
2205 | lock_kernel(); | 2206 | lock_kernel(); |
2206 | j = 0; | 2207 | j = 0; |
2208 | fdt = files_fdtable(files); | ||
2207 | for (;;) { | 2209 | for (;;) { |
2208 | unsigned long set; | 2210 | unsigned long set; |
2209 | i = j * __NFDBITS; | 2211 | i = j * __NFDBITS; |
2210 | if (i >= files->max_fdset || i >= files->max_fds) | 2212 | if (i >= fdt->max_fdset || i >= fdt->max_fds) |
2211 | break; | 2213 | break; |
2212 | set = files->open_fds->fds_bits[j++]; | 2214 | set = fdt->open_fds->fds_bits[j++]; |
2213 | while (set) { | 2215 | while (set) { |
2214 | if (set & 1) { | 2216 | if (set & 1) { |
2215 | struct file *file = files->fd[i]; | 2217 | struct file *file = fdt->fd[i]; |
2216 | if (file) | 2218 | if (file) |
2217 | __steal_locks(file, from); | 2219 | __steal_locks(file, from); |
2218 | } | 2220 | } |
@@ -842,14 +842,16 @@ int get_unused_fd(void) | |||
842 | { | 842 | { |
843 | struct files_struct * files = current->files; | 843 | struct files_struct * files = current->files; |
844 | int fd, error; | 844 | int fd, error; |
845 | struct fdtable *fdt; | ||
845 | 846 | ||
846 | error = -EMFILE; | 847 | error = -EMFILE; |
847 | spin_lock(&files->file_lock); | 848 | spin_lock(&files->file_lock); |
848 | 849 | ||
849 | repeat: | 850 | repeat: |
850 | fd = find_next_zero_bit(files->open_fds->fds_bits, | 851 | fdt = files_fdtable(files); |
851 | files->max_fdset, | 852 | fd = find_next_zero_bit(fdt->open_fds->fds_bits, |
852 | files->next_fd); | 853 | fdt->max_fdset, |
854 | fdt->next_fd); | ||
853 | 855 | ||
854 | /* | 856 | /* |
855 | * N.B. For clone tasks sharing a files structure, this test | 857 | * N.B. For clone tasks sharing a files structure, this test |
@@ -872,14 +874,14 @@ repeat: | |||
872 | goto repeat; | 874 | goto repeat; |
873 | } | 875 | } |
874 | 876 | ||
875 | FD_SET(fd, files->open_fds); | 877 | FD_SET(fd, fdt->open_fds); |
876 | FD_CLR(fd, files->close_on_exec); | 878 | FD_CLR(fd, fdt->close_on_exec); |
877 | files->next_fd = fd + 1; | 879 | fdt->next_fd = fd + 1; |
878 | #if 1 | 880 | #if 1 |
879 | /* Sanity check */ | 881 | /* Sanity check */ |
880 | if (files->fd[fd] != NULL) { | 882 | if (fdt->fd[fd] != NULL) { |
881 | printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd); | 883 | printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd); |
882 | files->fd[fd] = NULL; | 884 | fdt->fd[fd] = NULL; |
883 | } | 885 | } |
884 | #endif | 886 | #endif |
885 | error = fd; | 887 | error = fd; |
@@ -893,9 +895,10 @@ EXPORT_SYMBOL(get_unused_fd); | |||
893 | 895 | ||
894 | static inline void __put_unused_fd(struct files_struct *files, unsigned int fd) | 896 | static inline void __put_unused_fd(struct files_struct *files, unsigned int fd) |
895 | { | 897 | { |
896 | __FD_CLR(fd, files->open_fds); | 898 | struct fdtable *fdt = files_fdtable(files); |
897 | if (fd < files->next_fd) | 899 | __FD_CLR(fd, fdt->open_fds); |
898 | files->next_fd = fd; | 900 | if (fd < fdt->next_fd) |
901 | fdt->next_fd = fd; | ||
899 | } | 902 | } |
900 | 903 | ||
901 | void fastcall put_unused_fd(unsigned int fd) | 904 | void fastcall put_unused_fd(unsigned int fd) |
@@ -924,10 +927,12 @@ EXPORT_SYMBOL(put_unused_fd); | |||
924 | void fastcall fd_install(unsigned int fd, struct file * file) | 927 | void fastcall fd_install(unsigned int fd, struct file * file) |
925 | { | 928 | { |
926 | struct files_struct *files = current->files; | 929 | struct files_struct *files = current->files; |
930 | struct fdtable *fdt; | ||
927 | spin_lock(&files->file_lock); | 931 | spin_lock(&files->file_lock); |
928 | if (unlikely(files->fd[fd] != NULL)) | 932 | fdt = files_fdtable(files); |
933 | if (unlikely(fdt->fd[fd] != NULL)) | ||
929 | BUG(); | 934 | BUG(); |
930 | files->fd[fd] = file; | 935 | fdt->fd[fd] = file; |
931 | spin_unlock(&files->file_lock); | 936 | spin_unlock(&files->file_lock); |
932 | } | 937 | } |
933 | 938 | ||
@@ -1010,15 +1015,17 @@ asmlinkage long sys_close(unsigned int fd) | |||
1010 | { | 1015 | { |
1011 | struct file * filp; | 1016 | struct file * filp; |
1012 | struct files_struct *files = current->files; | 1017 | struct files_struct *files = current->files; |
1018 | struct fdtable *fdt; | ||
1013 | 1019 | ||
1014 | spin_lock(&files->file_lock); | 1020 | spin_lock(&files->file_lock); |
1015 | if (fd >= files->max_fds) | 1021 | fdt = files_fdtable(files); |
1022 | if (fd >= fdt->max_fds) | ||
1016 | goto out_unlock; | 1023 | goto out_unlock; |
1017 | filp = files->fd[fd]; | 1024 | filp = fdt->fd[fd]; |
1018 | if (!filp) | 1025 | if (!filp) |
1019 | goto out_unlock; | 1026 | goto out_unlock; |
1020 | files->fd[fd] = NULL; | 1027 | fdt->fd[fd] = NULL; |
1021 | FD_CLR(fd, files->close_on_exec); | 1028 | FD_CLR(fd, fdt->close_on_exec); |
1022 | __put_unused_fd(files, fd); | 1029 | __put_unused_fd(files, fd); |
1023 | spin_unlock(&files->file_lock); | 1030 | spin_unlock(&files->file_lock); |
1024 | return filp_close(filp, files); | 1031 | return filp_close(filp, files); |
diff --git a/fs/proc/array.c b/fs/proc/array.c index 37668fe998ad..d88d518d30f6 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -159,6 +159,7 @@ static inline char * task_state(struct task_struct *p, char *buffer) | |||
159 | { | 159 | { |
160 | struct group_info *group_info; | 160 | struct group_info *group_info; |
161 | int g; | 161 | int g; |
162 | struct fdtable *fdt = NULL; | ||
162 | 163 | ||
163 | read_lock(&tasklist_lock); | 164 | read_lock(&tasklist_lock); |
164 | buffer += sprintf(buffer, | 165 | buffer += sprintf(buffer, |
@@ -179,10 +180,12 @@ static inline char * task_state(struct task_struct *p, char *buffer) | |||
179 | p->gid, p->egid, p->sgid, p->fsgid); | 180 | p->gid, p->egid, p->sgid, p->fsgid); |
180 | read_unlock(&tasklist_lock); | 181 | read_unlock(&tasklist_lock); |
181 | task_lock(p); | 182 | task_lock(p); |
183 | if (p->files) | ||
184 | fdt = files_fdtable(p->files); | ||
182 | buffer += sprintf(buffer, | 185 | buffer += sprintf(buffer, |
183 | "FDSize:\t%d\n" | 186 | "FDSize:\t%d\n" |
184 | "Groups:\t", | 187 | "Groups:\t", |
185 | p->files ? p->files->max_fds : 0); | 188 | fdt ? fdt->max_fds : 0); |
186 | 189 | ||
187 | group_info = p->group_info; | 190 | group_info = p->group_info; |
188 | get_group_info(group_info); | 191 | get_group_info(group_info); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 84751f3f52d5..d0087a0b024b 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1039,6 +1039,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) | |||
1039 | int retval; | 1039 | int retval; |
1040 | char buf[NUMBUF]; | 1040 | char buf[NUMBUF]; |
1041 | struct files_struct * files; | 1041 | struct files_struct * files; |
1042 | struct fdtable *fdt; | ||
1042 | 1043 | ||
1043 | retval = -ENOENT; | 1044 | retval = -ENOENT; |
1044 | if (!pid_alive(p)) | 1045 | if (!pid_alive(p)) |
@@ -1062,8 +1063,9 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) | |||
1062 | if (!files) | 1063 | if (!files) |
1063 | goto out; | 1064 | goto out; |
1064 | spin_lock(&files->file_lock); | 1065 | spin_lock(&files->file_lock); |
1066 | fdt = files_fdtable(files); | ||
1065 | for (fd = filp->f_pos-2; | 1067 | for (fd = filp->f_pos-2; |
1066 | fd < files->max_fds; | 1068 | fd < fdt->max_fds; |
1067 | fd++, filp->f_pos++) { | 1069 | fd++, filp->f_pos++) { |
1068 | unsigned int i,j; | 1070 | unsigned int i,j; |
1069 | 1071 | ||
diff --git a/fs/select.c b/fs/select.c index b80e7eb0ac0d..2e56325c73c4 100644 --- a/fs/select.c +++ b/fs/select.c | |||
@@ -132,11 +132,13 @@ static int max_select_fd(unsigned long n, fd_set_bits *fds) | |||
132 | unsigned long *open_fds; | 132 | unsigned long *open_fds; |
133 | unsigned long set; | 133 | unsigned long set; |
134 | int max; | 134 | int max; |
135 | struct fdtable *fdt; | ||
135 | 136 | ||
136 | /* handle last in-complete long-word first */ | 137 | /* handle last in-complete long-word first */ |
137 | set = ~(~0UL << (n & (__NFDBITS-1))); | 138 | set = ~(~0UL << (n & (__NFDBITS-1))); |
138 | n /= __NFDBITS; | 139 | n /= __NFDBITS; |
139 | open_fds = current->files->open_fds->fds_bits+n; | 140 | fdt = files_fdtable(current->files); |
141 | open_fds = fdt->open_fds->fds_bits+n; | ||
140 | max = 0; | 142 | max = 0; |
141 | if (set) { | 143 | if (set) { |
142 | set &= BITS(fds, n); | 144 | set &= BITS(fds, n); |
@@ -299,6 +301,7 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s | |||
299 | char *bits; | 301 | char *bits; |
300 | long timeout; | 302 | long timeout; |
301 | int ret, size, max_fdset; | 303 | int ret, size, max_fdset; |
304 | struct fdtable *fdt; | ||
302 | 305 | ||
303 | timeout = MAX_SCHEDULE_TIMEOUT; | 306 | timeout = MAX_SCHEDULE_TIMEOUT; |
304 | if (tvp) { | 307 | if (tvp) { |
@@ -326,7 +329,8 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s | |||
326 | goto out_nofds; | 329 | goto out_nofds; |
327 | 330 | ||
328 | /* max_fdset can increase, so grab it once to avoid race */ | 331 | /* max_fdset can increase, so grab it once to avoid race */ |
329 | max_fdset = current->files->max_fdset; | 332 | fdt = files_fdtable(current->files); |
333 | max_fdset = fdt->max_fdset; | ||
330 | if (n > max_fdset) | 334 | if (n > max_fdset) |
331 | n = max_fdset; | 335 | n = max_fdset; |
332 | 336 | ||
@@ -464,9 +468,11 @@ asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long ti | |||
464 | unsigned int i; | 468 | unsigned int i; |
465 | struct poll_list *head; | 469 | struct poll_list *head; |
466 | struct poll_list *walk; | 470 | struct poll_list *walk; |
471 | struct fdtable *fdt; | ||
467 | 472 | ||
468 | /* Do a sanity check on nfds ... */ | 473 | /* Do a sanity check on nfds ... */ |
469 | if (nfds > current->files->max_fdset && nfds > OPEN_MAX) | 474 | fdt = files_fdtable(current->files); |
475 | if (nfds > fdt->max_fdset && nfds > OPEN_MAX) | ||
470 | return -EINVAL; | 476 | return -EINVAL; |
471 | 477 | ||
472 | if (timeout) { | 478 | if (timeout) { |