wkq.h 1.78 KB
Newer Older
J. R. Okajima's avatar
J. R. Okajima committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2005-2019 Junjiro R. Okajima
 */

/*
 * workqueue for asynchronous/super-io operations
 * todo: try new credentials management scheme
 */

#ifndef __AUFS_WKQ_H__
#define __AUFS_WKQ_H__

#ifdef __KERNEL__

#include <linux/wait.h>

struct super_block;

/* ---------------------------------------------------------------------- */

/*
 * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
 */
struct au_nowait_tasks {
	atomic_t		nw_len;
	wait_queue_head_t	nw_wq;
};

/* ---------------------------------------------------------------------- */

typedef void (*au_wkq_func_t)(void *args);

/* wkq flags */
#define AuWkq_WAIT	1
J. R. Okajima's avatar
J. R. Okajima committed
36
#define AuWkq_NEST	(1 << 1)
J. R. Okajima's avatar
J. R. Okajima committed
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#define au_ftest_wkq(flags, name)	((flags) & AuWkq_##name)
#define au_fset_wkq(flags, name) \
	do { (flags) |= AuWkq_##name; } while (0)
#define au_fclr_wkq(flags, name) \
	do { (flags) &= ~AuWkq_##name; } while (0)

/* wkq.c */
int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
		  unsigned int flags);
void au_nwt_init(struct au_nowait_tasks *nwt);
int __init au_wkq_init(void);
void au_wkq_fin(void);

/* ---------------------------------------------------------------------- */

static inline int au_wkq_test(void)
{
	return current->flags & PF_WQ_WORKER;
}

static inline int au_wkq_wait(au_wkq_func_t func, void *args)
{
	return au_wkq_do_wait(AuWkq_WAIT, func, args);
}

static inline void au_nwt_done(struct au_nowait_tasks *nwt)
{
	if (atomic_dec_and_test(&nwt->nw_len))
		wake_up_all(&nwt->nw_wq);
}

static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
{
	wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
	return 0;
}

#endif /* __KERNEL__ */
#endif /* __AUFS_WKQ_H__ */