lkml.org 
[lkml]   [1999]   [Jun]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectExtended f_count patch (SMP-safe handling of struct file)
	News:
* the only function in fs/file-table.c that still needs the big lock
is fput(). And only for two calls. The rest is SMP-safe.
* inuse_filp is no more. Instead of the one huge list we are keeping
per-superblock lists + per-tty lists + anonymous list (pipes and sockets).
That should speed up tty layer - it used to run through the whole list,
procfs stuff (on proc_unregister() - it did the same) and quota (we don't
have to traverse the whole list anymore).
* New type: struct file_list (fs.h). Header for the file list.
struct file contains the pointer to file_list (f_list). super_block and
tty_struct contain struct file_list (s_files and tty_files resp.).
* New function: file_move(struct file*, struct file_list*); moves
the file to list. SMP-safe. If device driver wants to keep a list of files
- fine, just move them (in ->open()) to a private list. BTW, AF_UNIX
garbage collector will win big way from such change, but I didn't do it
yet (per-PF lists).

I'll post cleaner version this evening. Patch is against 2.3.8-pre2.
diff -urN linux-2.3.8-pre2/arch/alpha/kernel/osf_sys.c linux-bird.f_count/arch/alpha/kernel/osf_sys.c
--- linux-2.3.8-pre2/arch/alpha/kernel/osf_sys.c Mon Jun 21 12:35:49 1999
+++ linux-bird.f_count/arch/alpha/kernel/osf_sys.c Tue Jun 22 14:24:30 1999
@@ -255,6 +255,7 @@
struct file *file = NULL;
unsigned long ret = -EBADF;

+ down(&current->mm->mmap_sem);
lock_kernel();
#if 0
if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED))
@@ -272,6 +273,7 @@
fput(file);
out:
unlock_kernel();
+ up(&current->mm->mmap_sem);
return ret;
}

diff -urN linux-2.3.8-pre2/arch/arm/kernel/sys_arm.c linux-bird.f_count/arch/arm/kernel/sys_arm.c
--- linux-2.3.8-pre2/arch/arm/kernel/sys_arm.c Mon Jun 21 14:09:15 1999
+++ linux-bird.f_count/arch/arm/kernel/sys_arm.c Tue Jun 22 14:24:31 1999
@@ -72,6 +72,7 @@
struct file * file = NULL;
struct mmap_arg_struct a;

+ down(&current->mm->mmap_sem);
lock_kernel();
if (copy_from_user(&a, arg, sizeof(a)))
goto out;
@@ -87,6 +88,7 @@
fput(file);
out:
unlock_kernel();
+ up(&current->mm->mmap_sem);
return error;
}

diff -urN linux-2.3.8-pre2/arch/mips/kernel/irixelf.c linux-bird.f_count/arch/mips/kernel/irixelf.c
--- linux-2.3.8-pre2/arch/mips/kernel/irixelf.c Mon Jun 21 13:32:20 1999
+++ linux-bird.f_count/arch/mips/kernel/irixelf.c Tue Jun 22 14:24:31 1999
@@ -850,13 +850,12 @@

len = 0;
file = current->files->fd[fd];
+ if (!file || !file->f_op)
+ return -EACCES;
dentry = file->f_dentry;
inode = dentry->d_inode;
elf_bss = 0;

- if (!file || !file->f_op)
- return -EACCES;
-
/* Seek to the beginning of the file. */
if (file->f_op->llseek) {
if ((error = file->f_op->llseek(file, 0, 0)) != 0)
diff -urN linux-2.3.8-pre2/arch/mips/kernel/syscall.c linux-bird.f_count/arch/mips/kernel/syscall.c
--- linux-2.3.8-pre2/arch/mips/kernel/syscall.c Mon Jun 21 12:35:57 1999
+++ linux-bird.f_count/arch/mips/kernel/syscall.c Tue Jun 22 14:24:31 1999
@@ -61,6 +61,7 @@
struct file * file = NULL;
unsigned long error = -EFAULT;

+ down(&current->mm->mmap_sem);
lock_kernel();
if (!(flags & MAP_ANONYMOUS)) {
error = -EBADF;
@@ -74,6 +75,7 @@
fput(file);
out:
unlock_kernel();
+ up(&current->mm->mmap_sem);
return error;
}

diff -urN linux-2.3.8-pre2/arch/mips/kernel/sysirix.c linux-bird.f_count/arch/mips/kernel/sysirix.c
--- linux-2.3.8-pre2/arch/mips/kernel/sysirix.c Mon Jun 21 13:32:21 1999
+++ linux-bird.f_count/arch/mips/kernel/sysirix.c Tue Jun 22 14:24:31 1999
@@ -1103,6 +1103,7 @@
struct file *file = NULL;
unsigned long retval;

+ down(&current->mm->mmap_sem);
lock_kernel();
if(!(flags & MAP_ANONYMOUS)) {
if(!(file = fget(fd))) {
@@ -1130,6 +1131,7 @@

out:
unlock_kernel();
+ up(&current->mm->mmap_sem);
return retval;
}

diff -urN linux-2.3.8-pre2/arch/ppc/kernel/syscalls.c linux-bird.f_count/arch/ppc/kernel/syscalls.c
--- linux-2.3.8-pre2/arch/ppc/kernel/syscalls.c Mon Jun 21 13:32:31 1999
+++ linux-bird.f_count/arch/ppc/kernel/syscalls.c Tue Jun 22 14:24:31 1999
@@ -201,12 +201,16 @@

lock_kernel();
if (!(flags & MAP_ANONYMOUS)) {
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ if (!(file = fget(fd)))
goto out;
}

flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ down(&current->mm->mmap_sem);
ret = do_mmap(file, addr, len, prot, flags, offset);
+ up(&current->mm->mmap_sem);
+ if (file)
+ fput(file);
out:
unlock_kernel();
return ret;
diff -urN linux-2.3.8-pre2/arch/sparc/kernel/sunos_ioctl.c linux-bird.f_count/arch/sparc/kernel/sunos_ioctl.c
--- linux-2.3.8-pre2/arch/sparc/kernel/sunos_ioctl.c Mon Jun 21 12:36:02 1999
+++ linux-bird.f_count/arch/sparc/kernel/sunos_ioctl.c Tue Jun 22 14:24:31 1999
@@ -40,7 +40,7 @@
int ret = -EBADF;

lock_kernel();
- if (fd >= SUNOS_NR_OPEN || !(filp = current->files->fd [fd]))
+ if (fd >= SUNOS_NR_OPEN || !(filp = fcheck(fd)))
goto out;

/* First handle an easy compat. case for tty ldisc. */
diff -urN linux-2.3.8-pre2/arch/sparc/mm/srmmu.c linux-bird.f_count/arch/sparc/mm/srmmu.c
--- linux-2.3.8-pre2/arch/sparc/mm/srmmu.c Mon Jun 21 12:36:02 1999
+++ linux-bird.f_count/arch/sparc/mm/srmmu.c Tue Jun 22 14:24:31 1999
@@ -2076,6 +2076,7 @@
goto done;
inode = file->f_dentry->d_inode;
offset = (address & PAGE_MASK) - vma->vm_start;
+ spin_lock(&inode->i_shared_lock);
vmaring = inode->i_mmap;
do {
/* Do not mistake ourselves as another mapping. */
@@ -2109,6 +2110,7 @@
}
}
} while ((vmaring = vmaring->vm_next_share) != NULL);
+ spin_unlock(&inode->i_shared_lock);

