diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-08-21 09:56:33 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-26 21:09:56 -0400 |
commit | 6a6d27de340c89c5323565b49f7851362619925d (patch) | |
tree | b9b4ab23b43bd330584521917c9b2855c4a4e0cd | |
parent | 723a1d77431b0c568730ffac4dd0bcbbd3400031 (diff) |
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>
-rw-r--r-- | fs/exec.c | 41 | ||||
-rw-r--r-- | fs/file.c | 37 | ||||
-rw-r--r-- | include/linux/fdtable.h | 1 |
3 files changed, 44 insertions, 35 deletions
@@ -1006,40 +1006,6 @@ no_thread_group: | |||
1006 | return 0; | 1006 | return 0; |
1007 | } | 1007 | } |
1008 | 1008 | ||
1009 | /* | ||
1010 | * These functions flushes out all traces of the currently running executable | ||
1011 | * so that a new one can be started | ||
1012 | */ | ||
1013 | static void flush_old_files(struct files_struct * files) | ||
1014 | { | ||
1015 | long j = -1; | ||
1016 | struct fdtable *fdt; | ||
1017 | |||
1018 | spin_lock(&files->file_lock); | ||
1019 | for (;;) { | ||
1020 | unsigned long set, i; | ||
1021 | |||
1022 | j++; | ||
1023 | i = j * BITS_PER_LONG; | ||
1024 | fdt = files_fdtable(files); | ||
1025 | if (i >= fdt->max_fds) | ||
1026 | break; | ||
1027 | set = fdt->close_on_exec[j]; | ||
1028 | if (!set) | ||
1029 | continue; | ||
1030 | fdt->close_on_exec[j] = 0; | ||
1031 | spin_unlock(&files->file_lock); | ||
1032 | for ( ; set ; i++,set >>= 1) { | ||
1033 | if (set & 1) { | ||
1034 | sys_close(i); | ||
1035 | } | ||
1036 | } | ||
1037 | spin_lock(&files->file_lock); | ||
1038 | |||
1039 | } | ||
1040 | spin_unlock(&files->file_lock); | ||
1041 | } | ||
1042 | |||
1043 | char *get_task_comm(char *buf, struct task_struct *tsk) | 1009 | char *get_task_comm(char *buf, struct task_struct *tsk) |
1044 | { | 1010 | { |
1045 | /* buf must be at least sizeof(tsk->comm) in size */ | 1011 | /* 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 | } | 1016 | } |
1051 | EXPORT_SYMBOL_GPL(get_task_comm); | 1017 | EXPORT_SYMBOL_GPL(get_task_comm); |
1052 | 1018 | ||
1019 | /* | ||
1020 | * These functions flushes out all traces of the currently running executable | ||
1021 | * so that a new one can be started | ||
1022 | */ | ||
1023 | |||
1053 | void set_task_comm(struct task_struct *tsk, char *buf) | 1024 | void set_task_comm(struct task_struct *tsk, char *buf) |
1054 | { | 1025 | { |
1055 | task_lock(tsk); | 1026 | task_lock(tsk); |
@@ -1171,7 +1142,7 @@ void setup_new_exec(struct linux_binprm * bprm) | |||
1171 | current->self_exec_id++; | 1142 | current->self_exec_id++; |
1172 | 1143 | ||
1173 | flush_signal_handlers(current, 0); | 1144 | flush_signal_handlers(current, 0); |
1174 | flush_old_files(current->files); | 1145 | do_close_on_exec(current->files); |
1175 | } | 1146 | } |
1176 | EXPORT_SYMBOL(setup_new_exec); | 1147 | EXPORT_SYMBOL(setup_new_exec); |
1177 | 1148 | ||
@@ -652,6 +652,43 @@ out_unlock: | |||
652 | return -EBADF; | 652 | return -EBADF; |
653 | } | 653 | } |
654 | 654 | ||
655 | void do_close_on_exec(struct files_struct *files) | ||
656 | { | ||
657 | unsigned i; | ||
658 | struct fdtable *fdt; | ||
659 | |||
660 | /* exec unshares first */ | ||
661 | BUG_ON(atomic_read(&files->count) != 1); | ||
662 | spin_lock(&files->file_lock); | ||
663 | for (i = 0; ; i++) { | ||
664 | unsigned long set; | ||
665 | unsigned fd = i * BITS_PER_LONG; | ||
666 | fdt = files_fdtable(files); | ||
667 | if (fd >= fdt->max_fds) | ||
668 | break; | ||
669 | set = fdt->close_on_exec[i]; | ||
670 | if (!set) | ||
671 | continue; | ||
672 | fdt->close_on_exec[i] = 0; | ||
673 | for ( ; set ; fd++, set >>= 1) { | ||
674 | struct file *file; | ||
675 | if (!(set & 1)) | ||
676 | continue; | ||
677 | file = fdt->fd[fd]; | ||
678 | if (!file) | ||
679 | continue; | ||
680 | rcu_assign_pointer(fdt->fd[fd], NULL); | ||
681 | __put_unused_fd(files, fd); | ||
682 | spin_unlock(&files->file_lock); | ||
683 | filp_close(file, files); | ||
684 | cond_resched(); | ||
685 | spin_lock(&files->file_lock); | ||
686 | } | ||
687 | |||
688 | } | ||
689 | spin_unlock(&files->file_lock); | ||
690 | } | ||
691 | |||
655 | struct file *fget(unsigned int fd) | 692 | struct file *fget(unsigned int fd) |
656 | { | 693 | { |
657 | struct file *file; | 694 | struct file *file; |
diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h index 59488f2392bc..ef4b2137e6bc 100644 --- a/include/linux/fdtable.h +++ b/include/linux/fdtable.h | |||
@@ -118,6 +118,7 @@ void put_files_struct(struct files_struct *fs); | |||
118 | void reset_files_struct(struct files_struct *); | 118 | void reset_files_struct(struct files_struct *); |
119 | int unshare_files(struct files_struct **); | 119 | int unshare_files(struct files_struct **); |
120 | struct files_struct *dup_fd(struct files_struct *, int *); | 120 | struct files_struct *dup_fd(struct files_struct *, int *); |
121 | void do_close_on_exec(struct files_struct *); | ||
121 | 122 | ||
122 | extern int __alloc_fd(struct files_struct *files, | 123 | extern int __alloc_fd(struct files_struct *files, |
123 | unsigned start, unsigned end, unsigned flags); | 124 | unsigned start, unsigned end, unsigned flags); |