]>
git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blob - fs/aufs/dinfo.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2005-2020 Junjiro R. Okajima
5 * This program, aufs is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 void au_di_init_once(void *_dinfo
)
27 struct au_dinfo
*dinfo
= _dinfo
;
29 au_rw_init(&dinfo
->di_rwsem
);
32 struct au_dinfo
*au_di_alloc(struct super_block
*sb
, unsigned int lsc
)
34 struct au_dinfo
*dinfo
;
37 dinfo
= au_cache_alloc_dinfo();
41 nbr
= au_sbbot(sb
) + 1;
44 dinfo
->di_hdentry
= kcalloc(nbr
, sizeof(*dinfo
->di_hdentry
), GFP_NOFS
);
45 if (dinfo
->di_hdentry
) {
46 au_rw_write_lock_nested(&dinfo
->di_rwsem
, lsc
);
50 dinfo
->di_bdiropq
= -1;
51 dinfo
->di_tmpfile
= 0;
52 for (i
= 0; i
< nbr
; i
++)
53 dinfo
->di_hdentry
[i
].hd_id
= -1;
57 au_cache_free_dinfo(dinfo
);
64 void au_di_free(struct au_dinfo
*dinfo
)
67 aufs_bindex_t bbot
, bindex
;
69 /* dentry may not be revalidated */
70 bindex
= dinfo
->di_btop
;
72 bbot
= dinfo
->di_bbot
;
73 p
= au_hdentry(dinfo
, bindex
);
74 while (bindex
++ <= bbot
)
77 au_kfree_try_rcu(dinfo
->di_hdentry
);
78 au_cache_free_dinfo(dinfo
);
81 void au_di_swap(struct au_dinfo
*a
, struct au_dinfo
*b
)
86 AuRwMustWriteLock(&a
->di_rwsem
);
87 AuRwMustWriteLock(&b
->di_rwsem
);
89 #define DiSwap(v, name) \
92 a->di_##name = b->di_##name; \
106 void au_di_cp(struct au_dinfo
*dst
, struct au_dinfo
*src
)
108 AuRwMustWriteLock(&dst
->di_rwsem
);
109 AuRwMustWriteLock(&src
->di_rwsem
);
111 dst
->di_btop
= src
->di_btop
;
112 dst
->di_bbot
= src
->di_bbot
;
113 dst
->di_bwh
= src
->di_bwh
;
114 dst
->di_bdiropq
= src
->di_bdiropq
;
118 int au_di_init(struct dentry
*dentry
)
121 struct super_block
*sb
;
122 struct au_dinfo
*dinfo
;
126 dinfo
= au_di_alloc(sb
, AuLsc_DI_CHILD
);
128 atomic_set(&dinfo
->di_generation
, au_sigen(sb
));
129 /* smp_mb(); */ /* atomic_set */
130 dentry
->d_fsdata
= dinfo
;
137 void au_di_fin(struct dentry
*dentry
)
139 struct au_dinfo
*dinfo
;
141 dinfo
= au_di(dentry
);
142 AuRwDestroy(&dinfo
->di_rwsem
);
146 int au_di_realloc(struct au_dinfo
*dinfo
, int nbr
, int may_shrink
)
149 struct au_hdentry
*hdp
;
151 AuRwMustWriteLock(&dinfo
->di_rwsem
);
154 sz
= sizeof(*hdp
) * (dinfo
->di_bbot
+ 1);
157 hdp
= au_kzrealloc(dinfo
->di_hdentry
, sz
, sizeof(*hdp
) * nbr
, GFP_NOFS
,
160 dinfo
->di_hdentry
= hdp
;
167 /* ---------------------------------------------------------------------- */
169 static void do_ii_write_lock(struct inode
*inode
, unsigned int lsc
)
173 ii_write_lock_child(inode
);
175 case AuLsc_DI_CHILD2
:
176 ii_write_lock_child2(inode
);
178 case AuLsc_DI_CHILD3
:
179 ii_write_lock_child3(inode
);
181 case AuLsc_DI_PARENT
:
182 ii_write_lock_parent(inode
);
184 case AuLsc_DI_PARENT2
:
185 ii_write_lock_parent2(inode
);
187 case AuLsc_DI_PARENT3
:
188 ii_write_lock_parent3(inode
);
195 static void do_ii_read_lock(struct inode
*inode
, unsigned int lsc
)
199 ii_read_lock_child(inode
);
201 case AuLsc_DI_CHILD2
:
202 ii_read_lock_child2(inode
);
204 case AuLsc_DI_CHILD3
:
205 ii_read_lock_child3(inode
);
207 case AuLsc_DI_PARENT
:
208 ii_read_lock_parent(inode
);
210 case AuLsc_DI_PARENT2
:
211 ii_read_lock_parent2(inode
);
213 case AuLsc_DI_PARENT3
:
214 ii_read_lock_parent3(inode
);
221 void di_read_lock(struct dentry
*d
, int flags
, unsigned int lsc
)
225 au_rw_read_lock_nested(&au_di(d
)->di_rwsem
, lsc
);
226 if (d_really_is_positive(d
)) {
228 if (au_ftest_lock(flags
, IW
))
229 do_ii_write_lock(inode
, lsc
);
230 else if (au_ftest_lock(flags
, IR
))
231 do_ii_read_lock(inode
, lsc
);
235 void di_read_unlock(struct dentry
*d
, int flags
)
239 if (d_really_is_positive(d
)) {
241 if (au_ftest_lock(flags
, IW
)) {
242 au_dbg_verify_dinode(d
);
243 ii_write_unlock(inode
);
244 } else if (au_ftest_lock(flags
, IR
)) {
245 au_dbg_verify_dinode(d
);
246 ii_read_unlock(inode
);
249 au_rw_read_unlock(&au_di(d
)->di_rwsem
);
252 void di_downgrade_lock(struct dentry
*d
, int flags
)
254 if (d_really_is_positive(d
) && au_ftest_lock(flags
, IR
))
255 ii_downgrade_lock(d_inode(d
));
256 au_rw_dgrade_lock(&au_di(d
)->di_rwsem
);
259 void di_write_lock(struct dentry
*d
, unsigned int lsc
)
261 au_rw_write_lock_nested(&au_di(d
)->di_rwsem
, lsc
);
262 if (d_really_is_positive(d
))
263 do_ii_write_lock(d_inode(d
), lsc
);
266 void di_write_unlock(struct dentry
*d
)
268 au_dbg_verify_dinode(d
);
269 if (d_really_is_positive(d
))
270 ii_write_unlock(d_inode(d
));
271 au_rw_write_unlock(&au_di(d
)->di_rwsem
);
274 void di_write_lock2_child(struct dentry
*d1
, struct dentry
*d2
, int isdir
)
277 || d_inode(d1
) == d_inode(d2
)
278 || d1
->d_sb
!= d2
->d_sb
);
280 if ((isdir
&& au_test_subdir(d1
, d2
))
282 di_write_lock_child(d1
);
283 di_write_lock_child2(d2
);
285 di_write_lock_child(d2
);
286 di_write_lock_child2(d1
);
290 void di_write_lock2_parent(struct dentry
*d1
, struct dentry
*d2
, int isdir
)
293 || d_inode(d1
) == d_inode(d2
)
294 || d1
->d_sb
!= d2
->d_sb
);
296 if ((isdir
&& au_test_subdir(d1
, d2
))
298 di_write_lock_parent(d1
);
299 di_write_lock_parent2(d2
);
301 di_write_lock_parent(d2
);
302 di_write_lock_parent2(d1
);
306 void di_write_unlock2(struct dentry
*d1
, struct dentry
*d2
)
309 if (d_inode(d1
) == d_inode(d2
))
310 au_rw_write_unlock(&au_di(d2
)->di_rwsem
);
315 /* ---------------------------------------------------------------------- */
317 struct dentry
*au_h_dptr(struct dentry
*dentry
, aufs_bindex_t bindex
)
321 DiMustAnyLock(dentry
);
323 if (au_dbtop(dentry
) < 0 || bindex
< au_dbtop(dentry
))
325 AuDebugOn(bindex
< 0);
326 d
= au_hdentry(au_di(dentry
), bindex
)->hd_dentry
;
327 AuDebugOn(d
&& au_dcount(d
) <= 0);
332 * extended version of au_h_dptr().
333 * returns a hashed and positive (or linkable) h_dentry in bindex, NULL, or
336 struct dentry
*au_h_d_alias(struct dentry
*dentry
, aufs_bindex_t bindex
)
338 struct dentry
*h_dentry
;
339 struct inode
*inode
, *h_inode
;
341 AuDebugOn(d_really_is_negative(dentry
));
344 if (au_dbtop(dentry
) <= bindex
345 && bindex
<= au_dbbot(dentry
))
346 h_dentry
= au_h_dptr(dentry
, bindex
);
347 if (h_dentry
&& !au_d_linkable(h_dentry
)) {
349 goto out
; /* success */
352 inode
= d_inode(dentry
);
353 AuDebugOn(bindex
< au_ibtop(inode
));
354 AuDebugOn(au_ibbot(inode
) < bindex
);
355 h_inode
= au_h_iptr(inode
, bindex
);
356 h_dentry
= d_find_alias(h_inode
);
358 if (!IS_ERR(h_dentry
)) {
359 if (!au_d_linkable(h_dentry
))
360 goto out
; /* success */
366 if (au_opt_test(au_mntflags(dentry
->d_sb
), PLINK
)) {
367 h_dentry
= au_plink_lkup(inode
, bindex
);
368 AuDebugOn(!h_dentry
);
369 if (!IS_ERR(h_dentry
)) {
370 if (!au_d_hashed_positive(h_dentry
))
371 goto out
; /* success */
378 AuDbgDentry(h_dentry
);
382 aufs_bindex_t
au_dbtail(struct dentry
*dentry
)
384 aufs_bindex_t bbot
, bwh
;
386 bbot
= au_dbbot(dentry
);
388 bwh
= au_dbwh(dentry
);
391 if (0 < bwh
&& bwh
< bbot
)
397 aufs_bindex_t
au_dbtaildir(struct dentry
*dentry
)
399 aufs_bindex_t bbot
, bopq
;
401 bbot
= au_dbtail(dentry
);
403 bopq
= au_dbdiropq(dentry
);
404 if (0 <= bopq
&& bopq
< bbot
)
410 /* ---------------------------------------------------------------------- */
412 void au_set_h_dptr(struct dentry
*dentry
, aufs_bindex_t bindex
,
413 struct dentry
*h_dentry
)
415 struct au_dinfo
*dinfo
;
416 struct au_hdentry
*hd
;
417 struct au_branch
*br
;
419 DiMustWriteLock(dentry
);
421 dinfo
= au_di(dentry
);
422 hd
= au_hdentry(dinfo
, bindex
);
424 hd
->hd_dentry
= h_dentry
;
426 br
= au_sbr(dentry
->d_sb
, bindex
);
427 hd
->hd_id
= br
->br_id
;
431 int au_dbrange_test(struct dentry
*dentry
)
434 aufs_bindex_t btop
, bbot
;
437 btop
= au_dbtop(dentry
);
438 bbot
= au_dbbot(dentry
);
440 AuDebugOn(bbot
< 0 && btop
> bbot
);
443 AuDebugOn(bbot
>= 0);
449 int au_digen_test(struct dentry
*dentry
, unsigned int sigen
)
454 if (unlikely(au_digen(dentry
) != sigen
455 || au_iigen_test(d_inode(dentry
), sigen
)))
461 void au_update_digen(struct dentry
*dentry
)
463 atomic_set(&au_di(dentry
)->di_generation
, au_sigen(dentry
->d_sb
));
464 /* smp_mb(); */ /* atomic_set */
467 void au_update_dbrange(struct dentry
*dentry
, int do_put_zero
)
469 struct au_dinfo
*dinfo
;
471 struct au_hdentry
*hdp
;
472 aufs_bindex_t bindex
, bbot
;
474 DiMustWriteLock(dentry
);
476 dinfo
= au_di(dentry
);
477 if (!dinfo
|| dinfo
->di_btop
< 0)
481 bbot
= dinfo
->di_bbot
;
482 bindex
= dinfo
->di_btop
;
483 hdp
= au_hdentry(dinfo
, bindex
);
484 for (; bindex
<= bbot
; bindex
++, hdp
++) {
485 h_d
= hdp
->hd_dentry
;
486 if (h_d
&& d_is_negative(h_d
))
487 au_set_h_dptr(dentry
, bindex
, NULL
);
492 hdp
= au_hdentry(dinfo
, dinfo
->di_btop
);
493 for (; dinfo
->di_btop
<= dinfo
->di_bbot
; dinfo
->di_btop
++, hdp
++)
496 if (dinfo
->di_btop
> dinfo
->di_bbot
) {
502 hdp
= au_hdentry(dinfo
, dinfo
->di_bbot
);
503 for (; dinfo
->di_bbot
>= 0; dinfo
->di_bbot
--, hdp
--)
506 AuDebugOn(dinfo
->di_btop
> dinfo
->di_bbot
|| dinfo
->di_bbot
< 0);
509 void au_update_dbtop(struct dentry
*dentry
)
511 aufs_bindex_t bindex
, bbot
;
512 struct dentry
*h_dentry
;
514 bbot
= au_dbbot(dentry
);
515 for (bindex
= au_dbtop(dentry
); bindex
<= bbot
; bindex
++) {
516 h_dentry
= au_h_dptr(dentry
, bindex
);
519 if (d_is_positive(h_dentry
)) {
520 au_set_dbtop(dentry
, bindex
);
523 au_set_h_dptr(dentry
, bindex
, NULL
);
527 void au_update_dbbot(struct dentry
*dentry
)
529 aufs_bindex_t bindex
, btop
;
530 struct dentry
*h_dentry
;
532 btop
= au_dbtop(dentry
);
533 for (bindex
= au_dbbot(dentry
); bindex
>= btop
; bindex
--) {
534 h_dentry
= au_h_dptr(dentry
, bindex
);
537 if (d_is_positive(h_dentry
)) {
538 au_set_dbbot(dentry
, bindex
);
541 au_set_h_dptr(dentry
, bindex
, NULL
);
545 int au_find_dbindex(struct dentry
*dentry
, struct dentry
*h_dentry
)
547 aufs_bindex_t bindex
, bbot
;
549 bbot
= au_dbbot(dentry
);
550 for (bindex
= au_dbtop(dentry
); bindex
<= bbot
; bindex
++)
551 if (au_h_dptr(dentry
, bindex
) == h_dentry
)