if(alias_found && ((pte_val(pte) & SRMMU_CACHE) != 0)) {
pgdp = srmmu_pgd_offset(vma->vm_mm, address);
diff -urN linux-2.3.8-pre2/arch/sparc/mm/sun4c.c linux-bird.f_count/arch/sparc/mm/sun4c.c
--- linux-2.3.8-pre2/arch/sparc/mm/sun4c.c Mon Jun 21 12:36:02 1999
+++ linux-bird.f_count/arch/sparc/mm/sun4c.c Tue Jun 22 14:24:31 1999
@@ -2682,8 +2682,10 @@
inode = dentry->d_inode;
if(inode) {
unsigned long offset = (address & PAGE_MASK) - vma->vm_start;
- struct vm_area_struct *vmaring = inode->i_mmap;
+ struct vm_area_struct *vmaring;
int alias_found = 0;
+ spin_lock(&inode->i_shared_lock);
+ vmaring = inode->i_mmap;
do {
unsigned long vaddr = vmaring->vm_start + offset;
unsigned long start;
@@ -2712,6 +2714,7 @@
}
}
} while ((vmaring = vmaring->vm_next_share) != NULL);
+ spin_unlock(&inode->i_shared_lock);

if(alias_found && !(pte_val(pte) & _SUN4C_PAGE_NOCACHE)) {
pgdp = sun4c_pgd_offset(vma->vm_mm, address);
diff -urN linux-2.3.8-pre2/arch/sparc64/kernel/sys_sparc32.c linux-bird.f_count/arch/sparc64/kernel/sys_sparc32.c
--- linux-2.3.8-pre2/arch/sparc64/kernel/sys_sparc32.c Mon Jun 21 13:42:00 1999
+++ linux-bird.f_count/arch/sparc64/kernel/sys_sparc32.c Tue Jun 22 14:24:31 1999
@@ -2335,8 +2335,8 @@
break;
}
/* Bump the usage count and install the file. */
- fp[i]->f_count++;
- current->files->fd[new_fd] = fp[i];
+ atomic_inc(&fp[i]->f_count);
+ fd_install(new_fd, fp[i]);
}

if (i > 0) {
diff -urN linux-2.3.8-pre2/arch/sparc64/kernel/sys_sunos32.c linux-bird.f_count/arch/sparc64/kernel/sys_sunos32.c
--- linux-2.3.8-pre2/arch/sparc64/kernel/sys_sunos32.c Mon Jun 21 14:09:57 1999
+++ linux-bird.f_count/arch/sparc64/kernel/sys_sunos32.c Tue Jun 22 14:24:31 1999
@@ -712,7 +712,7 @@
struct inode *inode;
struct file *file;

- file = current->files->fd [fd];
+ file = fcheck(fd);
if(!file)
return 0;

diff -urN linux-2.3.8-pre2/arch/sparc64/solaris/misc.c linux-bird.f_count/arch/sparc64/solaris/misc.c
--- linux-2.3.8-pre2/arch/sparc64/solaris/misc.c Mon Jun 21 12:36:05 1999
+++ linux-bird.f_count/arch/sparc64/solaris/misc.c Tue Jun 22 14:24:31 1999
@@ -83,6 +83,7 @@
}
}

