2 * Copyright (C) 2005-2013 Junjiro R. Okajima
4 * This program, aufs is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * workqueue for asynchronous/super-io operations
21 * todo: try new dredential scheme
24 #include <linux/module.h>
27 /* internal workqueue named AUFS_WKQ_NAME */
29 static struct workqueue_struct *au_wkq;
32 struct work_struct wk;
35 unsigned int flags; /* see wkq.h */
40 struct completion *comp;
43 /* ---------------------------------------------------------------------- */
45 static void wkq_func(struct work_struct *wk)
47 struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
49 AuDebugOn(current_fsuid());
50 AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
52 wkinfo->func(wkinfo->args);
53 if (au_ftest_wkq(wkinfo->flags, WAIT))
54 complete(wkinfo->comp);
56 kobject_put(wkinfo->kobj);
57 module_put(THIS_MODULE); /* todo: ?? */
63 * Since struct completion is large, try allocating it dynamically.
65 #if 1 /* defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS) */
66 #define AuWkqCompDeclare(name) struct completion *comp = NULL
68 static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
70 *comp = kmalloc(sizeof(**comp), GFP_NOFS);
72 init_completion(*comp);
79 static void au_wkq_comp_free(struct completion *comp)
87 #define AuWkqCompDeclare(name) \
88 DECLARE_COMPLETION_ONSTACK(_ ## name); \
89 struct completion *comp = &_ ## name
91 static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
97 static void au_wkq_comp_free(struct completion *comp __maybe_unused)
101 #endif /* 4KSTACKS */
103 static void au_wkq_run(struct au_wkinfo *wkinfo)
105 if (au_ftest_wkq(wkinfo->flags, NEST)) {
107 AuWarn1("wkq from wkq, due to a dead dir by UDBA?\n");
108 AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT));
111 au_dbg_verify_kthread();
113 if (au_ftest_wkq(wkinfo->flags, WAIT)) {
114 INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
115 queue_work(au_wkq, &wkinfo->wk);
117 INIT_WORK(&wkinfo->wk, wkq_func);
118 schedule_work(&wkinfo->wk);
123 * Be careful. It is easy to make deadlock happen.
124 * processA: lock, wkq and wait
125 * processB: wkq and wait, lock in wkq
128 int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
131 AuWkqCompDeclare(comp);
132 struct au_wkinfo wkinfo = {
138 err = au_wkq_comp_alloc(&wkinfo, &comp);
141 /* no timeout, no interrupt */
142 wait_for_completion(wkinfo.comp);
143 au_wkq_comp_free(comp);
144 destroy_work_on_stack(&wkinfo.wk);
152 * Note: dget/dput() in func for aufs dentries are not supported. It will be a
153 * problem in a concurrent umounting.
155 int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
159 struct au_wkinfo *wkinfo;
161 atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
164 * wkq_func() must free this wkinfo.
165 * it highly depends upon the implementation of workqueue.
168 wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
170 wkinfo->kobj = &au_sbi(sb)->si_kobj;
171 wkinfo->flags = flags & ~AuWkq_WAIT;
175 kobject_get(wkinfo->kobj);
176 __module_get(THIS_MODULE); /* todo: ?? */
181 au_nwt_done(&au_sbi(sb)->si_nowait);
187 /* ---------------------------------------------------------------------- */
189 void au_nwt_init(struct au_nowait_tasks *nwt)
191 atomic_set(&nwt->nw_len, 0);
192 /* smp_mb(); */ /* atomic_set */
193 init_waitqueue_head(&nwt->nw_wq);
196 void au_wkq_fin(void)
198 destroy_workqueue(au_wkq);
201 int __init au_wkq_init(void)
206 BUILD_BUG_ON(!WQ_RESCUER);
207 au_wkq = alloc_workqueue(AUFS_WKQ_NAME, !WQ_RESCUER, WQ_DFL_ACTIVE);
209 err = PTR_ERR(au_wkq);