diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2014-08-07 07:35:19 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-08-07 14:40:08 -0400 |
| commit | 17c0a5aaffa63da6b5c73a31e36616bdcd12d143 (patch) | |
| tree | 5dfe2d6eaf41ee01aad44eaad06766dc67c74545 /kernel | |
| parent | 0aec09d049d7e994eba54bad4376dd8f58eab797 (diff) | |
make acct_kill() wait for file closing.
Do actual closing of file via schedule_work(). And use
__fput_sync() there.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/acct.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/kernel/acct.c b/kernel/acct.c index 6fd375f15626..d9ebc96b1126 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
| @@ -92,6 +92,8 @@ struct bsd_acct_struct { | |||
| 92 | unsigned long needcheck; | 92 | unsigned long needcheck; |
| 93 | struct file *file; | 93 | struct file *file; |
| 94 | struct pid_namespace *ns; | 94 | struct pid_namespace *ns; |
| 95 | struct work_struct work; | ||
| 96 | struct completion done; | ||
| 95 | }; | 97 | }; |
| 96 | 98 | ||
| 97 | static void acct_free_rcu(struct rcu_head *head) | 99 | static void acct_free_rcu(struct rcu_head *head) |
| @@ -176,15 +178,27 @@ again: | |||
| 176 | return res; | 178 | return res; |
| 177 | } | 179 | } |
| 178 | 180 | ||
| 181 | static void close_work(struct work_struct *work) | ||
| 182 | { | ||
| 183 | struct bsd_acct_struct *acct = container_of(work, struct bsd_acct_struct, work); | ||
| 184 | struct file *file = acct->file; | ||
| 185 | mnt_unpin(file->f_path.mnt); | ||
| 186 | if (file->f_op->flush) | ||
| 187 | file->f_op->flush(file, NULL); | ||
| 188 | __fput_sync(file); | ||
| 189 | complete(&acct->done); | ||
| 190 | } | ||
| 191 | |||
| 179 | static void acct_kill(struct bsd_acct_struct *acct, | 192 | static void acct_kill(struct bsd_acct_struct *acct, |
| 180 | struct bsd_acct_struct *new) | 193 | struct bsd_acct_struct *new) |
| 181 | { | 194 | { |
| 182 | if (acct) { | 195 | if (acct) { |
| 183 | struct file *file = acct->file; | ||
| 184 | struct pid_namespace *ns = acct->ns; | 196 | struct pid_namespace *ns = acct->ns; |
| 185 | do_acct_process(acct); | 197 | do_acct_process(acct); |
| 186 | mnt_unpin(file->f_path.mnt); | 198 | INIT_WORK(&acct->work, close_work); |
| 187 | filp_close(file, NULL); | 199 | init_completion(&acct->done); |
| 200 | schedule_work(&acct->work); | ||
| 201 | wait_for_completion(&acct->done); | ||
| 188 | spin_lock(&acct_lock); | 202 | spin_lock(&acct_lock); |
| 189 | hlist_del(&acct->m_list); | 203 | hlist_del(&acct->m_list); |
| 190 | hlist_del(&acct->s_list); | 204 | hlist_del(&acct->s_list); |