+ down(&current->mm->mmap_sem);
retval = -ENOMEM;
if(!(flags & MAP_FIXED) && !addr) {
unsigned long attempt = get_unmapped_area(addr, len);
@@ -102,6 +103,7 @@
if(!ret_type)
retval = ((retval < 0xf0000000) ? 0 : retval);
out_putf:
+ up(&current->mm->mmap_sem);
if (file)
fput(file);
out:
diff -urN linux-2.3.8-pre2/drivers/block/loop.c linux-bird.f_count/drivers/block/loop.c
--- linux-2.3.8-pre2/drivers/block/loop.c Mon Jun 21 13:19:53 1999
+++ linux-bird.f_count/drivers/block/loop.c Tue Jun 22 14:24:31 1999
@@ -391,6 +391,7 @@
lo->lo_backing_file->f_dentry = file->f_dentry;
lo->lo_backing_file->f_op = file->f_op;
lo->lo_backing_file->private_data = file->private_data;
+ file_move(lo->lo_backing_file, file->f_list);

error = get_write_access(inode);
if (error) {
diff -urN linux-2.3.8-pre2/drivers/char/sysrq.c linux-bird.f_count/drivers/char/sysrq.c
--- linux-2.3.8-pre2/drivers/char/sysrq.c Mon Jun 21 12:36:12 1999
+++ linux-bird.f_count/drivers/char/sysrq.c Tue Jun 22 14:24:31 1999
@@ -150,15 +150,6 @@

/* Aux routines for the syncer */

-static void all_files_read_only(void) /* Kill write permissions of all files */
-{
- struct file *file;
-
- for (file = inuse_filps; file; file = file->f_next)
- if (file->f_dentry && file->f_count && S_ISREG(file->f_dentry->d_inode->i_mode))
- file->f_mode &= ~2;
-}
-
static int is_local_disk(kdev_t dev) /* Guess if the device is a local hard drive */
{
unsigned int major = MAJOR(dev);
@@ -192,6 +183,7 @@
struct super_block *sb = get_super(dev);
struct vfsmount *vfsmnt;
int ret, flags;
+ struct file *file;

if (!sb) {
printk("Superblock not found\n");
@@ -201,6 +193,13 @@
printk("R/O\n");
return;
}
+
+ spin_lock(&sb->s_files.fl_lock);
+ for (file = sb->s_files.fl_list; file; file = file->f_next)
+ if (file->f_dentry && atomic_read(&file->f_count)
+ && S_ISREG(file->f_dentry->d_inode->i_mode))
+ file->f_mode &= ~2;
+ spin_unlock(&sb->s_files.fl_lock);
DQUOT_OFF(dev);
fsync_dev(dev);
flags = MS_RDONLY;
@@ -239,9 +238,6 @@
lock_kernel();
remount_flag = (emergency_sync_scheduled == EMERG_REMOUNT);
emergency_sync_scheduled = 0;
-
- if (remount_flag)
- all_files_read_only();

for (mnt = vfsmntlist; mnt; mnt = mnt->mnt_next)
if (is_local_disk(mnt->mnt_dev))
diff -urN linux-2.3.8-pre2/drivers/char/tpqic02.c linux-bird.f_count/drivers/char/tpqic02.c
--- linux-2.3.8-pre2/drivers/char/tpqic02.c Mon Jun 21 12:49:55 1999
+++ linux-bird.f_count/drivers/char/tpqic02.c Tue Jun 22 14:24:31 1999
@@ -2216,7 +2216,7 @@
}

/* Only one at a time from here on... */
- if (filp->f_count>1) /* filp->f_count==1 for the first open() */
+ if (atomic_read(&filp->f_count)>1) /* filp->f_count==1 for the first open() */
{
return -EBUSY;
}
diff -urN linux-2.3.8-pre2/drivers/char/tty_io.c linux-bird.f_count/drivers/char/tty_io.c
--- linux-2.3.8-pre2/drivers/char/tty_io.c Mon Jun 21 13:56:26 1999
+++ linux-bird.f_count/drivers/char/tty_io.c Tue Jun 22 14:24:31 1999
@@ -176,10 +176,12 @@
struct file *f;
int count = 0;

- for(f = inuse_filps; f; f = f->f_next) {
+ spin_lock(&tty->tty_files.fl_lock);
+ for(f = tty->tty_files.fl_list; f; f = f->f_next) {
if(f->private_data == tty)
count++;
}
+ spin_unlock(&tty->tty_files.fl_lock);
if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
tty->driver.subtype == PTY_TYPE_SLAVE &&
tty->link && tty->link->count)
@@ -395,13 +397,10 @@
lock_kernel();

check_tty_count(tty, "do_tty_hangup");
- for (filp = inuse_filps; filp; filp = filp->f_next) {
- if (filp->private_data != tty)
- continue;
+ spin_lock(&tty->tty_files.fl_lock);
+ for (filp = tty->tty_files.fl_list; filp; filp = filp->f_next) {
if (!filp->f_dentry)
continue;
- if (!filp->f_dentry->d_inode)
- continue;
if (filp->f_dentry->d_inode->i_rdev == CONSOLE_DEV ||
filp->f_dentry->d_inode->i_rdev == SYSCONS_DEV) {
cons_filp = filp;
@@ -410,9 +409,10 @@
if (filp->f_op != &tty_fops)
continue;
closecount++;
- tty_fasync(-1, filp, 0);
+ tty_fasync(-1, filp, 0); /* can't block */
filp->f_op = &hung_up_tty_fops;
}
+ spin_unlock(&tty->tty_files.fl_lock);

/* FIXME! What are the locking issues here? This may me overdoing things.. */
{
@@ -1303,6 +1303,7 @@
init_dev_done:
#endif
filp->private_data = tty;
+ file_move(file, &tty->tty_files);
check_tty_count(tty, "tty_open");
if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
tty->driver.subtype == PTY_TYPE_MASTER)
@@ -1933,6 +1934,8 @@
tty->tq_hangup.routine = do_tty_hangup;
tty->tq_hangup.data = tty;
sema_init(&tty->atomic_read, 1);
+ init_spin_lock(&tty->tty_files.fl_lock);
+ tty->tty_files.fl_list = NULL;
}

/*
diff -urN linux-2.3.8-pre2/drivers/scsi/st.c linux-bird.f_count/drivers/scsi/st.c
--- linux-2.3.8-pre2/drivers/scsi/st.c Mon Jun 21 13:12:01 1999
+++ linux-bird.f_count/drivers/scsi/st.c Tue Jun 22 14:24:31 1999
@@ -890,7 +890,7 @@
kdev_t devt = inode->i_rdev;
int dev;

- if (filp->f_count > 1)
+ if (atomic_read(&filp->f_count) > 1)
return 0;

dev = TAPE_NR(devt);
diff -urN linux-2.3.8-pre2/drivers/sgi/char/usema.c linux-bird.f_count/drivers/sgi/char/usema.c
--- linux-2.3.8-pre2/drivers/sgi/char/usema.c Mon Jun 21 13:07:41 1999
+++ linux-bird.f_count/drivers/sgi/char/usema.c Tue Jun 22 14:24:31 1999
@@ -50,8 +50,8 @@
if (newfd < 0)
return newfd;

- current->files->fd [newfd] = usema->filp;
- usema->filp->f_count++;
+ atomic_inc(&usema->filp->f_count);
+ fd_install(newfd, usema->filp);
/* Is that it? */
printk("UIOCATTACHSEMA: new usema fd is %d", newfd);
return newfd;
diff -urN linux-2.3.8-pre2/fs/dquot.c linux-bird.f_count/fs/dquot.c
--- linux-2.3.8-pre2/fs/dquot.c Mon Jun 21 12:55:30 1999
+++ linux-bird.f_count/fs/dquot.c Tue Jun 22 14:24:31 1999
@@ -583,20 +583,22 @@
if (!sb || !sb->dq_op)
return; /* nothing to do */

- for (filp = inuse_filps; filp; filp = filp->f_next) {
+ spin_lock(&sb->s_files.fl_lock);
+ for (filp = sb->s_files.fl_list; filp; filp = filp->f_next) {
if (!filp->f_dentry)
continue;
- if (filp->f_dentry->d_sb != sb)
- continue;
inode = filp->f_dentry->d_inode;
if (!inode)
continue;
/* N.B. race problem -- filp could become unused */
if (filp->f_mode & FMODE_WRITE) {
+ spin_unlock(&sb->s_files.fl_lock);
sb->dq_op->initialize(inode, type);
inode->i_flags |= S_QUOTA;
+ spin_lock(&sb->s_files.fl_lock);
}
}
+ spin_unlock(&sb->s_files.fl_lock);
}

static void reset_dquot_ptrs(kdev_t dev, short type)
@@ -614,11 +616,10 @@
/* free any quota for unused dentries */
shrink_dcache_sb(sb);

- for (filp = inuse_filps; filp; filp = filp->f_next) {
+ spin_lock(&sb->s_files.fl_lock);
+ for (filp = sb->s_files.fl_list; filp; filp = filp->f_next) {
if (!filp->f_dentry)
continue;
- if (filp->f_dentry->d_sb != sb)
- continue;
inode = filp->f_dentry->d_inode;
if (!inode)
continue;
@@ -637,12 +638,14 @@
inode->i_flags &= ~S_QUOTA;
put_it:
if (dquot != NODQUOT) {
+ spin_unlock(&sb->s_files.fl_lock);
dqput(dquot);
/* we may have blocked ... */
goto restart;
}
}
}
+ spin_unlock(&sb->s_files.fl_lock);
}

static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
diff -urN linux-2.3.8-pre2/fs/exec.c linux-bird.f_count/fs/exec.c
--- linux-2.3.8-pre2/fs/exec.c Mon Jun 21 13:30:15 1999
+++ linux-bird.f_count/fs/exec.c Tue Jun 22 14:24:31 1999
@@ -123,8 +123,12 @@
{
struct inode * inode = dentry->d_inode;
struct file * f;
+ struct file_list * l = NULL;
int fd, error;

+ if (inode->i_sb)
+ l = &inode->i_sb->s_files;
+
error = -EINVAL;
if (!inode->i_op || !inode->i_op->default_file_ops)
goto out;
@@ -145,6 +149,7 @@
if (error)
goto out_filp;
}
+ file_move(f, l);
fd_install(fd, f);
dget(dentry);
}
@@ -563,7 +568,8 @@
if ((retval = permission(inode, MAY_EXEC)) != 0)
return retval;
/* better not execute files which are being written to */
- if (inode->i_writecount > 0)
+ /* WARNING. Read comments in fs/namei.c::get_write_access() */
+ if (atomic_read(&inode->i_writecount) > 0)
return -ETXTBSY;

bprm->e_uid = current->euid;
diff -urN linux-2.3.8-pre2/fs/file_table.c linux-bird.f_count/fs/file_table.c
--- linux-2.3.8-pre2/fs/file_table.c Mon Jun 21 13:30:15 1999
+++ linux-bird.f_count/fs/file_table.c Tue Jun 22 14:24:31 1999
@@ -20,25 +20,21 @@

/* Free list management, if you are here you must have f_count == 0 */
static struct file * free_filps = NULL;
-
-static void insert_file_free(struct file *file)
-{
- if((file->f_next = free_filps) != NULL)
- free_filps->f_pprev = &file->f_next;
- free_filps = file;
- file->f_pprev = &free_filps;
- nr_free_files++;
-}
-
-/* The list of in-use filp's must be exported (ugh...) */
-struct file *inuse_filps = NULL;
-
-static inline void put_inuse(struct file *file)
-{
- if((file->f_next = inuse_filps) != NULL)
- inuse_filps->f_pprev = &file->f_next;
- inuse_filps = file;
- file->f_pprev = &inuse_filps;
+/* Here the new files go */
+static struct file_list anon_list = { NULL, SPIN_LOCK_UNLOCKED };
+/* And here the free ones sit */
+static struct file_list free_list = { NULL, SPIN_LOCK_UNLOCKED };
+
+static struct file *insert_file_list(struct file *file, struct file_list *list,
+ int *count)
+{
+ spin_lock(&list.fl_lock);
+ if ( (file->f_next = list.fl_list) != NULL)
+ list.fl_list->f_pprev = &file->f_next;
+ list.fl_list = file;
+ file->f_pprev = &list.fl_list;
+ if (count) *count++;
+ spin_unlock(&list.fl_lock);
}

/* It does not matter which list it is on. */
@@ -67,24 +63,28 @@
/* Find an unused file structure and return a pointer to it.
* Returns NULL, if there are no more free file structures or
* we run out of memory.
+ *
+ * SMP-safe.
*/
struct file * get_empty_filp(void)
{
static int old_max = 0;
struct file * f;

+ spin_lock(&free_list.fl_lock);
if (nr_free_files > NR_RESERVED_FILES) {
used_one:
- f = free_filps;
+ f = free_list.fl_list;
remove_filp(f);
nr_free_files--;
new_one:
+ spin_unlock(&free_list.fl_lock);
memset(f, 0, sizeof(*f));
- f->f_count = 1;
+ atomic_set(&f->f_count,1);
f->f_version = ++event;
f->f_uid = current->fsuid;
f->f_gid = current->fsgid;
- put_inuse(f);
+ insert_file_list(file, anon_list, NULL);
return f;
}
/*
@@ -96,7 +96,9 @@
* Allocate a new one if we're below the limit.
*/
if (nr_files < max_files) {
+ spin_unlock(&free_list.fl_lock);
f = kmem_cache_alloc(filp_cache, SLAB_KERNEL);
+ spin_lock(&free_list.fl_lock);
if (f) {
nr_files++;
goto new_one;
@@ -108,6 +110,7 @@
printk("VFS: file-max limit %d reached\n", max_files);
old_max = max_files;
}
+ spin_unlock(&free_list.fl_lock);
return NULL;
}

@@ -120,7 +123,7 @@
{
memset(filp, 0, sizeof(*filp));
filp->f_mode = mode;
- filp->f_count = 1;
+ atomic_set(&filp->f_count, 1);
filp->f_dentry = dentry;
filp->f_uid = current->fsuid;
filp->f_gid = current->fsgid;
@@ -133,22 +136,67 @@

void fput(struct file *file)
{
- int count = file->f_count-1;
+ if (atomic_dec_and_test(&file->f_count)) {
+ atomic_inc(&file->f_count);
+
+ locks_remove_flock(file); /* Still need the */
+ __fput(file); /* big lock here. */

- if (!count) {
- locks_remove_flock(file);
- __fput(file);
- file->f_count = 0;
+ atomic_set(&file->f_count, 0);
+ spin_lock(&list.fl_lock);
remove_filp(file);
- insert_file_free(file);
- } else
- file->f_count = count;
+ spin_unlock(&list.fl_lock);
+ insert_file_list(file, free_list, &nr_free_files);
+ }
}

+/* Here. put_filp() is SMP-safe now. */
+
void put_filp(struct file *file)
{
- if(--file->f_count == 0) {
+ if(atomic_dec_and_test(&file->f_count)) {
+ struct lise_list *list = file->f_list;
+ spin_lock(&list.fl_lock);
remove_filp(file);
- insert_file_free(file);
+ spin_unlock(&list.fl_lock);
+ insert_file_list(file, free_list, &nr_free_files);
+ }
+}
+
+void file_move(struct file *file, struct file_list *list)
+{
+ strcut file_list *old_list = file->f_list;
+ if (!list || list == old_list)
+ return;
+ spin_lock(&old_list.fl_lock);
+ remove_filp(file);
+ spin_unlock(&old_list.fl_lock);
+ insert_file_list(file, list, NULL);
+}
+
+int fs_may_remount_ro(struct super_block *sb)
+{
+ struct file *file;
+
+ /* Check that no files are currently opened for writing. */
+ spin_lock(&sb->s_files.fl_lock);
+ for (file = sb->s_files.fl_list; file; file = file->f_next) {
+ struct inode *inode;
+ inode = file->f_dentry->d_inode;
+ if (!inode)
+ continue;
+
+ /* File with pending delete? */
+ if (inode->i_nlink == 0)
+ goto too_bad;
+
+ /* Writable file? */
+ if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE))
+ return 0;
}
+ spin_unlock(&sb->s_files.fl_lock);
+ return 1; /* Tis' cool bro. */
+too_bad:
+ spin_unlock(&sb->s_files.fl_lock);
+ return 0;
}
diff -urN linux-2.3.8-pre2/fs/hpfs/mmap.c linux-bird.f_count/fs/hpfs/mmap.c
--- linux-2.3.8-pre2/fs/hpfs/mmap.c Mon Jun 21 13:03:49 1999
+++ linux-bird.f_count/fs/hpfs/mmap.c Tue Jun 22 14:24:31 1999
@@ -119,9 +119,9 @@
mark_inode_dirty(inode);
}*/

- vma->vm_file = file;
/*inode->i_count++;*/
- file->f_count++;
+ atomic_inc(&file->f_count);
+ vma->vm_file = file;
vma->vm_ops = &hpfs_file_mmap;
/*printk("end mmap\n");*/
return 0;
diff -urN linux-2.3.8-pre2/fs/inode.c linux-bird.f_count/fs/inode.c
--- linux-2.3.8-pre2/fs/inode.c Mon Jun 21 14:12:09 1999
+++ linux-bird.f_count/fs/inode.c Tue Jun 22 14:24:31 1999
@@ -130,6 +130,7 @@
INIT_LIST_HEAD(&inode->i_hash);
INIT_LIST_HEAD(&inode->i_dentry);
sema_init(&inode->i_sem, 1);
+ spin_lock_init(&inode->i_shared_lock);
}

static inline void write_inode(struct inode *inode)
@@ -521,7 +522,7 @@
inode->i_sock = 0;
inode->i_op = NULL;
inode->i_nlink = 1;
- inode->i_writecount = 0;
+ atomic_set(&inode->i_writecount, 0);
inode->i_size = 0;
inode->i_generation = 0;
memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
@@ -806,31 +807,6 @@
if (max > MAX_INODE)
max = MAX_INODE;
max_inodes = max;
-}
-
-/* This belongs in file_table.c, not here... */
-int fs_may_remount_ro(struct super_block *sb)
-{
- struct file *file;
-
- /* Check that no files are currently opened for writing. */
- for (file = inuse_filps; file; file = file->f_next) {
- struct inode *inode;
- if (!file->f_dentry)
- continue;
- inode = file->f_dentry->d_inode;
- if (!inode || inode->i_sb != sb)
- continue;
-
- /* File with pending delete? */
- if (inode->i_nlink == 0)
- return 0;
-
- /* Writable file? */
- if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE))
- return 0;
- }
- return 1; /* Tis' cool bro. */
}

