Commit 17c0a5aaffa63da6b5c73a31e36616bdcd12d143

Authored by Al Viro
1 parent 0aec09d049

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>

Showing 1 changed file with 17 additions and 3 deletions Side-by-side Diff

... ... @@ -92,6 +92,8 @@
92 92 unsigned long needcheck;
93 93 struct file *file;
94 94 struct pid_namespace *ns;
  95 + struct work_struct work;
  96 + struct completion done;
95 97 };
96 98  
97 99 static void acct_free_rcu(struct rcu_head *head)
98 100  
99 101  
... ... @@ -176,15 +178,27 @@
176 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 192 static void acct_kill(struct bsd_acct_struct *acct,
180 193 struct bsd_acct_struct *new)
181 194 {
182 195 if (acct) {
183   - struct file *file = acct->file;
184 196 struct pid_namespace *ns = acct->ns;
185 197 do_acct_process(acct);
186   - mnt_unpin(file->f_path.mnt);
187   - filp_close(file, NULL);
  198 + INIT_WORK(&acct->work, close_work);
  199 + init_completion(&acct->done);
  200 + schedule_work(&acct->work);
  201 + wait_for_completion(&acct->done);
188 202 spin_lock(&acct_lock);
189 203 hlist_del(&acct->m_list);
190 204 hlist_del(&acct->s_list);