]>
git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - fs/aufs/dcsub.c
2 * Copyright (C) 2005-2016 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 * sub-routines for dentry cache
24 static void au_dpage_free(struct au_dpage
*dpage
)
30 for (i
= 0; i
< dpage
->ndentry
; i
++)
32 au_delayed_free_page((unsigned long)dpage
->dentries
);
35 int au_dpages_init(struct au_dcsub_pages
*dpages
, gfp_t gfp
)
41 dpages
->dpages
= kmalloc(sizeof(*dpages
->dpages
), gfp
);
42 if (unlikely(!dpages
->dpages
))
45 p
= (void *)__get_free_page(gfp
);
49 dpages
->dpages
[0].ndentry
= 0;
50 dpages
->dpages
[0].dentries
= p
;
52 return 0; /* success */
55 au_delayed_kfree(dpages
->dpages
);
60 void au_dpages_free(struct au_dcsub_pages
*dpages
)
66 for (i
= 0; i
< dpages
->ndpage
; i
++)
68 au_delayed_kfree(dpages
->dpages
);
71 static int au_dpages_append(struct au_dcsub_pages
*dpages
,
72 struct dentry
*dentry
, gfp_t gfp
)
75 struct au_dpage
*dpage
;
78 dpage
= dpages
->dpages
+ dpages
->ndpage
- 1;
79 sz
= PAGE_SIZE
/ sizeof(dentry
);
80 if (unlikely(dpage
->ndentry
>= sz
)) {
83 sz
= dpages
->ndpage
* sizeof(*dpages
->dpages
);
84 p
= au_kzrealloc(dpages
->dpages
, sz
,
85 sz
+ sizeof(*dpages
->dpages
), gfp
,
91 dpage
= dpages
->dpages
+ dpages
->ndpage
;
92 p
= (void *)__get_free_page(gfp
);
101 AuDebugOn(au_dcount(dentry
) <= 0);
102 dpage
->dentries
[dpage
->ndentry
++] = dget_dlock(dentry
);
103 return 0; /* success */
109 /* todo: BAD approach */
110 /* copied from linux/fs/dcache.c */
118 extern void d_walk(struct dentry
*parent
, void *data
,
119 enum d_walk_ret (*enter
)(void *, struct dentry
*),
120 void (*finish
)(void *));
122 struct ac_dpages_arg
{
124 struct au_dcsub_pages
*dpages
;
125 struct super_block
*sb
;
130 static enum d_walk_ret
au_call_dpages_append(void *_arg
, struct dentry
*dentry
)
133 struct ac_dpages_arg
*arg
= _arg
;
135 ret
= D_WALK_CONTINUE
;
136 if (dentry
->d_sb
== arg
->sb
138 && au_dcount(dentry
) > 0
140 && (!arg
->test
|| arg
->test(dentry
, arg
->arg
))) {
141 arg
->err
= au_dpages_append(arg
->dpages
, dentry
, GFP_ATOMIC
);
142 if (unlikely(arg
->err
))
149 int au_dcsub_pages(struct au_dcsub_pages
*dpages
, struct dentry
*root
,
150 au_dpages_test test
, void *arg
)
152 struct ac_dpages_arg args
= {
160 d_walk(root
, &args
, au_call_dpages_append
, NULL
);
165 int au_dcsub_pages_rev(struct au_dcsub_pages
*dpages
, struct dentry
*dentry
,
166 int do_include
, au_dpages_test test
, void *arg
)
171 write_seqlock(&rename_lock
);
172 spin_lock(&dentry
->d_lock
);
174 && au_dcount(dentry
) > 0
175 && (!test
|| test(dentry
, arg
)))
176 err
= au_dpages_append(dpages
, dentry
, GFP_ATOMIC
);
177 spin_unlock(&dentry
->d_lock
);
182 * RCU for vfsmount is unnecessary since this is a traverse in a single
185 while (!IS_ROOT(dentry
)) {
186 dentry
= dentry
->d_parent
; /* rename_lock is locked */
187 spin_lock(&dentry
->d_lock
);
188 if (au_dcount(dentry
) > 0
189 && (!test
|| test(dentry
, arg
)))
190 err
= au_dpages_append(dpages
, dentry
, GFP_ATOMIC
);
191 spin_unlock(&dentry
->d_lock
);
197 write_sequnlock(&rename_lock
);
201 static inline int au_dcsub_dpages_aufs(struct dentry
*dentry
, void *arg
)
203 return au_di(dentry
) && dentry
->d_sb
== arg
;
206 int au_dcsub_pages_rev_aufs(struct au_dcsub_pages
*dpages
,
207 struct dentry
*dentry
, int do_include
)
209 return au_dcsub_pages_rev(dpages
, dentry
, do_include
,
210 au_dcsub_dpages_aufs
, dentry
->d_sb
);
213 int au_test_subdir(struct dentry
*d1
, struct dentry
*d2
)
215 struct path path
[2] = {
224 return path_is_under(path
+ 0, path
+ 1);