void update_atime (struct inode *inode)
diff -urN linux-2.3.8-pre2/fs/locks.c linux-bird.f_count/fs/locks.c
--- linux-2.3.8-pre2/fs/locks.c Tue Jun 22 09:06:09 1999
+++ linux-bird.f_count/fs/locks.c Tue Jun 22 14:24:31 1999
@@ -400,16 +400,23 @@

/* Don't allow mandatory locks on files that may be memory mapped
* and shared.
+ *
+ * Since do_mmap() is protected by big lock we are safe here, but as
+ * soon as it will go we will have a bunch of interesting stuff to
+ * care of.
*/
if (IS_MANDLOCK(inode) &&
(inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID &&
inode->i_mmap) {
- struct vm_area_struct *vma = inode->i_mmap;
+ struct vm_area_struct *vma;
error = -EAGAIN;
+ spin_lock(&inode->i_shared_lock);
+ vma = inode->i_mmap;
do {
if (vma->vm_flags & VM_MAYSHARE)
- goto out_putf;
+ goto out_putf_unlock;
} while ((vma = vma->vm_next_share) != NULL);
+ spin_unlock(&inode->i_shared_lock);
}

error = -EINVAL;
@@ -461,6 +468,9 @@
fput(filp);
out:
return error;
+out_putf_unlock:
+ spin_unlock(&inode->i_shared_lock);
+ goto out_putf;
}

/*
diff -urN linux-2.3.8-pre2/fs/namei.c linux-bird.f_count/fs/namei.c
--- linux-2.3.8-pre2/fs/namei.c Mon Jun 21 13:07:59 1999
+++ linux-bird.f_count/fs/namei.c Tue Jun 22 14:24:31 1999
@@ -171,18 +171,22 @@
* 0: no writers, no VM_DENYWRITE mappings
* < 0: (-i_writecount) vm_area_structs with VM_DENYWRITE set exist
* > 0: (i_writecount) users are writing to the file.
+ *
+ * WARNING: as soon as we will move get_write_access(), do_mmap() or
+ * prepare_binfmt() out of the big lock we will need a spinlock protecting
+ * the checks in all 3. For the time being it is not needed.
*/
int get_write_access(struct inode * inode)
{
- if (inode->i_writecount < 0)
+ if (atomic_read(&inode->i_writecount) < 0)
return -ETXTBSY;
- inode->i_writecount++;
+ atomic_inc(&inode->i_writecount);
return 0;
}

