20
20
* workqueue for asynchronous/super-io/delegated operations
22
* $Id: wkq.c,v 1.6 2008/06/02 02:35:50 sfjro Exp $
22
* $Id: wkq.c,v 1.10 2008/07/14 00:17:48 sfjro Exp $
25
25
#include <linux/module.h>
198
#if defined(CONFIG_4KSTACKS) || defined(Test4KSTACKS)
199
#define AuWkqCompDeclare(name) struct completion *comp = NULL
201
static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
203
*comp = kmalloc(sizeof(**comp), GFP_NOFS);
205
init_completion(*comp);
206
wkinfo->comp = *comp;
212
static void au_wkq_comp_free(struct completion *comp)
219
#define AuWkqCompDeclare(name) \
220
DECLARE_COMPLETION_ONSTACK(_ ## name); \
221
struct completion *comp = &_ ## name
223
static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
225
wkinfo->comp = *comp;
229
static void au_wkq_comp_free(struct completion *comp)
233
#endif /* 4KSTACKS */
198
235
int au_wkq_run(au_wkq_func_t func, void *args, struct super_block *sb,
199
236
unsigned int flags)
202
DECLARE_COMPLETION_ONSTACK(comp);
239
AuWkqCompDeclare(comp);
203
240
struct au_wkinfo _wkinfo = {
208
244
}, *wkinfo = &_wkinfo;
245
const unsigned char do_wait = au_ftest_wkq(flags, WAIT);
210
247
LKTRTrace("0x%x\n", flags);
211
/* in dlgt mode, inotify will be fired from aufsd */
212
AuDebugOn(au_ftest_wkq(flags, DLGT) && au_test_wkq(current));
248
#if 1 /* tmp debug */
249
if (au_test_wkq(current))
252
AuDebugOn(au_test_wkq(current));
215
do_wait = au_ftest_wkq(flags, WAIT);
216
if (unlikely(!do_wait)) {
255
err = au_wkq_comp_alloc(wkinfo, &comp);
219
261
* wkq_func() must free this wkinfo.
220
262
* it highly depends upon the implementation of workqueue.
223
wkinfo = kmalloc(sizeof(*wkinfo), GFP_TEMPORARY);
265
wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
224
266
if (unlikely(!wkinfo))
237
279
INIT_WORK(&wkinfo->wk, wkq_func);
238
280
dlgt_cred_store(flags, wkinfo);
241
283
/* no timeout, no interrupt */
242
284
wait_for_completion(wkinfo->comp);
285
au_wkq_comp_free(comp);
269
313
/* '+1' is for accounting of nowait queue */
271
au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_KERNEL);
315
au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_NOFS);
272
316
if (unlikely(!au_wkq))
277
321
au_wkq[i].q = create_singlethread_workqueue(AUFS_WKQ_NAME);
278
322
if (au_wkq[i].q && !IS_ERR(au_wkq[i].q)) {
279
323
atomic_set(&au_wkq[i].busy, 0);
280
au_wkq[i].max_busy = 0;
324
au_wkq_max_busy_init(au_wkq + i);
289
333
/* nowait accounting */
290
334
nowaitq = au_wkq + aufs_nwkq;
291
335
atomic_set(&nowaitq->busy, 0);
292
nowaitq->max_busy = 0;
336
au_wkq_max_busy_init(nowaitq);
293
337
nowaitq->q = NULL;
294
338
/* smp_mb(); */ /* atomic_set */