Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 8191
b: refs/heads/master
c: badf166
h: refs/heads/master
i:
  8189: dbd7a4e
  8187: 299b1f1
  8183: 6e833d6
  8175: 93059b3
  8159: ad005b4
  8127: 49379f9
  8063: 8a28a69
  7935: b221087
  7679: 424844c
  7167: 4561ccd
  6143: 9167c97
  4095: 39ad1ee
v: v3
  • Loading branch information
Dipankar Sarma authored and Linus Torvalds committed Sep 9, 2005
1 parent fded0de commit 08f97ba
Show file tree
Hide file tree
Showing 18 changed files with 212 additions and 125 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c0dfb2905126e9e94edebbce8d3e05001301f52d
refs/heads/master: badf16621c1f9d1ac753be056fce11b43d6e0be5
4 changes: 3 additions & 1 deletion trunk/arch/alpha/kernel/osf_sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,7 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
size_t size;
long timeout;
int ret = -EINVAL;
struct fdtable *fdt;

timeout = MAX_SCHEDULE_TIMEOUT;
if (tvp) {
Expand All @@ -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;

/*
Expand Down
7 changes: 5 additions & 2 deletions trunk/arch/ia64/kernel/perfmon.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <linux/pagemap.h>
#include <linux/mount.h>
#include <linux/bitops.h>
#include <linux/rcupdate.h>

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

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

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

Expand Down
8 changes: 5 additions & 3 deletions trunk/arch/sparc64/solaris/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,11 +293,13 @@ static struct module_info {
static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
{
struct inode *ino;
struct fdtable *fdt;
/* I wonder which of these tests are superfluous... --patrik */
spin_lock(&current->files->file_lock);
if (! current->files->fd[fd] ||
! current->files->fd[fd]->f_dentry ||
! (ino = current->files->fd[fd]->f_dentry->d_inode) ||
fdt = files_fdtable(current->files);
if (! fdt->fd[fd] ||
! fdt->fd[fd]->f_dentry ||
! (ino = fdt->fd[fd]->f_dentry->d_inode) ||
! S_ISSOCK(ino->i_mode)) {
spin_unlock(&current->files->file_lock);
return TBADF;
Expand Down
4 changes: 3 additions & 1 deletion trunk/drivers/char/tty_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -2454,6 +2454,7 @@ static void __do_SAK(void *arg)
int i;
struct file *filp;
struct tty_ldisc *disc;
struct fdtable *fdt;

if (!tty)
return;
Expand All @@ -2480,7 +2481,8 @@ static void __do_SAK(void *arg)
task_lock(p);
if (p->files) {
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);
if (!filp)
continue;
Expand Down
8 changes: 5 additions & 3 deletions trunk/fs/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -798,19 +798,21 @@ static inline int de_thread(struct task_struct *tsk)
static inline void flush_old_files(struct files_struct * files)
{
long j = -1;
struct fdtable *fdt;

spin_lock(&files->file_lock);
for (;;) {
unsigned long set, i;

j++;
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;
set = files->close_on_exec->fds_bits[j];
set = fdt->close_on_exec->fds_bits[j];
if (!set)
continue;
files->close_on_exec->fds_bits[j] = 0;
fdt->close_on_exec->fds_bits[j] = 0;
spin_unlock(&files->file_lock);
for ( ; set ; i++,set >>= 1) {
if (set & 1) {
Expand Down
47 changes: 29 additions & 18 deletions trunk/fs/fcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,24 @@
void fastcall set_close_on_exec(unsigned int fd, int flag)
{
struct files_struct *files = current->files;
struct fdtable *fdt;
spin_lock(&files->file_lock);
fdt = files_fdtable(files);
if (flag)
FD_SET(fd, files->close_on_exec);
FD_SET(fd, fdt->close_on_exec);
else
FD_CLR(fd, files->close_on_exec);
FD_CLR(fd, fdt->close_on_exec);
spin_unlock(&files->file_lock);
}

static inline int get_close_on_exec(unsigned int fd)
{
struct files_struct *files = current->files;
struct fdtable *fdt;
int res;
spin_lock(&files->file_lock);
res = FD_ISSET(fd, files->close_on_exec);
fdt = files_fdtable(files);
res = FD_ISSET(fd, fdt->close_on_exec);
spin_unlock(&files->file_lock);
return res;
}
Expand All @@ -54,24 +58,26 @@ static int locate_fd(struct files_struct *files,
unsigned int newfd;
unsigned int start;
int error;
struct fdtable *fdt;

error = -EINVAL;
if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
goto out;

fdt = files_fdtable(files);
repeat:
/*
* Someone might have closed fd's in the range
* orig_start..files->next_fd
* orig_start..fdt->next_fd
*/
start = orig_start;
if (start < files->next_fd)
start = files->next_fd;
if (start < fdt->next_fd)
start = fdt->next_fd;

newfd = start;
if (start < files->max_fdset) {
newfd = find_next_zero_bit(files->open_fds->fds_bits,
files->max_fdset, start);
if (start < fdt->max_fdset) {
newfd = find_next_zero_bit(fdt->open_fds->fds_bits,
fdt->max_fdset, start);
}

error = -EMFILE;
Expand All @@ -89,8 +95,8 @@ static int locate_fd(struct files_struct *files,
if (error)
goto repeat;

if (start <= files->next_fd)
files->next_fd = newfd + 1;
if (start <= fdt->next_fd)
fdt->next_fd = newfd + 1;

error = newfd;

Expand All @@ -101,13 +107,16 @@ static int locate_fd(struct files_struct *files,
static int dupfd(struct file *file, unsigned int start)
{
struct files_struct * files = current->files;
struct fdtable *fdt;
int fd;

spin_lock(&files->file_lock);
fd = locate_fd(files, file, start);
if (fd >= 0) {
FD_SET(fd, files->open_fds);
FD_CLR(fd, files->close_on_exec);
/* locate_fd() may have expanded fdtable, load the ptr */
fdt = files_fdtable(files);
FD_SET(fd, fdt->open_fds);
FD_CLR(fd, fdt->close_on_exec);
spin_unlock(&files->file_lock);
fd_install(fd, file);
} else {
Expand All @@ -123,6 +132,7 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
int err = -EBADF;
struct file * file, *tofree;
struct files_struct * files = current->files;
struct fdtable *fdt;

spin_lock(&files->file_lock);
if (!(file = fcheck(oldfd)))
Expand All @@ -148,13 +158,14 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)

/* Yes. It's a race. In user space. Nothing sane to do */
err = -EBUSY;
tofree = files->fd[newfd];
if (!tofree && FD_ISSET(newfd, files->open_fds))
fdt = files_fdtable(files);
tofree = fdt->fd[newfd];
if (!tofree && FD_ISSET(newfd, fdt->open_fds))
goto out_fput;

files->fd[newfd] = file;
FD_SET(newfd, files->open_fds);
FD_CLR(newfd, files->close_on_exec);
fdt->fd[newfd] = file;
FD_SET(newfd, fdt->open_fds);
FD_CLR(newfd, fdt->close_on_exec);
spin_unlock(&files->file_lock);

if (tofree)
Expand Down
42 changes: 25 additions & 17 deletions trunk/fs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,15 @@ static int expand_fd_array(struct files_struct *files, int nr)
{
struct file **new_fds;
int error, nfds;
struct fdtable *fdt;


error = -EMFILE;
if (files->max_fds >= NR_OPEN || nr >= NR_OPEN)
fdt = files_fdtable(files);
if (fdt->max_fds >= NR_OPEN || nr >= NR_OPEN)
goto out;

nfds = files->max_fds;
nfds = fdt->max_fds;
spin_unlock(&files->file_lock);

/*
Expand Down Expand Up @@ -95,13 +97,14 @@ static int expand_fd_array(struct files_struct *files, int nr)
goto out;

/* Copy the existing array and install the new pointer */
fdt = files_fdtable(files);

if (nfds > files->max_fds) {
if (nfds > fdt->max_fds) {
struct file **old_fds;
int i;

old_fds = xchg(&files->fd, new_fds);
i = xchg(&files->max_fds, nfds);
old_fds = xchg(&fdt->fd, new_fds);
i = xchg(&fdt->max_fds, nfds);

/* Don't copy/clear the array if we are creating a new
fd array for fork() */
Expand Down Expand Up @@ -164,12 +167,14 @@ static int expand_fdset(struct files_struct *files, int nr)
{
fd_set *new_openset = NULL, *new_execset = NULL;
int error, nfds = 0;
struct fdtable *fdt;

error = -EMFILE;
if (files->max_fdset >= NR_OPEN || nr >= NR_OPEN)
fdt = files_fdtable(files);
if (fdt->max_fdset >= NR_OPEN || nr >= NR_OPEN)
goto out;

nfds = files->max_fdset;
nfds = fdt->max_fdset;
spin_unlock(&files->file_lock);

/* Expand to the max in easy steps */
Expand All @@ -193,24 +198,25 @@ static int expand_fdset(struct files_struct *files, int nr)
error = 0;

/* Copy the existing tables and install the new pointers */
if (nfds > files->max_fdset) {
int i = files->max_fdset / (sizeof(unsigned long) * 8);
int count = (nfds - files->max_fdset) / 8;
fdt = files_fdtable(files);
if (nfds > fdt->max_fdset) {
int i = fdt->max_fdset / (sizeof(unsigned long) * 8);
int count = (nfds - fdt->max_fdset) / 8;

/*
* Don't copy the entire array if the current fdset is
* not yet initialised.
*/
if (i) {
memcpy (new_openset, files->open_fds, files->max_fdset/8);
memcpy (new_execset, files->close_on_exec, files->max_fdset/8);
memcpy (new_openset, fdt->open_fds, fdt->max_fdset/8);
memcpy (new_execset, fdt->close_on_exec, fdt->max_fdset/8);
memset (&new_openset->fds_bits[i], 0, count);
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);
nfds = xchg(&fdt->max_fdset, nfds);
new_openset = xchg(&fdt->open_fds, new_openset);
new_execset = xchg(&fdt->close_on_exec, new_execset);
spin_unlock(&files->file_lock);
free_fdset (new_openset, nfds);
free_fdset (new_execset, nfds);
Expand All @@ -237,13 +243,15 @@ static int expand_fdset(struct files_struct *files, int nr)
int expand_files(struct files_struct *files, int nr)
{
int err, expand = 0;
struct fdtable *fdt;

if (nr >= files->max_fdset) {
fdt = files_fdtable(files);
if (nr >= fdt->max_fdset) {
expand = 1;
if ((err = expand_fdset(files, nr)))
goto out;
}
if (nr >= files->max_fds) {
if (nr >= fdt->max_fds) {
expand = 1;
if ((err = expand_fd_array(files, nr)))
goto out;
Expand Down
8 changes: 5 additions & 3 deletions trunk/fs/locks.c
Original file line number Diff line number Diff line change
Expand Up @@ -2198,21 +2198,23 @@ void steal_locks(fl_owner_t from)
{
struct files_struct *files = current->files;
int i, j;
struct fdtable *fdt;

if (from == files)
return;

lock_kernel();
j = 0;
fdt = files_fdtable(files);
for (;;) {
unsigned long set;
i = j * __NFDBITS;
if (i >= files->max_fdset || i >= files->max_fds)
if (i >= fdt->max_fdset || i >= fdt->max_fds)
break;
set = files->open_fds->fds_bits[j++];
set = fdt->open_fds->fds_bits[j++];
while (set) {
if (set & 1) {
struct file *file = files->fd[i];
struct file *file = fdt->fd[i];
if (file)
__steal_locks(file, from);
}
Expand Down
Loading

0 comments on commit 08f97ba

Please sign in to comment.