void put_write_access(struct inode * inode)
{
- inode->i_writecount--;
+ atomic_dec(&inode->i_writecount);
}

/*
diff -urN linux-2.3.8-pre2/fs/nfs/write.c linux-bird.f_count/fs/nfs/write.c
--- linux-2.3.8-pre2/fs/nfs/write.c Mon Jun 21 14:31:25 1999
+++ linux-bird.f_count/fs/nfs/write.c Tue Jun 22 14:24:31 1999
@@ -305,6 +305,7 @@
goto out_req;

/* Put the task on inode's writeback request list. */
+ atomic_inc(&file->f_count);
wreq->wb_file = file;
wreq->wb_pid = current->pid;
wreq->wb_page = page;
@@ -467,7 +468,6 @@
* The IO completion will then free the page and the dentry.
*/
get_page(page);
- file->f_count++;

/* Schedule request */
synchronous = schedule_write_request(req, synchronous);
diff -urN linux-2.3.8-pre2/fs/nfsd/vfs.c linux-bird.f_count/fs/nfsd/vfs.c
--- linux-2.3.8-pre2/fs/nfsd/vfs.c Mon Jun 21 13:08:12 1999
+++ linux-bird.f_count/fs/nfsd/vfs.c Tue Jun 22 14:24:31 1999
@@ -342,7 +342,7 @@

memset(filp, 0, sizeof(*filp));
filp->f_op = inode->i_op->default_file_ops;
- filp->f_count = 1;
+ atomic_set(&filp->f_count, 1);
filp->f_flags = wflag? O_WRONLY : O_RDONLY;
filp->f_mode = wflag? FMODE_WRITE : FMODE_READ;
filp->f_dentry = dentry;
@@ -360,7 +360,7 @@
/* I nearly added put_filp() call here, but this filp
* is really on callers stack frame. -DaveM
*/
- filp->f_count--;
+ atomic_dec(&filp->f_count);
}
}
out_nfserr:
@@ -585,7 +585,7 @@
* nice and simple solution (IMHO), and it seems to
* work:-)
*/
- if (EX_WGATHER(exp) && (inode->i_writecount > 1
+ if (EX_WGATHER(exp) && (atomic_read(&inode->i_writecount) > 1
|| (last_ino == inode->i_ino && last_dev == inode->i_dev))) {
#if 0
interruptible_sleep_on_timeout(&inode->i_wait, 10 * HZ / 1000);
diff -urN linux-2.3.8-pre2/fs/open.c linux-bird.f_count/fs/open.c
--- linux-2.3.8-pre2/fs/open.c Mon Jun 21 13:12:23 1999
+++ linux-bird.f_count/fs/open.c Tue Jun 22 14:24:31 1999
@@ -663,6 +663,8 @@
f->f_op = NULL;
if (inode->i_op)
f->f_op = inode->i_op->default_file_ops;
+ if (inode->i_sb)
+ file_move(f, &inode->i_sb->s_files);
if (f->f_op && f->f_op->open) {
error = f->f_op->open(inode,f);
if (error)
@@ -790,7 +792,7 @@
int retval;
struct dentry *dentry = filp->f_dentry;

- if (filp->f_count == 0) {
+ if (atomic_read(&filp->f_count) == 0) {
printk("VFS: Close: file count is 0\n");
return 0;
}
diff -urN linux-2.3.8-pre2/fs/proc/inode.c linux-bird.f_count/fs/proc/inode.c
--- linux-2.3.8-pre2/fs/proc/inode.c Mon Jun 21 13:39:45 1999
+++ linux-bird.f_count/fs/proc/inode.c Tue Jun 22 14:24:32 1999
@@ -87,13 +87,26 @@
}
}

+struct super_block *proc_super_blocks = NULL;
+
+static void proc_put_super(struct super_block *sb)
+{
+ struct super_block **p = &proc_super_blocks;
+ while (*p != sb) {
+ if (!*p) /* should never happen */
+ return;
+ p = (struct super_block **)&(*p)->u.generic_sbp;
+ }
+ *p = (struct super_block *)(*p)->u.generic.sbp;
+}
+
static struct super_operations proc_sops = {
proc_read_inode,
proc_write_inode,
proc_put_inode,
proc_delete_inode, /* delete_inode(struct inode *) */
NULL,
- NULL,
+ proc_put_super,
NULL,
proc_statfs,
NULL
@@ -323,6 +336,8 @@
if (!s->s_root)
goto out_no_root;
parse_options(data, &root_inode->i_uid, &root_inode->i_gid);
+ sb->generic_sbp = (void*) proc_super_blocks;
+ proc_super_blocks = sb;
unlock_super(s);
return s;

diff -urN linux-2.3.8-pre2/fs/proc/root.c linux-bird.f_count/fs/proc/root.c
--- linux-2.3.8-pre2/fs/proc/root.c Mon Jun 21 14:31:30 1999
+++ linux-bird.f_count/fs/proc/root.c Tue Jun 22 14:24:32 1999
@@ -366,23 +366,34 @@
static void proc_kill_inodes(int ino)
{
struct file *filp;
+ struct super_block *sb;

- /* inuse_filps is protected by the single kernel lock */
- for (filp = inuse_filps; filp; filp = filp->f_next) {
- struct dentry * dentry;
- struct inode * inode;
+ /*
+ * Actually it's a partial revoke(). We have to go through all
+ * copies of procfs. proc_super_blocks is protected by the big
+ * lock for the time being.
+ */
+ for (sb = proc_super_blocks;
+ sb;
+ sb = (struct super_block*)sb->u.generic_sbp) {
+ spin_lock(&sb->s_files.fl_lock);
+ for (filp = sb->s_files.fl_list; filp; filp = filp->f_next) {
+ struct dentry * dentry;
+ struct inode * inode;

- dentry = filp->f_dentry;
- if (!dentry)
- continue;
- if (dentry->d_op != &proc_dentry_operations)
- continue;
- inode = dentry->d_inode;
- if (!inode)
- continue;
- if (inode->i_ino != ino)
- continue;
- filp->f_op = NULL;
+ dentry = filp->f_dentry;
+ if (!dentry)
+ continue;
+ if (dentry->d_op != &proc_dentry_operations)
+ continue;
+ inode = dentry->d_inode;
+ if (!inode)
+ continue;
+ if (inode->i_ino != ino)
+ continue;
+ filp->f_op = NULL;
+ }
+ spin_unlock(&sb->s_files.fl_lock);
}
}

diff -urN linux-2.3.8-pre2/fs/select.c linux-bird.f_count/fs/select.c
--- linux-2.3.8-pre2/fs/select.c Mon Jun 21 13:12:24 1999
+++ linux-bird.f_count/fs/select.c Tue Jun 22 14:24:32 1999
@@ -65,8 +65,8 @@
struct poll_table_entry * entry;
ok_table:
entry = p->entry + p->nr;
+ atomic_inc(&filp->f_count);
entry->filp = filp;
- filp->f_count++;
entry->wait_address = wait_address;
init_waitqueue_entry(&entry->wait, current);
add_wait_queue(wait_address,&entry->wait);
diff -urN linux-2.3.8-pre2/fs/super.c linux-bird.f_count/fs/super.c
--- linux-2.3.8-pre2/fs/super.c Mon Jun 21 14:12:10 1999
+++ linux-bird.f_count/fs/super.c Tue Jun 22 14:24:32 1999
@@ -531,6 +531,8 @@
INIT_LIST_HEAD(&s->s_dirty);
list_add (&s->s_list, super_blocks.prev);
init_waitqueue_head(&s->s_wait);
+ spin_lock_init(&s->files->fl_lock);
+ s->files->fl_list = NULL;
}
return s;
}
diff -urN linux-2.3.8-pre2/include/linux/file.h linux-bird.f_count/include/linux/file.h
--- linux-2.3.8-pre2/include/linux/file.h Mon Jun 21 13:40:25 1999
+++ linux-bird.f_count/include/linux/file.h Tue Jun 22 14:24:32 1999
@@ -32,12 +32,13 @@
return file;
}

+/* Still needs a protection against modifications of current->files->fd[] */
extern inline struct file * fget(unsigned int fd)
{
struct file * file = fcheck(fd);

if (file)
- file->f_count++;
+ atomic_inc(&file->f_count);
return file;
}

diff -urN linux-2.3.8-pre2/include/linux/fs.h linux-bird.f_count/include/linux/fs.h
--- linux-2.3.8-pre2/include/linux/fs.h Mon Jun 21 14:36:57 1999
+++ linux-bird.f_count/include/linux/fs.h Tue Jun 22 14:24:32 1999
@@ -234,13 +234,30 @@
typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate);
void init_buffer(struct buffer_head *, kdev_t, int, bh_end_io_t *, void *);

-#define __buffer_state(bh, state) (((bh)->b_state & (1UL << BH_##state)) != 0)
+static inline int buffer_uptodate(struct buffer_head * bh)
+{
+ return test_bit(BH_Uptodate, &bh->b_state);
+}
+
+static inline int buffer_dirty(struct buffer_head * bh)
+{
+ return test_bit(BH_Dirty, &bh->b_state);
+}

-#define buffer_uptodate(bh) __buffer_state(bh,Uptodate)
-#define buffer_dirty(bh) __buffer_state(bh,Dirty)
-#define buffer_locked(bh) __buffer_state(bh,Lock)
-#define buffer_req(bh) __buffer_state(bh,Req)
-#define buffer_protected(bh) __buffer_state(bh,Protected)
+static inline int buffer_locked(struct buffer_head * bh)
+{
+ return test_bit(BH_Lock, &bh->b_state);
+}
+
+static inline int buffer_req(struct buffer_head * bh)
+{
+ return test_bit(BH_Req, &bh->b_state);
+}
+
+static inline int buffer_protected(struct buffer_head * bh)
+{
+ return test_bit(BH_Protected, &bh->b_state);
+}

#define buffer_page(bh) (mem_map + MAP_NR((bh)->b_data))
#define touch_buffer(bh) set_bit(PG_referenced, &buffer_page(bh)->flags)
@@ -345,6 +362,7 @@
struct file_lock *i_flock;
struct vm_area_struct *i_mmap;
struct page *i_pages;
+ spinlock_t i_shared_lock;
struct dquot *i_dquot[MAXQUOTAS];
struct pipe_inode_info *i_pipe;

@@ -353,7 +371,7 @@
unsigned int i_flags;
unsigned char i_sock;

- int i_writecount;
+ atomic_t i_writecount;
unsigned int i_attr_flags;
__u32 i_generation;
union {
@@ -404,7 +422,8 @@
struct file_operations *f_op;
mode_t f_mode;
loff_t f_pos;
- unsigned int f_count, f_flags;
+ atomic_t f_count;
+ unsigned int f_flags;
unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;
struct fown_struct f_owner;
unsigned int f_uid, f_gid;
@@ -414,6 +433,7 @@

/* needed for tty driver, and maybe others */
void *private_data;
+ struct file_list *f_list; /* pointer back to the list */
};

extern int init_private_file(struct file *, struct dentry *, int);
@@ -481,6 +501,11 @@

extern int fasync_helper(int, struct file *, int, struct fasync_struct **);

+struct file_list {
+ struct file * fl_list;
+ spinlock_t fl_lock;
+};
+
#include <linux/minix_fs_sb.h>
#include <linux/ext2_fs_sb.h>
#include <linux/hpfs_fs_sb.h>
@@ -522,6 +547,7 @@
short int s_ibasket_count;
short int s_ibasket_max;
struct list_head s_dirty; /* dirty inodes */
+ struct file_list s_files;

union {
struct minix_sb_info minix_sb;
@@ -731,8 +757,6 @@
extern struct file_operations write_pipe_fops;
extern struct file_operations rdwr_pipe_fops;

-extern struct file_system_type *get_fs_type(const char *);
-
extern int fs_may_remount_ro(struct super_block *);
extern int fs_may_mount(kdev_t);

@@ -846,6 +870,7 @@
extern void insert_inode_hash(struct inode *);
extern void remove_inode_hash(struct inode *);
extern struct file * get_empty_filp(void);
+extern void file_move(struct file *f, struct file_list *list);
extern struct buffer_head * get_hash_table(kdev_t, int, int);
extern struct buffer_head * getblk(kdev_t, int, int);
extern struct buffer_head * find_buffer(kdev_t, int, int);
diff -urN linux-2.3.8-pre2/include/linux/proc_fs.h linux-bird.f_count/include/linux/proc_fs.h
--- linux-2.3.8-pre2/include/linux/proc_fs.h Mon Jun 21 14:27:29 1999
+++ linux-bird.f_count/include/linux/proc_fs.h Tue Jun 22 14:24:32 1999
@@ -374,6 +374,7 @@
}
}

