]>
git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - fs/aufs/dynop.c
2 * Copyright (C) 2010-2017 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, see <http://www.gnu.org/licenses/>.
19 * dynamically customizable operations for regular files
24 #define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
27 * How large will these lists be?
28 * Usually just a few elements, 20-30 at most for each, I guess.
30 static struct au_sphlhead dynop
[AuDyLast
];
32 static struct au_dykey
*dy_gfind_get(struct au_sphlhead
*sphl
, const void *h_op
)
34 struct au_dykey
*key
, *tmp
;
35 struct hlist_head
*head
;
40 hlist_for_each_entry_rcu(tmp
, head
, dk_hnode
)
41 if (tmp
->dk_op
.dy_hop
== h_op
) {
43 kref_get(&key
->dk_kref
);
51 static struct au_dykey
*dy_bradd(struct au_branch
*br
, struct au_dykey
*key
)
53 struct au_dykey
**k
, *found
;
54 const void *h_op
= key
->dk_op
.dy_hop
;
59 for (i
= 0; i
< AuBrDynOp
; i
++)
61 if (k
[i
]->dk_op
.dy_hop
== h_op
) {
68 spin_lock(&br
->br_dykey_lock
);
69 for (; i
< AuBrDynOp
; i
++)
71 if (k
[i
]->dk_op
.dy_hop
== h_op
) {
79 spin_unlock(&br
->br_dykey_lock
);
80 BUG_ON(i
== AuBrDynOp
); /* expand the array */
86 /* kref_get() if @key is already added */
87 static struct au_dykey
*dy_gadd(struct au_sphlhead
*sphl
, struct au_dykey
*key
)
89 struct au_dykey
*tmp
, *found
;
90 struct hlist_head
*head
;
91 const void *h_op
= key
->dk_op
.dy_hop
;
95 spin_lock(&sphl
->spin
);
96 hlist_for_each_entry(tmp
, head
, dk_hnode
)
97 if (tmp
->dk_op
.dy_hop
== h_op
) {
98 kref_get(&tmp
->dk_kref
);
103 hlist_add_head_rcu(&key
->dk_hnode
, head
);
104 spin_unlock(&sphl
->spin
);
111 static void dy_free_rcu(struct rcu_head
*rcu
)
113 struct au_dykey
*key
;
115 key
= container_of(rcu
, struct au_dykey
, dk_rcu
);
120 static void dy_free(struct kref
*kref
)
122 struct au_dykey
*key
;
123 struct au_sphlhead
*sphl
;
125 key
= container_of(kref
, struct au_dykey
, dk_kref
);
126 sphl
= dynop
+ key
->dk_op
.dy_type
;
127 au_sphl_del_rcu(&key
->dk_hnode
, sphl
);
128 call_rcu(&key
->dk_rcu
, dy_free_rcu
);
131 void au_dy_put(struct au_dykey
*key
)
133 kref_put(&key
->dk_kref
, dy_free
);
136 /* ---------------------------------------------------------------------- */
138 #define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
140 #ifdef CONFIG_AUFS_DEBUG
141 #define DyDbgDeclare(cnt) unsigned int cnt = 0
142 #define DyDbgInc(cnt) do { cnt++; } while (0)
144 #define DyDbgDeclare(cnt) do {} while (0)
145 #define DyDbgInc(cnt) do {} while (0)
148 #define DySet(func, dst, src, h_op, h_sb) do { \
152 dst.func = src.func; \
154 AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
158 #define DySetForce(func, dst, src) do { \
159 AuDebugOn(!src.func); \
161 dst.func = src.func; \
164 #define DySetAop(func) \
165 DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
166 #define DySetAopForce(func) \
167 DySetForce(func, dyaop->da_op, aufs_aop)
169 static void dy_aop(struct au_dykey
*key
, const void *h_op
,
170 struct super_block
*h_sb __maybe_unused
)
172 struct au_dyaop
*dyaop
= (void *)key
;
173 const struct address_space_operations
*h_aop
= h_op
;
176 AuDbg("%s\n", au_sbtype(h_sb
));
179 DySetAopForce(readpage
); /* force */
180 DySetAop(writepages
);
181 DySetAop(set_page_dirty
);
183 DySetAop(write_begin
);
186 DySetAop(invalidatepage
);
187 DySetAop(releasepage
);
189 /* this one will be changed according to an aufs mount option */
191 DySetAop(migratepage
);
192 DySetAop(isolate_page
);
193 DySetAop(putback_page
);
194 DySetAop(launder_page
);
195 DySetAop(is_partially_uptodate
);
196 DySetAop(is_dirty_writeback
);
197 DySetAop(error_remove_page
);
198 DySetAop(swap_activate
);
199 DySetAop(swap_deactivate
);
201 DyDbgSize(cnt
, *h_aop
);
204 /* ---------------------------------------------------------------------- */
206 static void dy_bug(struct kref
*kref
)
211 static struct au_dykey
*dy_get(struct au_dynop
*op
, struct au_branch
*br
)
213 struct au_dykey
*key
, *old
;
214 struct au_sphlhead
*sphl
;
217 void (*set
)(struct au_dykey
*key
, const void *h_op
,
218 struct super_block
*h_sb __maybe_unused
);
220 static const struct op a
[] = {
222 .sz
= sizeof(struct au_dyaop
),
228 sphl
= dynop
+ op
->dy_type
;
229 key
= dy_gfind_get(sphl
, op
->dy_hop
);
231 goto out_add
; /* success */
234 key
= kzalloc(p
->sz
, GFP_NOFS
);
235 if (unlikely(!key
)) {
236 key
= ERR_PTR(-ENOMEM
);
240 key
->dk_op
.dy_hop
= op
->dy_hop
;
241 kref_init(&key
->dk_kref
);
242 p
->set(key
, op
->dy_hop
, au_br_sb(br
));
243 old
= dy_gadd(sphl
, key
);
250 old
= dy_bradd(br
, key
);
252 /* its ref-count should never be zero here */
253 kref_put(&key
->dk_kref
, dy_bug
);
258 /* ---------------------------------------------------------------------- */
260 * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
261 * This behaviour is necessary to return an error from open(O_DIRECT) instead
262 * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
263 * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
264 * See the aufs manual in detail.
266 static void dy_adx(struct au_dyaop
*dyaop
, int do_dx
)
269 dyaop
->da_op
.direct_IO
= NULL
;
271 dyaop
->da_op
.direct_IO
= aufs_aop
.direct_IO
;
274 static struct au_dyaop
*dy_aget(struct au_branch
*br
,
275 const struct address_space_operations
*h_aop
,
278 struct au_dyaop
*dyaop
;
281 op
.dy_type
= AuDy_AOP
;
283 dyaop
= (void *)dy_get(&op
, br
);
286 dy_adx(dyaop
, do_dx
);
292 int au_dy_iaop(struct inode
*inode
, aufs_bindex_t bindex
,
293 struct inode
*h_inode
)
296 struct super_block
*sb
;
297 struct au_branch
*br
;
298 struct au_dyaop
*dyaop
;
300 AuDebugOn(!S_ISREG(h_inode
->i_mode
));
301 IiMustWriteLock(inode
);
304 br
= au_sbr(sb
, bindex
);
305 do_dx
= !!au_opt_test(au_mntflags(sb
), DIO
);
306 dyaop
= dy_aget(br
, h_inode
->i_mapping
->a_ops
, do_dx
);
307 err
= PTR_ERR(dyaop
);
309 /* unnecessary to call dy_fput() */
313 inode
->i_mapping
->a_ops
= &dyaop
->da_op
;
320 * Is it safe to replace a_ops during the inode/file is in operation?
323 int au_dy_irefresh(struct inode
*inode
)
327 struct inode
*h_inode
;
330 if (S_ISREG(inode
->i_mode
)) {
331 btop
= au_ibtop(inode
);
332 h_inode
= au_h_iptr(inode
, btop
);
333 err
= au_dy_iaop(inode
, btop
, h_inode
);
338 void au_dy_arefresh(int do_dx
)
340 struct au_sphlhead
*sphl
;
341 struct hlist_head
*head
;
342 struct au_dykey
*key
;
344 sphl
= dynop
+ AuDy_AOP
;
346 spin_lock(&sphl
->spin
);
347 hlist_for_each_entry(key
, head
, dk_hnode
)
348 dy_adx((void *)key
, do_dx
);
349 spin_unlock(&sphl
->spin
);
352 /* ---------------------------------------------------------------------- */
354 void __init
au_dy_init(void)
358 /* make sure that 'struct au_dykey *' can be any type */
359 BUILD_BUG_ON(offsetof(struct au_dyaop
, da_key
));
361 for (i
= 0; i
< AuDyLast
; i
++)
362 au_sphl_init(dynop
+ i
);
369 for (i
= 0; i
< AuDyLast
; i
++)
370 WARN_ON(!hlist_empty(&dynop
[i
].head
));