diff -urN -X dontdiff linux/fs/fcntl.c fixes/fs/fcntl.c --- linux/fs/fcntl.c Fri Jul 28 09:58:59 2000 +++ fixes/fs/fcntl.c Mon Aug 7 09:00:46 2000 @@ -132,7 +132,7 @@ struct file * file; struct files_struct * files = current->files; - write_lock(¤t->files->file_lock); + write_lock(&files->file_lock); if (!(file = fcheck(oldfd))) goto out_unlock; err = newfd; @@ -158,7 +158,7 @@ FD_SET(newfd, files->open_fds); write_unlock(&files->file_lock); - do_close(newfd, 0); + do_close(files, newfd, 0); write_lock(&files->file_lock); allocate_fd(files, file, newfd); @@ -167,7 +167,7 @@ out: return err; out_unlock: - write_unlock(¤t->files->file_lock); + write_unlock(&files->file_lock); goto out; } diff -urN -X dontdiff linux/fs/open.c fixes/fs/open.c --- linux/fs/open.c Tue Jul 11 19:26:50 2000 +++ fixes/fs/open.c Mon Aug 7 09:01:19 2000 @@ -804,11 +804,10 @@ * or not in the open-files bitmap. dup2 uses this to retain the fd * without races. */ -int do_close(unsigned int fd, int release) +int do_close(struct files_struct *files, unsigned int fd, int release) { int error; struct file * filp; - struct files_struct * files = current->files; error = -EBADF; write_lock(&files->file_lock); @@ -829,7 +828,7 @@ asmlinkage long sys_close(unsigned int fd) { - return do_close(fd, 1); + return do_close(current->files, fd, 1); } /* diff -urN -X dontdiff linux/fs/super.c fixes/fs/super.c --- linux/fs/super.c Fri Jul 28 09:59:00 2000 +++ fixes/fs/super.c Mon Aug 7 09:05:15 2000 @@ -1566,15 +1566,21 @@ struct vfsmount *new_rootmnt) { struct task_struct *p; + struct fs_struct *fs; read_lock(&tasklist_lock); for_each_task(p) { - /* FIXME - unprotected usage of ->fs + (harmless) race */ - if (!p->fs) continue; - if (p->fs->root == old_root && p->fs->rootmnt == old_rootmnt) - set_fs_root(p->fs, new_rootmnt, new_root); - if (p->fs->pwd == old_root && p->fs->pwdmnt == old_rootmnt) - set_fs_pwd(p->fs, new_rootmnt, new_root); + task_lock(p); + fs = p->fs; + if (fs) { + atomic_inc(&fs->count); + task_unlock(p); + if (fs->root==old_root && fs->rootmnt==old_rootmnt) + set_fs_root(fs, new_rootmnt, new_root); + if (fs->pwd==old_root && fs->pwdmnt==old_rootmnt) + set_fs_pwd(fs, new_rootmnt, new_root); + put_fs_struct(fs); + } } read_unlock(&tasklist_lock); } diff -urN -X dontdiff linux/include/linux/fs.h fixes/include/linux/fs.h --- linux/include/linux/fs.h Mon Aug 7 08:57:58 2000 +++ fixes/include/linux/fs.h Mon Aug 7 09:06:12 2000 @@ -875,7 +875,7 @@ asmlinkage long sys_open(const char *, int, int); asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */ -extern int do_close(unsigned int, int); /* yes, it's really unsigned */ +extern int do_close(struct files_struct *, unsigned int, int); /* yes, it's really unsigned */ extern int do_truncate(struct dentry *, loff_t start); extern struct file *filp_open(const char *, int, int);