+extern struct super_block *proc_super_blocks;
extern struct dentry_operations proc_dentry_operations;
extern struct super_block *proc_read_super(struct super_block *,void *,int);
extern int init_proc_fs(void);
diff -urN linux-2.3.8-pre2/include/linux/tty.h linux-bird.f_count/include/linux/tty.h
--- linux-2.3.8-pre2/include/linux/tty.h Mon Jun 21 12:40:29 1999
+++ linux-bird.f_count/include/linux/tty.h Tue Jun 22 14:24:32 1999
@@ -277,6 +277,7 @@
struct tq_struct tq_hangup;
void *disc_data;
void *driver_data;
+ struct file_list tty_files;

#define N_TTY_BUF_SIZE 4096

diff -urN linux-2.3.8-pre2/ipc/shm.c linux-bird.f_count/ipc/shm.c
--- linux-2.3.8-pre2/ipc/shm.c Mon Jun 21 13:50:07 1999
+++ linux-bird.f_count/ipc/shm.c Tue Jun 22 14:24:32 1999
@@ -547,6 +547,7 @@
unsigned int id;
struct shmid_kernel *shp;

+ lock_kernel();
id = SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK;
shp = shm_segs[id];
if (shp == IPC_UNUSED) {
@@ -557,6 +558,7 @@
shp->u.shm_nattch++;
shp->u.shm_atime = CURRENT_TIME;
shp->u.shm_lpid = current->pid;
+ unlock_kernel();
}

/*
@@ -570,6 +572,7 @@
struct shmid_kernel *shp;
int id;

+ lock_kernel();
/* remove from the list of attaches of the shm segment */
id = SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK;
shp = shm_segs[id];
@@ -578,6 +581,7 @@
shp->u.shm_dtime = CURRENT_TIME;
if (--shp->u.shm_nattch <= 0 && shp->u.shm_perm.mode & SHM_DEST)
killseg (id);
+ unlock_kernel();
}

