aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-08-07 07:35:19 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2014-08-07 14:40:08 -0400
commit17c0a5aaffa63da6b5c73a31e36616bdcd12d143 (patch)
tree5dfe2d6eaf41ee01aad44eaad06766dc67c74545 /kernel
parent0aec09d049d7e994eba54bad4376dd8f58eab797 (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.c20
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
97static void acct_free_rcu(struct rcu_head *head) 99static void acct_free_rcu(struct rcu_head *head)
@@ -176,15 +178,27 @@ again:
176 return res; 178 return res;
177} 179}
178 180
181static 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
179static void acct_kill(struct bsd_acct_struct *acct, 192static 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);