pretty much every member of the files struct is protected by the file_lock
rwlock now. so it makes no sense to use xchg any more (extra unnecessary
atomic ops). plus, there's two cases where the lock is missing. i bet
you can't hit the race in practice, but it's easy to fix.
diff -urNX dontdiff linux-orig/fs/file.c linux-willy/fs/file.c
--- linux-orig/fs/file.c Tue Nov 28 23:43:39 2000
+++ linux-willy/fs/file.c Sat Feb 10 00:26:59 2001
@@ -98,8 +98,10 @@
struct file **old_fds;
int i;
- old_fds = xchg(&files->fd, new_fds);
- i = xchg(&files->max_fds, nfds);
+ old_fds = files->fd;
+ files->fd = new_fds;
+ i = files->max_fds;
+ files->max_fds = nfds;
/* Don't copy/clear the array if we are creating a new
fd array for fork() */
@@ -195,6 +197,8 @@
/* Copy the existing tables and install the new pointers */
if (nfds > files->max_fdset) {
+ int ofds;
+ fd_set *old_openset, *old_execset;
int i = files->max_fdset / (sizeof(unsigned long) * 8);
int count = (nfds - files->max_fdset) / 8;
@@ -209,12 +213,15 @@
memset (&new_execset->fds_bits[i], 0, count);
}
- nfds = xchg(&files->max_fdset, nfds);
- new_openset = xchg(&files->open_fds, new_openset);
- new_execset = xchg(&files->close_on_exec, new_execset);
+ ofds = files->max_fdset;
+ files->max_fdset = nfds;
+ old_openset = files->open_fds;
+ files->open_fds = new_openset;
+ old_execset = files->close_on_exec;
+ files->close_on_exec = new_execset;
write_unlock(&files->file_lock);
- free_fdset (new_openset, nfds);
- free_fdset (new_execset, nfds);
+ free_fdset (old_openset, ofds);
+ free_fdset (old_execset, ofds);
write_lock(&files->file_lock);
return 0;
}
diff -urNX dontdiff linux-orig/fs/select.c linux-willy/fs/select.c
--- linux-orig/fs/select.c Thu Nov 16 13:54:18 2000
+++ linux-willy/fs/select.c Sat Feb 10 00:32:42 2001
@@ -285,8 +285,10 @@
if (n < 0)
goto out_nofds;
+ read_lock(¤t->files->file_lock);
if (n > current->files->max_fdset)
n = current->files->max_fdset;
+ read_unlock(¤t->files->file_lock);
/*
* We need 6 bitmaps (in/out/ex for both incoming and outgoing),
@@ -414,7 +416,11 @@
int nchunks, nleft;
/* Do a sanity check on nfds ... */
- if (nfds > current->files->max_fds)
+ read_lock(¤t->files->file_lock);
+ i = current->files->max_fds;
+ read_unlock(¤t->files->file_lock);
+
+ if (nfds > i)
return -EINVAL;
if (timeout) {
diff -urNX dontdiff linux-orig/kernel/exit.c linux-willy/kernel/exit.c
--- linux-orig/kernel/exit.c Thu Jan 4 02:00:35 2001
+++ linux-willy/kernel/exit.c Sat Feb 10 00:44:37 2001
@@ -186,9 +186,11 @@
set = files->open_fds->fds_bits[j++];
while (set) {
if (set & 1) {
- struct file * file = xchg(&files->fd[i], NULL);
- if (file)
+ struct file * file = files->fd[i];
+ if (file) {
+ files->fd[i] = NULL;
filp_close(file, files);
+ }
}
i++;
set >>= 1;
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]