/*
diff -urN linux-2.3.8-pre2/kernel/acct.c linux-bird.f_count/kernel/acct.c
--- linux-2.3.8-pre2/kernel/acct.c Mon Jun 21 14:18:12 1999
+++ linux-bird.f_count/kernel/acct.c Tue Jun 22 14:24:32 1999
@@ -276,7 +276,7 @@
*/
if (!file)
return 0;
- file->f_count++;
+ atomic_inc(&file->f_count);
if (!check_free_space(file)) {
fput(file);
return 0;
diff -urN linux-2.3.8-pre2/kernel/exit.c linux-bird.f_count/kernel/exit.c
--- linux-2.3.8-pre2/kernel/exit.c Mon Jun 21 12:40:36 1999
+++ linux-bird.f_count/kernel/exit.c Tue Jun 22 14:24:32 1999
@@ -166,11 +166,9 @@
break;
while (set) {
if (set & 1) {
- struct file * file = files->fd[i];
- if (file) {
- files->fd[i] = NULL;
+ struct file * file = xchg(&files->fd[i], NULL);
+ if (file)
filp_close(file, files);
- }
}
i++;
set >>= 1;
diff -urN linux-2.3.8-pre2/kernel/fork.c linux-bird.f_count/kernel/fork.c
--- linux-2.3.8-pre2/kernel/fork.c Mon Jun 21 13:18:00 1999
+++ linux-bird.f_count/kernel/fork.c Tue Jun 22 14:24:32 1999
@@ -243,22 +243,28 @@
if (!tmp)
goto fail_nomem;
*tmp = *mpnt;
+ /*
+ * Accurate here. We need to be sure that nothing will
+ * alter mpnt->vm_file before we increment f_count.
+ */
tmp->vm_flags &= ~VM_LOCKED;
tmp->vm_mm = mm;
mm->map_count++;
tmp->vm_next = NULL;
file = tmp->vm_file;
if (file) {
- file->f_count++;
+ atomic_inc(&file->f_count);
if (tmp->vm_flags & VM_DENYWRITE)
- file->f_dentry->d_inode->i_writecount--;
+ atomic_dec(&file->f_dentry->d_inode->i_writecount);

+ spin_lock(&file->f_dentry->d_inode->i_shared_lock);
/* insert tmp into the share list, just after mpnt */
if((tmp->vm_next_share = mpnt->vm_next_share) != NULL)
mpnt->vm_next_share->vm_pprev_share =
&tmp->vm_next_share;
mpnt->vm_next_share = tmp;
tmp->vm_pprev_share = &mpnt->vm_next_share;
+ spin_unlock(&file->f_dentry->d_inode->i_shared_lock);
}

/* Copy the pages, but defer checking for errors */
@@ -483,9 +489,9 @@
old_fds = oldf->fd;
for (; i != 0; i--) {
struct file *f = *old_fds++;
- *new_fds = f;
if (f)
- f->f_count++;
+ atomic_inc(&f->f_count);
+ *new_fds = f;
new_fds++;
}
/* This is long word aligned thus could use a optimized version */
diff -urN linux-2.3.8-pre2/mm/filemap.c linux-bird.f_count/mm/filemap.c
--- linux-2.3.8-pre2/mm/filemap.c Tue Jun 22 09:06:09 1999
+++ linux-bird.f_count/mm/filemap.c Tue Jun 22 14:26:04 1999
@@ -1473,7 +1473,7 @@
* If a task terminates while we're swapping the page, the vma and
* and file could be released ... increment the count to be safe.
*/
- file->f_count++;
+ atomic_inc(&file->f_count);
result = do_write_page(inode, file, (const char *) page, offset);
fput(file);
return result;
diff -urN linux-2.3.8-pre2/mm/memory.c linux-bird.f_count/mm/memory.c
--- linux-2.3.8-pre2/mm/memory.c Mon Jun 21 13:50:10 1999
+++ linux-bird.f_count/mm/memory.c Tue Jun 22 14:24:32 1999
@@ -723,8 +723,9 @@
struct vm_area_struct * mpnt;

truncate_inode_pages(inode, offset);
+ spin_lock(&inode->i_shared_lock);
if (!inode->i_mmap)
- return;
+ goto out_unlock;
mpnt = inode->i_mmap;
do {
struct mm_struct *mm = mpnt->vm_mm;
@@ -755,6 +756,8 @@
zap_page_range(mm, start, len);
flush_tlb_range(mm, start, end);
} while ((mpnt = mpnt->vm_next_share) != NULL);
+out_unlock:
+ spin_unlock(&inode->i_shared_lock);
}


diff -urN linux-2.3.8-pre2/mm/mlock.c linux-bird.f_count/mm/mlock.c
--- linux-2.3.8-pre2/mm/mlock.c Mon Jun 21 13:09:09 1999
+++ linux-bird.f_count/mm/mlock.c Tue Jun 22 14:24:32 1999
@@ -31,7 +31,7 @@
vma->vm_offset += vma->vm_start - n->vm_start;
n->vm_flags = newflags;
if (n->vm_file)
- n->vm_file->f_count++;
+ atomic_inc(&n->vm_file->f_count);
if (n->vm_ops && n->vm_ops->open)
n->vm_ops->open(n);
insert_vm_struct(current->mm, n);
@@ -52,7 +52,7 @@
n->vm_offset += n->vm_start - vma->vm_start;
n->vm_flags = newflags;
if (n->vm_file)
- n->vm_file->f_count++;
+ atomic_inc(&n->vm_file->f_count);
if (n->vm_ops && n->vm_ops->open)
n->vm_ops->open(n);
insert_vm_struct(current->mm, n);
@@ -82,7 +82,7 @@
right->vm_offset += right->vm_start - left->vm_start;
vma->vm_flags = newflags;
if (vma->vm_file)
- vma->vm_file->f_count += 2;
+ atomic_add(2, &vma->vm_file->f_count);

if (vma->vm_ops && vma->vm_ops->open) {
vma->vm_ops->open(left);
@@ -179,7 +179,6 @@
int error = -ENOMEM;

down(&current->mm->mmap_sem);
- lock_kernel();
len = (len + (start & ~PAGE_MASK) + ~PAGE_MASK) & PAGE_MASK;
start &= PAGE_MASK;

@@ -200,7 +199,6 @@

error = do_mlock(start, len, 1);
out:
- unlock_kernel();
up(&current->mm->mmap_sem);
return error;
}
@@ -210,11 +208,9 @@
int ret;

down(&current->mm->mmap_sem);
- lock_kernel();
len = (len + (start & ~PAGE_MASK) + ~PAGE_MASK) & PAGE_MASK;
start &= PAGE_MASK;
ret = do_mlock(start, len, 0);
- unlock_kernel();
up(&current->mm->mmap_sem);
return ret;
}
@@ -254,7 +250,6 @@
int ret = -EINVAL;

down(&current->mm->mmap_sem);
- lock_kernel();
if (!flags || (flags & ~(MCL_CURRENT | MCL_FUTURE)))
goto out;

@@ -272,7 +267,6 @@

ret = do_mlockall(flags);
out:
- unlock_kernel();
up(&current->mm->mmap_sem);
return ret;
}
@@ -282,9 +276,7 @@
int ret;

down(&current->mm->mmap_sem);
- lock_kernel();
ret = do_mlockall(0);
- unlock_kernel();
up(&current->mm->mmap_sem);
return ret;
}
diff -urN linux-2.3.8-pre2/mm/mmap.c linux-bird.f_count/mm/mmap.c
--- linux-2.3.8-pre2/mm/mmap.c Mon Jun 21 13:50:10 1999
+++ linux-bird.f_count/mm/mmap.c Tue Jun 22 14:24:32 1999
@@ -77,10 +77,12 @@

if (file) {
if (vma->vm_flags & VM_DENYWRITE)
- file->f_dentry->d_inode->i_writecount++;
+ atomic_inc(&file->f_dentry->d_inode->i_writecount);
+ spin_lock(&file->f_dentry->d_inode->i_shared_lock);
if(vma->vm_next_share)
vma->vm_next_share->vm_pprev_share = vma->vm_pprev_share;
*vma->vm_pprev_share = vma->vm_next_share;
+ spin_unlock(&file->f_dentry->d_inode->i_shared_lock);
}
}

