]>
Commit | Line | Data |
---|---|---|
e14748e8 SF |
1 | /* |
2 | * Copyright (C) 2005-2016 Junjiro R. Okajima | |
3 | * | |
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. | |
8 | * | |
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. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | */ | |
17 | ||
18 | /* | |
19 | * module initialization and module-global | |
20 | */ | |
21 | ||
22 | #ifndef __AUFS_MODULE_H__ | |
23 | #define __AUFS_MODULE_H__ | |
24 | ||
25 | #ifdef __KERNEL__ | |
26 | ||
27 | #include <linux/slab.h> | |
28 | #include "debug.h" | |
29 | ||
30 | struct path; | |
31 | struct seq_file; | |
32 | ||
33 | /* module parameters */ | |
34 | extern int sysaufs_brs; | |
35 | extern bool au_userns; | |
36 | ||
37 | /* ---------------------------------------------------------------------- */ | |
38 | ||
39 | extern int au_dir_roflags; | |
40 | ||
41 | void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink); | |
42 | void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp, | |
43 | int may_shrink); | |
44 | ||
45 | static inline int au_kmidx_sub(size_t sz, size_t new_sz) | |
46 | { | |
47 | #ifndef CONFIG_SLOB | |
48 | return kmalloc_index(sz) - kmalloc_index(new_sz); | |
49 | #else | |
50 | return -1; /* SLOB is untested */ | |
51 | #endif | |
52 | } | |
53 | ||
54 | int au_seq_path(struct seq_file *seq, struct path *path); | |
55 | ||
56 | #ifdef CONFIG_PROC_FS | |
57 | /* procfs.c */ | |
58 | int __init au_procfs_init(void); | |
59 | void au_procfs_fin(void); | |
60 | #else | |
61 | AuStubInt0(au_procfs_init, void); | |
62 | AuStubVoid(au_procfs_fin, void); | |
63 | #endif | |
64 | ||
65 | /* ---------------------------------------------------------------------- */ | |
66 | ||
67 | /* kmem cache and delayed free */ | |
68 | enum { | |
69 | AuCache_DINFO, | |
70 | AuCache_ICNTNR, | |
71 | AuCache_FINFO, | |
72 | AuCache_VDIR, | |
73 | AuCache_DEHSTR, | |
74 | AuCache_HNOTIFY, /* must be last */ | |
75 | AuCache_Last | |
76 | }; | |
77 | ||
78 | enum { | |
79 | AU_DFREE_KFREE, | |
80 | AU_DFREE_FREE_PAGE, | |
81 | AU_DFREE_Last | |
82 | }; | |
83 | ||
84 | struct au_cache { | |
85 | struct kmem_cache *cache; | |
86 | struct llist_head llist; /* delayed free */ | |
87 | }; | |
88 | ||
89 | /* | |
90 | * in order to reduce the cost of the internal timer, consolidate all the | |
91 | * delayed free works into a single delayed_work. | |
92 | */ | |
93 | struct au_dfree { | |
94 | struct au_cache cache[AuCache_Last]; | |
95 | struct llist_head llist[AU_DFREE_Last]; | |
96 | struct delayed_work dwork; | |
97 | }; | |
98 | ||
99 | extern struct au_dfree au_dfree; | |
100 | ||
101 | #define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD) | |
102 | #define AuCache(type) KMEM_CACHE(type, AuCacheFlags) | |
103 | #define AuCacheCtor(type, ctor) \ | |
104 | kmem_cache_create(#type, sizeof(struct type), \ | |
105 | __alignof__(struct type), AuCacheFlags, ctor) | |
106 | ||
107 | #define AU_DFREE_DELAY msecs_to_jiffies(10) | |
108 | #define AU_DFREE_BODY(lnode, llist) do { \ | |
109 | if (llist_add(lnode, llist)) \ | |
110 | schedule_delayed_work(&au_dfree.dwork, \ | |
111 | AU_DFREE_DELAY); \ | |
112 | } while (0) | |
113 | #define AU_CACHE_DFREE_FUNC(name, idx, lnode) \ | |
114 | void au_cache_dfree_##name(struct au_##name *p) \ | |
115 | { \ | |
116 | struct au_cache *cp = au_dfree.cache + AuCache_##idx; \ | |
117 | AU_DFREE_BODY(&p->lnode, &cp->llist); \ | |
118 | } | |
119 | ||
120 | #define AuCacheFuncs(name, index) \ | |
121 | static inline struct au_##name *au_cache_alloc_##name(void) \ | |
122 | { return kmem_cache_alloc(au_dfree.cache[AuCache_##index].cache, GFP_NOFS); } \ | |
123 | static inline void au_cache_free_##name(struct au_##name *p) \ | |
124 | { kmem_cache_free(au_dfree.cache[AuCache_##index].cache, p); } \ | |
125 | void au_cache_dfree_##name(struct au_##name *p) | |
126 | ||
127 | AuCacheFuncs(dinfo, DINFO); | |
128 | AuCacheFuncs(icntnr, ICNTNR); | |
129 | AuCacheFuncs(finfo, FINFO); | |
130 | AuCacheFuncs(vdir, VDIR); | |
131 | AuCacheFuncs(vdir_dehstr, DEHSTR); | |
132 | #ifdef CONFIG_AUFS_HNOTIFY | |
133 | AuCacheFuncs(hnotify, HNOTIFY); | |
134 | #endif | |
135 | ||
136 | static inline void au_delayed_kfree(const void *p) | |
137 | { | |
138 | AuDebugOn(!p); | |
139 | AuDebugOn(ksize(p) < sizeof(struct llist_node)); | |
140 | ||
141 | AU_DFREE_BODY((void *)p, au_dfree.llist + AU_DFREE_KFREE); | |
142 | } | |
143 | ||
144 | /* cast only */ | |
145 | static inline void au_free_page(void *p) | |
146 | { | |
147 | free_page((unsigned long)p); | |
148 | } | |
149 | ||
150 | static inline void au_delayed_free_page(unsigned long addr) | |
151 | { | |
152 | AU_DFREE_BODY((void *)addr, au_dfree.llist + AU_DFREE_FREE_PAGE); | |
153 | } | |
154 | ||
155 | #endif /* __KERNEL__ */ | |
156 | #endif /* __AUFS_MODULE_H__ */ |