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: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
723a1d7743
commit
6a6d27de34
3 changed files with 44 additions and 35 deletions
41
fs/exec.c
41
fs/exec.c
|
@ -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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
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);
|
||||||
|
|
||||||
|
|
37
fs/file.c
37
fs/file.c
|
@ -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);
|
||||||
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);
|
||||||
|
|
Loading…
Reference in a new issue