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

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

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
Loading
Loading
Loading
Loading
+6 −35
Original line number Diff line number Diff line
@@ -1006,40 +1006,6 @@ static int de_thread(struct task_struct *tsk)
	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)
{
	/* 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);

/*
 * 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)
{
	task_lock(tsk);
@@ -1171,7 +1142,7 @@ void setup_new_exec(struct linux_binprm * bprm)
	current->self_exec_id++;
			
	flush_signal_handlers(current, 0);
	flush_old_files(current->files);
	do_close_on_exec(current->files);
}
EXPORT_SYMBOL(setup_new_exec);

+37 −0
Original line number Diff line number Diff line
@@ -652,6 +652,43 @@ int __close_fd(struct files_struct *files, unsigned fd)
	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 *file;
+1 −0
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@ void put_files_struct(struct files_struct *fs);
void reset_files_struct(struct files_struct *);
int unshare_files(struct files_struct **);
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,
		      unsigned start, unsigned end, unsigned flags);