@@ -294,7 +296,12 @@
if (file) {
int correct_wcount = 0;
if (vma->vm_flags & VM_DENYWRITE) {
- if (file->f_dentry->d_inode->i_writecount > 0) {
+ /*
+ * WARNING: when we will take it out of the big lock
+ * we will need a spinlock here. See comments in
+ * fs/namei.c::get_write_access()
+ */
+ if (atomic_read(&file->f_dentry->d_inode->i_writecount) > 0) {
error = -ETXTBSY;
goto free_vma;
}
@@ -303,17 +310,17 @@
* might). In any case, this takes care of any
* race that this might cause.
*/
- file->f_dentry->d_inode->i_writecount--;
+ atomic_dec(&file->f_dentry->d_inode->i_writecount);
correct_wcount = 1;
}
error = file->f_op->mmap(file, vma);
/* Fix up the count if necessary, then check for an error */
if (correct_wcount)
- file->f_dentry->d_inode->i_writecount++;
+ atomic_inc(&file->f_dentry->d_inode->i_writecount);
if (error)
goto unmap_and_free_vma;
+ atomic_inc(&file->f_count);
vma->vm_file = file;
- file->f_count++;
}

/*
@@ -547,7 +554,7 @@
mpnt->vm_file = area->vm_file;
mpnt->vm_pte = area->vm_pte;
if (mpnt->vm_file)
- mpnt->vm_file->f_count++;
+ atomic_inc(&mpnt->vm_file->f_count);
if (mpnt->vm_ops && mpnt->vm_ops->open)
mpnt->vm_ops->open(mpnt);
area->vm_end = addr; /* Truncate area */
@@ -875,13 +882,14 @@
if (file) {
struct inode * inode = file->f_dentry->d_inode;
if (vmp->vm_flags & VM_DENYWRITE)
- inode->i_writecount--;
-
+ atomic_dec(&inode->i_writecount);
+ spin_lock(&inode->i_shared_lock);
/* insert vmp into inode's share list */
if((vmp->vm_next_share = inode->i_mmap) != NULL)
inode->i_mmap->vm_pprev_share = &vmp->vm_next_share;
inode->i_mmap = vmp;
vmp->vm_pprev_share = &inode->i_mmap;
+ spin_unlock(&inode->i_shared_lock);
}
}

@@ -948,7 +956,7 @@
mm->map_count--;
remove_shared_vm_struct(mpnt);
if (mpnt->vm_file)
- fput(mpnt->vm_file);
+ fput(mpnt->vm_file); /* This one is safe */
kmem_cache_free(vm_area_cachep, mpnt);
mpnt = prev;
}
diff -urN linux-2.3.8-pre2/mm/mprotect.c linux-bird.f_count/mm/mprotect.c
--- linux-2.3.8-pre2/mm/mprotect.c Mon Jun 21 12:37:03 1999
+++ linux-bird.f_count/mm/mprotect.c Tue Jun 22 14:24:32 1999
@@ -103,7 +103,7 @@
n->vm_flags = newflags;
n->vm_page_prot = prot;
if (n->vm_file)
- n->vm_file->f_count++;
+ atomic_inc(&n->vm_file->f_count);
if (n->vm_ops && n->vm_ops->open)
n->vm_ops->open(n);
insert_vm_struct(current->mm, n);
@@ -126,7 +126,7 @@
n->vm_flags = newflags;
n->vm_page_prot = prot;
if (n->vm_file)
- n->vm_file->f_count++;
+ atomic_inc(&n->vm_file->f_count);
if (n->vm_ops && n->vm_ops->open)
n->vm_ops->open(n);
insert_vm_struct(current->mm, n);
@@ -158,7 +158,7 @@
vma->vm_flags = newflags;
vma->vm_page_prot = prot;
if (vma->vm_file)
- vma->vm_file->f_count += 2;
+ atomic_add(2,&vma->vm_file->f_count);
if (vma->vm_ops && vma->vm_ops->open) {
vma->vm_ops->open(left);
vma->vm_ops->open(right);
@@ -212,7 +212,6 @@
return 0;

down(&current->mm->mmap_sem);
- lock_kernel();

vma = find_vma(current->mm, start);
error = -EFAULT;
@@ -249,7 +248,6 @@
}
merge_segments(current->mm, start, end);
out:
- unlock_kernel();
up(&current->mm->mmap_sem);
return error;
}
diff -urN linux-2.3.8-pre2/mm/mremap.c linux-bird.f_count/mm/mremap.c
--- linux-2.3.8-pre2/mm/mremap.c Mon Jun 21 13:36:06 1999
+++ linux-bird.f_count/mm/mremap.c Tue Jun 22 14:24:32 1999
@@ -134,14 +134,12 @@
new_vma->vm_start = new_addr;
new_vma->vm_end = new_addr+new_len;
new_vma->vm_offset = vma->vm_offset + (addr - vma->vm_start);
- lock_kernel();
if (new_vma->vm_file)
- new_vma->vm_file->f_count++;
+ atomic_inc(&new_vma->vm_file->f_count);
if (new_vma->vm_ops && new_vma->vm_ops->open)
new_vma->vm_ops->open(new_vma);
insert_vm_struct(current->mm, new_vma);
merge_segments(current->mm, new_vma->vm_start, new_vma->vm_end);
- unlock_kernel();
do_munmap(addr, old_len);
current->mm->total_vm += new_len >> PAGE_SHIFT;
if (new_vma->vm_flags & VM_LOCKED) {
diff -urN linux-2.3.8-pre2/net/core/scm.c linux-bird.f_count/net/core/scm.c
--- linux-2.3.8-pre2/net/core/scm.c Mon Jun 21 12:37:05 1999
+++ linux-bird.f_count/net/core/scm.c Tue Jun 22 14:24:32 1999
@@ -232,8 +232,8 @@
break;
}
/* Bump the usage count and install the file. */
- fp[i]->f_count++;
- current->files->fd[new_fd] = fp[i];
+ atomic_inc(&fp[i]->f_count);
+ fd_install(new_fd, fp[i]);
}

if (i > 0)
@@ -271,10 +271,9 @@

new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL);
if (new_fpl) {
- memcpy(new_fpl, fpl, sizeof(*fpl));
-
for (i=fpl->count-1; i>=0; i--)
- fpl->fp[i]->f_count++;
+ atomic_inc(&fpl->fp[i]->f_count);
+ memcpy(new_fpl, fpl, sizeof(*fpl));
}
return new_fpl;
}
diff -urN linux-2.3.8-pre2/net/socket.c linux-bird.f_count/net/socket.c
--- linux-2.3.8-pre2/net/socket.c Mon Jun 21 13:40:46 1999
+++ linux-bird.f_count/net/socket.c Tue Jun 22 14:24:32 1999
@@ -217,11 +217,11 @@
*/
inode->i_count++;

- fd_install(fd, file);
file->f_op = &socket_file_ops;
file->f_mode = 3;
file->f_flags = O_RDWR;
file->f_pos = 0;
+ fd_install(fd, file);
}
return fd;
}
diff -urN linux-2.3.8-pre2/net/sunrpc/xprt.c linux-bird.f_count/net/sunrpc/xprt.c
--- linux-2.3.8-pre2/net/sunrpc/xprt.c Mon Jun 21 13:41:07 1999
+++ linux-bird.f_count/net/sunrpc/xprt.c Tue Jun 22 14:24:32 1999
@@ -1455,8 +1455,8 @@

proto = (sock->type == SOCK_DGRAM)? IPPROTO_UDP : IPPROTO_TCP;
if ((xprt = xprt_setup(sock, proto, ap, to)) != NULL) {
+ atomic_inc(&file->f_count);
xprt->file = file;
- file->f_count++;
}

return xprt;
diff -urN linux-2.3.8-pre2/net/unix/garbage.c linux-bird.f_count/net/unix/garbage.c
--- linux-2.3.8-pre2/net/unix/garbage.c Mon Jun 21 12:37:10 1999
+++ linux-bird.f_count/net/unix/garbage.c Tue Jun 22 14:24:32 1999
@@ -199,7 +199,8 @@
* in flight we are in use.
*/
if(s->socket && s->socket->file &&
- s->socket->file->f_count > s->protinfo.af_unix.inflight)
+ atomic_read(&s->socket->file->f_count) >
+ s->protinfo.af_unix.inflight)
maybe_unmark_and_push(s);
}
\
 
 \ /
  Last update: 2005-03-22 13:52    [W:0.294 / U:0.712 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site