diff options
author | Dipankar Sarma <dipankar@in.ibm.com> | 2005-09-16 22:28:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-17 14:50:02 -0400 |
commit | 4fb3a53860cee2aaaf81186c451b7da0b95b45c1 (patch) | |
tree | db66ba7d3886644729707586aed781c445e12c16 | |
parent | af4e5a218e18ad588d60a4f9d6f8fb5db1a32587 (diff) |
[PATCH] files: fix preemption issues
With the new fdtable locking rules, you have to protect fdtable with either
->file_lock or rcu_read_lock/unlock(). There are some places where we
aren't doing either. This patch fixes those places.
Signed-off-by: Dipankar Sarma <dipankar@in.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/alpha/kernel/osf_sys.c | 7 | ||||
-rw-r--r-- | arch/ia64/kernel/perfmon.c | 3 | ||||
-rw-r--r-- | fs/locks.c | 3 | ||||
-rw-r--r-- | fs/proc/array.c | 3 | ||||
-rw-r--r-- | kernel/exit.c | 6 |
5 files changed, 20 insertions, 2 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 0636116210d2..01fe990d3e54 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/namei.h> | 37 | #include <linux/namei.h> |
38 | #include <linux/uio.h> | 38 | #include <linux/uio.h> |
39 | #include <linux/vfs.h> | 39 | #include <linux/vfs.h> |
40 | #include <linux/rcupdate.h> | ||
40 | 41 | ||
41 | #include <asm/fpu.h> | 42 | #include <asm/fpu.h> |
42 | #include <asm/io.h> | 43 | #include <asm/io.h> |
@@ -975,6 +976,7 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, | |||
975 | long timeout; | 976 | long timeout; |
976 | int ret = -EINVAL; | 977 | int ret = -EINVAL; |
977 | struct fdtable *fdt; | 978 | struct fdtable *fdt; |
979 | int max_fdset; | ||
978 | 980 | ||
979 | timeout = MAX_SCHEDULE_TIMEOUT; | 981 | timeout = MAX_SCHEDULE_TIMEOUT; |
980 | if (tvp) { | 982 | if (tvp) { |
@@ -996,8 +998,11 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, | |||
996 | } | 998 | } |
997 | } | 999 | } |
998 | 1000 | ||
1001 | rcu_read_lock(); | ||
999 | fdt = files_fdtable(current->files); | 1002 | fdt = files_fdtable(current->files); |
1000 | if (n < 0 || n > fdt->max_fdset) | 1003 | max_fdset = fdt->max_fdset; |
1004 | rcu_read_unlock(); | ||
1005 | if (n < 0 || n > max_fdset) | ||
1001 | goto out_nofds; | 1006 | goto out_nofds; |
1002 | 1007 | ||
1003 | /* | 1008 | /* |
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index af42cda6be80..d71731ee5b61 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c | |||
@@ -2218,12 +2218,13 @@ static void | |||
2218 | pfm_free_fd(int fd, struct file *file) | 2218 | pfm_free_fd(int fd, struct file *file) |
2219 | { | 2219 | { |
2220 | struct files_struct *files = current->files; | 2220 | struct files_struct *files = current->files; |
2221 | struct fdtable *fdt = files_fdtable(files); | 2221 | struct fdtable *fdt; |
2222 | 2222 | ||
2223 | /* | 2223 | /* |
2224 | * there ie no fd_uninstall(), so we do it here | 2224 | * there ie no fd_uninstall(), so we do it here |
2225 | */ | 2225 | */ |
2226 | spin_lock(&files->file_lock); | 2226 | spin_lock(&files->file_lock); |
2227 | fdt = files_fdtable(files); | ||
2227 | rcu_assign_pointer(fdt->fd[fd], NULL); | 2228 | rcu_assign_pointer(fdt->fd[fd], NULL); |
2228 | spin_unlock(&files->file_lock); | 2229 | spin_unlock(&files->file_lock); |
2229 | 2230 | ||
diff --git a/fs/locks.c b/fs/locks.c index c2c09b4798d6..f7daa5f48949 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -124,6 +124,7 @@ | |||
124 | #include <linux/smp_lock.h> | 124 | #include <linux/smp_lock.h> |
125 | #include <linux/syscalls.h> | 125 | #include <linux/syscalls.h> |
126 | #include <linux/time.h> | 126 | #include <linux/time.h> |
127 | #include <linux/rcupdate.h> | ||
127 | 128 | ||
128 | #include <asm/semaphore.h> | 129 | #include <asm/semaphore.h> |
129 | #include <asm/uaccess.h> | 130 | #include <asm/uaccess.h> |
@@ -2205,6 +2206,7 @@ void steal_locks(fl_owner_t from) | |||
2205 | 2206 | ||
2206 | lock_kernel(); | 2207 | lock_kernel(); |
2207 | j = 0; | 2208 | j = 0; |
2209 | rcu_read_lock(); | ||
2208 | fdt = files_fdtable(files); | 2210 | fdt = files_fdtable(files); |
2209 | for (;;) { | 2211 | for (;;) { |
2210 | unsigned long set; | 2212 | unsigned long set; |
@@ -2222,6 +2224,7 @@ void steal_locks(fl_owner_t from) | |||
2222 | set >>= 1; | 2224 | set >>= 1; |
2223 | } | 2225 | } |
2224 | } | 2226 | } |
2227 | rcu_read_unlock(); | ||
2225 | unlock_kernel(); | 2228 | unlock_kernel(); |
2226 | } | 2229 | } |
2227 | EXPORT_SYMBOL(steal_locks); | 2230 | EXPORT_SYMBOL(steal_locks); |
diff --git a/fs/proc/array.c b/fs/proc/array.c index d88d518d30f6..d84eecacbeaf 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -74,6 +74,7 @@ | |||
74 | #include <linux/file.h> | 74 | #include <linux/file.h> |
75 | #include <linux/times.h> | 75 | #include <linux/times.h> |
76 | #include <linux/cpuset.h> | 76 | #include <linux/cpuset.h> |
77 | #include <linux/rcupdate.h> | ||
77 | 78 | ||
78 | #include <asm/uaccess.h> | 79 | #include <asm/uaccess.h> |
79 | #include <asm/pgtable.h> | 80 | #include <asm/pgtable.h> |
@@ -180,12 +181,14 @@ static inline char * task_state(struct task_struct *p, char *buffer) | |||
180 | p->gid, p->egid, p->sgid, p->fsgid); | 181 | p->gid, p->egid, p->sgid, p->fsgid); |
181 | read_unlock(&tasklist_lock); | 182 | read_unlock(&tasklist_lock); |
182 | task_lock(p); | 183 | task_lock(p); |
184 | rcu_read_lock(); | ||
183 | if (p->files) | 185 | if (p->files) |
184 | fdt = files_fdtable(p->files); | 186 | fdt = files_fdtable(p->files); |
185 | buffer += sprintf(buffer, | 187 | buffer += sprintf(buffer, |
186 | "FDSize:\t%d\n" | 188 | "FDSize:\t%d\n" |
187 | "Groups:\t", | 189 | "Groups:\t", |
188 | fdt ? fdt->max_fds : 0); | 190 | fdt ? fdt->max_fds : 0); |
191 | rcu_read_unlock(); | ||
189 | 192 | ||
190 | group_info = p->group_info; | 193 | group_info = p->group_info; |
191 | get_group_info(group_info); | 194 | get_group_info(group_info); |
diff --git a/kernel/exit.c b/kernel/exit.c index 6d2089a1bce7..ee6d8b8abef5 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -371,6 +371,12 @@ static inline void close_files(struct files_struct * files) | |||
371 | struct fdtable *fdt; | 371 | struct fdtable *fdt; |
372 | 372 | ||
373 | j = 0; | 373 | j = 0; |
374 | |||
375 | /* | ||
376 | * It is safe to dereference the fd table without RCU or | ||
377 | * ->file_lock because this is the last reference to the | ||
378 | * files structure. | ||
379 | */ | ||
374 | fdt = files_fdtable(files); | 380 | fdt = files_fdtable(files); |
375 | for (;;) { | 381 | for (;;) { |
376 | unsigned long set; | 382 | unsigned long set; |