]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blob - fs/aufs/dinfo.c
UBUNTU: SAUCE: Update aufs to 5.4.3 20200302
[mirror_ubuntu-focal-kernel.git] / fs / aufs / dinfo.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2005-2020 Junjiro R. Okajima
4 *
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.
9 *
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.
14 *
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/>.
17 */
18
19 /*
20 * dentry private data
21 */
22
23 #include "aufs.h"
24
25 void au_di_init_once(void *_dinfo)
26 {
27 struct au_dinfo *dinfo = _dinfo;
28
29 au_rw_init(&dinfo->di_rwsem);
30 }
31
32 struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc)
33 {
34 struct au_dinfo *dinfo;
35 int nbr, i;
36
37 dinfo = au_cache_alloc_dinfo();
38 if (unlikely(!dinfo))
39 goto out;
40
41 nbr = au_sbbot(sb) + 1;
42 if (nbr <= 0)
43 nbr = 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);
47 dinfo->di_btop = -1;
48 dinfo->di_bbot = -1;
49 dinfo->di_bwh = -1;
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;
54 goto out;
55 }
56
57 au_cache_free_dinfo(dinfo);
58 dinfo = NULL;
59
60 out:
61 return dinfo;
62 }
63
64 void au_di_free(struct au_dinfo *dinfo)
65 {
66 struct au_hdentry *p;
67 aufs_bindex_t bbot, bindex;
68
69 /* dentry may not be revalidated */
70 bindex = dinfo->di_btop;
71 if (bindex >= 0) {
72 bbot = dinfo->di_bbot;
73 p = au_hdentry(dinfo, bindex);
74 while (bindex++ <= bbot)
75 au_hdput(p++);
76 }
77 au_kfree_try_rcu(dinfo->di_hdentry);
78 au_cache_free_dinfo(dinfo);
79 }
80
81 void au_di_swap(struct au_dinfo *a, struct au_dinfo *b)
82 {
83 struct au_hdentry *p;
84 aufs_bindex_t bi;
85
86 AuRwMustWriteLock(&a->di_rwsem);
87 AuRwMustWriteLock(&b->di_rwsem);
88
89 #define DiSwap(v, name) \
90 do { \
91 v = a->di_##name; \
92 a->di_##name = b->di_##name; \
93 b->di_##name = v; \
94 } while (0)
95
96 DiSwap(p, hdentry);
97 DiSwap(bi, btop);
98 DiSwap(bi, bbot);
99 DiSwap(bi, bwh);
100 DiSwap(bi, bdiropq);
101 /* smp_mb(); */
102
103 #undef DiSwap
104 }
105
106 void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src)
107 {
108 AuRwMustWriteLock(&dst->di_rwsem);
109 AuRwMustWriteLock(&src->di_rwsem);
110
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;
115 /* smp_mb(); */
116 }
117
118 int au_di_init(struct dentry *dentry)
119 {
120 int err;
121 struct super_block *sb;
122 struct au_dinfo *dinfo;
123
124 err = 0;
125 sb = dentry->d_sb;
126 dinfo = au_di_alloc(sb, AuLsc_DI_CHILD);
127 if (dinfo) {
128 atomic_set(&dinfo->di_generation, au_sigen(sb));
129 /* smp_mb(); */ /* atomic_set */
130 dentry->d_fsdata = dinfo;
131 } else
132 err = -ENOMEM;
133
134 return err;
135 }
136
137 void au_di_fin(struct dentry *dentry)
138 {
139 struct au_dinfo *dinfo;
140
141 dinfo = au_di(dentry);
142 AuRwDestroy(&dinfo->di_rwsem);
143 au_di_free(dinfo);
144 }
145
146 int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink)
147 {
148 int err, sz;
149 struct au_hdentry *hdp;
150
151 AuRwMustWriteLock(&dinfo->di_rwsem);
152
153 err = -ENOMEM;
154 sz = sizeof(*hdp) * (dinfo->di_bbot + 1);
155 if (!sz)
156 sz = sizeof(*hdp);
157 hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS,
158 may_shrink);
159 if (hdp) {
160 dinfo->di_hdentry = hdp;
161 err = 0;
162 }
163
164 return err;
165 }
166
167 /* ---------------------------------------------------------------------- */
168
169 static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
170 {
171 switch (lsc) {
172 case AuLsc_DI_CHILD:
173 ii_write_lock_child(inode);
174 break;
175 case AuLsc_DI_CHILD2:
176 ii_write_lock_child2(inode);
177 break;
178 case AuLsc_DI_CHILD3:
179 ii_write_lock_child3(inode);
180 break;
181 case AuLsc_DI_PARENT:
182 ii_write_lock_parent(inode);
183 break;
184 case AuLsc_DI_PARENT2:
185 ii_write_lock_parent2(inode);
186 break;
187 case AuLsc_DI_PARENT3:
188 ii_write_lock_parent3(inode);
189 break;
190 default:
191 BUG();
192 }
193 }
194
195 static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
196 {
197 switch (lsc) {
198 case AuLsc_DI_CHILD:
199 ii_read_lock_child(inode);
200 break;
201 case AuLsc_DI_CHILD2:
202 ii_read_lock_child2(inode);
203 break;
204 case AuLsc_DI_CHILD3:
205 ii_read_lock_child3(inode);
206 break;
207 case AuLsc_DI_PARENT:
208 ii_read_lock_parent(inode);
209 break;
210 case AuLsc_DI_PARENT2:
211 ii_read_lock_parent2(inode);
212 break;
213 case AuLsc_DI_PARENT3:
214 ii_read_lock_parent3(inode);
215 break;
216 default:
217 BUG();
218 }
219 }
220
221 void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
222 {
223 struct inode *inode;
224
225 au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
226 if (d_really_is_positive(d)) {
227 inode = d_inode(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);
232 }
233 }
234
235 void di_read_unlock(struct dentry *d, int flags)
236 {
237 struct inode *inode;
238
239 if (d_really_is_positive(d)) {
240 inode = d_inode(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);
247 }
248 }
249 au_rw_read_unlock(&au_di(d)->di_rwsem);
250 }
251
252 void di_downgrade_lock(struct dentry *d, int flags)
253 {
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);
257 }
258
259 void di_write_lock(struct dentry *d, unsigned int lsc)
260 {
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);
264 }
265
266 void di_write_unlock(struct dentry *d)
267 {
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);
272 }
273
274 void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
275 {
276 AuDebugOn(d1 == d2
277 || d_inode(d1) == d_inode(d2)
278 || d1->d_sb != d2->d_sb);
279
280 if ((isdir && au_test_subdir(d1, d2))
281 || d1 < d2) {
282 di_write_lock_child(d1);
283 di_write_lock_child2(d2);
284 } else {
285 di_write_lock_child(d2);
286 di_write_lock_child2(d1);
287 }
288 }
289
290 void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
291 {
292 AuDebugOn(d1 == d2
293 || d_inode(d1) == d_inode(d2)
294 || d1->d_sb != d2->d_sb);
295
296 if ((isdir && au_test_subdir(d1, d2))
297 || d1 < d2) {
298 di_write_lock_parent(d1);
299 di_write_lock_parent2(d2);
300 } else {
301 di_write_lock_parent(d2);
302 di_write_lock_parent2(d1);
303 }
304 }
305
306 void di_write_unlock2(struct dentry *d1, struct dentry *d2)
307 {
308 di_write_unlock(d1);
309 if (d_inode(d1) == d_inode(d2))
310 au_rw_write_unlock(&au_di(d2)->di_rwsem);
311 else
312 di_write_unlock(d2);
313 }
314
315 /* ---------------------------------------------------------------------- */
316
317 struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
318 {
319 struct dentry *d;
320
321 DiMustAnyLock(dentry);
322
323 if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry))
324 return NULL;
325 AuDebugOn(bindex < 0);
326 d = au_hdentry(au_di(dentry), bindex)->hd_dentry;
327 AuDebugOn(d && au_dcount(d) <= 0);
328 return d;
329 }
330
331 /*
332 * extended version of au_h_dptr().
333 * returns a hashed and positive (or linkable) h_dentry in bindex, NULL, or
334 * error.
335 */
336 struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex)
337 {
338 struct dentry *h_dentry;
339 struct inode *inode, *h_inode;
340
341 AuDebugOn(d_really_is_negative(dentry));
342
343 h_dentry = NULL;
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)) {
348 dget(h_dentry);
349 goto out; /* success */
350 }
351
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);
357 if (h_dentry) {
358 if (!IS_ERR(h_dentry)) {
359 if (!au_d_linkable(h_dentry))
360 goto out; /* success */
361 dput(h_dentry);
362 } else
363 goto out;
364 }
365
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 */
372 dput(h_dentry);
373 h_dentry = NULL;
374 }
375 }
376
377 out:
378 AuDbgDentry(h_dentry);
379 return h_dentry;
380 }
381
382 aufs_bindex_t au_dbtail(struct dentry *dentry)
383 {
384 aufs_bindex_t bbot, bwh;
385
386 bbot = au_dbbot(dentry);
387 if (0 <= bbot) {
388 bwh = au_dbwh(dentry);
389 if (!bwh)
390 return bwh;
391 if (0 < bwh && bwh < bbot)
392 return bwh - 1;
393 }
394 return bbot;
395 }
396
397 aufs_bindex_t au_dbtaildir(struct dentry *dentry)
398 {
399 aufs_bindex_t bbot, bopq;
400
401 bbot = au_dbtail(dentry);
402 if (0 <= bbot) {
403 bopq = au_dbdiropq(dentry);
404 if (0 <= bopq && bopq < bbot)
405 bbot = bopq;
406 }
407 return bbot;
408 }
409
410 /* ---------------------------------------------------------------------- */
411
412 void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
413 struct dentry *h_dentry)
414 {
415 struct au_dinfo *dinfo;
416 struct au_hdentry *hd;
417 struct au_branch *br;
418
419 DiMustWriteLock(dentry);
420
421 dinfo = au_di(dentry);
422 hd = au_hdentry(dinfo, bindex);
423 au_hdput(hd);
424 hd->hd_dentry = h_dentry;
425 if (h_dentry) {
426 br = au_sbr(dentry->d_sb, bindex);
427 hd->hd_id = br->br_id;
428 }
429 }
430
431 int au_dbrange_test(struct dentry *dentry)
432 {
433 int err;
434 aufs_bindex_t btop, bbot;
435
436 err = 0;
437 btop = au_dbtop(dentry);
438 bbot = au_dbbot(dentry);
439 if (btop >= 0)
440 AuDebugOn(bbot < 0 && btop > bbot);
441 else {
442 err = -EIO;
443 AuDebugOn(bbot >= 0);
444 }
445
446 return err;
447 }
448
449 int au_digen_test(struct dentry *dentry, unsigned int sigen)
450 {
451 int err;
452
453 err = 0;
454 if (unlikely(au_digen(dentry) != sigen
455 || au_iigen_test(d_inode(dentry), sigen)))
456 err = -EIO;
457
458 return err;
459 }
460
461 void au_update_digen(struct dentry *dentry)
462 {
463 atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
464 /* smp_mb(); */ /* atomic_set */
465 }
466
467 void au_update_dbrange(struct dentry *dentry, int do_put_zero)
468 {
469 struct au_dinfo *dinfo;
470 struct dentry *h_d;
471 struct au_hdentry *hdp;
472 aufs_bindex_t bindex, bbot;
473
474 DiMustWriteLock(dentry);
475
476 dinfo = au_di(dentry);
477 if (!dinfo || dinfo->di_btop < 0)
478 return;
479
480 if (do_put_zero) {
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);
488 }
489 }
490
491 dinfo->di_btop = 0;
492 hdp = au_hdentry(dinfo, dinfo->di_btop);
493 for (; dinfo->di_btop <= dinfo->di_bbot; dinfo->di_btop++, hdp++)
494 if (hdp->hd_dentry)
495 break;
496 if (dinfo->di_btop > dinfo->di_bbot) {
497 dinfo->di_btop = -1;
498 dinfo->di_bbot = -1;
499 return;
500 }
501
502 hdp = au_hdentry(dinfo, dinfo->di_bbot);
503 for (; dinfo->di_bbot >= 0; dinfo->di_bbot--, hdp--)
504 if (hdp->hd_dentry)
505 break;
506 AuDebugOn(dinfo->di_btop > dinfo->di_bbot || dinfo->di_bbot < 0);
507 }
508
509 void au_update_dbtop(struct dentry *dentry)
510 {
511 aufs_bindex_t bindex, bbot;
512 struct dentry *h_dentry;
513
514 bbot = au_dbbot(dentry);
515 for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) {
516 h_dentry = au_h_dptr(dentry, bindex);
517 if (!h_dentry)
518 continue;
519 if (d_is_positive(h_dentry)) {
520 au_set_dbtop(dentry, bindex);
521 return;
522 }
523 au_set_h_dptr(dentry, bindex, NULL);
524 }
525 }
526
527 void au_update_dbbot(struct dentry *dentry)
528 {
529 aufs_bindex_t bindex, btop;
530 struct dentry *h_dentry;
531
532 btop = au_dbtop(dentry);
533 for (bindex = au_dbbot(dentry); bindex >= btop; bindex--) {
534 h_dentry = au_h_dptr(dentry, bindex);
535 if (!h_dentry)
536 continue;
537 if (d_is_positive(h_dentry)) {
538 au_set_dbbot(dentry, bindex);
539 return;
540 }
541 au_set_h_dptr(dentry, bindex, NULL);
542 }
543 }
544
545 int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
546 {
547 aufs_bindex_t bindex, bbot;
548
549 bbot = au_dbbot(dentry);
550 for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++)
551 if (au_h_dptr(dentry, bindex) == h_dentry)
552 return bindex;
553 return -1;
554 }