Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit badf1662 authored by Dipankar Sarma's avatar Dipankar Sarma Committed by Linus Torvalds
Browse files

[PATCH] files: break up files struct



In order for the RCU to work, the file table array, sets and their sizes must
be updated atomically.  Instead of ensuring this through too many memory
barriers, we put the arrays and their sizes in a separate structure.  This
patch takes the first step of putting the file table elements in a separate
structure fdtable that is embedded withing files_struct.  It also changes all
the users to refer to the file table using files_fdtable() macro.  Subsequent
applciation of RCU becomes easier after this.

Signed-off-by: default avatarDipankar Sarma <dipankar@in.ibm.com>
Signed-Off-By: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent c0dfb290
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -974,6 +974,7 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
	size_t size;
	size_t size;
	long timeout;
	long timeout;
	int ret = -EINVAL;
	int ret = -EINVAL;
	struct fdtable *fdt;


	timeout = MAX_SCHEDULE_TIMEOUT;
	timeout = MAX_SCHEDULE_TIMEOUT;
	if (tvp) {
	if (tvp) {
@@ -995,7 +996,8 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
		}
		}
	}
	}


	if (n < 0 || n > current->files->max_fdset)
	fdt = files_fdtable(current->files);
	if (n < 0 || n > fdt->max_fdset)
		goto out_nofds;
		goto out_nofds;


	/*
	/*
+5 −2
Original line number Original line Diff line number Diff line
@@ -38,6 +38,7 @@
#include <linux/pagemap.h>
#include <linux/pagemap.h>
#include <linux/mount.h>
#include <linux/mount.h>
#include <linux/bitops.h>
#include <linux/bitops.h>
#include <linux/rcupdate.h>


#include <asm/errno.h>
#include <asm/errno.h>
#include <asm/intrinsics.h>
#include <asm/intrinsics.h>
@@ -2217,15 +2218,17 @@ static void
pfm_free_fd(int fd, struct file *file)
pfm_free_fd(int fd, struct file *file)
{
{
	struct files_struct *files = current->files;
	struct files_struct *files = current->files;
	struct fdtable *fdt = files_fdtable(files);


	/* 
	/* 
	 * there ie no fd_uninstall(), so we do it here
	 * there ie no fd_uninstall(), so we do it here
	 */
	 */
	spin_lock(&files->file_lock);
	spin_lock(&files->file_lock);
        files->fd[fd] = NULL;
	rcu_assign_pointer(fdt->fd[fd], NULL);
	spin_unlock(&files->file_lock);
	spin_unlock(&files->file_lock);


	if (file) put_filp(file);
	if (file)
		put_filp(file);
	put_unused_fd(fd);
	put_unused_fd(fd);
}
}


+5 −3
Original line number Original line Diff line number Diff line
@@ -293,11 +293,13 @@ static struct module_info {
static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
{
{
	struct inode *ino;
	struct inode *ino;
	struct fdtable *fdt;
	/* I wonder which of these tests are superfluous... --patrik */
	/* I wonder which of these tests are superfluous... --patrik */
	spin_lock(&current->files->file_lock);
	spin_lock(&current->files->file_lock);
	if (! current->files->fd[fd] ||
	fdt = files_fdtable(current->files);
	    ! current->files->fd[fd]->f_dentry ||
	if (! fdt->fd[fd] ||
	    ! (ino = current->files->fd[fd]->f_dentry->d_inode) ||
	    ! fdt->fd[fd]->f_dentry ||
	    ! (ino = fdt->fd[fd]->f_dentry->d_inode) ||
	    ! S_ISSOCK(ino->i_mode)) {
	    ! S_ISSOCK(ino->i_mode)) {
		spin_unlock(&current->files->file_lock);
		spin_unlock(&current->files->file_lock);
		return TBADF;
		return TBADF;
+3 −1
Original line number Original line Diff line number Diff line
@@ -2454,6 +2454,7 @@ static void __do_SAK(void *arg)
	int		i;
	int		i;
	struct file	*filp;
	struct file	*filp;
	struct tty_ldisc *disc;
	struct tty_ldisc *disc;
	struct fdtable *fdt;
	
	
	if (!tty)
	if (!tty)
		return;
		return;
@@ -2480,7 +2481,8 @@ static void __do_SAK(void *arg)
		task_lock(p);
		task_lock(p);
		if (p->files) {
		if (p->files) {
			spin_lock(&p->files->file_lock);
			spin_lock(&p->files->file_lock);
			for (i=0; i < p->files->max_fds; i++) {
			fdt = files_fdtable(p->files);
			for (i=0; i < fdt->max_fds; i++) {
				filp = fcheck_files(p->files, i);
				filp = fcheck_files(p->files, i);
				if (!filp)
				if (!filp)
					continue;
					continue;
+5 −3
Original line number Original line Diff line number Diff line
@@ -798,6 +798,7 @@ no_thread_group:
static inline void flush_old_files(struct files_struct * files)
static inline void flush_old_files(struct files_struct * files)
{
{
	long j = -1;
	long j = -1;
	struct fdtable *fdt;


	spin_lock(&files->file_lock);
	spin_lock(&files->file_lock);
	for (;;) {
	for (;;) {
@@ -805,12 +806,13 @@ static inline void flush_old_files(struct files_struct * files)


		j++;
		j++;
		i = j * __NFDBITS;
		i = j * __NFDBITS;
		if (i >= files->max_fds || i >= files->max_fdset)
		fdt = files_fdtable(files);
		if (i >= fdt->max_fds || i >= fdt->max_fdset)
			break;
			break;
		set = files->close_on_exec->fds_bits[j];
		set = fdt->close_on_exec->fds_bits[j];
		if (!set)
		if (!set)
			continue;
			continue;
		files->close_on_exec->fds_bits[j] = 0;
		fdt->close_on_exec->fds_bits[j] = 0;
		spin_unlock(&files->file_lock);
		spin_unlock(&files->file_lock);
		for ( ; set ; i++,set >>= 1) {
		for ( ; set ; i++,set >>= 1) {
			if (set & 1) {
			if (set & 1) {
Loading