]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - fs/aufs/export.c
UBUNTU: SAUCE: Update aufs to 5.4.3 20200302
[mirror_ubuntu-focal-kernel.git] / fs / aufs / export.c
CommitLineData
a3a49a17
SF
1// SPDX-License-Identifier: GPL-2.0
2/*
e4a3f096 3 * Copyright (C) 2005-2020 Junjiro R. Okajima
a3a49a17
SF
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 * export via nfs
21 */
22
23#include <linux/exportfs.h>
24#include <linux/fs_struct.h>
25#include <linux/namei.h>
26#include <linux/nsproxy.h>
27#include <linux/random.h>
28#include <linux/writeback.h>
29#include "aufs.h"
30
31union conv {
32#ifdef CONFIG_AUFS_INO_T_64
33 __u32 a[2];
34#else
35 __u32 a[1];
36#endif
37 ino_t ino;
38};
39
40static ino_t decode_ino(__u32 *a)
41{
42 union conv u;
43
44 BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
45 u.a[0] = a[0];
46#ifdef CONFIG_AUFS_INO_T_64
47 u.a[1] = a[1];
48#endif
49 return u.ino;
50}
51
52static void encode_ino(__u32 *a, ino_t ino)
53{
54 union conv u;
55
56 u.ino = ino;
57 a[0] = u.a[0];
58#ifdef CONFIG_AUFS_INO_T_64
59 a[1] = u.a[1];
60#endif
61}
62
63/* NFS file handle */
64enum {
65 Fh_br_id,
66 Fh_sigen,
67#ifdef CONFIG_AUFS_INO_T_64
68 /* support 64bit inode number */
69 Fh_ino1,
70 Fh_ino2,
71 Fh_dir_ino1,
72 Fh_dir_ino2,
73#else
74 Fh_ino1,
75 Fh_dir_ino1,
76#endif
77 Fh_igen,
78 Fh_h_type,
79 Fh_tail,
80
81 Fh_ino = Fh_ino1,
82 Fh_dir_ino = Fh_dir_ino1
83};
84
85static int au_test_anon(struct dentry *dentry)
86{
87 /* note: read d_flags without d_lock */
88 return !!(dentry->d_flags & DCACHE_DISCONNECTED);
89}
90
91int au_test_nfsd(void)
92{
93 int ret;
94 struct task_struct *tsk = current;
95 char comm[sizeof(tsk->comm)];
96
97 ret = 0;
98 if (tsk->flags & PF_KTHREAD) {
99 get_task_comm(comm, tsk);
100 ret = !strcmp(comm, "nfsd");
101 }
102
103 return ret;
104}
105
106/* ---------------------------------------------------------------------- */
107/* inode generation external table */
108
109void au_xigen_inc(struct inode *inode)
110{
111 loff_t pos;
112 ssize_t sz;
113 __u32 igen;
114 struct super_block *sb;
115 struct au_sbinfo *sbinfo;
116
117 sb = inode->i_sb;
118 AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
119
120 sbinfo = au_sbi(sb);
121 pos = inode->i_ino;
122 pos *= sizeof(igen);
123 igen = inode->i_generation + 1;
124 sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
125 sizeof(igen), &pos);
126 if (sz == sizeof(igen))
127 return; /* success */
128
129 if (unlikely(sz >= 0))
130 AuIOErr("xigen error (%zd)\n", sz);
131}
132
133int au_xigen_new(struct inode *inode)
134{
135 int err;
136 loff_t pos;
137 ssize_t sz;
138 struct super_block *sb;
139 struct au_sbinfo *sbinfo;
140 struct file *file;
141
142 err = 0;
143 /* todo: dirty, at mount time */
144 if (inode->i_ino == AUFS_ROOT_INO)
145 goto out;
146 sb = inode->i_sb;
147 SiMustAnyLock(sb);
148 if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
149 goto out;
150
151 err = -EFBIG;
152 pos = inode->i_ino;
153 if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
154 AuIOErr1("too large i%lld\n", pos);
155 goto out;
156 }
157 pos *= sizeof(inode->i_generation);
158
159 err = 0;
160 sbinfo = au_sbi(sb);
161 file = sbinfo->si_xigen;
162 BUG_ON(!file);
163
164 if (vfsub_f_size_read(file)
165 < pos + sizeof(inode->i_generation)) {
166 inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
167 sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
168 sizeof(inode->i_generation), &pos);
169 } else
170 sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
171 sizeof(inode->i_generation), &pos);
172 if (sz == sizeof(inode->i_generation))
173 goto out; /* success */
174
175 err = sz;
176 if (unlikely(sz >= 0)) {
177 err = -EIO;
178 AuIOErr("xigen error (%zd)\n", sz);
179 }
180
181out:
182 return err;
183}
184
185int au_xigen_set(struct super_block *sb, struct path *path)
186{
187 int err;
188 struct au_sbinfo *sbinfo;
189 struct file *file;
190
191 SiMustWriteLock(sb);
192
193 sbinfo = au_sbi(sb);
194 file = au_xino_create2(sb, path, sbinfo->si_xigen);
195 err = PTR_ERR(file);
196 if (IS_ERR(file))
197 goto out;
198 err = 0;
199 if (sbinfo->si_xigen)
200 fput(sbinfo->si_xigen);
201 sbinfo->si_xigen = file;
202
203out:
204 AuTraceErr(err);
205 return err;
206}
207
208void au_xigen_clr(struct super_block *sb)
209{
210 struct au_sbinfo *sbinfo;
211
212 SiMustWriteLock(sb);
213
214 sbinfo = au_sbi(sb);
215 if (sbinfo->si_xigen) {
216 fput(sbinfo->si_xigen);
217 sbinfo->si_xigen = NULL;
218 }
219}
220
221/* ---------------------------------------------------------------------- */
222
223static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
224 ino_t dir_ino)
225{
226 struct dentry *dentry, *d;
227 struct inode *inode;
228 unsigned int sigen;
229
230 dentry = NULL;
231 inode = ilookup(sb, ino);
232 if (!inode)
233 goto out;
234
235 dentry = ERR_PTR(-ESTALE);
236 sigen = au_sigen(sb);
237 if (unlikely(au_is_bad_inode(inode)
238 || IS_DEADDIR(inode)
239 || sigen != au_iigen(inode, NULL)))
240 goto out_iput;
241
242 dentry = NULL;
243 if (!dir_ino || S_ISDIR(inode->i_mode))
244 dentry = d_find_alias(inode);
245 else {
246 spin_lock(&inode->i_lock);
247 hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) {
248 spin_lock(&d->d_lock);
249 if (!au_test_anon(d)
250 && d_inode(d->d_parent)->i_ino == dir_ino) {
251 dentry = dget_dlock(d);
252 spin_unlock(&d->d_lock);
253 break;
254 }
255 spin_unlock(&d->d_lock);
256 }
257 spin_unlock(&inode->i_lock);
258 }
259 if (unlikely(dentry && au_digen_test(dentry, sigen))) {
260 /* need to refresh */
261 dput(dentry);
262 dentry = NULL;
263 }
264
265out_iput:
266 iput(inode);
267out:
268 AuTraceErrPtr(dentry);
269 return dentry;
270}
271
272/* ---------------------------------------------------------------------- */
273
274/* todo: dirty? */
275/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
276
277struct au_compare_mnt_args {
278 /* input */
279 struct super_block *sb;
280
281 /* output */
282 struct vfsmount *mnt;
283};
284
285static int au_compare_mnt(struct vfsmount *mnt, void *arg)
286{
287 struct au_compare_mnt_args *a = arg;
288
289 if (mnt->mnt_sb != a->sb)
290 return 0;
291 a->mnt = mntget(mnt);
292 return 1;
293}
294
295static struct vfsmount *au_mnt_get(struct super_block *sb)
296{
297 int err;
298 struct path root;
299 struct au_compare_mnt_args args = {
300 .sb = sb
301 };
302
303 get_fs_root(current->fs, &root);
304 rcu_read_lock();
305 err = iterate_mounts(au_compare_mnt, &args, root.mnt);
306 rcu_read_unlock();
307 path_put(&root);
308 AuDebugOn(!err);
309 AuDebugOn(!args.mnt);
310 return args.mnt;
311}
312
313struct au_nfsd_si_lock {
314 unsigned int sigen;
315 aufs_bindex_t bindex, br_id;
316 unsigned char force_lock;
317};
318
319static int si_nfsd_read_lock(struct super_block *sb,
320 struct au_nfsd_si_lock *nsi_lock)
321{
322 int err;
323 aufs_bindex_t bindex;
324
325 si_read_lock(sb, AuLock_FLUSH);
326
327 /* branch id may be wrapped around */
328 err = 0;
329 bindex = au_br_index(sb, nsi_lock->br_id);
330 if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
331 goto out; /* success */
332
333 err = -ESTALE;
334 bindex = -1;
335 if (!nsi_lock->force_lock)
336 si_read_unlock(sb);
337
338out:
339 nsi_lock->bindex = bindex;
340 return err;
341}
342
343struct find_name_by_ino {
344 struct dir_context ctx;
345 int called, found;
346 ino_t ino;
347 char *name;
348 int namelen;
349};
350
351static int
352find_name_by_ino(struct dir_context *ctx, const char *name, int namelen,
353 loff_t offset, u64 ino, unsigned int d_type)
354{
355 struct find_name_by_ino *a = container_of(ctx, struct find_name_by_ino,
356 ctx);
357
358 a->called++;
359 if (a->ino != ino)
360 return 0;
361
362 memcpy(a->name, name, namelen);
363 a->namelen = namelen;
364 a->found = 1;
365 return 1;
366}
367
368static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
369 struct au_nfsd_si_lock *nsi_lock)
370{
371 struct dentry *dentry, *parent;
372 struct file *file;
373 struct inode *dir;
374 struct find_name_by_ino arg = {
375 .ctx = {
376 .actor = find_name_by_ino
377 }
378 };
379 int err;
380
381 parent = path->dentry;
382 if (nsi_lock)
383 si_read_unlock(parent->d_sb);
384 file = vfsub_dentry_open(path, au_dir_roflags);
385 dentry = (void *)file;
386 if (IS_ERR(file))
387 goto out;
388
389 dentry = ERR_PTR(-ENOMEM);
390 arg.name = (void *)__get_free_page(GFP_NOFS);
391 if (unlikely(!arg.name))
392 goto out_file;
393 arg.ino = ino;
394 arg.found = 0;
395 do {
396 arg.called = 0;
397 /* smp_mb(); */
398 err = vfsub_iterate_dir(file, &arg.ctx);
399 } while (!err && !arg.found && arg.called);
400 dentry = ERR_PTR(err);
401 if (unlikely(err))
402 goto out_name;
403 /* instead of ENOENT */
404 dentry = ERR_PTR(-ESTALE);
405 if (!arg.found)
406 goto out_name;
407
408 /* do not call vfsub_lkup_one() */
409 dir = d_inode(parent);
410 dentry = vfsub_lookup_one_len_unlocked(arg.name, parent, arg.namelen);
411 AuTraceErrPtr(dentry);
412 if (IS_ERR(dentry))
413 goto out_name;
414 AuDebugOn(au_test_anon(dentry));
415 if (unlikely(d_really_is_negative(dentry))) {
416 dput(dentry);
417 dentry = ERR_PTR(-ENOENT);
418 }
419
420out_name:
421 free_page((unsigned long)arg.name);
422out_file:
423 fput(file);
424out:
425 if (unlikely(nsi_lock
426 && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
427 if (!IS_ERR(dentry)) {
428 dput(dentry);
429 dentry = ERR_PTR(-ESTALE);
430 }
431 AuTraceErrPtr(dentry);
432 return dentry;
433}
434
435static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
436 ino_t dir_ino,
437 struct au_nfsd_si_lock *nsi_lock)
438{
439 struct dentry *dentry;
440 struct path path;
441
442 if (dir_ino != AUFS_ROOT_INO) {
443 path.dentry = decode_by_ino(sb, dir_ino, 0);
444 dentry = path.dentry;
445 if (!path.dentry || IS_ERR(path.dentry))
446 goto out;
447 AuDebugOn(au_test_anon(path.dentry));
448 } else
449 path.dentry = dget(sb->s_root);
450
451 path.mnt = au_mnt_get(sb);
452 dentry = au_lkup_by_ino(&path, ino, nsi_lock);
453 path_put(&path);
454
455out:
456 AuTraceErrPtr(dentry);
457 return dentry;
458}
459
460/* ---------------------------------------------------------------------- */
461
462static int h_acceptable(void *expv, struct dentry *dentry)
463{
464 return 1;
465}
466
467static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
468 char *buf, int len, struct super_block *sb)
469{
470 char *p;
471 int n;
472 struct path path;
473
474 p = d_path(h_rootpath, buf, len);
475 if (IS_ERR(p))
476 goto out;
477 n = strlen(p);
478
479 path.mnt = h_rootpath->mnt;
480 path.dentry = h_parent;
481 p = d_path(&path, buf, len);
482 if (IS_ERR(p))
483 goto out;
484 if (n != 1)
485 p += n;
486
487 path.mnt = au_mnt_get(sb);
488 path.dentry = sb->s_root;
489 p = d_path(&path, buf, len - strlen(p));
490 mntput(path.mnt);
491 if (IS_ERR(p))
492 goto out;
493 if (n != 1)
494 p[strlen(p)] = '/';
495
496out:
497 AuTraceErrPtr(p);
498 return p;
499}
500
501static
502struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh,
503 int fh_len, struct au_nfsd_si_lock *nsi_lock)
504{
505 struct dentry *dentry, *h_parent, *root;
506 struct super_block *h_sb;
507 char *pathname, *p;
508 struct vfsmount *h_mnt;
509 struct au_branch *br;
510 int err;
511 struct path path;
512
513 br = au_sbr(sb, nsi_lock->bindex);
514 h_mnt = au_br_mnt(br);
515 h_sb = h_mnt->mnt_sb;
516 /* todo: call lower fh_to_dentry()? fh_to_parent()? */
517 lockdep_off();
518 h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
519 fh_len - Fh_tail, fh[Fh_h_type],
520 h_acceptable, /*context*/NULL);
521 lockdep_on();
522 dentry = h_parent;
523 if (unlikely(!h_parent || IS_ERR(h_parent))) {
524 AuWarn1("%s decode_fh failed, %ld\n",
525 au_sbtype(h_sb), PTR_ERR(h_parent));
526 goto out;
527 }
528 dentry = NULL;
529 if (unlikely(au_test_anon(h_parent))) {
530 AuWarn1("%s decode_fh returned a disconnected dentry\n",
531 au_sbtype(h_sb));
532 goto out_h_parent;
533 }
534
535 dentry = ERR_PTR(-ENOMEM);
536 pathname = (void *)__get_free_page(GFP_NOFS);
537 if (unlikely(!pathname))
538 goto out_h_parent;
539
540 root = sb->s_root;
541 path.mnt = h_mnt;
542 di_read_lock_parent(root, !AuLock_IR);
543 path.dentry = au_h_dptr(root, nsi_lock->bindex);
544 di_read_unlock(root, !AuLock_IR);
545 p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
546 dentry = (void *)p;
547 if (IS_ERR(p))
548 goto out_pathname;
549
550 si_read_unlock(sb);
551 err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
552 dentry = ERR_PTR(err);
553 if (unlikely(err))
554 goto out_relock;
555
556 dentry = ERR_PTR(-ENOENT);
557 AuDebugOn(au_test_anon(path.dentry));
558 if (unlikely(d_really_is_negative(path.dentry)))
559 goto out_path;
560
561 if (ino != d_inode(path.dentry)->i_ino)
562 dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
563 else
564 dentry = dget(path.dentry);
565
566out_path:
567 path_put(&path);
568out_relock:
569 if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
570 if (!IS_ERR(dentry)) {
571 dput(dentry);
572 dentry = ERR_PTR(-ESTALE);
573 }
574out_pathname:
575 free_page((unsigned long)pathname);
576out_h_parent:
577 dput(h_parent);
578out:
579 AuTraceErrPtr(dentry);
580 return dentry;
581}
582
583/* ---------------------------------------------------------------------- */
584
585static struct dentry *
586aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
587 int fh_type)
588{
589 struct dentry *dentry;
590 __u32 *fh = fid->raw;
591 struct au_branch *br;
592 ino_t ino, dir_ino;
593 struct au_nfsd_si_lock nsi_lock = {
594 .force_lock = 0
595 };
596
597 dentry = ERR_PTR(-ESTALE);
598 /* it should never happen, but the file handle is unreliable */
599 if (unlikely(fh_len < Fh_tail))
600 goto out;
601 nsi_lock.sigen = fh[Fh_sigen];
602 nsi_lock.br_id = fh[Fh_br_id];
603
604 /* branch id may be wrapped around */
605 br = NULL;
606 if (unlikely(si_nfsd_read_lock(sb, &nsi_lock)))
607 goto out;
608 nsi_lock.force_lock = 1;
609
610 /* is this inode still cached? */
611 ino = decode_ino(fh + Fh_ino);
612 /* it should never happen */
613 if (unlikely(ino == AUFS_ROOT_INO))
614 goto out_unlock;
615
616 dir_ino = decode_ino(fh + Fh_dir_ino);
617 dentry = decode_by_ino(sb, ino, dir_ino);
618 if (IS_ERR(dentry))
619 goto out_unlock;
620 if (dentry)
621 goto accept;
622
623 /* is the parent dir cached? */
624 br = au_sbr(sb, nsi_lock.bindex);
625 au_lcnt_inc(&br->br_nfiles);
626 dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
627 if (IS_ERR(dentry))
628 goto out_unlock;
629 if (dentry)
630 goto accept;
631
632 /* lookup path */
633 dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock);
634 if (IS_ERR(dentry))
635 goto out_unlock;
636 if (unlikely(!dentry))
637 /* todo?: make it ESTALE */
638 goto out_unlock;
639
640accept:
641 if (!au_digen_test(dentry, au_sigen(sb))
642 && d_inode(dentry)->i_generation == fh[Fh_igen])
643 goto out_unlock; /* success */
644
645 dput(dentry);
646 dentry = ERR_PTR(-ESTALE);
647out_unlock:
648 if (br)
649 au_lcnt_dec(&br->br_nfiles);
650 si_read_unlock(sb);
651out:
652 AuTraceErrPtr(dentry);
653 return dentry;
654}
655
656#if 0 /* reserved for future use */
657/* support subtreecheck option */
658static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
659 int fh_len, int fh_type)
660{
661 struct dentry *parent;
662 __u32 *fh = fid->raw;
663 ino_t dir_ino;
664
665 dir_ino = decode_ino(fh + Fh_dir_ino);
666 parent = decode_by_ino(sb, dir_ino, 0);
667 if (IS_ERR(parent))
668 goto out;
669 if (!parent)
670 parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
671 dir_ino, fh, fh_len);
672
673out:
674 AuTraceErrPtr(parent);
675 return parent;
676}
677#endif
678
679/* ---------------------------------------------------------------------- */
680
681static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len,
682 struct inode *dir)
683{
684 int err;
685 aufs_bindex_t bindex;
686 struct super_block *sb, *h_sb;
687 struct dentry *dentry, *parent, *h_parent;
688 struct inode *h_dir;
689 struct au_branch *br;
690
691 err = -ENOSPC;
692 if (unlikely(*max_len <= Fh_tail)) {
693 AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
694 goto out;
695 }
696
697 err = FILEID_ROOT;
698 if (inode->i_ino == AUFS_ROOT_INO) {
699 AuDebugOn(inode->i_ino != AUFS_ROOT_INO);
700 goto out;
701 }
702
703 h_parent = NULL;
704 sb = inode->i_sb;
705 err = si_read_lock(sb, AuLock_FLUSH);
706 if (unlikely(err))
707 goto out;
708
709#ifdef CONFIG_AUFS_DEBUG
710 if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
711 AuWarn1("NFS-exporting requires xino\n");
712#endif
713 err = -EIO;
714 parent = NULL;
715 ii_read_lock_child(inode);
716 bindex = au_ibtop(inode);
717 if (!dir) {
718 dentry = d_find_any_alias(inode);
719 if (unlikely(!dentry))
720 goto out_unlock;
721 AuDebugOn(au_test_anon(dentry));
722 parent = dget_parent(dentry);
723 dput(dentry);
724 if (unlikely(!parent))
725 goto out_unlock;
726 if (d_really_is_positive(parent))
727 dir = d_inode(parent);
728 }
729
730 ii_read_lock_parent(dir);
731 h_dir = au_h_iptr(dir, bindex);
732 ii_read_unlock(dir);
733 if (unlikely(!h_dir))
734 goto out_parent;
735 h_parent = d_find_any_alias(h_dir);
736 if (unlikely(!h_parent))
737 goto out_hparent;
738
739 err = -EPERM;
740 br = au_sbr(sb, bindex);
741 h_sb = au_br_sb(br);
742 if (unlikely(!h_sb->s_export_op)) {
743 AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
744 goto out_hparent;
745 }
746
747 fh[Fh_br_id] = br->br_id;
748 fh[Fh_sigen] = au_sigen(sb);
749 encode_ino(fh + Fh_ino, inode->i_ino);
750 encode_ino(fh + Fh_dir_ino, dir->i_ino);
751 fh[Fh_igen] = inode->i_generation;
752
753 *max_len -= Fh_tail;
754 fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
755 max_len,
756 /*connectable or subtreecheck*/0);
757 err = fh[Fh_h_type];
758 *max_len += Fh_tail;
759 /* todo: macros? */
760 if (err != FILEID_INVALID)
761 err = 99;
762 else
763 AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
764
765out_hparent:
766 dput(h_parent);
767out_parent:
768 dput(parent);
769out_unlock:
770 ii_read_unlock(inode);
771 si_read_unlock(sb);
772out:
773 if (unlikely(err < 0))
774 err = FILEID_INVALID;
775 return err;
776}
777
778/* ---------------------------------------------------------------------- */
779
780static int aufs_commit_metadata(struct inode *inode)
781{
782 int err;
783 aufs_bindex_t bindex;
784 struct super_block *sb;
785 struct inode *h_inode;
786 int (*f)(struct inode *inode);
787
788 sb = inode->i_sb;
789 si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
790 ii_write_lock_child(inode);
791 bindex = au_ibtop(inode);
792 AuDebugOn(bindex < 0);
793 h_inode = au_h_iptr(inode, bindex);
794
795 f = h_inode->i_sb->s_export_op->commit_metadata;
796 if (f)
797 err = f(h_inode);
798 else {
799 struct writeback_control wbc = {
800 .sync_mode = WB_SYNC_ALL,
801 .nr_to_write = 0 /* metadata only */
802 };
803
804 err = sync_inode(h_inode, &wbc);
805 }
806
807 au_cpup_attr_timesizes(inode);
808 ii_write_unlock(inode);
809 si_read_unlock(sb);
810 return err;
811}
812
813/* ---------------------------------------------------------------------- */
814
815static struct export_operations aufs_export_op = {
816 .fh_to_dentry = aufs_fh_to_dentry,
817 /* .fh_to_parent = aufs_fh_to_parent, */
818 .encode_fh = aufs_encode_fh,
819 .commit_metadata = aufs_commit_metadata
820};
821
822void au_export_init(struct super_block *sb)
823{
824 struct au_sbinfo *sbinfo;
825 __u32 u;
826
827 BUILD_BUG_ON_MSG(IS_BUILTIN(CONFIG_AUFS_FS)
828 && IS_MODULE(CONFIG_EXPORTFS),
829 AUFS_NAME ": unsupported configuration "
830 "CONFIG_EXPORTFS=m and CONFIG_AUFS_FS=y");
831
832 sb->s_export_op = &aufs_export_op;
833 sbinfo = au_sbi(sb);
834 sbinfo->si_xigen = NULL;
835 get_random_bytes(&u, sizeof(u));
836 BUILD_BUG_ON(sizeof(u) != sizeof(int));
837 atomic_set(&sbinfo->si_xigen_next, u);
838}