Commit 6a6d27de authored by Al Viro's avatar Al Viro

take close-on-exec logics to fs/file.c, clean it up a bit

... and add cond_resched() there, while we are at it.  We can
get large latencies as is...
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 723a1d77
...@@ -1006,40 +1006,6 @@ static int de_thread(struct task_struct *tsk) ...@@ -1006,40 +1006,6 @@ static int de_thread(struct task_struct *tsk)
return 0; return 0;
} }
/*
* These functions flushes out all traces of the currently running executable
* so that a new one can be started
*/
static 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 * BITS_PER_LONG;
fdt = files_fdtable(files);
if (i >= fdt->max_fds)
break;
set = fdt->close_on_exec[j];
if (!set)
continue;
fdt->close_on_exec[j] = 0;
spin_unlock(&files->file_lock);
for ( ; set ; i++,set >>= 1) {
if (set & 1) {
sys_close(i);
}
}
spin_lock(&files->file_lock);
}
spin_unlock(&files->file_lock);
}
char *get_task_comm(char *buf, struct task_struct *tsk) char *get_task_comm(char *buf, struct task_struct *tsk)
{ {
/* buf must be at least sizeof(tsk->comm) in size */ /* buf must be at least sizeof(tsk->comm) in size */
...@@ -1050,6 +1016,11 @@ char *get_task_comm(char *buf, struct task_struct *tsk) ...@@ -1050,6 +1016,11 @@ char *get_task_comm(char *buf, struct task_struct *tsk)
} }
EXPORT_SYMBOL_GPL(get_task_comm); EXPORT_SYMBOL_GPL(get_task_comm);
/*
* These functions flushes out all traces of the currently running executable
* so that a new one can be started
*/
void set_task_comm(struct task_struct *tsk, char *buf) void set_task_comm(struct task_struct *tsk, char *buf)
{ {
task_lock(tsk); task_lock(tsk);
...@@ -1171,7 +1142,7 @@ void setup_new_exec(struct linux_binprm * bprm) ...@@ -1171,7 +1142,7 @@ void setup_new_exec(struct linux_binprm * bprm)
current->self_exec_id++; current->self_exec_id++;
flush_signal_handlers(current, 0); flush_signal_handlers(current, 0);
flush_old_files(current->files); do_close_on_exec(current->files);
} }
EXPORT_SYMBOL(setup_new_exec); EXPORT_SYMBOL(setup_new_exec);
......
...@@ -652,6 +652,43 @@ int __close_fd(struct files_struct *files, unsigned fd) ...@@ -652,6 +652,43 @@ int __close_fd(struct files_struct *files, unsigned fd)
return -EBADF; return -EBADF;
} }
void do_close_on_exec(struct files_struct *files)
{
unsigned i;
struct fdtable *fdt;
/* exec unshares first */
BUG_ON(atomic_read(&files->count) != 1);
spin_lock(&files->file_lock);
for (i = 0; ; i++) {
unsigned long set;
unsigned fd = i * BITS_PER_LONG;
fdt = files_fdtable(files);
if (fd >= fdt->max_fds)
break;
set = fdt->close_on_exec[i];
if (!set)
continue;
fdt->close_on_exec[i] = 0;
for ( ; set ; fd++, set >>= 1) {
struct file *file;
if (!(set & 1))
continue;
file = fdt->fd[fd];
if (!file)
continue;
rcu_assign_pointer(fdt->fd[fd], NULL);
__put_unused_fd(files, fd);
spin_unlock(&files->file_lock);
filp_close(file, files);
cond_resched();
spin_lock(&files->file_lock);
}
}
spin_unlock(&files->file_lock);
}
struct file *fget(unsigned int fd) struct file *fget(unsigned int fd)
{ {
struct file *file; struct file *file;
......
...@@ -118,6 +118,7 @@ void put_files_struct(struct files_struct *fs); ...@@ -118,6 +118,7 @@ void put_files_struct(struct files_struct *fs);
void reset_files_struct(struct files_struct *); void reset_files_struct(struct files_struct *);
int unshare_files(struct files_struct **); int unshare_files(struct files_struct **);
struct files_struct *dup_fd(struct files_struct *, int *); struct files_struct *dup_fd(struct files_struct *, int *);
void do_close_on_exec(struct files_struct *);
extern int __alloc_fd(struct files_struct *files, extern int __alloc_fd(struct files_struct *files,
unsigned start, unsigned end, unsigned flags); unsigned start, unsigned end, unsigned flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment