]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs4.patch
- 4.14.255
[packages/kernel.git] / kernel-aufs4.patch
CommitLineData
0b1ff5c3
JR
1diff -urNp -x '*.orig' linux-4.14/Documentation/ABI/testing/debugfs-aufs linux-4.14/Documentation/ABI/testing/debugfs-aufs
2--- linux-4.14/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
3+++ linux-4.14/Documentation/ABI/testing/debugfs-aufs 2021-02-24 21:42:43.437781422 +0100
86dc4139 4@@ -0,0 +1,50 @@
7f207e10
AM
5+What: /debug/aufs/si_<id>/
6+Date: March 2009
f6b6e03d 7+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
8+Description:
9+ Under /debug/aufs, a directory named si_<id> is created
10+ per aufs mount, where <id> is a unique id generated
11+ internally.
1facf9fc 12+
86dc4139
AM
13+What: /debug/aufs/si_<id>/plink
14+Date: Apr 2013
f6b6e03d 15+Contact: J. R. Okajima <hooanon05g@gmail.com>
86dc4139
AM
16+Description:
17+ It has three lines and shows the information about the
18+ pseudo-link. The first line is a single number
19+ representing a number of buckets. The second line is a
20+ number of pseudo-links per buckets (separated by a
21+ blank). The last line is a single number representing a
22+ total number of psedo-links.
23+ When the aufs mount option 'noplink' is specified, it
24+ will show "1\n0\n0\n".
25+
7f207e10
AM
26+What: /debug/aufs/si_<id>/xib
27+Date: March 2009
f6b6e03d 28+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
29+Description:
30+ It shows the consumed blocks by xib (External Inode Number
31+ Bitmap), its block size and file size.
32+ When the aufs mount option 'noxino' is specified, it
33+ will be empty. About XINO files, see the aufs manual.
34+
35+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
36+Date: March 2009
f6b6e03d 37+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
38+Description:
39+ It shows the consumed blocks by xino (External Inode Number
40+ Translation Table), its link count, block size and file
41+ size.
42+ When the aufs mount option 'noxino' is specified, it
43+ will be empty. About XINO files, see the aufs manual.
44+
45+What: /debug/aufs/si_<id>/xigen
46+Date: March 2009
f6b6e03d 47+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
48+Description:
49+ It shows the consumed blocks by xigen (External Inode
50+ Generation Table), its block size and file size.
51+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
52+ be created.
53+ When the aufs mount option 'noxino' is specified, it
54+ will be empty. About XINO files, see the aufs manual.
0b1ff5c3
JR
55diff -urNp -x '*.orig' linux-4.14/Documentation/ABI/testing/sysfs-aufs linux-4.14/Documentation/ABI/testing/sysfs-aufs
56--- linux-4.14/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
57+++ linux-4.14/Documentation/ABI/testing/sysfs-aufs 2021-02-24 21:42:43.437781422 +0100
392086de 58@@ -0,0 +1,31 @@
7f207e10
AM
59+What: /sys/fs/aufs/si_<id>/
60+Date: March 2009
f6b6e03d 61+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
62+Description:
63+ Under /sys/fs/aufs, a directory named si_<id> is created
64+ per aufs mount, where <id> is a unique id generated
65+ internally.
66+
67+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
68+Date: March 2009
f6b6e03d 69+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
70+Description:
71+ It shows the abolute path of a member directory (which
72+ is called branch) in aufs, and its permission.
73+
392086de
AM
74+What: /sys/fs/aufs/si_<id>/brid0, brid1 ... bridN
75+Date: July 2013
f6b6e03d 76+Contact: J. R. Okajima <hooanon05g@gmail.com>
392086de
AM
77+Description:
78+ It shows the id of a member directory (which is called
79+ branch) in aufs.
80+
7f207e10
AM
81+What: /sys/fs/aufs/si_<id>/xi_path
82+Date: March 2009
f6b6e03d 83+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
84+Description:
85+ It shows the abolute path of XINO (External Inode Number
86+ Bitmap, Translation Table and Generation Table) file
87+ even if it is the default path.
88+ When the aufs mount option 'noxino' is specified, it
89+ will be empty. About XINO files, see the aufs manual.
0b1ff5c3
JR
90diff -urNp -x '*.orig' linux-4.14/Documentation/filesystems/aufs/README linux-4.14/Documentation/filesystems/aufs/README
91--- linux-4.14/Documentation/filesystems/aufs/README 1970-01-01 01:00:00.000000000 +0100
92+++ linux-4.14/Documentation/filesystems/aufs/README 2021-02-24 21:42:43.441114748 +0100
93@@ -0,0 +1,393 @@
94+
95+Aufs4 -- advanced multi layered unification filesystem version 4.x
96+http://aufs.sf.net
97+Junjiro R. Okajima
98+
99+
100+0. Introduction
101+----------------------------------------
102+In the early days, aufs was entirely re-designed and re-implemented
103+Unionfs Version 1.x series. Adding many original ideas, approaches,
104+improvements and implementations, it becomes totally different from
105+Unionfs while keeping the basic features.
106+Recently, Unionfs Version 2.x series begin taking some of the same
107+approaches to aufs1's.
108+Unionfs is being developed by Professor Erez Zadok at Stony Brook
109+University and his team.
110+
111+Aufs4 supports linux-4.0 and later, and for linux-3.x series try aufs3.
112+If you want older kernel version support, try aufs2-2.6.git or
113+aufs2-standalone.git repository, aufs1 from CVS on SourceForge.
114+
115+Note: it becomes clear that "Aufs was rejected. Let's give it up."
116+ According to Christoph Hellwig, linux rejects all union-type
117+ filesystems but UnionMount.
118+<http://marc.info/?l=linux-kernel&m=123938533724484&w=2>
119+
120+PS. Al Viro seems have a plan to merge aufs as well as overlayfs and
121+ UnionMount, and he pointed out an issue around a directory mutex
122+ lock and aufs addressed it. But it is still unsure whether aufs will
123+ be merged (or any other union solution).
124+<http://marc.info/?l=linux-kernel&m=136312705029295&w=1>
125+
126+
127+1. Features
128+----------------------------------------
129+- unite several directories into a single virtual filesystem. The member
130+ directory is called as a branch.
131+- you can specify the permission flags to the branch, which are 'readonly',
132+ 'readwrite' and 'whiteout-able.'
133+- by upper writable branch, internal copyup and whiteout, files/dirs on
134+ readonly branch are modifiable logically.
135+- dynamic branch manipulation, add, del.
136+- etc...
137+
138+Also there are many enhancements in aufs, such as:
139+- test only the highest one for the directory permission (dirperm1)
140+- copyup on open (coo=)
141+- 'move' policy for copy-up between two writable branches, after
142+ checking free space.
143+- xattr, acl
144+- readdir(3) in userspace.
145+- keep inode number by external inode number table
146+- keep the timestamps of file/dir in internal copyup operation
147+- seekable directory, supporting NFS readdir.
148+- whiteout is hardlinked in order to reduce the consumption of inodes
149+ on branch
150+- do not copyup, nor create a whiteout when it is unnecessary
151+- revert a single systemcall when an error occurs in aufs
152+- remount interface instead of ioctl
153+- maintain /etc/mtab by an external command, /sbin/mount.aufs.
154+- loopback mounted filesystem as a branch
155+- kernel thread for removing the dir who has a plenty of whiteouts
156+- support copyup sparse file (a file which has a 'hole' in it)
157+- default permission flags for branches
158+- selectable permission flags for ro branch, whether whiteout can
159+ exist or not
160+- export via NFS.
161+- support <sysfs>/fs/aufs and <debugfs>/aufs.
162+- support multiple writable branches, some policies to select one
163+ among multiple writable branches.
164+- a new semantics for link(2) and rename(2) to support multiple
165+ writable branches.
166+- no glibc changes are required.
167+- pseudo hardlink (hardlink over branches)
168+- allow a direct access manually to a file on branch, e.g. bypassing aufs.
169+ including NFS or remote filesystem branch.
170+- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX.
171+- and more...
172+
173+Currently these features are dropped temporary from aufs4.
174+See design/08plan.txt in detail.
175+- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs
176+ (robr)
177+- statistics of aufs thread (/sys/fs/aufs/stat)
178+
179+Features or just an idea in the future (see also design/*.txt),
180+- reorder the branch index without del/re-add.
181+- permanent xino files for NFSD
182+- an option for refreshing the opened files after add/del branches
183+- light version, without branch manipulation. (unnecessary?)
184+- copyup in userspace
185+- inotify in userspace
186+- readv/writev
187+
188+
189+2. Download
190+----------------------------------------
191+There are three GIT trees for aufs4, aufs4-linux.git,
192+aufs4-standalone.git, and aufs-util.git. Note that there is no "4" in
193+"aufs-util.git."
194+While the aufs-util is always necessary, you need either of aufs4-linux
195+or aufs4-standalone.
196+
197+The aufs4-linux tree includes the whole linux mainline GIT tree,
198+git://git.kernel.org/.../torvalds/linux.git.
199+And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot
200+build aufs4 as an external kernel module.
201+Several extra patches are not included in this tree. Only
202+aufs4-standalone tree contains them. They are described in the later
203+section "Configuration and Compilation."
204+
205+On the other hand, the aufs4-standalone tree has only aufs source files
206+and necessary patches, and you can select CONFIG_AUFS_FS=m.
207+But you need to apply all aufs patches manually.
208+
209+You will find GIT branches whose name is in form of "aufs4.x" where "x"
210+represents the linux kernel version, "linux-4.x". For instance,
211+"aufs4.0" is for linux-4.0. For latest "linux-4.x-rcN", use
212+"aufs4.x-rcN" branch.
213+
214+o aufs4-linux tree
215+$ git clone --reference /your/linux/git/tree \
216+ git://github.com/sfjro/aufs4-linux.git aufs4-linux.git
217+- if you don't have linux GIT tree, then remove "--reference ..."
218+$ cd aufs4-linux.git
219+$ git checkout origin/aufs4.0
220+
221+Or You may want to directly git-pull aufs into your linux GIT tree, and
222+leave the patch-work to GIT.
223+$ cd /your/linux/git/tree
224+$ git remote add aufs4 git://github.com/sfjro/aufs4-linux.git
225+$ git fetch aufs4
226+$ git checkout -b my4.0 v4.0
227+$ (add your local change...)
228+$ git pull aufs4 aufs4.0
229+- now you have v4.0 + your_changes + aufs4.0 in you my4.0 branch.
230+- you may need to solve some conflicts between your_changes and
231+ aufs4.0. in this case, git-rerere is recommended so that you can
232+ solve the similar conflicts automatically when you upgrade to 4.1 or
233+ later in the future.
234+
235+o aufs4-standalone tree
236+$ git clone git://github.com/sfjro/aufs4-standalone.git aufs4-standalone.git
237+$ cd aufs4-standalone.git
238+$ git checkout origin/aufs4.0
239+
240+o aufs-util tree
241+$ git clone git://git.code.sf.net/p/aufs/aufs-util aufs-util.git
242+- note that the public aufs-util.git is on SourceForge instead of
243+ GitHUB.
244+$ cd aufs-util.git
245+$ git checkout origin/aufs4.0
246+
247+Note: The 4.x-rcN branch is to be used with `rc' kernel versions ONLY.
248+The minor version number, 'x' in '4.x', of aufs may not always
249+follow the minor version number of the kernel.
250+Because changes in the kernel that cause the use of a new
251+minor version number do not always require changes to aufs-util.
252+
253+Since aufs-util has its own minor version number, you may not be
254+able to find a GIT branch in aufs-util for your kernel's
255+exact minor version number.
256+In this case, you should git-checkout the branch for the
257+nearest lower number.
258+
259+For (an unreleased) example:
260+If you are using "linux-4.10" and the "aufs4.10" branch
261+does not exist in aufs-util repository, then "aufs4.9", "aufs4.8"
262+or something numerically smaller is the branch for your kernel.
263+
264+Also you can view all branches by
265+ $ git branch -a
266+
267+
268+3. Configuration and Compilation
269+----------------------------------------
270+Make sure you have git-checkout'ed the correct branch.
271+
272+For aufs4-linux tree,
273+- enable CONFIG_AUFS_FS.
274+- set other aufs configurations if necessary.
275+
276+For aufs4-standalone tree,
277+There are several ways to build.
278+
279+1.
280+- apply ./aufs4-kbuild.patch to your kernel source files.
281+- apply ./aufs4-base.patch too.
282+- apply ./aufs4-mmap.patch too.
283+- apply ./aufs4-standalone.patch too, if you have a plan to set
284+ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs4-standalone.patch.
285+- copy ./{Documentation,fs,include/uapi/linux/aufs_type.h} files to your
286+ kernel source tree. Never copy $PWD/include/uapi/linux/Kbuild.
287+- enable CONFIG_AUFS_FS, you can select either
288+ =m or =y.
289+- and build your kernel as usual.
290+- install the built kernel.
291+ Note: Since linux-3.9, every filesystem module requires an alias
292+ "fs-<fsname>". You should make sure that "fs-aufs" is listed in your
293+ modules.aliases file if you set CONFIG_AUFS_FS=m.
294+- install the header files too by "make headers_install" to the
295+ directory where you specify. By default, it is $PWD/usr.
296+ "make help" shows a brief note for headers_install.
297+- and reboot your system.
298+
299+2.
300+- module only (CONFIG_AUFS_FS=m).
301+- apply ./aufs4-base.patch to your kernel source files.
302+- apply ./aufs4-mmap.patch too.
303+- apply ./aufs4-standalone.patch too.
304+- build your kernel, don't forget "make headers_install", and reboot.
305+- edit ./config.mk and set other aufs configurations if necessary.
306+ Note: You should read $PWD/fs/aufs/Kconfig carefully which describes
307+ every aufs configurations.
308+- build the module by simple "make".
309+ Note: Since linux-3.9, every filesystem module requires an alias
310+ "fs-<fsname>". You should make sure that "fs-aufs" is listed in your
311+ modules.aliases file.
312+- you can specify ${KDIR} make variable which points to your kernel
313+ source tree.
314+- install the files
315+ + run "make install" to install the aufs module, or copy the built
316+ $PWD/aufs.ko to /lib/modules/... and run depmod -a (or reboot simply).
317+ + run "make install_headers" (instead of headers_install) to install
318+ the modified aufs header file (you can specify DESTDIR which is
319+ available in aufs standalone version's Makefile only), or copy
320+ $PWD/usr/include/linux/aufs_type.h to /usr/include/linux or wherever
321+ you like manually. By default, the target directory is $PWD/usr.
322+- no need to apply aufs4-kbuild.patch, nor copying source files to your
323+ kernel source tree.
324+
325+Note: The header file aufs_type.h is necessary to build aufs-util
326+ as well as "make headers_install" in the kernel source tree.
327+ headers_install is subject to be forgotten, but it is essentially
328+ necessary, not only for building aufs-util.
329+ You may not meet problems without headers_install in some older
330+ version though.
331+
332+And then,
333+- read README in aufs-util, build and install it
334+- note that your distribution may contain an obsoleted version of
335+ aufs_type.h in /usr/include/linux or something. When you build aufs
336+ utilities, make sure that your compiler refers the correct aufs header
337+ file which is built by "make headers_install."
338+- if you want to use readdir(3) in userspace or pathconf(3) wrapper,
339+ then run "make install_ulib" too. And refer to the aufs manual in
340+ detail.
341+
342+There several other patches in aufs4-standalone.git. They are all
343+optional. When you meet some problems, they will help you.
344+- aufs4-loopback.patch
345+ Supports a nested loopback mount in a branch-fs. This patch is
346+ unnecessary until aufs produces a message like "you may want to try
347+ another patch for loopback file".
348+- vfs-ino.patch
349+ Modifies a system global kernel internal function get_next_ino() in
350+ order to stop assigning 0 for an inode-number. Not directly related to
351+ aufs, but recommended generally.
352+- tmpfs-idr.patch
353+ Keeps the tmpfs inode number as the lowest value. Effective to reduce
354+ the size of aufs XINO files for tmpfs branch. Also it prevents the
355+ duplication of inode number, which is important for backup tools and
356+ other utilities. When you find aufs XINO files for tmpfs branch
357+ growing too much, try this patch.
358+- lockdep-debug.patch
359+ Because aufs is not only an ordinary filesystem (callee of VFS), but
360+ also a caller of VFS functions for branch filesystems, subclassing of
361+ the internal locks for LOCKDEP is necessary. LOCKDEP is a debugging
362+ feature of linux kernel. If you enable CONFIG_LOCKDEP, then you will
363+ need to apply this debug patch to expand several constant values.
364+ If don't know what LOCKDEP, then you don't have apply this patch.
365+
366+
367+4. Usage
368+----------------------------------------
369+At first, make sure aufs-util are installed, and please read the aufs
370+manual, aufs.5 in aufs-util.git tree.
371+$ man -l aufs.5
372+
373+And then,
374+$ mkdir /tmp/rw /tmp/aufs
375+# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs
376+
377+Here is another example. The result is equivalent.
378+# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs
379+ Or
380+# mount -t aufs -o br:/tmp/rw none /tmp/aufs
381+# mount -o remount,append:${HOME} /tmp/aufs
382+
383+Then, you can see whole tree of your home dir through /tmp/aufs. If
384+you modify a file under /tmp/aufs, the one on your home directory is
385+not affected, instead the same named file will be newly created under
386+/tmp/rw. And all of your modification to a file will be applied to
387+the one under /tmp/rw. This is called the file based Copy on Write
388+(COW) method.
389+Aufs mount options are described in aufs.5.
390+If you run chroot or something and make your aufs as a root directory,
391+then you need to customize the shutdown script. See the aufs manual in
392+detail.
393+
394+Additionally, there are some sample usages of aufs which are a
395+diskless system with network booting, and LiveCD over NFS.
396+See sample dir in CVS tree on SourceForge.
397+
398+
399+5. Contact
400+----------------------------------------
401+When you have any problems or strange behaviour in aufs, please let me
402+know with:
403+- /proc/mounts (instead of the output of mount(8))
404+- /sys/module/aufs/*
405+- /sys/fs/aufs/* (if you have them)
406+- /debug/aufs/* (if you have them)
407+- linux kernel version
408+ if your kernel is not plain, for example modified by distributor,
409+ the url where i can download its source is necessary too.
410+- aufs version which was printed at loading the module or booting the
411+ system, instead of the date you downloaded.
412+- configuration (define/undefine CONFIG_AUFS_xxx)
413+- kernel configuration or /proc/config.gz (if you have it)
414+- behaviour which you think to be incorrect
415+- actual operation, reproducible one is better
416+- mailto: aufs-users at lists.sourceforge.net
417+
418+Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches,
419+and Feature Requests) on SourceForge. Please join and write to
420+aufs-users ML.
421+
422+
423+6. Acknowledgements
424+----------------------------------------
425+Thanks to everyone who have tried and are using aufs, whoever
426+have reported a bug or any feedback.
427+
428+Especially donators:
429+Tomas Matejicek(slax.org) made a donation (much more than once).
430+ Since Apr 2010, Tomas M (the author of Slax and Linux Live
431+ scripts) is making "doubling" donations.
432+ Unfortunately I cannot list all of the donators, but I really
433+ appreciate.
434+ It ends Aug 2010, but the ordinary donation URL is still available.
435+ <http://sourceforge.net/donate/index.php?group_id=167503>
436+Dai Itasaka made a donation (2007/8).
437+Chuck Smith made a donation (2008/4, 10 and 12).
438+Henk Schoneveld made a donation (2008/9).
439+Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10).
440+Francois Dupoux made a donation (2008/11).
441+Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public
442+ aufs2 GIT tree (2009/2).
443+William Grant made a donation (2009/3).
444+Patrick Lane made a donation (2009/4).
445+The Mail Archive (mail-archive.com) made donations (2009/5).
446+Nippy Networks (Ed Wildgoose) made a donation (2009/7).
447+New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11).
448+Pavel Pronskiy made a donation (2011/2).
449+Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy
450+ Networks (Ed Wildgoose) made a donation for hardware (2011/3).
451+Max Lekomcev (DOM-TV project) made a donation (2011/7, 12, 2012/3, 6 and
452+11).
453+Sam Liddicott made a donation (2011/9).
454+Era Scarecrow made a donation (2013/4).
455+Bor Ratajc made a donation (2013/4).
456+Alessandro Gorreta made a donation (2013/4).
457+POIRETTE Marc made a donation (2013/4).
458+Alessandro Gorreta made a donation (2013/4).
459+lauri kasvandik made a donation (2013/5).
460+"pemasu from Finland" made a donation (2013/7).
461+The Parted Magic Project made a donation (2013/9 and 11).
462+Pavel Barta made a donation (2013/10).
463+Nikolay Pertsev made a donation (2014/5).
464+James B made a donation (2014/7 and 2015/7).
465+Stefano Di Biase made a donation (2014/8).
466+Daniel Epellei made a donation (2015/1).
467+OmegaPhil made a donation (2016/1).
468+Tomasz Szewczyk made a donation (2016/4).
469+James Burry made a donation (2016/12).
470+
471+Thank you very much.
472+Donations are always, including future donations, very important and
473+helpful for me to keep on developing aufs.
474+
475+
476+7.
477+----------------------------------------
478+If you are an experienced user, no explanation is needed. Aufs is
479+just a linux filesystem.
480+
481+
482+Enjoy!
483+
484+# Local variables: ;
485+# mode: text;
486+# End: ;
487diff -urNp -x '*.orig' linux-4.14/Documentation/filesystems/aufs/design/01intro.txt linux-4.14/Documentation/filesystems/aufs/design/01intro.txt
488--- linux-4.14/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 01:00:00.000000000 +0100
489+++ linux-4.14/Documentation/filesystems/aufs/design/01intro.txt 2021-02-24 21:42:43.437781422 +0100
1c60b727 490@@ -0,0 +1,171 @@
53392da6 491+
a2654f78 492+# Copyright (C) 2005-2017 Junjiro R. Okajima
53392da6
AM
493+#
494+# This program is free software; you can redistribute it and/or modify
495+# it under the terms of the GNU General Public License as published by
496+# the Free Software Foundation; either version 2 of the License, or
497+# (at your option) any later version.
498+#
499+# This program is distributed in the hope that it will be useful,
500+# but WITHOUT ANY WARRANTY; without even the implied warranty of
501+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
502+# GNU General Public License for more details.
503+#
504+# You should have received a copy of the GNU General Public License
523b37e3 505+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
506+
507+Introduction
508+----------------------------------------
509+
3c1bdaff 510+aufs [ei ju: ef es] | /ey-yoo-ef-es/ | [a u f s]
53392da6
AM
511+1. abbrev. for "advanced multi-layered unification filesystem".
512+2. abbrev. for "another unionfs".
513+3. abbrev. for "auf das" in German which means "on the" in English.
514+ Ex. "Butter aufs Brot"(G) means "butter onto bread"(E).
515+ But "Filesystem aufs Filesystem" is hard to understand.
1c60b727 516+4. abbrev. for "African Urban Fashion Show".
53392da6
AM
517+
518+AUFS is a filesystem with features:
519+- multi layered stackable unification filesystem, the member directory
520+ is called as a branch.
521+- branch permission and attribute, 'readonly', 'real-readonly',
7e9cd9fe 522+ 'readwrite', 'whiteout-able', 'link-able whiteout', etc. and their
53392da6
AM
523+ combination.
524+- internal "file copy-on-write".
525+- logical deletion, whiteout.
526+- dynamic branch manipulation, adding, deleting and changing permission.
527+- allow bypassing aufs, user's direct branch access.
528+- external inode number translation table and bitmap which maintains the
529+ persistent aufs inode number.
530+- seekable directory, including NFS readdir.
531+- file mapping, mmap and sharing pages.
532+- pseudo-link, hardlink over branches.
533+- loopback mounted filesystem as a branch.
534+- several policies to select one among multiple writable branches.
535+- revert a single systemcall when an error occurs in aufs.
536+- and more...
537+
538+
539+Multi Layered Stackable Unification Filesystem
540+----------------------------------------------------------------------
541+Most people already knows what it is.
542+It is a filesystem which unifies several directories and provides a
543+merged single directory. When users access a file, the access will be
544+passed/re-directed/converted (sorry, I am not sure which English word is
545+correct) to the real file on the member filesystem. The member
546+filesystem is called 'lower filesystem' or 'branch' and has a mode
547+'readonly' and 'readwrite.' And the deletion for a file on the lower
548+readonly branch is handled by creating 'whiteout' on the upper writable
549+branch.
550+
551+On LKML, there have been discussions about UnionMount (Jan Blunck,
552+Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took
553+different approaches to implement the merged-view.
554+The former tries putting it into VFS, and the latter implements as a
555+separate filesystem.
556+(If I misunderstand about these implementations, please let me know and
557+I shall correct it. Because it is a long time ago when I read their
558+source files last time).
559+
560+UnionMount's approach will be able to small, but may be hard to share
561+branches between several UnionMount since the whiteout in it is
562+implemented in the inode on branch filesystem and always
563+shared. According to Bharata's post, readdir does not seems to be
564+finished yet.
565+There are several missing features known in this implementations such as
566+- for users, the inode number may change silently. eg. copy-up.
567+- link(2) may break by copy-up.
568+- read(2) may get an obsoleted filedata (fstat(2) too).
569+- fcntl(F_SETLK) may be broken by copy-up.
570+- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after
571+ open(O_RDWR).
572+
7e9cd9fe
AM
573+In linux-3.18, "overlay" filesystem (formerly known as "overlayfs") was
574+merged into mainline. This is another implementation of UnionMount as a
575+separated filesystem. All the limitations and known problems which
576+UnionMount are equally inherited to "overlay" filesystem.
577+
578+Unionfs has a longer history. When I started implementing a stackable
579+filesystem (Aug 2005), it already existed. It has virtual super_block,
580+inode, dentry and file objects and they have an array pointing lower
581+same kind objects. After contributing many patches for Unionfs, I
582+re-started my project AUFS (Jun 2006).
53392da6
AM
583+
584+In AUFS, the structure of filesystem resembles to Unionfs, but I
585+implemented my own ideas, approaches and enhancements and it became
586+totally different one.
587+
588+Comparing DM snapshot and fs based implementation
589+- the number of bytes to be copied between devices is much smaller.
590+- the type of filesystem must be one and only.
591+- the fs must be writable, no readonly fs, even for the lower original
592+ device. so the compression fs will not be usable. but if we use
593+ loopback mount, we may address this issue.
594+ for instance,
595+ mount /cdrom/squashfs.img /sq
596+ losetup /sq/ext2.img
597+ losetup /somewhere/cow
598+ dmsetup "snapshot /dev/loop0 /dev/loop1 ..."
599+- it will be difficult (or needs more operations) to extract the
600+ difference between the original device and COW.
601+- DM snapshot-merge may help a lot when users try merging. in the
602+ fs-layer union, users will use rsync(1).
603+
7e9cd9fe
AM
604+You may want to read my old paper "Filesystems in LiveCD"
605+(http://aufs.sourceforge.net/aufs2/report/sq/sq.pdf).
53392da6 606+
7e9cd9fe
AM
607+
608+Several characters/aspects/persona of aufs
53392da6
AM
609+----------------------------------------------------------------------
610+
7e9cd9fe 611+Aufs has several characters, aspects or persona.
53392da6
AM
612+1. a filesystem, callee of VFS helper
613+2. sub-VFS, caller of VFS helper for branches
614+3. a virtual filesystem which maintains persistent inode number
615+4. reader/writer of files on branches such like an application
616+
617+1. Callee of VFS Helper
618+As an ordinary linux filesystem, aufs is a callee of VFS. For instance,
619+unlink(2) from an application reaches sys_unlink() kernel function and
620+then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it
621+calls filesystem specific unlink operation. Actually aufs implements the
622+unlink operation but it behaves like a redirector.
623+
624+2. Caller of VFS Helper for Branches
625+aufs_unlink() passes the unlink request to the branch filesystem as if
626+it were called from VFS. So the called unlink operation of the branch
627+filesystem acts as usual. As a caller of VFS helper, aufs should handle
628+every necessary pre/post operation for the branch filesystem.
629+- acquire the lock for the parent dir on a branch
630+- lookup in a branch
631+- revalidate dentry on a branch
632+- mnt_want_write() for a branch
633+- vfs_unlink() for a branch
634+- mnt_drop_write() for a branch
635+- release the lock on a branch
636+
637+3. Persistent Inode Number
638+One of the most important issue for a filesystem is to maintain inode
639+numbers. This is particularly important to support exporting a
640+filesystem via NFS. Aufs is a virtual filesystem which doesn't have a
641+backend block device for its own. But some storage is necessary to
7e9cd9fe
AM
642+keep and maintain the inode numbers. It may be a large space and may not
643+suit to keep in memory. Aufs rents some space from its first writable
644+branch filesystem (by default) and creates file(s) on it. These files
645+are created by aufs internally and removed soon (currently) keeping
646+opened.
53392da6
AM
647+Note: Because these files are removed, they are totally gone after
648+ unmounting aufs. It means the inode numbers are not persistent
649+ across unmount or reboot. I have a plan to make them really
650+ persistent which will be important for aufs on NFS server.
651+
652+4. Read/Write Files Internally (copy-on-write)
653+Because a branch can be readonly, when you write a file on it, aufs will
654+"copy-up" it to the upper writable branch internally. And then write the
655+originally requested thing to the file. Generally kernel doesn't
656+open/read/write file actively. In aufs, even a single write may cause a
657+internal "file copy". This behaviour is very similar to cp(1) command.
658+
659+Some people may think it is better to pass such work to user space
660+helper, instead of doing in kernel space. Actually I am still thinking
661+about it. But currently I have implemented it in kernel space.
0b1ff5c3
JR
662diff -urNp -x '*.orig' linux-4.14/Documentation/filesystems/aufs/design/02struct.txt linux-4.14/Documentation/filesystems/aufs/design/02struct.txt
663--- linux-4.14/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 01:00:00.000000000 +0100
664+++ linux-4.14/Documentation/filesystems/aufs/design/02struct.txt 2021-02-24 21:42:43.437781422 +0100
7e9cd9fe 665@@ -0,0 +1,258 @@
53392da6 666+
a2654f78 667+# Copyright (C) 2005-2017 Junjiro R. Okajima
53392da6
AM
668+#
669+# This program is free software; you can redistribute it and/or modify
670+# it under the terms of the GNU General Public License as published by
671+# the Free Software Foundation; either version 2 of the License, or
672+# (at your option) any later version.
673+#
674+# This program is distributed in the hope that it will be useful,
675+# but WITHOUT ANY WARRANTY; without even the implied warranty of
676+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
677+# GNU General Public License for more details.
678+#
679+# You should have received a copy of the GNU General Public License
523b37e3 680+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
681+
682+Basic Aufs Internal Structure
683+
684+Superblock/Inode/Dentry/File Objects
685+----------------------------------------------------------------------
686+As like an ordinary filesystem, aufs has its own
687+superblock/inode/dentry/file objects. All these objects have a
688+dynamically allocated array and store the same kind of pointers to the
689+lower filesystem, branch.
690+For example, when you build a union with one readwrite branch and one
691+readonly, mounted /au, /rw and /ro respectively.
692+- /au = /rw + /ro
693+- /ro/fileA exists but /rw/fileA
694+
695+Aufs lookup operation finds /ro/fileA and gets dentry for that. These
696+pointers are stored in a aufs dentry. The array in aufs dentry will be,
7e9cd9fe 697+- [0] = NULL (because /rw/fileA doesn't exist)
53392da6
AM
698+- [1] = /ro/fileA
699+
700+This style of an array is essentially same to the aufs
701+superblock/inode/dentry/file objects.
702+
703+Because aufs supports manipulating branches, ie. add/delete/change
7e9cd9fe
AM
704+branches dynamically, these objects has its own generation. When
705+branches are changed, the generation in aufs superblock is
706+incremented. And a generation in other object are compared when it is
707+accessed. When a generation in other objects are obsoleted, aufs
708+refreshes the internal array.
53392da6
AM
709+
710+
711+Superblock
712+----------------------------------------------------------------------
713+Additionally aufs superblock has some data for policies to select one
714+among multiple writable branches, XIB files, pseudo-links and kobject.
715+See below in detail.
7e9cd9fe
AM
716+About the policies which supports copy-down a directory, see
717+wbr_policy.txt too.
53392da6
AM
718+
719+
720+Branch and XINO(External Inode Number Translation Table)
721+----------------------------------------------------------------------
722+Every branch has its own xino (external inode number translation table)
723+file. The xino file is created and unlinked by aufs internally. When two
724+members of a union exist on the same filesystem, they share the single
725+xino file.
726+The struct of a xino file is simple, just a sequence of aufs inode
727+numbers which is indexed by the lower inode number.
728+In the above sample, assume the inode number of /ro/fileA is i111 and
729+aufs assigns the inode number i999 for fileA. Then aufs writes 999 as
730+4(8) bytes at 111 * 4(8) bytes offset in the xino file.
731+
732+When the inode numbers are not contiguous, the xino file will be sparse
733+which has a hole in it and doesn't consume as much disk space as it
734+might appear. If your branch filesystem consumes disk space for such
735+holes, then you should specify 'xino=' option at mounting aufs.
736+
7e9cd9fe
AM
737+Aufs has a mount option to free the disk blocks for such holes in XINO
738+files on tmpfs or ramdisk. But it is not so effective actually. If you
739+meet a problem of disk shortage due to XINO files, then you should try
740+"tmpfs-ino.patch" (and "vfs-ino.patch" too) in aufs4-standalone.git.
741+The patch localizes the assignment inumbers per tmpfs-mount and avoid
742+the holes in XINO files.
743+
53392da6 744+Also a writable branch has three kinds of "whiteout bases". All these
7e9cd9fe 745+are existed when the branch is joined to aufs, and their names are
53392da6
AM
746+whiteout-ed doubly, so that users will never see their names in aufs
747+hierarchy.
7e9cd9fe 748+1. a regular file which will be hardlinked to all whiteouts.
53392da6 749+2. a directory to store a pseudo-link.
7e9cd9fe 750+3. a directory to store an "orphan"-ed file temporary.
53392da6
AM
751+
752+1. Whiteout Base
753+ When you remove a file on a readonly branch, aufs handles it as a
754+ logical deletion and creates a whiteout on the upper writable branch
755+ as a hardlink of this file in order not to consume inode on the
756+ writable branch.
757+2. Pseudo-link Dir
758+ See below, Pseudo-link.
759+3. Step-Parent Dir
760+ When "fileC" exists on the lower readonly branch only and it is
761+ opened and removed with its parent dir, and then user writes
762+ something into it, then aufs copies-up fileC to this
763+ directory. Because there is no other dir to store fileC. After
764+ creating a file under this dir, the file is unlinked.
765+
766+Because aufs supports manipulating branches, ie. add/delete/change
7e9cd9fe
AM
767+dynamically, a branch has its own id. When the branch order changes,
768+aufs finds the new index by searching the branch id.
53392da6
AM
769+
770+
771+Pseudo-link
772+----------------------------------------------------------------------
773+Assume "fileA" exists on the lower readonly branch only and it is
774+hardlinked to "fileB" on the branch. When you write something to fileA,
775+aufs copies-up it to the upper writable branch. Additionally aufs
776+creates a hardlink under the Pseudo-link Directory of the writable
777+branch. The inode of a pseudo-link is kept in aufs super_block as a
778+simple list. If fileB is read after unlinking fileA, aufs returns
779+filedata from the pseudo-link instead of the lower readonly
780+branch. Because the pseudo-link is based upon the inode, to keep the
7e9cd9fe 781+inode number by xino (see above) is essentially necessary.
53392da6
AM
782+
783+All the hardlinks under the Pseudo-link Directory of the writable branch
784+should be restored in a proper location later. Aufs provides a utility
785+to do this. The userspace helpers executed at remounting and unmounting
786+aufs by default.
787+During this utility is running, it puts aufs into the pseudo-link
788+maintenance mode. In this mode, only the process which began the
789+maintenance mode (and its child processes) is allowed to operate in
790+aufs. Some other processes which are not related to the pseudo-link will
791+be allowed to run too, but the rest have to return an error or wait
792+until the maintenance mode ends. If a process already acquires an inode
793+mutex (in VFS), it has to return an error.
794+
795+
796+XIB(external inode number bitmap)
797+----------------------------------------------------------------------
798+Addition to the xino file per a branch, aufs has an external inode number
7e9cd9fe
AM
799+bitmap in a superblock object. It is also an internal file such like a
800+xino file.
53392da6
AM
801+It is a simple bitmap to mark whether the aufs inode number is in-use or
802+not.
803+To reduce the file I/O, aufs prepares a single memory page to cache xib.
804+
7e9cd9fe 805+As well as XINO files, aufs has a feature to truncate/refresh XIB to
53392da6
AM
806+reduce the number of consumed disk blocks for these files.
807+
808+
809+Virtual or Vertical Dir, and Readdir in Userspace
810+----------------------------------------------------------------------
811+In order to support multiple layers (branches), aufs readdir operation
812+constructs a virtual dir block on memory. For readdir, aufs calls
813+vfs_readdir() internally for each dir on branches, merges their entries
814+with eliminating the whiteout-ed ones, and sets it to file (dir)
815+object. So the file object has its entry list until it is closed. The
816+entry list will be updated when the file position is zero and becomes
7e9cd9fe 817+obsoleted. This decision is made in aufs automatically.
53392da6
AM
818+
819+The dynamically allocated memory block for the name of entries has a
820+unit of 512 bytes (by default) and stores the names contiguously (no
821+padding). Another block for each entry is handled by kmem_cache too.
822+During building dir blocks, aufs creates hash list and judging whether
823+the entry is whiteouted by its upper branch or already listed.
824+The merged result is cached in the corresponding inode object and
825+maintained by a customizable life-time option.
826+
827+Some people may call it can be a security hole or invite DoS attack
828+since the opened and once readdir-ed dir (file object) holds its entry
829+list and becomes a pressure for system memory. But I'd say it is similar
830+to files under /proc or /sys. The virtual files in them also holds a
831+memory page (generally) while they are opened. When an idea to reduce
832+memory for them is introduced, it will be applied to aufs too.
833+For those who really hate this situation, I've developed readdir(3)
834+library which operates this merging in userspace. You just need to set
835+LD_PRELOAD environment variable, and aufs will not consume no memory in
836+kernel space for readdir(3).
837+
838+
839+Workqueue
840+----------------------------------------------------------------------
841+Aufs sometimes requires privilege access to a branch. For instance,
842+in copy-up/down operation. When a user process is going to make changes
843+to a file which exists in the lower readonly branch only, and the mode
844+of one of ancestor directories may not be writable by a user
845+process. Here aufs copy-up the file with its ancestors and they may
846+require privilege to set its owner/group/mode/etc.
847+This is a typical case of a application character of aufs (see
848+Introduction).
849+
850+Aufs uses workqueue synchronously for this case. It creates its own
851+workqueue. The workqueue is a kernel thread and has privilege. Aufs
852+passes the request to call mkdir or write (for example), and wait for
853+its completion. This approach solves a problem of a signal handler
854+simply.
855+If aufs didn't adopt the workqueue and changed the privilege of the
7e9cd9fe
AM
856+process, then the process may receive the unexpected SIGXFSZ or other
857+signals.
53392da6
AM
858+
859+Also aufs uses the system global workqueue ("events" kernel thread) too
860+for asynchronous tasks, such like handling inotify/fsnotify, re-creating a
861+whiteout base and etc. This is unrelated to a privilege.
862+Most of aufs operation tries acquiring a rw_semaphore for aufs
863+superblock at the beginning, at the same time waits for the completion
864+of all queued asynchronous tasks.
865+
866+
867+Whiteout
868+----------------------------------------------------------------------
869+The whiteout in aufs is very similar to Unionfs's. That is represented
870+by its filename. UnionMount takes an approach of a file mode, but I am
871+afraid several utilities (find(1) or something) will have to support it.
872+
873+Basically the whiteout represents "logical deletion" which stops aufs to
874+lookup further, but also it represents "dir is opaque" which also stop
7e9cd9fe 875+further lookup.
53392da6
AM
876+
877+In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively.
878+In order to make several functions in a single systemcall to be
879+revertible, aufs adopts an approach to rename a directory to a temporary
880+unique whiteouted name.
881+For example, in rename(2) dir where the target dir already existed, aufs
882+renames the target dir to a temporary unique whiteouted name before the
7e9cd9fe 883+actual rename on a branch, and then handles other actions (make it opaque,
53392da6
AM
884+update the attributes, etc). If an error happens in these actions, aufs
885+simply renames the whiteouted name back and returns an error. If all are
886+succeeded, aufs registers a function to remove the whiteouted unique
887+temporary name completely and asynchronously to the system global
888+workqueue.
889+
890+
891+Copy-up
892+----------------------------------------------------------------------
893+It is a well-known feature or concept.
894+When user modifies a file on a readonly branch, aufs operate "copy-up"
895+internally and makes change to the new file on the upper writable branch.
896+When the trigger systemcall does not update the timestamps of the parent
897+dir, aufs reverts it after copy-up.
c2b27bf2
AM
898+
899+
900+Move-down (aufs3.9 and later)
901+----------------------------------------------------------------------
902+"Copy-up" is one of the essential feature in aufs. It copies a file from
903+the lower readonly branch to the upper writable branch when a user
904+changes something about the file.
905+"Move-down" is an opposite action of copy-up. Basically this action is
906+ran manually instead of automatically and internally.
076b876e
AM
907+For desgin and implementation, aufs has to consider these issues.
908+- whiteout for the file may exist on the lower branch.
909+- ancestor directories may not exist on the lower branch.
910+- diropq for the ancestor directories may exist on the upper branch.
911+- free space on the lower branch will reduce.
912+- another access to the file may happen during moving-down, including
7e9cd9fe 913+ UDBA (see "Revalidate Dentry and UDBA").
076b876e
AM
914+- the file should not be hard-linked nor pseudo-linked. they should be
915+ handled by auplink utility later.
c2b27bf2
AM
916+
917+Sometimes users want to move-down a file from the upper writable branch
918+to the lower readonly or writable branch. For instance,
919+- the free space of the upper writable branch is going to run out.
920+- create a new intermediate branch between the upper and lower branch.
921+- etc.
922+
923+For this purpose, use "aumvdown" command in aufs-util.git.
0b1ff5c3
JR
924diff -urNp -x '*.orig' linux-4.14/Documentation/filesystems/aufs/design/03atomic_open.txt linux-4.14/Documentation/filesystems/aufs/design/03atomic_open.txt
925--- linux-4.14/Documentation/filesystems/aufs/design/03atomic_open.txt 1970-01-01 01:00:00.000000000 +0100
926+++ linux-4.14/Documentation/filesystems/aufs/design/03atomic_open.txt 2021-02-24 21:42:43.437781422 +0100
b912730e
AM
927@@ -0,0 +1,85 @@
928+
a2654f78 929+# Copyright (C) 2015-2017 Junjiro R. Okajima
b912730e
AM
930+#
931+# This program is free software; you can redistribute it and/or modify
932+# it under the terms of the GNU General Public License as published by
933+# the Free Software Foundation; either version 2 of the License, or
934+# (at your option) any later version.
935+#
936+# This program is distributed in the hope that it will be useful,
937+# but WITHOUT ANY WARRANTY; without even the implied warranty of
938+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
939+# GNU General Public License for more details.
940+#
941+# You should have received a copy of the GNU General Public License
942+# along with this program. If not, see <http://www.gnu.org/licenses/>.
943+
944+Support for a branch who has its ->atomic_open()
945+----------------------------------------------------------------------
946+The filesystems who implement its ->atomic_open() are not majority. For
947+example NFSv4 does, and aufs should call NFSv4 ->atomic_open,
948+particularly for open(O_CREAT|O_EXCL, 0400) case. Other than
949+->atomic_open(), NFSv4 returns an error for this open(2). While I am not
950+sure whether all filesystems who have ->atomic_open() behave like this,
951+but NFSv4 surely returns the error.
952+
953+In order to support ->atomic_open() for aufs, there are a few
954+approaches.
955+
956+A. Introduce aufs_atomic_open()
957+ - calls one of VFS:do_last(), lookup_open() or atomic_open() for
958+ branch fs.
959+B. Introduce aufs_atomic_open() calling create, open and chmod. this is
960+ an aufs user Pip Cet's approach
961+ - calls aufs_create(), VFS finish_open() and notify_change().
962+ - pass fake-mode to finish_open(), and then correct the mode by
963+ notify_change().
964+C. Extend aufs_open() to call branch fs's ->atomic_open()
965+ - no aufs_atomic_open().
966+ - aufs_lookup() registers the TID to an aufs internal object.
967+ - aufs_create() does nothing when the matching TID is registered, but
968+ registers the mode.
969+ - aufs_open() calls branch fs's ->atomic_open() when the matching
970+ TID is registered.
971+D. Extend aufs_open() to re-try branch fs's ->open() with superuser's
972+ credential
973+ - no aufs_atomic_open().
974+ - aufs_create() registers the TID to an internal object. this info
975+ represents "this process created this file just now."
976+ - when aufs gets EACCES from branch fs's ->open(), then confirm the
977+ registered TID and re-try open() with superuser's credential.
978+
979+Pros and cons for each approach.
980+
981+A.
982+ - straightforward but highly depends upon VFS internal.
983+ - the atomic behavaiour is kept.
984+ - some of parameters such as nameidata are hard to reproduce for
985+ branch fs.
986+ - large overhead.
987+B.
988+ - easy to implement.
989+ - the atomic behavaiour is lost.
990+C.
991+ - the atomic behavaiour is kept.
992+ - dirty and tricky.
993+ - VFS checks whether the file is created correctly after calling
994+ ->create(), which means this approach doesn't work.
995+D.
996+ - easy to implement.
997+ - the atomic behavaiour is lost.
998+ - to open a file with superuser's credential and give it to a user
999+ process is a bad idea, since the file object keeps the credential
1000+ in it. It may affect LSM or something. This approach doesn't work
1001+ either.
1002+
1003+The approach A is ideal, but it hard to implement. So here is a
1004+variation of A, which is to be implemented.
1005+
1006+A-1. Introduce aufs_atomic_open()
1007+ - calls branch fs ->atomic_open() if exists. otherwise calls
1008+ vfs_create() and finish_open().
1009+ - the demerit is that the several checks after branch fs
1010+ ->atomic_open() are lost. in the ordinary case, the checks are
1011+ done by VFS:do_last(), lookup_open() and atomic_open(). some can
1012+ be implemented in aufs, but not all I am afraid.
0b1ff5c3
JR
1013diff -urNp -x '*.orig' linux-4.14/Documentation/filesystems/aufs/design/03lookup.txt linux-4.14/Documentation/filesystems/aufs/design/03lookup.txt
1014--- linux-4.14/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 01:00:00.000000000 +0100
1015+++ linux-4.14/Documentation/filesystems/aufs/design/03lookup.txt 2021-02-24 21:42:43.437781422 +0100
7e9cd9fe 1016@@ -0,0 +1,113 @@
53392da6 1017+
a2654f78 1018+# Copyright (C) 2005-2017 Junjiro R. Okajima
53392da6
AM
1019+#
1020+# This program is free software; you can redistribute it and/or modify
1021+# it under the terms of the GNU General Public License as published by
1022+# the Free Software Foundation; either version 2 of the License, or
1023+# (at your option) any later version.
1024+#
1025+# This program is distributed in the hope that it will be useful,
1026+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1027+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1028+# GNU General Public License for more details.
1029+#
1030+# You should have received a copy of the GNU General Public License
523b37e3 1031+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1032+
1033+Lookup in a Branch
1034+----------------------------------------------------------------------
1035+Since aufs has a character of sub-VFS (see Introduction), it operates
7e9cd9fe
AM
1036+lookup for branches as VFS does. It may be a heavy work. But almost all
1037+lookup operation in aufs is the simplest case, ie. lookup only an entry
1038+directly connected to its parent. Digging down the directory hierarchy
1039+is unnecessary. VFS has a function lookup_one_len() for that use, and
1040+aufs calls it.
1041+
1042+When a branch is a remote filesystem, aufs basically relies upon its
53392da6
AM
1043+->d_revalidate(), also aufs forces the hardest revalidate tests for
1044+them.
1045+For d_revalidate, aufs implements three levels of revalidate tests. See
1046+"Revalidate Dentry and UDBA" in detail.
1047+
1048+
076b876e
AM
1049+Test Only the Highest One for the Directory Permission (dirperm1 option)
1050+----------------------------------------------------------------------
1051+Let's try case study.
1052+- aufs has two branches, upper readwrite and lower readonly.
1053+ /au = /rw + /ro
1054+- "dirA" exists under /ro, but /rw. and its mode is 0700.
1055+- user invoked "chmod a+rx /au/dirA"
1056+- the internal copy-up is activated and "/rw/dirA" is created and its
7e9cd9fe 1057+ permission bits are set to world readable.
076b876e
AM
1058+- then "/au/dirA" becomes world readable?
1059+
1060+In this case, /ro/dirA is still 0700 since it exists in readonly branch,
1061+or it may be a natively readonly filesystem. If aufs respects the lower
1062+branch, it should not respond readdir request from other users. But user
1063+allowed it by chmod. Should really aufs rejects showing the entries
1064+under /ro/dirA?
1065+
7e9cd9fe
AM
1066+To be honest, I don't have a good solution for this case. So aufs
1067+implements 'dirperm1' and 'nodirperm1' mount options, and leave it to
1068+users.
076b876e
AM
1069+When dirperm1 is specified, aufs checks only the highest one for the
1070+directory permission, and shows the entries. Otherwise, as usual, checks
1071+every dir existing on all branches and rejects the request.
1072+
1073+As a side effect, dirperm1 option improves the performance of aufs
1074+because the number of permission check is reduced when the number of
1075+branch is many.
1076+
1077+
53392da6
AM
1078+Revalidate Dentry and UDBA (User's Direct Branch Access)
1079+----------------------------------------------------------------------
1080+Generally VFS helpers re-validate a dentry as a part of lookup.
1081+0. digging down the directory hierarchy.
1082+1. lock the parent dir by its i_mutex.
1083+2. lookup the final (child) entry.
1084+3. revalidate it.
1085+4. call the actual operation (create, unlink, etc.)
1086+5. unlock the parent dir
1087+
1088+If the filesystem implements its ->d_revalidate() (step 3), then it is
1089+called. Actually aufs implements it and checks the dentry on a branch is
1090+still valid.
1091+But it is not enough. Because aufs has to release the lock for the
1092+parent dir on a branch at the end of ->lookup() (step 2) and
1093+->d_revalidate() (step 3) while the i_mutex of the aufs dir is still
1094+held by VFS.
1095+If the file on a branch is changed directly, eg. bypassing aufs, after
1096+aufs released the lock, then the subsequent operation may cause
1097+something unpleasant result.
1098+
1099+This situation is a result of VFS architecture, ->lookup() and
1100+->d_revalidate() is separated. But I never say it is wrong. It is a good
1101+design from VFS's point of view. It is just not suitable for sub-VFS
1102+character in aufs.
1103+
1104+Aufs supports such case by three level of revalidation which is
1105+selectable by user.
1106+1. Simple Revalidate
1107+ Addition to the native flow in VFS's, confirm the child-parent
1108+ relationship on the branch just after locking the parent dir on the
1109+ branch in the "actual operation" (step 4). When this validation
1110+ fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still
1111+ checks the validation of the dentry on branches.
1112+2. Monitor Changes Internally by Inotify/Fsnotify
1113+ Addition to above, in the "actual operation" (step 4) aufs re-lookup
1114+ the dentry on the branch, and returns EBUSY if it finds different
1115+ dentry.
1116+ Additionally, aufs sets the inotify/fsnotify watch for every dir on branches
1117+ during it is in cache. When the event is notified, aufs registers a
1118+ function to kernel 'events' thread by schedule_work(). And the
1119+ function sets some special status to the cached aufs dentry and inode
1120+ private data. If they are not cached, then aufs has nothing to
1121+ do. When the same file is accessed through aufs (step 0-3) later,
1122+ aufs will detect the status and refresh all necessary data.
1123+ In this mode, aufs has to ignore the event which is fired by aufs
1124+ itself.
1125+3. No Extra Validation
1126+ This is the simplest test and doesn't add any additional revalidation
7e9cd9fe 1127+ test, and skip the revalidation in step 4. It is useful and improves
53392da6
AM
1128+ aufs performance when system surely hide the aufs branches from user,
1129+ by over-mounting something (or another method).
0b1ff5c3
JR
1130diff -urNp -x '*.orig' linux-4.14/Documentation/filesystems/aufs/design/04branch.txt linux-4.14/Documentation/filesystems/aufs/design/04branch.txt
1131--- linux-4.14/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 01:00:00.000000000 +0100
1132+++ linux-4.14/Documentation/filesystems/aufs/design/04branch.txt 2021-02-24 21:42:43.437781422 +0100
7e9cd9fe 1133@@ -0,0 +1,74 @@
53392da6 1134+
a2654f78 1135+# Copyright (C) 2005-2017 Junjiro R. Okajima
53392da6
AM
1136+#
1137+# This program is free software; you can redistribute it and/or modify
1138+# it under the terms of the GNU General Public License as published by
1139+# the Free Software Foundation; either version 2 of the License, or
1140+# (at your option) any later version.
1141+#
1142+# This program is distributed in the hope that it will be useful,
1143+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1144+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1145+# GNU General Public License for more details.
1146+#
1147+# You should have received a copy of the GNU General Public License
523b37e3 1148+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1149+
1150+Branch Manipulation
1151+
1152+Since aufs supports dynamic branch manipulation, ie. add/remove a branch
1153+and changing its permission/attribute, there are a lot of works to do.
1154+
1155+
1156+Add a Branch
1157+----------------------------------------------------------------------
1158+o Confirm the adding dir exists outside of aufs, including loopback
7e9cd9fe 1159+ mount, and its various attributes.
53392da6
AM
1160+o Initialize the xino file and whiteout bases if necessary.
1161+ See struct.txt.
1162+
1163+o Check the owner/group/mode of the directory
1164+ When the owner/group/mode of the adding directory differs from the
1165+ existing branch, aufs issues a warning because it may impose a
1166+ security risk.
1167+ For example, when a upper writable branch has a world writable empty
1168+ top directory, a malicious user can create any files on the writable
1169+ branch directly, like copy-up and modify manually. If something like
1170+ /etc/{passwd,shadow} exists on the lower readonly branch but the upper
1171+ writable branch, and the writable branch is world-writable, then a
1172+ malicious guy may create /etc/passwd on the writable branch directly
1173+ and the infected file will be valid in aufs.
7e9cd9fe 1174+ I am afraid it can be a security issue, but aufs can do nothing except
53392da6
AM
1175+ producing a warning.
1176+
1177+
1178+Delete a Branch
1179+----------------------------------------------------------------------
1180+o Confirm the deleting branch is not busy
1181+ To be general, there is one merit to adopt "remount" interface to
1182+ manipulate branches. It is to discard caches. At deleting a branch,
1183+ aufs checks the still cached (and connected) dentries and inodes. If
1184+ there are any, then they are all in-use. An inode without its
1185+ corresponding dentry can be alive alone (for example, inotify/fsnotify case).
1186+
1187+ For the cached one, aufs checks whether the same named entry exists on
1188+ other branches.
1189+ If the cached one is a directory, because aufs provides a merged view
1190+ to users, as long as one dir is left on any branch aufs can show the
1191+ dir to users. In this case, the branch can be removed from aufs.
1192+ Otherwise aufs rejects deleting the branch.
1193+
1194+ If any file on the deleting branch is opened by aufs, then aufs
1195+ rejects deleting.
1196+
1197+
1198+Modify the Permission of a Branch
1199+----------------------------------------------------------------------
1200+o Re-initialize or remove the xino file and whiteout bases if necessary.
1201+ See struct.txt.
1202+
1203+o rw --> ro: Confirm the modifying branch is not busy
1204+ Aufs rejects the request if any of these conditions are true.
1205+ - a file on the branch is mmap-ed.
1206+ - a regular file on the branch is opened for write and there is no
1207+ same named entry on the upper branch.
0b1ff5c3
JR
1208diff -urNp -x '*.orig' linux-4.14/Documentation/filesystems/aufs/design/05wbr_policy.txt linux-4.14/Documentation/filesystems/aufs/design/05wbr_policy.txt
1209--- linux-4.14/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 01:00:00.000000000 +0100
1210+++ linux-4.14/Documentation/filesystems/aufs/design/05wbr_policy.txt 2021-02-24 21:42:43.437781422 +0100
523b37e3 1211@@ -0,0 +1,64 @@
53392da6 1212+
a2654f78 1213+# Copyright (C) 2005-2017 Junjiro R. Okajima
53392da6
AM
1214+#
1215+# This program is free software; you can redistribute it and/or modify
1216+# it under the terms of the GNU General Public License as published by
1217+# the Free Software Foundation; either version 2 of the License, or
1218+# (at your option) any later version.
1219+#
1220+# This program is distributed in the hope that it will be useful,
1221+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1222+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1223+# GNU General Public License for more details.
1224+#
1225+# You should have received a copy of the GNU General Public License
523b37e3 1226+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1227+
1228+Policies to Select One among Multiple Writable Branches
1229+----------------------------------------------------------------------
1230+When the number of writable branch is more than one, aufs has to decide
1231+the target branch for file creation or copy-up. By default, the highest
1232+writable branch which has the parent (or ancestor) dir of the target
1233+file is chosen (top-down-parent policy).
1234+By user's request, aufs implements some other policies to select the
7e9cd9fe
AM
1235+writable branch, for file creation several policies, round-robin,
1236+most-free-space, and other policies. For copy-up, top-down-parent,
1237+bottom-up-parent, bottom-up and others.
53392da6
AM
1238+
1239+As expected, the round-robin policy selects the branch in circular. When
1240+you have two writable branches and creates 10 new files, 5 files will be
1241+created for each branch. mkdir(2) systemcall is an exception. When you
1242+create 10 new directories, all will be created on the same branch.
1243+And the most-free-space policy selects the one which has most free
1244+space among the writable branches. The amount of free space will be
1245+checked by aufs internally, and users can specify its time interval.
1246+
1247+The policies for copy-up is more simple,
1248+top-down-parent is equivalent to the same named on in create policy,
1249+bottom-up-parent selects the writable branch where the parent dir
1250+exists and the nearest upper one from the copyup-source,
1251+bottom-up selects the nearest upper writable branch from the
1252+copyup-source, regardless the existence of the parent dir.
1253+
1254+There are some rules or exceptions to apply these policies.
1255+- If there is a readonly branch above the policy-selected branch and
1256+ the parent dir is marked as opaque (a variation of whiteout), or the
1257+ target (creating) file is whiteout-ed on the upper readonly branch,
1258+ then the result of the policy is ignored and the target file will be
1259+ created on the nearest upper writable branch than the readonly branch.
1260+- If there is a writable branch above the policy-selected branch and
1261+ the parent dir is marked as opaque or the target file is whiteouted
1262+ on the branch, then the result of the policy is ignored and the target
1263+ file will be created on the highest one among the upper writable
1264+ branches who has diropq or whiteout. In case of whiteout, aufs removes
1265+ it as usual.
1266+- link(2) and rename(2) systemcalls are exceptions in every policy.
1267+ They try selecting the branch where the source exists as possible
1268+ since copyup a large file will take long time. If it can't be,
1269+ ie. the branch where the source exists is readonly, then they will
1270+ follow the copyup policy.
1271+- There is an exception for rename(2) when the target exists.
1272+ If the rename target exists, aufs compares the index of the branches
1273+ where the source and the target exists and selects the higher
1274+ one. If the selected branch is readonly, then aufs follows the
1275+ copyup policy.
0b1ff5c3
JR
1276diff -urNp -x '*.orig' linux-4.14/Documentation/filesystems/aufs/design/06dirren.dot linux-4.14/Documentation/filesystems/aufs/design/06dirren.dot
1277--- linux-4.14/Documentation/filesystems/aufs/design/06dirren.dot 1970-01-01 01:00:00.000000000 +0100
1278+++ linux-4.14/Documentation/filesystems/aufs/design/06dirren.dot 2021-02-24 21:42:43.437781422 +0100
8b6a4947
AM
1279@@ -0,0 +1,31 @@
1280+
1281+// to view this graph, run dot(1) command in GRAPHVIZ.
1282+
1283+digraph G {
1284+node [shape=box];
1285+whinfo [label="detailed info file\n(lower_brid_root-hinum, h_inum, namelen, old name)"];
1286+
1287+node [shape=oval];
1288+
1289+aufs_rename -> whinfo [label="store/remove"];
1290+
1291+node [shape=oval];
1292+inode_list [label="h_inum list in branch\ncache"];
1293+
1294+node [shape=box];
1295+whinode [label="h_inum list file"];
1296+
1297+node [shape=oval];
1298+brmgmt [label="br_add/del/mod/umount"];
1299+
1300+brmgmt -> inode_list [label="create/remove"];
1301+brmgmt -> whinode [label="load/store"];
1302+
1303+inode_list -> whinode [style=dashed,dir=both];
1304+
1305+aufs_rename -> inode_list [label="add/del"];
1306+
1307+aufs_lookup -> inode_list [label="search"];
1308+
1309+aufs_lookup -> whinfo [label="load/remove"];
1310+}
0b1ff5c3
JR
1311diff -urNp -x '*.orig' linux-4.14/Documentation/filesystems/aufs/design/06dirren.txt linux-4.14/Documentation/filesystems/aufs/design/06dirren.txt
1312--- linux-4.14/Documentation/filesystems/aufs/design/06dirren.txt 1970-01-01 01:00:00.000000000 +0100
1313+++ linux-4.14/Documentation/filesystems/aufs/design/06dirren.txt 2021-02-24 21:42:43.437781422 +0100
8b6a4947
AM
1314@@ -0,0 +1,102 @@
1315+
1316+# Copyright (C) 2017 Junjiro R. Okajima
1317+#
1318+# This program is free software; you can redistribute it and/or modify
1319+# it under the terms of the GNU General Public License as published by
1320+# the Free Software Foundation; either version 2 of the License, or
1321+# (at your option) any later version.
1322+#
1323+# This program is distributed in the hope that it will be useful,
1324+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1325+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1326+# GNU General Public License for more details.
1327+#
1328+# You should have received a copy of the GNU General Public License
1329+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1330+
1331+Special handling for renaming a directory (DIRREN)
1332+----------------------------------------------------------------------
1333+First, let's assume we have a simple usecase.
1334+
1335+- /u = /rw + /ro
1336+- /rw/dirA exists
1337+- /ro/dirA and /ro/dirA/file exist too
1338+- there is no dirB on both branches
1339+- a user issues rename("dirA", "dirB")
1340+
1341+Now, what should aufs behave against this rename(2)?
1342+There are a few possible cases.
1343+
1344+A. returns EROFS.
1345+ since dirA exists on a readonly branch which cannot be renamed.
1346+B. returns EXDEV.
1347+ it is possible to copy-up dirA (only the dir itself), but the child
1348+ entries ("file" in this case) should not be. it must be a bad
1349+ approach to copy-up recursively.
1350+C. returns a success.
1351+ even the branch /ro is readonly, aufs tries renaming it. Obviously it
1352+ is a violation of aufs' policy.
1353+D. construct an extra information which indicates that /ro/dirA should
1354+ be handled as the name of dirB.
1355+ overlayfs has a similar feature called REDIRECT.
1356+
1357+Until now, aufs implements the case B only which returns EXDEV, and
1358+expects the userspace application behaves like mv(1) which tries
1359+issueing rename(2) recursively.
1360+
1361+A new aufs feature called DIRREN is introduced which implements the case
1362+D. There are several "extra information" added.
1363+
1364+1. detailed info per renamed directory
1365+ path: /rw/dirB/$AUFS_WH_DR_INFO_PFX.<lower branch-id>
1366+2. the inode-number list of directories on a branch
1367+ path: /rw/dirB/$AUFS_WH_DR_BRHINO
1368+
1369+The filename of "detailed info per directory" represents the lower
1370+branch, and its format is
1371+- a type of the branch id
1372+ one of these.
1373+ + uuid (not implemented yet)
1374+ + fsid
1375+ + dev
1376+- the inode-number of the branch root dir
1377+
1378+And it contains these info in a single regular file.
1379+- magic number
1380+- branch's inode-number of the logically renamed dir
1381+- the name of the before-renamed dir
1382+
1383+The "detailed info per directory" file is created in aufs rename(2), and
1384+loaded in any lookup.
1385+The info is considered in lookup for the matching case only. Here
1386+"matching" means that the root of branch (in the info filename) is same
1387+to the current looking-up branch. After looking-up the before-renamed
1388+name, the inode-number is compared. And the matched dentry is used.
1389+
1390+The "inode-number list of directories" is a regular file which contains
1391+simply the inode-numbers on the branch. The file is created or updated
1392+in removing the branch, and loaded in adding the branch. Its lifetime is
1393+equal to the branch.
1394+The list is refered in lookup, and when the current target inode is
1395+found in the list, the aufs tries loading the "detailed info per
1396+directory" and get the changed and valid name of the dir.
1397+
1398+Theoretically these "extra informaiton" may be able to be put into XATTR
1399+in the dir inode. But aufs doesn't choose this way because
1400+1. XATTR may not be supported by the branch (or its configuration)
1401+2. XATTR may have its size limit.
1402+3. XATTR may be less easy to convert than a regular file, when the
1403+ format of the info is changed in the future.
1404+At the same time, I agree that the regular file approach is much slower
1405+than XATTR approach. So, in the future, aufs may take the XATTR or other
1406+better approach.
1407+
1408+This DIRREN feature is enabled by aufs configuration, and is activated
1409+by a new mount option.
1410+
1411+For the more complicated case, there is a work with UDBA option, which
1412+is to dected the direct access to the branches (by-passing aufs) and to
1413+maintain the cashes in aufs. Since a single cached aufs dentry may
1414+contains two names, before- and after-rename, the name comparision in
1415+UDBA handler may not work correctly. In this case, the behaviour will be
1416+equivalen to udba=reval case.
0b1ff5c3
JR
1417diff -urNp -x '*.orig' linux-4.14/Documentation/filesystems/aufs/design/06fhsm.txt linux-4.14/Documentation/filesystems/aufs/design/06fhsm.txt
1418--- linux-4.14/Documentation/filesystems/aufs/design/06fhsm.txt 1970-01-01 01:00:00.000000000 +0100
1419+++ linux-4.14/Documentation/filesystems/aufs/design/06fhsm.txt 2021-02-24 21:42:43.441114748 +0100
076b876e
AM
1420@@ -0,0 +1,120 @@
1421+
a2654f78 1422+# Copyright (C) 2011-2017 Junjiro R. Okajima
076b876e
AM
1423+#
1424+# This program is free software; you can redistribute it and/or modify
1425+# it under the terms of the GNU General Public License as published by
1426+# the Free Software Foundation; either version 2 of the License, or
1427+# (at your option) any later version.
1428+#
1429+# This program is distributed in the hope that it will be useful,
1430+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1431+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1432+# GNU General Public License for more details.
1433+#
1434+# You should have received a copy of the GNU General Public License
1435+# along with this program; if not, write to the Free Software
1436+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1437+
1438+
1439+File-based Hierarchical Storage Management (FHSM)
1440+----------------------------------------------------------------------
1441+Hierarchical Storage Management (or HSM) is a well-known feature in the
1442+storage world. Aufs provides this feature as file-based with multiple
7e9cd9fe 1443+writable branches, based upon the principle of "Colder, the Lower".
076b876e 1444+Here the word "colder" means that the less used files, and "lower" means
7e9cd9fe 1445+that the position in the order of the stacked branches vertically.
076b876e
AM
1446+These multiple writable branches are prioritized, ie. the topmost one
1447+should be the fastest drive and be used heavily.
1448+
1449+o Characters in aufs FHSM story
1450+- aufs itself and a new branch attribute.
1451+- a new ioctl interface to move-down and to establish a connection with
1452+ the daemon ("move-down" is a converse of "copy-up").
1453+- userspace tool and daemon.
1454+
1455+The userspace daemon establishes a connection with aufs and waits for
1456+the notification. The notified information is very similar to struct
1457+statfs containing the number of consumed blocks and inodes.
1458+When the consumed blocks/inodes of a branch exceeds the user-specified
1459+upper watermark, the daemon activates its move-down process until the
1460+consumed blocks/inodes reaches the user-specified lower watermark.
1461+
1462+The actual move-down is done by aufs based upon the request from
1463+user-space since we need to maintain the inode number and the internal
1464+pointer arrays in aufs.
1465+
1466+Currently aufs FHSM handles the regular files only. Additionally they
1467+must not be hard-linked nor pseudo-linked.
1468+
1469+
1470+o Cowork of aufs and the user-space daemon
1471+ During the userspace daemon established the connection, aufs sends a
1472+ small notification to it whenever aufs writes something into the
1473+ writable branch. But it may cost high since aufs issues statfs(2)
1474+ internally. So user can specify a new option to cache the
1475+ info. Actually the notification is controlled by these factors.
1476+ + the specified cache time.
1477+ + classified as "force" by aufs internally.
1478+ Until the specified time expires, aufs doesn't send the info
1479+ except the forced cases. When aufs decide forcing, the info is always
1480+ notified to userspace.
1481+ For example, the number of free inodes is generally large enough and
1482+ the shortage of it happens rarely. So aufs doesn't force the
1483+ notification when creating a new file, directory and others. This is
1484+ the typical case which aufs doesn't force.
1485+ When aufs writes the actual filedata and the files consumes any of new
1486+ blocks, the aufs forces notifying.
1487+
1488+
1489+o Interfaces in aufs
1490+- New branch attribute.
1491+ + fhsm
1492+ Specifies that the branch is managed by FHSM feature. In other word,
1493+ participant in the FHSM.
1494+ When nofhsm is set to the branch, it will not be the source/target
1495+ branch of the move-down operation. This attribute is set
1496+ independently from coo and moo attributes, and if you want full
1497+ FHSM, you should specify them as well.
1498+- New mount option.
1499+ + fhsm_sec
1500+ Specifies a second to suppress many less important info to be
1501+ notified.
1502+- New ioctl.
1503+ + AUFS_CTL_FHSM_FD
1504+ create a new file descriptor which userspace can read the notification
1505+ (a subset of struct statfs) from aufs.
1506+- Module parameter 'brs'
1507+ It has to be set to 1. Otherwise the new mount option 'fhsm' will not
1508+ be set.
1509+- mount helpers /sbin/mount.aufs and /sbin/umount.aufs
1510+ When there are two or more branches with fhsm attributes,
1511+ /sbin/mount.aufs invokes the user-space daemon and /sbin/umount.aufs
1512+ terminates it. As a result of remounting and branch-manipulation, the
1513+ number of branches with fhsm attribute can be one. In this case,
1514+ /sbin/mount.aufs will terminate the user-space daemon.
1515+
1516+
1517+Finally the operation is done as these steps in kernel-space.
1518+- make sure that,
1519+ + no one else is using the file.
1520+ + the file is not hard-linked.
1521+ + the file is not pseudo-linked.
1522+ + the file is a regular file.
1523+ + the parent dir is not opaqued.
1524+- find the target writable branch.
1525+- make sure the file is not whiteout-ed by the upper (than the target)
1526+ branch.
1527+- make the parent dir on the target branch.
1528+- mutex lock the inode on the branch.
1529+- unlink the whiteout on the target branch (if exists).
1530+- lookup and create the whiteout-ed temporary name on the target branch.
1531+- copy the file as the whiteout-ed temporary name on the target branch.
1532+- rename the whiteout-ed temporary name to the original name.
1533+- unlink the file on the source branch.
1534+- maintain the internal pointer array and the external inode number
1535+ table (XINO).
1536+- maintain the timestamps and other attributes of the parent dir and the
1537+ file.
1538+
1539+And of course, in every step, an error may happen. So the operation
1540+should restore the original file state after an error happens.
0b1ff5c3
JR
1541diff -urNp -x '*.orig' linux-4.14/Documentation/filesystems/aufs/design/06mmap.txt linux-4.14/Documentation/filesystems/aufs/design/06mmap.txt
1542--- linux-4.14/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 01:00:00.000000000 +0100
1543+++ linux-4.14/Documentation/filesystems/aufs/design/06mmap.txt 2021-02-24 21:42:43.441114748 +0100
b912730e 1544@@ -0,0 +1,72 @@
53392da6 1545+
a2654f78 1546+# Copyright (C) 2005-2017 Junjiro R. Okajima
53392da6
AM
1547+#
1548+# This program is free software; you can redistribute it and/or modify
1549+# it under the terms of the GNU General Public License as published by
1550+# the Free Software Foundation; either version 2 of the License, or
1551+# (at your option) any later version.
1552+#
1553+# This program is distributed in the hope that it will be useful,
1554+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1555+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1556+# GNU General Public License for more details.
1557+#
1558+# You should have received a copy of the GNU General Public License
523b37e3 1559+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1560+
1561+mmap(2) -- File Memory Mapping
1562+----------------------------------------------------------------------
1563+In aufs, the file-mapped pages are handled by a branch fs directly, no
1564+interaction with aufs. It means aufs_mmap() calls the branch fs's
1565+->mmap().
1566+This approach is simple and good, but there is one problem.
7e9cd9fe 1567+Under /proc, several entries show the mmapped files by its path (with
53392da6
AM
1568+device and inode number), and the printed path will be the path on the
1569+branch fs's instead of virtual aufs's.
1570+This is not a problem in most cases, but some utilities lsof(1) (and its
1571+user) may expect the path on aufs.
1572+
1573+To address this issue, aufs adds a new member called vm_prfile in struct
1574+vm_area_struct (and struct vm_region). The original vm_file points to
1575+the file on the branch fs in order to handle everything correctly as
1576+usual. The new vm_prfile points to a virtual file in aufs, and the
1577+show-functions in procfs refers to vm_prfile if it is set.
1578+Also we need to maintain several other places where touching vm_file
1579+such like
1580+- fork()/clone() copies vma and the reference count of vm_file is
1581+ incremented.
1582+- merging vma maintains the ref count too.
1583+
7e9cd9fe 1584+This is not a good approach. It just fakes the printed path. But it
53392da6
AM
1585+leaves all behaviour around f_mapping unchanged. This is surely an
1586+advantage.
1587+Actually aufs had adopted another complicated approach which calls
1588+generic_file_mmap() and handles struct vm_operations_struct. In this
1589+approach, aufs met a hard problem and I could not solve it without
1590+switching the approach.
b912730e
AM
1591+
1592+There may be one more another approach which is
1593+- bind-mount the branch-root onto the aufs-root internally
1594+- grab the new vfsmount (ie. struct mount)
1595+- lazy-umount the branch-root internally
1596+- in open(2) the aufs-file, open the branch-file with the hidden
1597+ vfsmount (instead of the original branch's vfsmount)
1598+- ideally this "bind-mount and lazy-umount" should be done atomically,
1599+ but it may be possible from userspace by the mount helper.
1600+
1601+Adding the internal hidden vfsmount and using it in opening a file, the
1602+file path under /proc will be printed correctly. This approach looks
1603+smarter, but is not possible I am afraid.
1604+- aufs-root may be bind-mount later. when it happens, another hidden
1605+ vfsmount will be required.
1606+- it is hard to get the chance to bind-mount and lazy-umount
1607+ + in kernel-space, FS can have vfsmount in open(2) via
1608+ file->f_path, and aufs can know its vfsmount. But several locks are
1609+ already acquired, and if aufs tries to bind-mount and lazy-umount
1610+ here, then it may cause a deadlock.
1611+ + in user-space, bind-mount doesn't invoke the mount helper.
1612+- since /proc shows dev and ino, aufs has to give vma these info. it
1613+ means a new member vm_prinode will be necessary. this is essentially
1614+ equivalent to vm_prfile described above.
1615+
1616+I have to give up this "looks-smater" approach.
0b1ff5c3
JR
1617diff -urNp -x '*.orig' linux-4.14/Documentation/filesystems/aufs/design/06xattr.txt linux-4.14/Documentation/filesystems/aufs/design/06xattr.txt
1618--- linux-4.14/Documentation/filesystems/aufs/design/06xattr.txt 1970-01-01 01:00:00.000000000 +0100
1619+++ linux-4.14/Documentation/filesystems/aufs/design/06xattr.txt 2021-02-24 21:42:43.441114748 +0100
c1595e42
JR
1620@@ -0,0 +1,96 @@
1621+
a2654f78 1622+# Copyright (C) 2014-2017 Junjiro R. Okajima
c1595e42
JR
1623+#
1624+# This program is free software; you can redistribute it and/or modify
1625+# it under the terms of the GNU General Public License as published by
1626+# the Free Software Foundation; either version 2 of the License, or
1627+# (at your option) any later version.
1628+#
1629+# This program is distributed in the hope that it will be useful,
1630+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1631+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1632+# GNU General Public License for more details.
1633+#
1634+# You should have received a copy of the GNU General Public License
1635+# along with this program; if not, write to the Free Software
1636+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1637+
1638+
1639+Listing XATTR/EA and getting the value
1640+----------------------------------------------------------------------
1641+For the inode standard attributes (owner, group, timestamps, etc.), aufs
1642+shows the values from the topmost existing file. This behaviour is good
7e9cd9fe 1643+for the non-dir entries since the bahaviour exactly matches the shown
c1595e42
JR
1644+information. But for the directories, aufs considers all the same named
1645+entries on the lower branches. Which means, if one of the lower entry
1646+rejects readdir call, then aufs returns an error even if the topmost
1647+entry allows it. This behaviour is necessary to respect the branch fs's
1648+security, but can make users confused since the user-visible standard
1649+attributes don't match the behaviour.
1650+To address this issue, aufs has a mount option called dirperm1 which
1651+checks the permission for the topmost entry only, and ignores the lower
1652+entry's permission.
1653+
1654+A similar issue can happen around XATTR.
1655+getxattr(2) and listxattr(2) families behave as if dirperm1 option is
7e9cd9fe
AM
1656+always set. Otherwise these very unpleasant situation would happen.
1657+- listxattr(2) may return the duplicated entries.
c1595e42
JR
1658+- users may not be able to remove or reset the XATTR forever,
1659+
1660+
1661+XATTR/EA support in the internal (copy,move)-(up,down)
1662+----------------------------------------------------------------------
7e9cd9fe 1663+Generally the extended attributes of inode are categorized as these.
c1595e42
JR
1664+- "security" for LSM and capability.
1665+- "system" for posix ACL, 'acl' mount option is required for the branch
1666+ fs generally.
1667+- "trusted" for userspace, CAP_SYS_ADMIN is required.
1668+- "user" for userspace, 'user_xattr' mount option is required for the
1669+ branch fs generally.
1670+
1671+Moreover there are some other categories. Aufs handles these rather
1672+unpopular categories as the ordinary ones, ie. there is no special
1673+condition nor exception.
1674+
1675+In copy-up, the support for XATTR on the dst branch may differ from the
1676+src branch. In this case, the copy-up operation will get an error and
7e9cd9fe
AM
1677+the original user operation which triggered the copy-up will fail. It
1678+can happen that even all copy-up will fail.
c1595e42
JR
1679+When both of src and dst branches support XATTR and if an error occurs
1680+during copying XATTR, then the copy-up should fail obviously. That is a
1681+good reason and aufs should return an error to userspace. But when only
7e9cd9fe 1682+the src branch support that XATTR, aufs should not return an error.
c1595e42
JR
1683+For example, the src branch supports ACL but the dst branch doesn't
1684+because the dst branch may natively un-support it or temporary
1685+un-support it due to "noacl" mount option. Of course, the dst branch fs
1686+may NOT return an error even if the XATTR is not supported. It is
1687+totally up to the branch fs.
1688+
1689+Anyway when the aufs internal copy-up gets an error from the dst branch
1690+fs, then aufs tries removing the just copied entry and returns the error
1691+to the userspace. The worst case of this situation will be all copy-up
1692+will fail.
1693+
1694+For the copy-up operation, there two basic approaches.
1695+- copy the specified XATTR only (by category above), and return the
7e9cd9fe 1696+ error unconditionally if it happens.
c1595e42
JR
1697+- copy all XATTR, and ignore the error on the specified category only.
1698+
1699+In order to support XATTR and to implement the correct behaviour, aufs
7e9cd9fe
AM
1700+chooses the latter approach and introduces some new branch attributes,
1701+"icexsec", "icexsys", "icextr", "icexusr", and "icexoth".
c1595e42 1702+They correspond to the XATTR namespaces (see above). Additionally, to be
7e9cd9fe
AM
1703+convenient, "icex" is also provided which means all "icex*" attributes
1704+are set (here the word "icex" stands for "ignore copy-error on XATTR").
c1595e42
JR
1705+
1706+The meaning of these attributes is to ignore the error from setting
1707+XATTR on that branch.
1708+Note that aufs tries copying all XATTR unconditionally, and ignores the
1709+error from the dst branch according to the specified attributes.
1710+
1711+Some XATTR may have its default value. The default value may come from
1712+the parent dir or the environment. If the default value is set at the
1713+file creating-time, it will be overwritten by copy-up.
1714+Some contradiction may happen I am afraid.
1715+Do we need another attribute to stop copying XATTR? I am unsure. For
1716+now, aufs implements the branch attributes to ignore the error.
0b1ff5c3
JR
1717diff -urNp -x '*.orig' linux-4.14/Documentation/filesystems/aufs/design/07export.txt linux-4.14/Documentation/filesystems/aufs/design/07export.txt
1718--- linux-4.14/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 01:00:00.000000000 +0100
1719+++ linux-4.14/Documentation/filesystems/aufs/design/07export.txt 2021-02-24 21:42:43.441114748 +0100
523b37e3 1720@@ -0,0 +1,58 @@
53392da6 1721+
a2654f78 1722+# Copyright (C) 2005-2017 Junjiro R. Okajima
53392da6
AM
1723+#
1724+# This program is free software; you can redistribute it and/or modify
1725+# it under the terms of the GNU General Public License as published by
1726+# the Free Software Foundation; either version 2 of the License, or
1727+# (at your option) any later version.
1728+#
1729+# This program is distributed in the hope that it will be useful,
1730+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1731+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1732+# GNU General Public License for more details.
1733+#
1734+# You should have received a copy of the GNU General Public License
523b37e3 1735+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1736+
1737+Export Aufs via NFS
1738+----------------------------------------------------------------------
1739+Here is an approach.
1740+- like xino/xib, add a new file 'xigen' which stores aufs inode
1741+ generation.
1742+- iget_locked(): initialize aufs inode generation for a new inode, and
1743+ store it in xigen file.
1744+- destroy_inode(): increment aufs inode generation and store it in xigen
1745+ file. it is necessary even if it is not unlinked, because any data of
1746+ inode may be changed by UDBA.
1747+- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise
1748+ build file handle by
1749+ + branch id (4 bytes)
1750+ + superblock generation (4 bytes)
1751+ + inode number (4 or 8 bytes)
1752+ + parent dir inode number (4 or 8 bytes)
1753+ + inode generation (4 bytes))
1754+ + return value of exportfs_encode_fh() for the parent on a branch (4
1755+ bytes)
1756+ + file handle for a branch (by exportfs_encode_fh())
1757+- fh_to_dentry():
1758+ + find the index of a branch from its id in handle, and check it is
1759+ still exist in aufs.
1760+ + 1st level: get the inode number from handle and search it in cache.
7e9cd9fe
AM
1761+ + 2nd level: if not found in cache, get the parent inode number from
1762+ the handle and search it in cache. and then open the found parent
1763+ dir, find the matching inode number by vfs_readdir() and get its
1764+ name, and call lookup_one_len() for the target dentry.
53392da6
AM
1765+ + 3rd level: if the parent dir is not cached, call
1766+ exportfs_decode_fh() for a branch and get the parent on a branch,
1767+ build a pathname of it, convert it a pathname in aufs, call
1768+ path_lookup(). now aufs gets a parent dir dentry, then handle it as
1769+ the 2nd level.
1770+ + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount
1771+ for every branch, but not itself. to get this, (currently) aufs
1772+ searches in current->nsproxy->mnt_ns list. it may not be a good
1773+ idea, but I didn't get other approach.
1774+ + test the generation of the gotten inode.
1775+- every inode operation: they may get EBUSY due to UDBA. in this case,
1776+ convert it into ESTALE for NFSD.
1777+- readdir(): call lockdep_on/off() because filldir in NFSD calls
1778+ lookup_one_len(), vfs_getattr(), encode_fh() and others.
0b1ff5c3
JR
1779diff -urNp -x '*.orig' linux-4.14/Documentation/filesystems/aufs/design/08shwh.txt linux-4.14/Documentation/filesystems/aufs/design/08shwh.txt
1780--- linux-4.14/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 01:00:00.000000000 +0100
1781+++ linux-4.14/Documentation/filesystems/aufs/design/08shwh.txt 2021-02-24 21:42:43.441114748 +0100
523b37e3 1782@@ -0,0 +1,52 @@
53392da6 1783+
a2654f78 1784+# Copyright (C) 2005-2017 Junjiro R. Okajima
53392da6
AM
1785+#
1786+# This program is free software; you can redistribute it and/or modify
1787+# it under the terms of the GNU General Public License as published by
1788+# the Free Software Foundation; either version 2 of the License, or
1789+# (at your option) any later version.
1790+#
1791+# This program is distributed in the hope that it will be useful,
1792+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1793+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1794+# GNU General Public License for more details.
1795+#
1796+# You should have received a copy of the GNU General Public License
523b37e3 1797+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1798+
1799+Show Whiteout Mode (shwh)
1800+----------------------------------------------------------------------
1801+Generally aufs hides the name of whiteouts. But in some cases, to show
1802+them is very useful for users. For instance, creating a new middle layer
1803+(branch) by merging existing layers.
1804+
1805+(borrowing aufs1 HOW-TO from a user, Michael Towers)
1806+When you have three branches,
1807+- Bottom: 'system', squashfs (underlying base system), read-only
1808+- Middle: 'mods', squashfs, read-only
1809+- Top: 'overlay', ram (tmpfs), read-write
1810+
1811+The top layer is loaded at boot time and saved at shutdown, to preserve
1812+the changes made to the system during the session.
1813+When larger changes have been made, or smaller changes have accumulated,
1814+the size of the saved top layer data grows. At this point, it would be
1815+nice to be able to merge the two overlay branches ('mods' and 'overlay')
1816+and rewrite the 'mods' squashfs, clearing the top layer and thus
1817+restoring save and load speed.
1818+
1819+This merging is simplified by the use of another aufs mount, of just the
1820+two overlay branches using the 'shwh' option.
1821+# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \
1822+ aufs /livesys/merge_union
1823+
1824+A merged view of these two branches is then available at
1825+/livesys/merge_union, and the new feature is that the whiteouts are
1826+visible!
1827+Note that in 'shwh' mode the aufs mount must be 'ro', which will disable
1828+writing to all branches. Also the default mode for all branches is 'ro'.
1829+It is now possible to save the combined contents of the two overlay
1830+branches to a new squashfs, e.g.:
1831+# mksquashfs /livesys/merge_union /path/to/newmods.squash
1832+
1833+This new squashfs archive can be stored on the boot device and the
1834+initramfs will use it to replace the old one at the next boot.
0b1ff5c3
JR
1835diff -urNp -x '*.orig' linux-4.14/Documentation/filesystems/aufs/design/10dynop.txt linux-4.14/Documentation/filesystems/aufs/design/10dynop.txt
1836--- linux-4.14/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 01:00:00.000000000 +0100
1837+++ linux-4.14/Documentation/filesystems/aufs/design/10dynop.txt 2021-02-24 21:42:43.441114748 +0100
7e9cd9fe 1838@@ -0,0 +1,47 @@
53392da6 1839+
a2654f78 1840+# Copyright (C) 2010-2017 Junjiro R. Okajima
53392da6
AM
1841+#
1842+# This program is free software; you can redistribute it and/or modify
1843+# it under the terms of the GNU General Public License as published by
1844+# the Free Software Foundation; either version 2 of the License, or
1845+# (at your option) any later version.
1846+#
1847+# This program is distributed in the hope that it will be useful,
1848+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1849+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1850+# GNU General Public License for more details.
1851+#
1852+# You should have received a copy of the GNU General Public License
523b37e3 1853+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1854+
1855+Dynamically customizable FS operations
1856+----------------------------------------------------------------------
1857+Generally FS operations (struct inode_operations, struct
1858+address_space_operations, struct file_operations, etc.) are defined as
1859+"static const", but it never means that FS have only one set of
1860+operation. Some FS have multiple sets of them. For instance, ext2 has
1861+three sets, one for XIP, for NOBH, and for normal.
1862+Since aufs overrides and redirects these operations, sometimes aufs has
7e9cd9fe 1863+to change its behaviour according to the branch FS type. More importantly
53392da6
AM
1864+VFS acts differently if a function (member in the struct) is set or
1865+not. It means aufs should have several sets of operations and select one
1866+among them according to the branch FS definition.
1867+
7e9cd9fe 1868+In order to solve this problem and not to affect the behaviour of VFS,
53392da6 1869+aufs defines these operations dynamically. For instance, aufs defines
7e9cd9fe
AM
1870+dummy direct_IO function for struct address_space_operations, but it may
1871+not be set to the address_space_operations actually. When the branch FS
1872+doesn't have it, aufs doesn't set it to its address_space_operations
1873+while the function definition itself is still alive. So the behaviour
1874+itself will not change, and it will return an error when direct_IO is
1875+not set.
53392da6
AM
1876+
1877+The lifetime of these dynamically generated operation object is
1878+maintained by aufs branch object. When the branch is removed from aufs,
1879+the reference counter of the object is decremented. When it reaches
1880+zero, the dynamically generated operation object will be freed.
1881+
7e9cd9fe
AM
1882+This approach is designed to support AIO (io_submit), Direct I/O and
1883+XIP (DAX) mainly.
1884+Currently this approach is applied to address_space_operations for
1885+regular files only.
0b1ff5c3
JR
1886diff -urNp -x '*.orig' linux-4.14/MAINTAINERS linux-4.14/MAINTAINERS
1887--- linux-4.14/MAINTAINERS 2021-02-24 21:42:34.681134057 +0100
1888+++ linux-4.14/MAINTAINERS 2021-02-24 21:42:43.431114768 +0100
1889@@ -2465,6 +2465,19 @@ F: include/linux/audit.h
1890 F: include/uapi/linux/audit.h
1891 F: kernel/audit*
1892
1893+AUFS (advanced multi layered unification filesystem) FILESYSTEM
1894+M: "J. R. Okajima" <hooanon05g@gmail.com>
1895+L: linux-unionfs@vger.kernel.org
1896+L: aufs-users@lists.sourceforge.net (members only)
1897+W: http://aufs.sourceforge.net
1898+T: git://github.com/sfjro/aufs4-linux.git
1899+S: Supported
1900+F: Documentation/filesystems/aufs/
1901+F: Documentation/ABI/testing/debugfs-aufs
1902+F: Documentation/ABI/testing/sysfs-aufs
1903+F: fs/aufs/
1904+F: include/uapi/linux/aufs_type.h
53392da6 1905+
0b1ff5c3
JR
1906 AUXILIARY DISPLAY DRIVERS
1907 M: Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>
1908 W: http://miguelojeda.es/auxdisplay.htm
1909diff -urNp -x '*.orig' linux-4.14/drivers/block/loop.c linux-4.14/drivers/block/loop.c
1910--- linux-4.14/drivers/block/loop.c 2021-02-24 21:42:34.864466934 +0100
1911+++ linux-4.14/drivers/block/loop.c 2021-02-24 21:42:43.447781402 +0100
1912@@ -605,6 +605,15 @@ static inline void loop_update_dio(struc
1913 lo->use_dio);
1914 }
1915
1916+static struct file *loop_real_file(struct file *file)
1917+{
1918+ struct file *f = NULL;
53392da6 1919+
0b1ff5c3
JR
1920+ if (file->f_path.dentry->d_sb->s_op->real_loop)
1921+ f = file->f_path.dentry->d_sb->s_op->real_loop(file);
1922+ return f;
1923+}
53392da6 1924+
0b1ff5c3
JR
1925 static void loop_reread_partitions(struct loop_device *lo,
1926 struct block_device *bdev)
1927 {
1928@@ -669,6 +678,7 @@ static int loop_change_fd(struct loop_de
1929 unsigned int arg)
1930 {
1931 struct file *file, *old_file;
1932+ struct file *f, *virt_file = NULL, *old_virt_file;
1933 struct inode *inode;
1934 int error;
1935
1936@@ -685,6 +695,12 @@ static int loop_change_fd(struct loop_de
1937 file = fget(arg);
1938 if (!file)
1939 goto out;
1940+ f = loop_real_file(file);
1941+ if (f) {
1942+ virt_file = file;
1943+ file = f;
1944+ get_file(file);
1945+ }
1946
1947 error = loop_validate_file(file, bdev);
1948 if (error)
1949@@ -692,6 +708,7 @@ static int loop_change_fd(struct loop_de
1950
1951 inode = file->f_mapping->host;
1952 old_file = lo->lo_backing_file;
1953+ old_virt_file = lo->lo_backing_virt_file;
1954
1955 error = -EINVAL;
1956
1957@@ -703,6 +720,7 @@ static int loop_change_fd(struct loop_de
1958 blk_mq_freeze_queue(lo->lo_queue);
1959 mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
1960 lo->lo_backing_file = file;
1961+ lo->lo_backing_virt_file = virt_file;
1962 lo->old_gfp_mask = mapping_gfp_mask(file->f_mapping);
1963 mapping_set_gfp_mask(file->f_mapping,
1964 lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
1965@@ -710,16 +728,38 @@ static int loop_change_fd(struct loop_de
1966 blk_mq_unfreeze_queue(lo->lo_queue);
1967
1968 fput(old_file);
1969+ if (old_virt_file)
1970+ fput(old_virt_file);
1971 if (lo->lo_flags & LO_FLAGS_PARTSCAN)
1972 loop_reread_partitions(lo, bdev);
1973 return 0;
1974
1975 out_putf:
1976 fput(file);
1977+ if (virt_file)
1978+ fput(virt_file);
1979 out:
1980 return error;
1981 }
1982
1983+/*
1984+ * for AUFS
1985+ * no get/put for file.
1986+ */
1987+struct file *loop_backing_file(struct super_block *sb)
1988+{
1989+ struct file *ret;
1990+ struct loop_device *l;
1e00d052 1991+
0b1ff5c3
JR
1992+ ret = NULL;
1993+ if (MAJOR(sb->s_dev) == LOOP_MAJOR) {
1994+ l = sb->s_bdev->bd_disk->private_data;
1995+ ret = l->lo_backing_file;
1996+ }
1997+ return ret;
1998+}
1999+EXPORT_SYMBOL_GPL(loop_backing_file);
53392da6 2000+
0b1ff5c3
JR
2001 /* loop sysfs attributes */
2002
2003 static ssize_t loop_attr_show(struct device *dev, char *page,
2004@@ -885,7 +925,7 @@ static int loop_prepare_queue(struct loo
2005 static int loop_set_fd(struct loop_device *lo, fmode_t mode,
2006 struct block_device *bdev, unsigned int arg)
2007 {
2008- struct file *file;
2009+ struct file *file, *f, *virt_file = NULL;
2010 struct inode *inode;
2011 struct address_space *mapping;
2012 int lo_flags = 0;
2013@@ -899,6 +939,12 @@ static int loop_set_fd(struct loop_devic
2014 file = fget(arg);
2015 if (!file)
2016 goto out;
2017+ f = loop_real_file(file);
2018+ if (f) {
2019+ virt_file = file;
2020+ file = f;
2021+ get_file(file);
2022+ }
2023
2024 error = -EBUSY;
2025 if (lo->lo_state != Lo_unbound)
2026@@ -931,6 +977,7 @@ static int loop_set_fd(struct loop_devic
2027 lo->lo_device = bdev;
2028 lo->lo_flags = lo_flags;
2029 lo->lo_backing_file = file;
2030+ lo->lo_backing_virt_file = virt_file;
2031 lo->transfer = NULL;
2032 lo->ioctl = NULL;
2033 lo->lo_sizelimit = 0;
2034@@ -964,6 +1011,8 @@ static int loop_set_fd(struct loop_devic
2035
2036 out_putf:
2037 fput(file);
2038+ if (virt_file)
2039+ fput(virt_file);
2040 out:
2041 /* This is safe: open() is still holding a reference. */
2042 module_put(THIS_MODULE);
2043@@ -1010,6 +1059,7 @@ loop_init_xfer(struct loop_device *lo, s
2044 static int loop_clr_fd(struct loop_device *lo)
2045 {
2046 struct file *filp = lo->lo_backing_file;
2047+ struct file *virt_filp = lo->lo_backing_virt_file;
2048 gfp_t gfp = lo->old_gfp_mask;
2049 struct block_device *bdev = lo->lo_device;
2050
2051@@ -1041,6 +1091,7 @@ static int loop_clr_fd(struct loop_devic
2052 spin_lock_irq(&lo->lo_lock);
2053 lo->lo_state = Lo_rundown;
2054 lo->lo_backing_file = NULL;
2055+ lo->lo_backing_virt_file = NULL;
2056 spin_unlock_irq(&lo->lo_lock);
2057
2058 loop_release_xfer(lo);
2059@@ -1088,6 +1139,8 @@ static int loop_clr_fd(struct loop_devic
2060 * bd_mutex which is usually taken before lo_ctl_mutex.
2061 */
2062 fput(filp);
2063+ if (virt_filp)
2064+ fput(virt_filp);
2065 return 0;
2066 }
2067
2068diff -urNp -x '*.orig' linux-4.14/drivers/block/loop.h linux-4.14/drivers/block/loop.h
2069--- linux-4.14/drivers/block/loop.h 2021-02-24 21:42:34.864466934 +0100
2070+++ linux-4.14/drivers/block/loop.h 2021-02-24 21:42:43.447781402 +0100
2071@@ -46,7 +46,7 @@ struct loop_device {
2072 int (*ioctl)(struct loop_device *, int cmd,
2073 unsigned long arg);
2074
2075- struct file * lo_backing_file;
2076+ struct file * lo_backing_file, *lo_backing_virt_file;
2077 struct block_device *lo_device;
2078 void *key_data;
2079
2080diff -urNp -x '*.orig' linux-4.14/fs/Kconfig linux-4.14/fs/Kconfig
2081--- linux-4.14/fs/Kconfig 2017-11-12 19:46:13.000000000 +0100
2082+++ linux-4.14/fs/Kconfig 2021-02-24 21:42:43.431114768 +0100
2083@@ -248,6 +248,7 @@ source "fs/pstore/Kconfig"
2084 source "fs/sysv/Kconfig"
2085 source "fs/ufs/Kconfig"
2086 source "fs/exofs/Kconfig"
2087+source "fs/aufs/Kconfig"
2088
2089 endif # MISC_FILESYSTEMS
2090
2091diff -urNp -x '*.orig' linux-4.14/fs/Makefile linux-4.14/fs/Makefile
2092--- linux-4.14/fs/Makefile 2017-11-12 19:46:13.000000000 +0100
2093+++ linux-4.14/fs/Makefile 2021-02-24 21:42:43.431114768 +0100
2094@@ -129,3 +129,4 @@ obj-y += exofs/ # Multiple modules
2095 obj-$(CONFIG_CEPH_FS) += ceph/
2096 obj-$(CONFIG_PSTORE) += pstore/
2097 obj-$(CONFIG_EFIVAR_FS) += efivarfs/
2098+obj-$(CONFIG_AUFS_FS) += aufs/
2099diff -urNp -x '*.orig' linux-4.14/fs/aufs/Kconfig linux-4.14/fs/aufs/Kconfig
2100--- linux-4.14/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
2101+++ linux-4.14/fs/aufs/Kconfig 2021-02-24 21:42:43.444448075 +0100
2102@@ -0,0 +1,198 @@
2103+config AUFS_FS
2104+ tristate "Aufs (Advanced multi layered unification filesystem) support"
2105+ help
2106+ Aufs is a stackable unification filesystem such as Unionfs,
2107+ which unifies several directories and provides a merged single
2108+ directory.
2109+ In the early days, aufs was entirely re-designed and
2110+ re-implemented Unionfs Version 1.x series. Introducing many
2111+ original ideas, approaches and improvements, it becomes totally
2112+ different from Unionfs while keeping the basic features.
53392da6 2113+
0b1ff5c3
JR
2114+if AUFS_FS
2115+choice
2116+ prompt "Maximum number of branches"
2117+ default AUFS_BRANCH_MAX_127
2118+ help
2119+ Specifies the maximum number of branches (or member directories)
2120+ in a single aufs. The larger value consumes more system
2121+ resources and has a minor impact to performance.
2122+config AUFS_BRANCH_MAX_127
2123+ bool "127"
2124+ help
2125+ Specifies the maximum number of branches (or member directories)
2126+ in a single aufs. The larger value consumes more system
2127+ resources and has a minor impact to performance.
2128+config AUFS_BRANCH_MAX_511
2129+ bool "511"
2130+ help
2131+ Specifies the maximum number of branches (or member directories)
2132+ in a single aufs. The larger value consumes more system
2133+ resources and has a minor impact to performance.
2134+config AUFS_BRANCH_MAX_1023
2135+ bool "1023"
2136+ help
2137+ Specifies the maximum number of branches (or member directories)
2138+ in a single aufs. The larger value consumes more system
2139+ resources and has a minor impact to performance.
2140+config AUFS_BRANCH_MAX_32767
2141+ bool "32767"
2142+ help
2143+ Specifies the maximum number of branches (or member directories)
2144+ in a single aufs. The larger value consumes more system
2145+ resources and has a minor impact to performance.
2146+endchoice
53392da6 2147+
0b1ff5c3
JR
2148+config AUFS_SBILIST
2149+ bool
2150+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
2151+ default y
2152+ help
2153+ Automatic configuration for internal use.
2154+ When aufs supports Magic SysRq or /proc, enabled automatically.
53392da6 2155+
0b1ff5c3
JR
2156+config AUFS_HNOTIFY
2157+ bool "Detect direct branch access (bypassing aufs)"
2158+ help
2159+ If you want to modify files on branches directly, eg. bypassing aufs,
2160+ and want aufs to detect the changes of them fully, then enable this
2161+ option and use 'udba=notify' mount option.
2162+ Currently there is only one available configuration, "fsnotify".
2163+ It will have a negative impact to the performance.
2164+ See detail in aufs.5.
53392da6 2165+
0b1ff5c3
JR
2166+choice
2167+ prompt "method" if AUFS_HNOTIFY
2168+ default AUFS_HFSNOTIFY
2169+config AUFS_HFSNOTIFY
2170+ bool "fsnotify"
2171+ select FSNOTIFY
2172+endchoice
38d290e6 2173+
0b1ff5c3
JR
2174+config AUFS_EXPORT
2175+ bool "NFS-exportable aufs"
2176+ depends on EXPORTFS
2177+ help
2178+ If you want to export your mounted aufs via NFS, then enable this
2179+ option. There are several requirements for this configuration.
2180+ See detail in aufs.5.
53392da6 2181+
0b1ff5c3
JR
2182+config AUFS_INO_T_64
2183+ bool
2184+ depends on AUFS_EXPORT
2185+ depends on 64BIT && !(ALPHA || S390)
2186+ default y
2187+ help
2188+ Automatic configuration for internal use.
2189+ /* typedef unsigned long/int __kernel_ino_t */
2190+ /* alpha and s390x are int */
53392da6 2191+
0b1ff5c3
JR
2192+config AUFS_XATTR
2193+ bool "support for XATTR/EA (including Security Labels)"
2194+ help
2195+ If your branch fs supports XATTR/EA and you want to make them
2196+ available in aufs too, then enable this opsion and specify the
2197+ branch attributes for EA.
2198+ See detail in aufs.5.
53392da6 2199+
0b1ff5c3
JR
2200+config AUFS_FHSM
2201+ bool "File-based Hierarchical Storage Management"
2202+ help
2203+ Hierarchical Storage Management (or HSM) is a well-known feature
2204+ in the storage world. Aufs provides this feature as file-based.
2205+ with multiple branches.
2206+ These multiple branches are prioritized, ie. the topmost one
2207+ should be the fastest drive and be used heavily.
53392da6 2208+
0b1ff5c3
JR
2209+config AUFS_RDU
2210+ bool "Readdir in userspace"
2211+ help
2212+ Aufs has two methods to provide a merged view for a directory,
2213+ by a user-space library and by kernel-space natively. The latter
2214+ is always enabled but sometimes large and slow.
2215+ If you enable this option, install the library in aufs2-util
2216+ package, and set some environment variables for your readdir(3),
2217+ then the work will be handled in user-space which generally
2218+ shows better performance in most cases.
2219+ See detail in aufs.5.
53392da6 2220+
0b1ff5c3
JR
2221+config AUFS_DIRREN
2222+ bool "Workaround for rename(2)-ing a directory"
2223+ help
2224+ By default, aufs returns EXDEV error in renameing a dir who has
2225+ his child on the lower branch, since it is a bad idea to issue
2226+ rename(2) internally for every lower branch. But user may not
2227+ accept this behaviour. So here is a workaround to allow such
2228+ rename(2) and store some extra infromation on the writable
2229+ branch. Obviously this costs high (and I don't like it).
2230+ To use this feature, you need to enable this configuration AND
2231+ to specify the mount option `dirren.'
2232+ See details in aufs.5 and the design documents.
53392da6 2233+
0b1ff5c3
JR
2234+config AUFS_SHWH
2235+ bool "Show whiteouts"
2236+ help
2237+ If you want to make the whiteouts in aufs visible, then enable
2238+ this option and specify 'shwh' mount option. Although it may
2239+ sounds like philosophy or something, but in technically it
2240+ simply shows the name of whiteout with keeping its behaviour.
53392da6 2241+
0b1ff5c3
JR
2242+config AUFS_BR_RAMFS
2243+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
2244+ help
2245+ If you want to use ramfs as an aufs branch fs, then enable this
2246+ option. Generally tmpfs is recommended.
2247+ Aufs prohibited them to be a branch fs by default, because
2248+ initramfs becomes unusable after switch_root or something
2249+ generally. If you sets initramfs as an aufs branch and boot your
2250+ system by switch_root, you will meet a problem easily since the
2251+ files in initramfs may be inaccessible.
2252+ Unless you are going to use ramfs as an aufs branch fs without
2253+ switch_root or something, leave it N.
53392da6 2254+
0b1ff5c3
JR
2255+config AUFS_BR_FUSE
2256+ bool "Fuse fs as an aufs branch"
2257+ depends on FUSE_FS
2258+ select AUFS_POLL
2259+ help
2260+ If you want to use fuse-based userspace filesystem as an aufs
2261+ branch fs, then enable this option.
2262+ It implements the internal poll(2) operation which is
2263+ implemented by fuse only (curretnly).
53392da6 2264+
0b1ff5c3
JR
2265+config AUFS_POLL
2266+ bool
2267+ help
2268+ Automatic configuration for internal use.
53392da6 2269+
0b1ff5c3
JR
2270+config AUFS_BR_HFSPLUS
2271+ bool "Hfsplus as an aufs branch"
2272+ depends on HFSPLUS_FS
2273+ default y
2274+ help
2275+ If you want to use hfsplus fs as an aufs branch fs, then enable
2276+ this option. This option introduces a small overhead at
2277+ copying-up a file on hfsplus.
53392da6 2278+
0b1ff5c3
JR
2279+config AUFS_BDEV_LOOP
2280+ bool
2281+ depends on BLK_DEV_LOOP
2282+ default y
2283+ help
2284+ Automatic configuration for internal use.
2285+ Convert =[ym] into =y.
53392da6 2286+
0b1ff5c3
JR
2287+config AUFS_DEBUG
2288+ bool "Debug aufs"
2289+ help
2290+ Enable this to compile aufs internal debug code.
2291+ It will have a negative impact to the performance.
53392da6 2292+
0b1ff5c3
JR
2293+config AUFS_MAGIC_SYSRQ
2294+ bool
2295+ depends on AUFS_DEBUG && MAGIC_SYSRQ
2296+ default y
2297+ help
2298+ Automatic configuration for internal use.
2299+ When aufs supports Magic SysRq, enabled automatically.
2300+endif
2301diff -urNp -x '*.orig' linux-4.14/fs/aufs/Makefile linux-4.14/fs/aufs/Makefile
2302--- linux-4.14/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
2303+++ linux-4.14/fs/aufs/Makefile 2021-02-24 21:42:43.444448075 +0100
2304@@ -0,0 +1,45 @@
53392da6 2305+
0b1ff5c3
JR
2306+include ${src}/magic.mk
2307+ifeq (${CONFIG_AUFS_FS},m)
2308+include ${src}/conf.mk
2309+endif
2310+-include ${src}/priv_def.mk
53392da6 2311+
0b1ff5c3
JR
2312+# cf. include/linux/kernel.h
2313+# enable pr_debug
2314+ccflags-y += -DDEBUG
2315+# sparse requires the full pathname
2316+ifdef M
2317+ccflags-y += -include ${M}/../../include/uapi/linux/aufs_type.h
2318+else
2319+ccflags-y += -include ${srctree}/include/uapi/linux/aufs_type.h
2320+endif
53392da6 2321+
0b1ff5c3
JR
2322+obj-$(CONFIG_AUFS_FS) += aufs.o
2323+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
2324+ wkq.o vfsub.o dcsub.o \
2325+ cpup.o whout.o wbr_policy.o \
2326+ dinfo.o dentry.o \
2327+ dynop.o \
2328+ finfo.o file.o f_op.o \
2329+ dir.o vdir.o \
2330+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
2331+ mvdown.o ioctl.o
53392da6 2332+
0b1ff5c3
JR
2333+# all are boolean
2334+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
2335+aufs-$(CONFIG_SYSFS) += sysfs.o
2336+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
2337+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
2338+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
2339+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
2340+aufs-$(CONFIG_AUFS_EXPORT) += export.o
2341+aufs-$(CONFIG_AUFS_XATTR) += xattr.o
2342+aufs-$(CONFIG_FS_POSIX_ACL) += posix_acl.o
2343+aufs-$(CONFIG_AUFS_DIRREN) += dirren.o
2344+aufs-$(CONFIG_AUFS_FHSM) += fhsm.o
2345+aufs-$(CONFIG_AUFS_POLL) += poll.o
2346+aufs-$(CONFIG_AUFS_RDU) += rdu.o
2347+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
2348+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
2349+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
2350diff -urNp -x '*.orig' linux-4.14/fs/aufs/aufs.h linux-4.14/fs/aufs/aufs.h
2351--- linux-4.14/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
2352+++ linux-4.14/fs/aufs/aufs.h 2021-02-24 21:42:43.441114748 +0100
8b6a4947 2353@@ -0,0 +1,60 @@
7f207e10 2354+/*
a2654f78 2355+ * Copyright (C) 2005-2017 Junjiro R. Okajima
7f207e10
AM
2356+ *
2357+ * This program, aufs is free software; you can redistribute it and/or modify
2358+ * it under the terms of the GNU General Public License as published by
2359+ * the Free Software Foundation; either version 2 of the License, or
2360+ * (at your option) any later version.
2361+ *
2362+ * This program is distributed in the hope that it will be useful,
2363+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2364+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2365+ * GNU General Public License for more details.
2366+ *
2367+ * You should have received a copy of the GNU General Public License
523b37e3 2368+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
2369+ */
2370+
2371+/*
2372+ * all header files
2373+ */
2374+
2375+#ifndef __AUFS_H__
2376+#define __AUFS_H__
2377+
2378+#ifdef __KERNEL__
2379+
2380+#define AuStub(type, name, body, ...) \
2381+ static inline type name(__VA_ARGS__) { body; }
2382+
2383+#define AuStubVoid(name, ...) \
2384+ AuStub(void, name, , __VA_ARGS__)
2385+#define AuStubInt0(name, ...) \
2386+ AuStub(int, name, return 0, __VA_ARGS__)
2387+
2388+#include "debug.h"
2389+
2390+#include "branch.h"
2391+#include "cpup.h"
2392+#include "dcsub.h"
2393+#include "dbgaufs.h"
2394+#include "dentry.h"
2395+#include "dir.h"
8b6a4947 2396+#include "dirren.h"
7f207e10
AM
2397+#include "dynop.h"
2398+#include "file.h"
2399+#include "fstype.h"
8b6a4947 2400+#include "hbl.h"
7f207e10
AM
2401+#include "inode.h"
2402+#include "loop.h"
2403+#include "module.h"
7f207e10
AM
2404+#include "opts.h"
2405+#include "rwsem.h"
7f207e10
AM
2406+#include "super.h"
2407+#include "sysaufs.h"
2408+#include "vfsub.h"
2409+#include "whout.h"
2410+#include "wkq.h"
2411+
2412+#endif /* __KERNEL__ */
2413+#endif /* __AUFS_H__ */
0b1ff5c3
JR
2414diff -urNp -x '*.orig' linux-4.14/fs/aufs/branch.c linux-4.14/fs/aufs/branch.c
2415--- linux-4.14/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
2416+++ linux-4.14/fs/aufs/branch.c 2021-02-24 21:42:43.441114748 +0100
8b6a4947 2417@@ -0,0 +1,1432 @@
7f207e10 2418+/*
a2654f78 2419+ * Copyright (C) 2005-2017 Junjiro R. Okajima
7f207e10
AM
2420+ *
2421+ * This program, aufs is free software; you can redistribute it and/or modify
2422+ * it under the terms of the GNU General Public License as published by
2423+ * the Free Software Foundation; either version 2 of the License, or
2424+ * (at your option) any later version.
2425+ *
2426+ * This program is distributed in the hope that it will be useful,
2427+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2428+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2429+ * GNU General Public License for more details.
2430+ *
2431+ * You should have received a copy of the GNU General Public License
523b37e3 2432+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
2433+ */
2434+
2435+/*
2436+ * branch management
2437+ */
2438+
027c5e7a 2439+#include <linux/compat.h>
7f207e10
AM
2440+#include <linux/statfs.h>
2441+#include "aufs.h"
2442+
2443+/*
2444+ * free a single branch
1facf9fc 2445+ */
2446+static void au_br_do_free(struct au_branch *br)
2447+{
2448+ int i;
2449+ struct au_wbr *wbr;
4a4d8108 2450+ struct au_dykey **key;
1facf9fc 2451+
027c5e7a 2452+ au_hnotify_fin_br(br);
8b6a4947
AM
2453+ /* always, regardless the mount option */
2454+ au_dr_hino_free(&br->br_dirren);
027c5e7a 2455+
1facf9fc 2456+ if (br->br_xino.xi_file)
2457+ fput(br->br_xino.xi_file);
521ced18
JR
2458+ for (i = br->br_xino.xi_nondir.total - 1; i >= 0; i--)
2459+ AuDebugOn(br->br_xino.xi_nondir.array[i]);
1c60b727 2460+ kfree(br->br_xino.xi_nondir.array);
1facf9fc 2461+
5afbbe0d
AM
2462+ AuDebugOn(au_br_count(br));
2463+ au_br_count_fin(br);
1facf9fc 2464+
2465+ wbr = br->br_wbr;
2466+ if (wbr) {
2467+ for (i = 0; i < AuBrWh_Last; i++)
2468+ dput(wbr->wbr_wh[i]);
2469+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 2470+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 2471+ }
2472+
076b876e
AM
2473+ if (br->br_fhsm) {
2474+ au_br_fhsm_fin(br->br_fhsm);
1c60b727 2475+ kfree(br->br_fhsm);
076b876e
AM
2476+ }
2477+
4a4d8108
AM
2478+ key = br->br_dykey;
2479+ for (i = 0; i < AuBrDynOp; i++, key++)
2480+ if (*key)
2481+ au_dy_put(*key);
2482+ else
2483+ break;
2484+
537831f9
AM
2485+ /* recursive lock, s_umount of branch's */
2486+ lockdep_off();
86dc4139 2487+ path_put(&br->br_path);
537831f9 2488+ lockdep_on();
1c60b727
AM
2489+ kfree(wbr);
2490+ kfree(br);
1facf9fc 2491+}
2492+
2493+/*
2494+ * frees all branches
2495+ */
2496+void au_br_free(struct au_sbinfo *sbinfo)
2497+{
2498+ aufs_bindex_t bmax;
2499+ struct au_branch **br;
2500+
dece6358
AM
2501+ AuRwMustWriteLock(&sbinfo->si_rwsem);
2502+
5afbbe0d 2503+ bmax = sbinfo->si_bbot + 1;
1facf9fc 2504+ br = sbinfo->si_branch;
2505+ while (bmax--)
2506+ au_br_do_free(*br++);
2507+}
2508+
2509+/*
2510+ * find the index of a branch which is specified by @br_id.
2511+ */
2512+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
2513+{
5afbbe0d 2514+ aufs_bindex_t bindex, bbot;
1facf9fc 2515+
5afbbe0d
AM
2516+ bbot = au_sbbot(sb);
2517+ for (bindex = 0; bindex <= bbot; bindex++)
1facf9fc 2518+ if (au_sbr_id(sb, bindex) == br_id)
2519+ return bindex;
2520+ return -1;
2521+}
2522+
2523+/* ---------------------------------------------------------------------- */
2524+
2525+/*
2526+ * add a branch
2527+ */
2528+
b752ccd1
AM
2529+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
2530+ struct dentry *h_root)
1facf9fc 2531+{
b752ccd1
AM
2532+ if (unlikely(h_adding == h_root
2533+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 2534+ return 1;
b752ccd1
AM
2535+ if (h_adding->d_sb != h_root->d_sb)
2536+ return 0;
2537+ return au_test_subdir(h_adding, h_root)
2538+ || au_test_subdir(h_root, h_adding);
1facf9fc 2539+}
2540+
2541+/*
2542+ * returns a newly allocated branch. @new_nbranch is a number of branches
2543+ * after adding a branch.
2544+ */
2545+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
2546+ int perm)
2547+{
2548+ struct au_branch *add_branch;
2549+ struct dentry *root;
5527c038 2550+ struct inode *inode;
4a4d8108 2551+ int err;
1facf9fc 2552+
4a4d8108 2553+ err = -ENOMEM;
be52b249 2554+ add_branch = kzalloc(sizeof(*add_branch), GFP_NOFS);
1facf9fc 2555+ if (unlikely(!add_branch))
2556+ goto out;
521ced18
JR
2557+ add_branch->br_xino.xi_nondir.total = 8; /* initial size */
2558+ add_branch->br_xino.xi_nondir.array
8b6a4947 2559+ = kcalloc(add_branch->br_xino.xi_nondir.total, sizeof(ino_t),
521ced18
JR
2560+ GFP_NOFS);
2561+ if (unlikely(!add_branch->br_xino.xi_nondir.array))
2562+ goto out_br;
1facf9fc 2563+
027c5e7a
AM
2564+ err = au_hnotify_init_br(add_branch, perm);
2565+ if (unlikely(err))
521ced18 2566+ goto out_xinondir;
027c5e7a 2567+
1facf9fc 2568+ if (au_br_writable(perm)) {
2569+ /* may be freed separately at changing the branch permission */
be52b249 2570+ add_branch->br_wbr = kzalloc(sizeof(*add_branch->br_wbr),
1facf9fc 2571+ GFP_NOFS);
2572+ if (unlikely(!add_branch->br_wbr))
027c5e7a 2573+ goto out_hnotify;
1facf9fc 2574+ }
2575+
076b876e
AM
2576+ if (au_br_fhsm(perm)) {
2577+ err = au_fhsm_br_alloc(add_branch);
2578+ if (unlikely(err))
2579+ goto out_wbr;
2580+ }
2581+
521ced18 2582+ root = sb->s_root;
e2f27e51 2583+ err = au_sbr_realloc(au_sbi(sb), new_nbranch, /*may_shrink*/0);
4a4d8108 2584+ if (!err)
e2f27e51 2585+ err = au_di_realloc(au_di(root), new_nbranch, /*may_shrink*/0);
5527c038
JR
2586+ if (!err) {
2587+ inode = d_inode(root);
1c60b727
AM
2588+ err = au_hinode_realloc(au_ii(inode), new_nbranch,
2589+ /*may_shrink*/0);
5527c038 2590+ }
4a4d8108
AM
2591+ if (!err)
2592+ return add_branch; /* success */
1facf9fc 2593+
076b876e 2594+out_wbr:
1c60b727 2595+ kfree(add_branch->br_wbr);
027c5e7a
AM
2596+out_hnotify:
2597+ au_hnotify_fin_br(add_branch);
521ced18 2598+out_xinondir:
1c60b727 2599+ kfree(add_branch->br_xino.xi_nondir.array);
4f0767ce 2600+out_br:
1c60b727 2601+ kfree(add_branch);
4f0767ce 2602+out:
4a4d8108 2603+ return ERR_PTR(err);
1facf9fc 2604+}
2605+
2606+/*
2607+ * test if the branch permission is legal or not.
2608+ */
2609+static int test_br(struct inode *inode, int brperm, char *path)
2610+{
2611+ int err;
2612+
4a4d8108
AM
2613+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
2614+ if (!err)
2615+ goto out;
1facf9fc 2616+
4a4d8108
AM
2617+ err = -EINVAL;
2618+ pr_err("write permission for readonly mount or inode, %s\n", path);
2619+
4f0767ce 2620+out:
1facf9fc 2621+ return err;
2622+}
2623+
2624+/*
2625+ * returns:
2626+ * 0: success, the caller will add it
2627+ * plus: success, it is already unified, the caller should ignore it
2628+ * minus: error
2629+ */
2630+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
2631+{
2632+ int err;
5afbbe0d 2633+ aufs_bindex_t bbot, bindex;
5527c038 2634+ struct dentry *root, *h_dentry;
1facf9fc 2635+ struct inode *inode, *h_inode;
2636+
2637+ root = sb->s_root;
5afbbe0d
AM
2638+ bbot = au_sbbot(sb);
2639+ if (unlikely(bbot >= 0
1facf9fc 2640+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
2641+ err = 1;
2642+ if (!remount) {
2643+ err = -EINVAL;
4a4d8108 2644+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 2645+ }
2646+ goto out;
2647+ }
2648+
2649+ err = -ENOSPC; /* -E2BIG; */
2650+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
5afbbe0d 2651+ || AUFS_BRANCH_MAX - 1 <= bbot)) {
4a4d8108 2652+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 2653+ goto out;
2654+ }
2655+
2656+ err = -EDOM;
5afbbe0d 2657+ if (unlikely(add->bindex < 0 || bbot + 1 < add->bindex)) {
4a4d8108 2658+ pr_err("bad index %d\n", add->bindex);
1facf9fc 2659+ goto out;
2660+ }
2661+
5527c038 2662+ inode = d_inode(add->path.dentry);
1facf9fc 2663+ err = -ENOENT;
2664+ if (unlikely(!inode->i_nlink)) {
4a4d8108 2665+ pr_err("no existence %s\n", add->pathname);
1facf9fc 2666+ goto out;
2667+ }
2668+
2669+ err = -EINVAL;
2670+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 2671+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 2672+ goto out;
2673+ }
2674+
2675+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
2676+ pr_err("unsupported filesystem, %s (%s)\n",
2677+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 2678+ goto out;
2679+ }
2680+
c1595e42
JR
2681+ if (unlikely(inode->i_sb->s_stack_depth)) {
2682+ pr_err("already stacked, %s (%s)\n",
2683+ add->pathname, au_sbtype(inode->i_sb));
2684+ goto out;
2685+ }
2686+
5527c038 2687+ err = test_br(d_inode(add->path.dentry), add->perm, add->pathname);
1facf9fc 2688+ if (unlikely(err))
2689+ goto out;
2690+
5afbbe0d 2691+ if (bbot < 0)
1facf9fc 2692+ return 0; /* success */
2693+
2694+ err = -EINVAL;
5afbbe0d 2695+ for (bindex = 0; bindex <= bbot; bindex++)
1facf9fc 2696+ if (unlikely(test_overlap(sb, add->path.dentry,
2697+ au_h_dptr(root, bindex)))) {
4a4d8108 2698+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 2699+ goto out;
2700+ }
2701+
2702+ err = 0;
2703+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
5527c038
JR
2704+ h_dentry = au_h_dptr(root, 0);
2705+ h_inode = d_inode(h_dentry);
1facf9fc 2706+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
0c3ec466
AM
2707+ || !uid_eq(h_inode->i_uid, inode->i_uid)
2708+ || !gid_eq(h_inode->i_gid, inode->i_gid))
2709+ pr_warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
2710+ add->pathname,
2711+ i_uid_read(inode), i_gid_read(inode),
2712+ (inode->i_mode & S_IALLUGO),
2713+ i_uid_read(h_inode), i_gid_read(h_inode),
2714+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 2715+ }
2716+
4f0767ce 2717+out:
1facf9fc 2718+ return err;
2719+}
2720+
2721+/*
2722+ * initialize or clean the whiteouts for an adding branch
2723+ */
2724+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
86dc4139 2725+ int new_perm)
1facf9fc 2726+{
2727+ int err, old_perm;
2728+ aufs_bindex_t bindex;
febd17d6 2729+ struct inode *h_inode;
1facf9fc 2730+ struct au_wbr *wbr;
2731+ struct au_hinode *hdir;
5527c038 2732+ struct dentry *h_dentry;
1facf9fc 2733+
86dc4139
AM
2734+ err = vfsub_mnt_want_write(au_br_mnt(br));
2735+ if (unlikely(err))
2736+ goto out;
2737+
1facf9fc 2738+ wbr = br->br_wbr;
2739+ old_perm = br->br_perm;
2740+ br->br_perm = new_perm;
2741+ hdir = NULL;
febd17d6 2742+ h_inode = NULL;
1facf9fc 2743+ bindex = au_br_index(sb, br->br_id);
2744+ if (0 <= bindex) {
5527c038 2745+ hdir = au_hi(d_inode(sb->s_root), bindex);
5afbbe0d 2746+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 2747+ } else {
5527c038 2748+ h_dentry = au_br_dentry(br);
febd17d6
JR
2749+ h_inode = d_inode(h_dentry);
2750+ inode_lock_nested(h_inode, AuLsc_I_PARENT);
1facf9fc 2751+ }
2752+ if (!wbr)
86dc4139 2753+ err = au_wh_init(br, sb);
1facf9fc 2754+ else {
2755+ wbr_wh_write_lock(wbr);
86dc4139 2756+ err = au_wh_init(br, sb);
1facf9fc 2757+ wbr_wh_write_unlock(wbr);
2758+ }
2759+ if (hdir)
5afbbe0d 2760+ au_hn_inode_unlock(hdir);
1facf9fc 2761+ else
febd17d6 2762+ inode_unlock(h_inode);
86dc4139 2763+ vfsub_mnt_drop_write(au_br_mnt(br));
1facf9fc 2764+ br->br_perm = old_perm;
2765+
2766+ if (!err && wbr && !au_br_writable(new_perm)) {
1c60b727 2767+ kfree(wbr);
1facf9fc 2768+ br->br_wbr = NULL;
2769+ }
2770+
86dc4139 2771+out:
1facf9fc 2772+ return err;
2773+}
2774+
2775+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
86dc4139 2776+ int perm)
1facf9fc 2777+{
2778+ int err;
4a4d8108 2779+ struct kstatfs kst;
1facf9fc 2780+ struct au_wbr *wbr;
2781+
2782+ wbr = br->br_wbr;
dece6358 2783+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 2784+ atomic_set(&wbr->wbr_wh_running, 0);
1facf9fc 2785+
4a4d8108
AM
2786+ /*
2787+ * a limit for rmdir/rename a dir
523b37e3 2788+ * cf. AUFS_MAX_NAMELEN in include/uapi/linux/aufs_type.h
4a4d8108 2789+ */
86dc4139 2790+ err = vfs_statfs(&br->br_path, &kst);
4a4d8108
AM
2791+ if (unlikely(err))
2792+ goto out;
2793+ err = -EINVAL;
2794+ if (kst.f_namelen >= NAME_MAX)
86dc4139 2795+ err = au_br_init_wh(sb, br, perm);
4a4d8108 2796+ else
523b37e3
AM
2797+ pr_err("%pd(%s), unsupported namelen %ld\n",
2798+ au_br_dentry(br),
86dc4139 2799+ au_sbtype(au_br_dentry(br)->d_sb), kst.f_namelen);
1facf9fc 2800+
4f0767ce 2801+out:
1facf9fc 2802+ return err;
2803+}
2804+
c1595e42 2805+/* initialize a new branch */
1facf9fc 2806+static int au_br_init(struct au_branch *br, struct super_block *sb,
2807+ struct au_opt_add *add)
2808+{
2809+ int err;
5527c038 2810+ struct inode *h_inode;
1facf9fc 2811+
2812+ err = 0;
521ced18
JR
2813+ spin_lock_init(&br->br_xino.xi_nondir.spin);
2814+ init_waitqueue_head(&br->br_xino.xi_nondir.wqh);
1facf9fc 2815+ br->br_perm = add->perm;
86dc4139 2816+ br->br_path = add->path; /* set first, path_get() later */
4a4d8108 2817+ spin_lock_init(&br->br_dykey_lock);
5afbbe0d 2818+ au_br_count_init(br);
1facf9fc 2819+ atomic_set(&br->br_xino_running, 0);
2820+ br->br_id = au_new_br_id(sb);
7f207e10 2821+ AuDebugOn(br->br_id < 0);
1facf9fc 2822+
8b6a4947
AM
2823+ /* always, regardless the given option */
2824+ err = au_dr_br_init(sb, br, &add->path);
2825+ if (unlikely(err))
2826+ goto out_err;
2827+
1facf9fc 2828+ if (au_br_writable(add->perm)) {
86dc4139 2829+ err = au_wbr_init(br, sb, add->perm);
1facf9fc 2830+ if (unlikely(err))
b752ccd1 2831+ goto out_err;
1facf9fc 2832+ }
2833+
2834+ if (au_opt_test(au_mntflags(sb), XINO)) {
5527c038
JR
2835+ h_inode = d_inode(add->path.dentry);
2836+ err = au_xino_br(sb, br, h_inode->i_ino,
1facf9fc 2837+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
2838+ if (unlikely(err)) {
2839+ AuDebugOn(br->br_xino.xi_file);
b752ccd1 2840+ goto out_err;
1facf9fc 2841+ }
2842+ }
2843+
2844+ sysaufs_br_init(br);
86dc4139 2845+ path_get(&br->br_path);
b752ccd1 2846+ goto out; /* success */
1facf9fc 2847+
4f0767ce 2848+out_err:
86dc4139 2849+ memset(&br->br_path, 0, sizeof(br->br_path));
4f0767ce 2850+out:
1facf9fc 2851+ return err;
2852+}
2853+
2854+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
5afbbe0d 2855+ struct au_branch *br, aufs_bindex_t bbot,
1facf9fc 2856+ aufs_bindex_t amount)
2857+{
2858+ struct au_branch **brp;
2859+
dece6358
AM
2860+ AuRwMustWriteLock(&sbinfo->si_rwsem);
2861+
1facf9fc 2862+ brp = sbinfo->si_branch + bindex;
2863+ memmove(brp + 1, brp, sizeof(*brp) * amount);
2864+ *brp = br;
5afbbe0d
AM
2865+ sbinfo->si_bbot++;
2866+ if (unlikely(bbot < 0))
2867+ sbinfo->si_bbot = 0;
1facf9fc 2868+}
2869+
2870+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
5afbbe0d 2871+ aufs_bindex_t bbot, aufs_bindex_t amount)
1facf9fc 2872+{
2873+ struct au_hdentry *hdp;
2874+
1308ab2a 2875+ AuRwMustWriteLock(&dinfo->di_rwsem);
2876+
5afbbe0d 2877+ hdp = au_hdentry(dinfo, bindex);
1facf9fc 2878+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
2879+ au_h_dentry_init(hdp);
5afbbe0d
AM
2880+ dinfo->di_bbot++;
2881+ if (unlikely(bbot < 0))
2882+ dinfo->di_btop = 0;
1facf9fc 2883+}
2884+
2885+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
5afbbe0d 2886+ aufs_bindex_t bbot, aufs_bindex_t amount)
1facf9fc 2887+{
2888+ struct au_hinode *hip;
2889+
1308ab2a 2890+ AuRwMustWriteLock(&iinfo->ii_rwsem);
2891+
5afbbe0d 2892+ hip = au_hinode(iinfo, bindex);
1facf9fc 2893+ memmove(hip + 1, hip, sizeof(*hip) * amount);
5afbbe0d
AM
2894+ au_hinode_init(hip);
2895+ iinfo->ii_bbot++;
2896+ if (unlikely(bbot < 0))
2897+ iinfo->ii_btop = 0;
1facf9fc 2898+}
2899+
86dc4139
AM
2900+static void au_br_do_add(struct super_block *sb, struct au_branch *br,
2901+ aufs_bindex_t bindex)
1facf9fc 2902+{
86dc4139 2903+ struct dentry *root, *h_dentry;
5527c038 2904+ struct inode *root_inode, *h_inode;
5afbbe0d 2905+ aufs_bindex_t bbot, amount;
1facf9fc 2906+
2907+ root = sb->s_root;
5527c038 2908+ root_inode = d_inode(root);
5afbbe0d
AM
2909+ bbot = au_sbbot(sb);
2910+ amount = bbot + 1 - bindex;
86dc4139 2911+ h_dentry = au_br_dentry(br);
53392da6 2912+ au_sbilist_lock();
5afbbe0d
AM
2913+ au_br_do_add_brp(au_sbi(sb), bindex, br, bbot, amount);
2914+ au_br_do_add_hdp(au_di(root), bindex, bbot, amount);
2915+ au_br_do_add_hip(au_ii(root_inode), bindex, bbot, amount);
1facf9fc 2916+ au_set_h_dptr(root, bindex, dget(h_dentry));
5527c038
JR
2917+ h_inode = d_inode(h_dentry);
2918+ au_set_h_iptr(root_inode, bindex, au_igrab(h_inode), /*flags*/0);
53392da6 2919+ au_sbilist_unlock();
1facf9fc 2920+}
2921+
2922+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
2923+{
2924+ int err;
5afbbe0d 2925+ aufs_bindex_t bbot, add_bindex;
1facf9fc 2926+ struct dentry *root, *h_dentry;
2927+ struct inode *root_inode;
2928+ struct au_branch *add_branch;
2929+
2930+ root = sb->s_root;
5527c038 2931+ root_inode = d_inode(root);
1facf9fc 2932+ IMustLock(root_inode);
5afbbe0d 2933+ IiMustWriteLock(root_inode);
1facf9fc 2934+ err = test_add(sb, add, remount);
2935+ if (unlikely(err < 0))
2936+ goto out;
2937+ if (err) {
2938+ err = 0;
2939+ goto out; /* success */
2940+ }
2941+
5afbbe0d
AM
2942+ bbot = au_sbbot(sb);
2943+ add_branch = au_br_alloc(sb, bbot + 2, add->perm);
1facf9fc 2944+ err = PTR_ERR(add_branch);
2945+ if (IS_ERR(add_branch))
2946+ goto out;
2947+
2948+ err = au_br_init(add_branch, sb, add);
2949+ if (unlikely(err)) {
2950+ au_br_do_free(add_branch);
2951+ goto out;
2952+ }
2953+
2954+ add_bindex = add->bindex;
1facf9fc 2955+ if (!remount)
86dc4139 2956+ au_br_do_add(sb, add_branch, add_bindex);
1facf9fc 2957+ else {
2958+ sysaufs_brs_del(sb, add_bindex);
86dc4139 2959+ au_br_do_add(sb, add_branch, add_bindex);
1facf9fc 2960+ sysaufs_brs_add(sb, add_bindex);
2961+ }
2962+
86dc4139 2963+ h_dentry = add->path.dentry;
1308ab2a 2964+ if (!add_bindex) {
1facf9fc 2965+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 2966+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
2967+ } else
5527c038 2968+ au_add_nlink(root_inode, d_inode(h_dentry));
1facf9fc 2969+
2970+ /*
4a4d8108 2971+ * this test/set prevents aufs from handling unnecesary notify events
027c5e7a 2972+ * of xino files, in case of re-adding a writable branch which was
1facf9fc 2973+ * once detached from aufs.
2974+ */
2975+ if (au_xino_brid(sb) < 0
2976+ && au_br_writable(add_branch->br_perm)
2977+ && !au_test_fs_bad_xino(h_dentry->d_sb)
2978+ && add_branch->br_xino.xi_file
2000de60 2979+ && add_branch->br_xino.xi_file->f_path.dentry->d_parent == h_dentry)
1facf9fc 2980+ au_xino_brid_set(sb, add_branch->br_id);
2981+
4f0767ce 2982+out:
1facf9fc 2983+ return err;
2984+}
2985+
2986+/* ---------------------------------------------------------------------- */
2987+
79b8bda9 2988+static unsigned long long au_farray_cb(struct super_block *sb, void *a,
076b876e
AM
2989+ unsigned long long max __maybe_unused,
2990+ void *arg)
2991+{
2992+ unsigned long long n;
2993+ struct file **p, *f;
8b6a4947
AM
2994+ struct hlist_bl_head *files;
2995+ struct hlist_bl_node *pos;
076b876e 2996+ struct au_finfo *finfo;
076b876e
AM
2997+
2998+ n = 0;
2999+ p = a;
3000+ files = &au_sbi(sb)->si_files;
8b6a4947
AM
3001+ hlist_bl_lock(files);
3002+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) {
076b876e
AM
3003+ f = finfo->fi_file;
3004+ if (file_count(f)
3005+ && !special_file(file_inode(f)->i_mode)) {
3006+ get_file(f);
3007+ *p++ = f;
3008+ n++;
3009+ AuDebugOn(n > max);
3010+ }
3011+ }
8b6a4947 3012+ hlist_bl_unlock(files);
076b876e
AM
3013+
3014+ return n;
3015+}
3016+
3017+static struct file **au_farray_alloc(struct super_block *sb,
3018+ unsigned long long *max)
3019+{
5afbbe0d 3020+ *max = au_nfiles(sb);
79b8bda9 3021+ return au_array_alloc(max, au_farray_cb, sb, /*arg*/NULL);
076b876e
AM
3022+}
3023+
3024+static void au_farray_free(struct file **a, unsigned long long max)
3025+{
3026+ unsigned long long ull;
3027+
3028+ for (ull = 0; ull < max; ull++)
3029+ if (a[ull])
3030+ fput(a[ull]);
be52b249 3031+ kvfree(a);
076b876e
AM
3032+}
3033+
3034+/* ---------------------------------------------------------------------- */
3035+
1facf9fc 3036+/*
3037+ * delete a branch
3038+ */
3039+
3040+/* to show the line number, do not make it inlined function */
4a4d8108 3041+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 3042+ if (do_info) \
4a4d8108 3043+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 3044+} while (0)
3045+
5afbbe0d
AM
3046+static int au_test_ibusy(struct inode *inode, aufs_bindex_t btop,
3047+ aufs_bindex_t bbot)
027c5e7a 3048+{
5afbbe0d 3049+ return (inode && !S_ISDIR(inode->i_mode)) || btop == bbot;
027c5e7a
AM
3050+}
3051+
5afbbe0d
AM
3052+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t btop,
3053+ aufs_bindex_t bbot)
027c5e7a 3054+{
5afbbe0d 3055+ return au_test_ibusy(d_inode(dentry), btop, bbot);
027c5e7a
AM
3056+}
3057+
1facf9fc 3058+/*
3059+ * test if the branch is deletable or not.
3060+ */
3061+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 3062+ unsigned int sigen, const unsigned int verbose)
1facf9fc 3063+{
3064+ int err, i, j, ndentry;
5afbbe0d 3065+ aufs_bindex_t btop, bbot;
1facf9fc 3066+ struct au_dcsub_pages dpages;
3067+ struct au_dpage *dpage;
3068+ struct dentry *d;
1facf9fc 3069+
3070+ err = au_dpages_init(&dpages, GFP_NOFS);
3071+ if (unlikely(err))
3072+ goto out;
3073+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
3074+ if (unlikely(err))
3075+ goto out_dpages;
3076+
1facf9fc 3077+ for (i = 0; !err && i < dpages.ndpage; i++) {
3078+ dpage = dpages.dpages + i;
3079+ ndentry = dpage->ndentry;
3080+ for (j = 0; !err && j < ndentry; j++) {
3081+ d = dpage->dentries[j];
c1595e42 3082+ AuDebugOn(au_dcount(d) <= 0);
027c5e7a 3083+ if (!au_digen_test(d, sigen)) {
1facf9fc 3084+ di_read_lock_child(d, AuLock_IR);
027c5e7a
AM
3085+ if (unlikely(au_dbrange_test(d))) {
3086+ di_read_unlock(d, AuLock_IR);
3087+ continue;
3088+ }
3089+ } else {
1facf9fc 3090+ di_write_lock_child(d);
027c5e7a
AM
3091+ if (unlikely(au_dbrange_test(d))) {
3092+ di_write_unlock(d);
3093+ continue;
3094+ }
1facf9fc 3095+ err = au_reval_dpath(d, sigen);
3096+ if (!err)
3097+ di_downgrade_lock(d, AuLock_IR);
3098+ else {
3099+ di_write_unlock(d);
3100+ break;
3101+ }
3102+ }
3103+
027c5e7a 3104+ /* AuDbgDentry(d); */
5afbbe0d
AM
3105+ btop = au_dbtop(d);
3106+ bbot = au_dbbot(d);
3107+ if (btop <= bindex
3108+ && bindex <= bbot
1facf9fc 3109+ && au_h_dptr(d, bindex)
5afbbe0d 3110+ && au_test_dbusy(d, btop, bbot)) {
1facf9fc 3111+ err = -EBUSY;
523b37e3 3112+ AuVerbose(verbose, "busy %pd\n", d);
027c5e7a 3113+ AuDbgDentry(d);
1facf9fc 3114+ }
3115+ di_read_unlock(d, AuLock_IR);
3116+ }
3117+ }
3118+
4f0767ce 3119+out_dpages:
1facf9fc 3120+ au_dpages_free(&dpages);
4f0767ce 3121+out:
1facf9fc 3122+ return err;
3123+}
3124+
3125+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 3126+ unsigned int sigen, const unsigned int verbose)
1facf9fc 3127+{
3128+ int err;
7f207e10
AM
3129+ unsigned long long max, ull;
3130+ struct inode *i, **array;
5afbbe0d 3131+ aufs_bindex_t btop, bbot;
1facf9fc 3132+
7f207e10
AM
3133+ array = au_iarray_alloc(sb, &max);
3134+ err = PTR_ERR(array);
3135+ if (IS_ERR(array))
3136+ goto out;
3137+
1facf9fc 3138+ err = 0;
7f207e10
AM
3139+ AuDbg("b%d\n", bindex);
3140+ for (ull = 0; !err && ull < max; ull++) {
3141+ i = array[ull];
076b876e
AM
3142+ if (unlikely(!i))
3143+ break;
7f207e10 3144+ if (i->i_ino == AUFS_ROOT_INO)
1facf9fc 3145+ continue;
3146+
7f207e10 3147+ /* AuDbgInode(i); */
537831f9 3148+ if (au_iigen(i, NULL) == sigen)
1facf9fc 3149+ ii_read_lock_child(i);
3150+ else {
3151+ ii_write_lock_child(i);
027c5e7a
AM
3152+ err = au_refresh_hinode_self(i);
3153+ au_iigen_dec(i);
1facf9fc 3154+ if (!err)
3155+ ii_downgrade_lock(i);
3156+ else {
3157+ ii_write_unlock(i);
3158+ break;
3159+ }
3160+ }
3161+
5afbbe0d
AM
3162+ btop = au_ibtop(i);
3163+ bbot = au_ibbot(i);
3164+ if (btop <= bindex
3165+ && bindex <= bbot
1facf9fc 3166+ && au_h_iptr(i, bindex)
5afbbe0d 3167+ && au_test_ibusy(i, btop, bbot)) {
1facf9fc 3168+ err = -EBUSY;
3169+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
7f207e10 3170+ AuDbgInode(i);
1facf9fc 3171+ }
3172+ ii_read_unlock(i);
3173+ }
7f207e10 3174+ au_iarray_free(array, max);
1facf9fc 3175+
7f207e10 3176+out:
1facf9fc 3177+ return err;
3178+}
3179+
b752ccd1
AM
3180+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
3181+ const unsigned int verbose)
1facf9fc 3182+{
3183+ int err;
3184+ unsigned int sigen;
3185+
3186+ sigen = au_sigen(root->d_sb);
3187+ DiMustNoWaiters(root);
5527c038 3188+ IiMustNoWaiters(d_inode(root));
1facf9fc 3189+ di_write_unlock(root);
b752ccd1 3190+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 3191+ if (!err)
b752ccd1 3192+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 3193+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
3194+
3195+ return err;
3196+}
3197+
076b876e
AM
3198+static int test_dir_busy(struct file *file, aufs_bindex_t br_id,
3199+ struct file **to_free, int *idx)
3200+{
3201+ int err;
c1595e42 3202+ unsigned char matched, root;
5afbbe0d 3203+ aufs_bindex_t bindex, bbot;
076b876e
AM
3204+ struct au_fidir *fidir;
3205+ struct au_hfile *hfile;
3206+
3207+ err = 0;
2000de60 3208+ root = IS_ROOT(file->f_path.dentry);
c1595e42
JR
3209+ if (root) {
3210+ get_file(file);
3211+ to_free[*idx] = file;
3212+ (*idx)++;
3213+ goto out;
3214+ }
3215+
076b876e 3216+ matched = 0;
076b876e
AM
3217+ fidir = au_fi(file)->fi_hdir;
3218+ AuDebugOn(!fidir);
5afbbe0d
AM
3219+ bbot = au_fbbot_dir(file);
3220+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++) {
076b876e
AM
3221+ hfile = fidir->fd_hfile + bindex;
3222+ if (!hfile->hf_file)
3223+ continue;
3224+
c1595e42 3225+ if (hfile->hf_br->br_id == br_id) {
076b876e 3226+ matched = 1;
076b876e 3227+ break;
c1595e42 3228+ }
076b876e 3229+ }
c1595e42 3230+ if (matched)
076b876e
AM
3231+ err = -EBUSY;
3232+
3233+out:
3234+ return err;
3235+}
3236+
3237+static int test_file_busy(struct super_block *sb, aufs_bindex_t br_id,
3238+ struct file **to_free, int opened)
3239+{
3240+ int err, idx;
3241+ unsigned long long ull, max;
5afbbe0d 3242+ aufs_bindex_t btop;
076b876e 3243+ struct file *file, **array;
076b876e
AM
3244+ struct dentry *root;
3245+ struct au_hfile *hfile;
3246+
3247+ array = au_farray_alloc(sb, &max);
3248+ err = PTR_ERR(array);
3249+ if (IS_ERR(array))
3250+ goto out;
3251+
3252+ err = 0;
3253+ idx = 0;
3254+ root = sb->s_root;
3255+ di_write_unlock(root);
3256+ for (ull = 0; ull < max; ull++) {
3257+ file = array[ull];
3258+ if (unlikely(!file))
3259+ break;
3260+
3261+ /* AuDbg("%pD\n", file); */
3262+ fi_read_lock(file);
5afbbe0d 3263+ btop = au_fbtop(file);
2000de60 3264+ if (!d_is_dir(file->f_path.dentry)) {
076b876e
AM
3265+ hfile = &au_fi(file)->fi_htop;
3266+ if (hfile->hf_br->br_id == br_id)
3267+ err = -EBUSY;
3268+ } else
3269+ err = test_dir_busy(file, br_id, to_free, &idx);
3270+ fi_read_unlock(file);
3271+ if (unlikely(err))
3272+ break;
3273+ }
3274+ di_write_lock_child(root);
3275+ au_farray_free(array, max);
3276+ AuDebugOn(idx > opened);
3277+
3278+out:
3279+ return err;
3280+}
3281+
3282+static void br_del_file(struct file **to_free, unsigned long long opened,
3283+ aufs_bindex_t br_id)
3284+{
3285+ unsigned long long ull;
5afbbe0d 3286+ aufs_bindex_t bindex, btop, bbot, bfound;
076b876e
AM
3287+ struct file *file;
3288+ struct au_fidir *fidir;
3289+ struct au_hfile *hfile;
3290+
3291+ for (ull = 0; ull < opened; ull++) {
3292+ file = to_free[ull];
3293+ if (unlikely(!file))
3294+ break;
3295+
3296+ /* AuDbg("%pD\n", file); */
2000de60 3297+ AuDebugOn(!d_is_dir(file->f_path.dentry));
076b876e
AM
3298+ bfound = -1;
3299+ fidir = au_fi(file)->fi_hdir;
3300+ AuDebugOn(!fidir);
3301+ fi_write_lock(file);
5afbbe0d
AM
3302+ btop = au_fbtop(file);
3303+ bbot = au_fbbot_dir(file);
3304+ for (bindex = btop; bindex <= bbot; bindex++) {
076b876e
AM
3305+ hfile = fidir->fd_hfile + bindex;
3306+ if (!hfile->hf_file)
3307+ continue;
3308+
3309+ if (hfile->hf_br->br_id == br_id) {
3310+ bfound = bindex;
3311+ break;
3312+ }
3313+ }
3314+ AuDebugOn(bfound < 0);
3315+ au_set_h_fptr(file, bfound, NULL);
5afbbe0d
AM
3316+ if (bfound == btop) {
3317+ for (btop++; btop <= bbot; btop++)
3318+ if (au_hf_dir(file, btop)) {
3319+ au_set_fbtop(file, btop);
076b876e
AM
3320+ break;
3321+ }
3322+ }
3323+ fi_write_unlock(file);
3324+ }
3325+}
3326+
1facf9fc 3327+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
3328+ const aufs_bindex_t bindex,
5afbbe0d 3329+ const aufs_bindex_t bbot)
1facf9fc 3330+{
3331+ struct au_branch **brp, **p;
3332+
dece6358
AM
3333+ AuRwMustWriteLock(&sbinfo->si_rwsem);
3334+
1facf9fc 3335+ brp = sbinfo->si_branch + bindex;
5afbbe0d
AM
3336+ if (bindex < bbot)
3337+ memmove(brp, brp + 1, sizeof(*brp) * (bbot - bindex));
3338+ sbinfo->si_branch[0 + bbot] = NULL;
3339+ sbinfo->si_bbot--;
1facf9fc 3340+
e2f27e51
AM
3341+ p = au_krealloc(sbinfo->si_branch, sizeof(*p) * bbot, AuGFP_SBILIST,
3342+ /*may_shrink*/1);
1facf9fc 3343+ if (p)
3344+ sbinfo->si_branch = p;
4a4d8108 3345+ /* harmless error */
1facf9fc 3346+}
3347+
3348+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
5afbbe0d 3349+ const aufs_bindex_t bbot)
1facf9fc 3350+{
3351+ struct au_hdentry *hdp, *p;
3352+
1308ab2a 3353+ AuRwMustWriteLock(&dinfo->di_rwsem);
3354+
5afbbe0d
AM
3355+ hdp = au_hdentry(dinfo, bindex);
3356+ if (bindex < bbot)
3357+ memmove(hdp, hdp + 1, sizeof(*hdp) * (bbot - bindex));
3358+ /* au_h_dentry_init(au_hdentry(dinfo, bbot); */
3359+ dinfo->di_bbot--;
1facf9fc 3360+
e2f27e51
AM
3361+ p = au_krealloc(dinfo->di_hdentry, sizeof(*p) * bbot, AuGFP_SBILIST,
3362+ /*may_shrink*/1);
1facf9fc 3363+ if (p)
3364+ dinfo->di_hdentry = p;
4a4d8108 3365+ /* harmless error */
1facf9fc 3366+}
3367+
3368+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
5afbbe0d 3369+ const aufs_bindex_t bbot)
1facf9fc 3370+{
3371+ struct au_hinode *hip, *p;
3372+
1308ab2a 3373+ AuRwMustWriteLock(&iinfo->ii_rwsem);
3374+
5afbbe0d
AM
3375+ hip = au_hinode(iinfo, bindex);
3376+ if (bindex < bbot)
3377+ memmove(hip, hip + 1, sizeof(*hip) * (bbot - bindex));
3378+ /* au_hinode_init(au_hinode(iinfo, bbot)); */
3379+ iinfo->ii_bbot--;
1facf9fc 3380+
e2f27e51
AM
3381+ p = au_krealloc(iinfo->ii_hinode, sizeof(*p) * bbot, AuGFP_SBILIST,
3382+ /*may_shrink*/1);
1facf9fc 3383+ if (p)
3384+ iinfo->ii_hinode = p;
4a4d8108 3385+ /* harmless error */
1facf9fc 3386+}
3387+
3388+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
3389+ struct au_branch *br)
3390+{
5afbbe0d 3391+ aufs_bindex_t bbot;
1facf9fc 3392+ struct au_sbinfo *sbinfo;
53392da6
AM
3393+ struct dentry *root, *h_root;
3394+ struct inode *inode, *h_inode;
3395+ struct au_hinode *hinode;
1facf9fc 3396+
dece6358
AM
3397+ SiMustWriteLock(sb);
3398+
1facf9fc 3399+ root = sb->s_root;
5527c038 3400+ inode = d_inode(root);
1facf9fc 3401+ sbinfo = au_sbi(sb);
5afbbe0d 3402+ bbot = sbinfo->si_bbot;
1facf9fc 3403+
53392da6
AM
3404+ h_root = au_h_dptr(root, bindex);
3405+ hinode = au_hi(inode, bindex);
3406+ h_inode = au_igrab(hinode->hi_inode);
3407+ au_hiput(hinode);
1facf9fc 3408+
53392da6 3409+ au_sbilist_lock();
5afbbe0d
AM
3410+ au_br_do_del_brp(sbinfo, bindex, bbot);
3411+ au_br_do_del_hdp(au_di(root), bindex, bbot);
3412+ au_br_do_del_hip(au_ii(inode), bindex, bbot);
53392da6
AM
3413+ au_sbilist_unlock();
3414+
8b6a4947
AM
3415+ /* ignore an error */
3416+ au_dr_br_fin(sb, br); /* always, regardless the mount option */
3417+
53392da6
AM
3418+ dput(h_root);
3419+ iput(h_inode);
3420+ au_br_do_free(br);
1facf9fc 3421+}
3422+
79b8bda9
AM
3423+static unsigned long long empty_cb(struct super_block *sb, void *array,
3424+ unsigned long long max, void *arg)
076b876e
AM
3425+{
3426+ return max;
3427+}
3428+
1facf9fc 3429+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
3430+{
3431+ int err, rerr, i;
076b876e 3432+ unsigned long long opened;
1facf9fc 3433+ unsigned int mnt_flags;
5afbbe0d 3434+ aufs_bindex_t bindex, bbot, br_id;
1facf9fc 3435+ unsigned char do_wh, verbose;
3436+ struct au_branch *br;
3437+ struct au_wbr *wbr;
076b876e
AM
3438+ struct dentry *root;
3439+ struct file **to_free;
1facf9fc 3440+
3441+ err = 0;
076b876e
AM
3442+ opened = 0;
3443+ to_free = NULL;
3444+ root = sb->s_root;
3445+ bindex = au_find_dbindex(root, del->h_path.dentry);
1facf9fc 3446+ if (bindex < 0) {
3447+ if (remount)
3448+ goto out; /* success */
3449+ err = -ENOENT;
4a4d8108 3450+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 3451+ goto out;
3452+ }
3453+ AuDbg("bindex b%d\n", bindex);
3454+
3455+ err = -EBUSY;
3456+ mnt_flags = au_mntflags(sb);
3457+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
5afbbe0d
AM
3458+ bbot = au_sbbot(sb);
3459+ if (unlikely(!bbot)) {
1facf9fc 3460+ AuVerbose(verbose, "no more branches left\n");
3461+ goto out;
3462+ }
3463+ br = au_sbr(sb, bindex);
86dc4139 3464+ AuDebugOn(!path_equal(&br->br_path, &del->h_path));
076b876e
AM
3465+
3466+ br_id = br->br_id;
5afbbe0d 3467+ opened = au_br_count(br);
076b876e 3468+ if (unlikely(opened)) {
79b8bda9 3469+ to_free = au_array_alloc(&opened, empty_cb, sb, NULL);
076b876e
AM
3470+ err = PTR_ERR(to_free);
3471+ if (IS_ERR(to_free))
3472+ goto out;
3473+
3474+ err = test_file_busy(sb, br_id, to_free, opened);
3475+ if (unlikely(err)) {
3476+ AuVerbose(verbose, "%llu file(s) opened\n", opened);
3477+ goto out;
3478+ }
1facf9fc 3479+ }
3480+
3481+ wbr = br->br_wbr;
3482+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
3483+ if (do_wh) {
1308ab2a 3484+ /* instead of WbrWhMustWriteLock(wbr) */
3485+ SiMustWriteLock(sb);
1facf9fc 3486+ for (i = 0; i < AuBrWh_Last; i++) {
3487+ dput(wbr->wbr_wh[i]);
3488+ wbr->wbr_wh[i] = NULL;
3489+ }
3490+ }
3491+
076b876e 3492+ err = test_children_busy(root, bindex, verbose);
1facf9fc 3493+ if (unlikely(err)) {
3494+ if (do_wh)
3495+ goto out_wh;
3496+ goto out;
3497+ }
3498+
3499+ err = 0;
076b876e
AM
3500+ if (to_free) {
3501+ /*
3502+ * now we confirmed the branch is deletable.
3503+ * let's free the remaining opened dirs on the branch.
3504+ */
3505+ di_write_unlock(root);
3506+ br_del_file(to_free, opened, br_id);
3507+ di_write_lock_child(root);
3508+ }
3509+
1facf9fc 3510+ if (!remount)
3511+ au_br_do_del(sb, bindex, br);
3512+ else {
3513+ sysaufs_brs_del(sb, bindex);
3514+ au_br_do_del(sb, bindex, br);
3515+ sysaufs_brs_add(sb, bindex);
3516+ }
3517+
1308ab2a 3518+ if (!bindex) {
5527c038 3519+ au_cpup_attr_all(d_inode(root), /*force*/1);
1308ab2a 3520+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
3521+ } else
5527c038 3522+ au_sub_nlink(d_inode(root), d_inode(del->h_path.dentry));
1facf9fc 3523+ if (au_opt_test(mnt_flags, PLINK))
3524+ au_plink_half_refresh(sb, br_id);
3525+
b752ccd1 3526+ if (au_xino_brid(sb) == br_id)
1facf9fc 3527+ au_xino_brid_set(sb, -1);
3528+ goto out; /* success */
3529+
4f0767ce 3530+out_wh:
1facf9fc 3531+ /* revert */
86dc4139 3532+ rerr = au_br_init_wh(sb, br, br->br_perm);
1facf9fc 3533+ if (rerr)
0c3ec466
AM
3534+ pr_warn("failed re-creating base whiteout, %s. (%d)\n",
3535+ del->pathname, rerr);
4f0767ce 3536+out:
076b876e
AM
3537+ if (to_free)
3538+ au_farray_free(to_free, opened);
1facf9fc 3539+ return err;
3540+}
3541+
3542+/* ---------------------------------------------------------------------- */
3543+
027c5e7a
AM
3544+static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg)
3545+{
3546+ int err;
5afbbe0d 3547+ aufs_bindex_t btop, bbot;
027c5e7a
AM
3548+ struct aufs_ibusy ibusy;
3549+ struct inode *inode, *h_inode;
3550+
3551+ err = -EPERM;
3552+ if (unlikely(!capable(CAP_SYS_ADMIN)))
3553+ goto out;
3554+
3555+ err = copy_from_user(&ibusy, arg, sizeof(ibusy));
3556+ if (!err)
3557+ err = !access_ok(VERIFY_WRITE, &arg->h_ino, sizeof(arg->h_ino));
3558+ if (unlikely(err)) {
3559+ err = -EFAULT;
3560+ AuTraceErr(err);
3561+ goto out;
3562+ }
3563+
3564+ err = -EINVAL;
3565+ si_read_lock(sb, AuLock_FLUSH);
5afbbe0d 3566+ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbbot(sb)))
027c5e7a
AM
3567+ goto out_unlock;
3568+
3569+ err = 0;
3570+ ibusy.h_ino = 0; /* invalid */
3571+ inode = ilookup(sb, ibusy.ino);
3572+ if (!inode
3573+ || inode->i_ino == AUFS_ROOT_INO
5afbbe0d 3574+ || au_is_bad_inode(inode))
027c5e7a
AM
3575+ goto out_unlock;
3576+
3577+ ii_read_lock_child(inode);
5afbbe0d
AM
3578+ btop = au_ibtop(inode);
3579+ bbot = au_ibbot(inode);
3580+ if (btop <= ibusy.bindex && ibusy.bindex <= bbot) {
027c5e7a 3581+ h_inode = au_h_iptr(inode, ibusy.bindex);
5afbbe0d 3582+ if (h_inode && au_test_ibusy(inode, btop, bbot))
027c5e7a
AM
3583+ ibusy.h_ino = h_inode->i_ino;
3584+ }
3585+ ii_read_unlock(inode);
3586+ iput(inode);
3587+
3588+out_unlock:
3589+ si_read_unlock(sb);
3590+ if (!err) {
3591+ err = __put_user(ibusy.h_ino, &arg->h_ino);
3592+ if (unlikely(err)) {
3593+ err = -EFAULT;
3594+ AuTraceErr(err);
3595+ }
3596+ }
3597+out:
3598+ return err;
3599+}
3600+
3601+long au_ibusy_ioctl(struct file *file, unsigned long arg)
3602+{
2000de60 3603+ return au_ibusy(file->f_path.dentry->d_sb, (void __user *)arg);
027c5e7a
AM
3604+}
3605+
3606+#ifdef CONFIG_COMPAT
3607+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg)
3608+{
2000de60 3609+ return au_ibusy(file->f_path.dentry->d_sb, compat_ptr(arg));
027c5e7a
AM
3610+}
3611+#endif
3612+
3613+/* ---------------------------------------------------------------------- */
3614+
1facf9fc 3615+/*
3616+ * change a branch permission
3617+ */
3618+
dece6358
AM
3619+static void au_warn_ima(void)
3620+{
3621+#ifdef CONFIG_IMA
1308ab2a 3622+ /* since it doesn't support mark_files_ro() */
027c5e7a 3623+ AuWarn1("RW -> RO makes IMA to produce wrong message\n");
dece6358
AM
3624+#endif
3625+}
3626+
1facf9fc 3627+static int do_need_sigen_inc(int a, int b)
3628+{
3629+ return au_br_whable(a) && !au_br_whable(b);
3630+}
3631+
3632+static int need_sigen_inc(int old, int new)
3633+{
3634+ return do_need_sigen_inc(old, new)
3635+ || do_need_sigen_inc(new, old);
3636+}
3637+
3638+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
3639+{
7f207e10 3640+ int err, do_warn;
027c5e7a 3641+ unsigned int mnt_flags;
7f207e10 3642+ unsigned long long ull, max;
e49829fe 3643+ aufs_bindex_t br_id;
38d290e6 3644+ unsigned char verbose, writer;
7f207e10 3645+ struct file *file, *hf, **array;
e49829fe 3646+ struct au_hfile *hfile;
1facf9fc 3647+
027c5e7a
AM
3648+ mnt_flags = au_mntflags(sb);
3649+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
3650+
7f207e10
AM
3651+ array = au_farray_alloc(sb, &max);
3652+ err = PTR_ERR(array);
3653+ if (IS_ERR(array))
1facf9fc 3654+ goto out;
3655+
7f207e10 3656+ do_warn = 0;
e49829fe 3657+ br_id = au_sbr_id(sb, bindex);
7f207e10
AM
3658+ for (ull = 0; ull < max; ull++) {
3659+ file = array[ull];
076b876e
AM
3660+ if (unlikely(!file))
3661+ break;
1facf9fc 3662+
523b37e3 3663+ /* AuDbg("%pD\n", file); */
1facf9fc 3664+ fi_read_lock(file);
3665+ if (unlikely(au_test_mmapped(file))) {
3666+ err = -EBUSY;
523b37e3 3667+ AuVerbose(verbose, "mmapped %pD\n", file);
7f207e10 3668+ AuDbgFile(file);
1facf9fc 3669+ FiMustNoWaiters(file);
3670+ fi_read_unlock(file);
7f207e10 3671+ goto out_array;
1facf9fc 3672+ }
3673+
e49829fe
JR
3674+ hfile = &au_fi(file)->fi_htop;
3675+ hf = hfile->hf_file;
7e9cd9fe 3676+ if (!d_is_reg(file->f_path.dentry)
1facf9fc 3677+ || !(file->f_mode & FMODE_WRITE)
e49829fe 3678+ || hfile->hf_br->br_id != br_id
7f207e10
AM
3679+ || !(hf->f_mode & FMODE_WRITE))
3680+ array[ull] = NULL;
3681+ else {
3682+ do_warn = 1;
3683+ get_file(file);
1facf9fc 3684+ }
3685+
1facf9fc 3686+ FiMustNoWaiters(file);
3687+ fi_read_unlock(file);
7f207e10
AM
3688+ fput(file);
3689+ }
1facf9fc 3690+
3691+ err = 0;
7f207e10 3692+ if (do_warn)
dece6358 3693+ au_warn_ima();
7f207e10
AM
3694+
3695+ for (ull = 0; ull < max; ull++) {
3696+ file = array[ull];
3697+ if (!file)
3698+ continue;
3699+
1facf9fc 3700+ /* todo: already flushed? */
523b37e3
AM
3701+ /*
3702+ * fs/super.c:mark_files_ro() is gone, but aufs keeps its
3703+ * approach which resets f_mode and calls mnt_drop_write() and
3704+ * file_release_write() for each file, because the branch
3705+ * attribute in aufs world is totally different from the native
3706+ * fs rw/ro mode.
3707+ */
7f207e10
AM
3708+ /* fi_read_lock(file); */
3709+ hfile = &au_fi(file)->fi_htop;
3710+ hf = hfile->hf_file;
3711+ /* fi_read_unlock(file); */
027c5e7a 3712+ spin_lock(&hf->f_lock);
38d290e6
JR
3713+ writer = !!(hf->f_mode & FMODE_WRITER);
3714+ hf->f_mode &= ~(FMODE_WRITE | FMODE_WRITER);
027c5e7a 3715+ spin_unlock(&hf->f_lock);
38d290e6
JR
3716+ if (writer) {
3717+ put_write_access(file_inode(hf));
c06a8ce3 3718+ __mnt_drop_write(hf->f_path.mnt);
1facf9fc 3719+ }
3720+ }
3721+
7f207e10
AM
3722+out_array:
3723+ au_farray_free(array, max);
4f0767ce 3724+out:
7f207e10 3725+ AuTraceErr(err);
1facf9fc 3726+ return err;
3727+}
3728+
3729+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 3730+ int *do_refresh)
1facf9fc 3731+{
3732+ int err, rerr;
3733+ aufs_bindex_t bindex;
3734+ struct dentry *root;
3735+ struct au_branch *br;
076b876e 3736+ struct au_br_fhsm *bf;
1facf9fc 3737+
3738+ root = sb->s_root;
1facf9fc 3739+ bindex = au_find_dbindex(root, mod->h_root);
3740+ if (bindex < 0) {
3741+ if (remount)
3742+ return 0; /* success */
3743+ err = -ENOENT;
4a4d8108 3744+ pr_err("%s no such branch\n", mod->path);
1facf9fc 3745+ goto out;
3746+ }
3747+ AuDbg("bindex b%d\n", bindex);
3748+
5527c038 3749+ err = test_br(d_inode(mod->h_root), mod->perm, mod->path);
1facf9fc 3750+ if (unlikely(err))
3751+ goto out;
3752+
3753+ br = au_sbr(sb, bindex);
86dc4139 3754+ AuDebugOn(mod->h_root != au_br_dentry(br));
1facf9fc 3755+ if (br->br_perm == mod->perm)
3756+ return 0; /* success */
3757+
076b876e
AM
3758+ /* pre-allocate for non-fhsm --> fhsm */
3759+ bf = NULL;
3760+ if (!au_br_fhsm(br->br_perm) && au_br_fhsm(mod->perm)) {
3761+ err = au_fhsm_br_alloc(br);
3762+ if (unlikely(err))
3763+ goto out;
3764+ bf = br->br_fhsm;
3765+ br->br_fhsm = NULL;
3766+ }
3767+
1facf9fc 3768+ if (au_br_writable(br->br_perm)) {
3769+ /* remove whiteout base */
86dc4139 3770+ err = au_br_init_wh(sb, br, mod->perm);
1facf9fc 3771+ if (unlikely(err))
076b876e 3772+ goto out_bf;
1facf9fc 3773+
3774+ if (!au_br_writable(mod->perm)) {
3775+ /* rw --> ro, file might be mmapped */
3776+ DiMustNoWaiters(root);
5527c038 3777+ IiMustNoWaiters(d_inode(root));
1facf9fc 3778+ di_write_unlock(root);
3779+ err = au_br_mod_files_ro(sb, bindex);
3780+ /* aufs_write_lock() calls ..._child() */
3781+ di_write_lock_child(root);
3782+
3783+ if (unlikely(err)) {
3784+ rerr = -ENOMEM;
be52b249 3785+ br->br_wbr = kzalloc(sizeof(*br->br_wbr),
1facf9fc 3786+ GFP_NOFS);
86dc4139
AM
3787+ if (br->br_wbr)
3788+ rerr = au_wbr_init(br, sb, br->br_perm);
1facf9fc 3789+ if (unlikely(rerr)) {
3790+ AuIOErr("nested error %d (%d)\n",
3791+ rerr, err);
3792+ br->br_perm = mod->perm;
3793+ }
3794+ }
3795+ }
3796+ } else if (au_br_writable(mod->perm)) {
3797+ /* ro --> rw */
3798+ err = -ENOMEM;
be52b249 3799+ br->br_wbr = kzalloc(sizeof(*br->br_wbr), GFP_NOFS);
1facf9fc 3800+ if (br->br_wbr) {
86dc4139 3801+ err = au_wbr_init(br, sb, mod->perm);
1facf9fc 3802+ if (unlikely(err)) {
1c60b727 3803+ kfree(br->br_wbr);
1facf9fc 3804+ br->br_wbr = NULL;
3805+ }
3806+ }
3807+ }
076b876e
AM
3808+ if (unlikely(err))
3809+ goto out_bf;
3810+
3811+ if (au_br_fhsm(br->br_perm)) {
3812+ if (!au_br_fhsm(mod->perm)) {
3813+ /* fhsm --> non-fhsm */
3814+ au_br_fhsm_fin(br->br_fhsm);
1c60b727 3815+ kfree(br->br_fhsm);
076b876e
AM
3816+ br->br_fhsm = NULL;
3817+ }
3818+ } else if (au_br_fhsm(mod->perm))
3819+ /* non-fhsm --> fhsm */
3820+ br->br_fhsm = bf;
3821+
076b876e
AM
3822+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
3823+ br->br_perm = mod->perm;
3824+ goto out; /* success */
1facf9fc 3825+
076b876e 3826+out_bf:
8b6a4947 3827+ kfree(bf);
076b876e
AM
3828+out:
3829+ AuTraceErr(err);
3830+ return err;
3831+}
3832+
3833+/* ---------------------------------------------------------------------- */
3834+
3835+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs)
3836+{
3837+ int err;
3838+ struct kstatfs kstfs;
3839+
3840+ err = vfs_statfs(&br->br_path, &kstfs);
1facf9fc 3841+ if (!err) {
076b876e
AM
3842+ stfs->f_blocks = kstfs.f_blocks;
3843+ stfs->f_bavail = kstfs.f_bavail;
3844+ stfs->f_files = kstfs.f_files;
3845+ stfs->f_ffree = kstfs.f_ffree;
1facf9fc 3846+ }
3847+
1facf9fc 3848+ return err;
3849+}
0b1ff5c3
JR
3850diff -urNp -x '*.orig' linux-4.14/fs/aufs/branch.h linux-4.14/fs/aufs/branch.h
3851--- linux-4.14/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
3852+++ linux-4.14/fs/aufs/branch.h 2021-02-24 21:42:43.441114748 +0100
8b6a4947 3853@@ -0,0 +1,333 @@
1facf9fc 3854+/*
a2654f78 3855+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 3856+ *
3857+ * This program, aufs is free software; you can redistribute it and/or modify
3858+ * it under the terms of the GNU General Public License as published by
3859+ * the Free Software Foundation; either version 2 of the License, or
3860+ * (at your option) any later version.
dece6358
AM
3861+ *
3862+ * This program is distributed in the hope that it will be useful,
3863+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3864+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3865+ * GNU General Public License for more details.
3866+ *
3867+ * You should have received a copy of the GNU General Public License
523b37e3 3868+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 3869+ */
3870+
3871+/*
3872+ * branch filesystems and xino for them
3873+ */
3874+
3875+#ifndef __AUFS_BRANCH_H__
3876+#define __AUFS_BRANCH_H__
3877+
3878+#ifdef __KERNEL__
3879+
1facf9fc 3880+#include <linux/mount.h>
8b6a4947 3881+#include "dirren.h"
4a4d8108 3882+#include "dynop.h"
1facf9fc 3883+#include "rwsem.h"
3884+#include "super.h"
3885+
3886+/* ---------------------------------------------------------------------- */
3887+
3888+/* a xino file */
3889+struct au_xino_file {
3890+ struct file *xi_file;
521ced18
JR
3891+ struct {
3892+ spinlock_t spin;
3893+ ino_t *array;
3894+ int total;
3895+ /* reserved for future use */
3896+ /* unsigned long *bitmap; */
3897+ wait_queue_head_t wqh;
3898+ } xi_nondir;
1facf9fc 3899+
3900+ /* todo: make xino files an array to support huge inode number */
3901+
3902+#ifdef CONFIG_DEBUG_FS
3903+ struct dentry *xi_dbgaufs;
3904+#endif
3905+};
3906+
076b876e
AM
3907+/* File-based Hierarchical Storage Management */
3908+struct au_br_fhsm {
3909+#ifdef CONFIG_AUFS_FHSM
3910+ struct mutex bf_lock;
3911+ unsigned long bf_jiffy;
3912+ struct aufs_stfs bf_stfs;
3913+ int bf_readable;
3914+#endif
3915+};
3916+
1facf9fc 3917+/* members for writable branch only */
3918+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
3919+struct au_wbr {
dece6358 3920+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 3921+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 3922+ atomic_t wbr_wh_running;
1facf9fc 3923+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
3924+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
3925+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
3926+
3927+ /* mfs mode */
3928+ unsigned long long wbr_bytes;
3929+};
3930+
4a4d8108
AM
3931+/* ext2 has 3 types of operations at least, ext3 has 4 */
3932+#define AuBrDynOp (AuDyLast * 4)
3933+
1716fcea
AM
3934+#ifdef CONFIG_AUFS_HFSNOTIFY
3935+/* support for asynchronous destruction */
3936+struct au_br_hfsnotify {
3937+ struct fsnotify_group *hfsn_group;
3938+};
3939+#endif
3940+
392086de
AM
3941+/* sysfs entries */
3942+struct au_brsysfs {
3943+ char name[16];
3944+ struct attribute attr;
3945+};
3946+
3947+enum {
3948+ AuBrSysfs_BR,
3949+ AuBrSysfs_BRID,
3950+ AuBrSysfs_Last
3951+};
3952+
1facf9fc 3953+/* protected by superblock rwsem */
3954+struct au_branch {
3955+ struct au_xino_file br_xino;
3956+
3957+ aufs_bindex_t br_id;
3958+
3959+ int br_perm;
86dc4139 3960+ struct path br_path;
4a4d8108
AM
3961+ spinlock_t br_dykey_lock;
3962+ struct au_dykey *br_dykey[AuBrDynOp];
5afbbe0d 3963+ struct percpu_counter br_count;
1facf9fc 3964+
3965+ struct au_wbr *br_wbr;
076b876e 3966+ struct au_br_fhsm *br_fhsm;
1facf9fc 3967+
3968+ /* xino truncation */
1facf9fc 3969+ atomic_t br_xino_running;
3970+
027c5e7a 3971+#ifdef CONFIG_AUFS_HFSNOTIFY
1716fcea 3972+ struct au_br_hfsnotify *br_hfsn;
027c5e7a
AM
3973+#endif
3974+
1facf9fc 3975+#ifdef CONFIG_SYSFS
392086de
AM
3976+ /* entries under sysfs per mount-point */
3977+ struct au_brsysfs br_sysfs[AuBrSysfs_Last];
1facf9fc 3978+#endif
8b6a4947
AM
3979+
3980+ struct au_dr_br br_dirren;
1facf9fc 3981+};
3982+
3983+/* ---------------------------------------------------------------------- */
3984+
86dc4139
AM
3985+static inline struct vfsmount *au_br_mnt(struct au_branch *br)
3986+{
3987+ return br->br_path.mnt;
3988+}
3989+
3990+static inline struct dentry *au_br_dentry(struct au_branch *br)
3991+{
3992+ return br->br_path.dentry;
3993+}
3994+
3995+static inline struct super_block *au_br_sb(struct au_branch *br)
3996+{
3997+ return au_br_mnt(br)->mnt_sb;
3998+}
3999+
5afbbe0d
AM
4000+static inline void au_br_get(struct au_branch *br)
4001+{
4002+ percpu_counter_inc(&br->br_count);
4003+}
4004+
4005+static inline void au_br_put(struct au_branch *br)
4006+{
4007+ percpu_counter_dec(&br->br_count);
4008+}
4009+
4010+static inline s64 au_br_count(struct au_branch *br)
4011+{
4012+ return percpu_counter_sum(&br->br_count);
4013+}
4014+
4015+static inline void au_br_count_init(struct au_branch *br)
4016+{
4017+ percpu_counter_init(&br->br_count, 0, GFP_NOFS);
4018+}
4019+
4020+static inline void au_br_count_fin(struct au_branch *br)
4021+{
4022+ percpu_counter_destroy(&br->br_count);
4023+}
4024+
1facf9fc 4025+static inline int au_br_rdonly(struct au_branch *br)
4026+{
8b6a4947 4027+ return (sb_rdonly(au_br_sb(br))
1facf9fc 4028+ || !au_br_writable(br->br_perm))
4029+ ? -EROFS : 0;
4030+}
4031+
4a4d8108 4032+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 4033+{
4a4d8108 4034+#ifdef CONFIG_AUFS_HNOTIFY
1e00d052 4035+ return !(brperm & AuBrPerm_RR);
1facf9fc 4036+#else
4037+ return 0;
4038+#endif
4039+}
4040+
b912730e
AM
4041+static inline int au_br_test_oflag(int oflag, struct au_branch *br)
4042+{
4043+ int err, exec_flag;
4044+
4045+ err = 0;
4046+ exec_flag = oflag & __FMODE_EXEC;
79b8bda9 4047+ if (unlikely(exec_flag && path_noexec(&br->br_path)))
b912730e
AM
4048+ err = -EACCES;
4049+
4050+ return err;
4051+}
4052+
1facf9fc 4053+/* ---------------------------------------------------------------------- */
4054+
4055+/* branch.c */
4056+struct au_sbinfo;
4057+void au_br_free(struct au_sbinfo *sinfo);
4058+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
4059+struct au_opt_add;
4060+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
4061+struct au_opt_del;
4062+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
027c5e7a
AM
4063+long au_ibusy_ioctl(struct file *file, unsigned long arg);
4064+#ifdef CONFIG_COMPAT
4065+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg);
4066+#endif
1facf9fc 4067+struct au_opt_mod;
4068+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 4069+ int *do_refresh);
076b876e
AM
4070+struct aufs_stfs;
4071+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs);
1facf9fc 4072+
4073+/* xino.c */
4074+static const loff_t au_loff_max = LLONG_MAX;
4075+
4076+int au_xib_trunc(struct super_block *sb);
5527c038 4077+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *buf, size_t size,
1facf9fc 4078+ loff_t *pos);
5527c038
JR
4079+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf,
4080+ size_t size, loff_t *pos);
1facf9fc 4081+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
4082+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
4083+ino_t au_xino_new_ino(struct super_block *sb);
b752ccd1 4084+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 4085+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4086+ ino_t ino);
4087+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4088+ ino_t *ino);
4089+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
4090+ struct file *base_file, int do_test);
4091+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
4092+
4093+struct au_opt_xino;
4094+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
4095+void au_xino_clr(struct super_block *sb);
4096+struct file *au_xino_def(struct super_block *sb);
4097+int au_xino_path(struct seq_file *seq, struct file *file);
4098+
521ced18
JR
4099+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex,
4100+ ino_t h_ino, int idx);
4101+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4102+ int *idx);
4103+
1facf9fc 4104+/* ---------------------------------------------------------------------- */
4105+
4106+/* Superblock to branch */
4107+static inline
4108+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
4109+{
4110+ return au_sbr(sb, bindex)->br_id;
4111+}
4112+
4113+static inline
4114+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
4115+{
86dc4139 4116+ return au_br_mnt(au_sbr(sb, bindex));
1facf9fc 4117+}
4118+
4119+static inline
4120+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
4121+{
86dc4139 4122+ return au_br_sb(au_sbr(sb, bindex));
1facf9fc 4123+}
4124+
5afbbe0d
AM
4125+static inline void au_sbr_get(struct super_block *sb, aufs_bindex_t bindex)
4126+{
4127+ au_br_get(au_sbr(sb, bindex));
4128+}
4129+
1facf9fc 4130+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
4131+{
5afbbe0d 4132+ au_br_put(au_sbr(sb, bindex));
1facf9fc 4133+}
4134+
4135+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
4136+{
4137+ return au_sbr(sb, bindex)->br_perm;
4138+}
4139+
4140+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
4141+{
4142+ return au_br_whable(au_sbr_perm(sb, bindex));
4143+}
4144+
4145+/* ---------------------------------------------------------------------- */
4146+
8b6a4947
AM
4147+#define wbr_wh_read_lock(wbr) au_rw_read_lock(&(wbr)->wbr_wh_rwsem)
4148+#define wbr_wh_write_lock(wbr) au_rw_write_lock(&(wbr)->wbr_wh_rwsem)
4149+#define wbr_wh_read_trylock(wbr) au_rw_read_trylock(&(wbr)->wbr_wh_rwsem)
4150+#define wbr_wh_write_trylock(wbr) au_rw_write_trylock(&(wbr)->wbr_wh_rwsem)
1facf9fc 4151+/*
8b6a4947
AM
4152+#define wbr_wh_read_trylock_nested(wbr) \
4153+ au_rw_read_trylock_nested(&(wbr)->wbr_wh_rwsem)
4154+#define wbr_wh_write_trylock_nested(wbr) \
4155+ au_rw_write_trylock_nested(&(wbr)->wbr_wh_rwsem)
4156+*/
1facf9fc 4157+
8b6a4947
AM
4158+#define wbr_wh_read_unlock(wbr) au_rw_read_unlock(&(wbr)->wbr_wh_rwsem)
4159+#define wbr_wh_write_unlock(wbr) au_rw_write_unlock(&(wbr)->wbr_wh_rwsem)
4160+#define wbr_wh_downgrade_lock(wbr) au_rw_dgrade_lock(&(wbr)->wbr_wh_rwsem)
4161+
4162+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&(wbr)->wbr_wh_rwsem)
4163+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&(wbr)->wbr_wh_rwsem)
4164+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&(wbr)->wbr_wh_rwsem)
dece6358 4165+
076b876e
AM
4166+/* ---------------------------------------------------------------------- */
4167+
4168+#ifdef CONFIG_AUFS_FHSM
4169+static inline void au_br_fhsm_init(struct au_br_fhsm *brfhsm)
4170+{
4171+ mutex_init(&brfhsm->bf_lock);
4172+ brfhsm->bf_jiffy = 0;
4173+ brfhsm->bf_readable = 0;
4174+}
4175+
4176+static inline void au_br_fhsm_fin(struct au_br_fhsm *brfhsm)
4177+{
4178+ mutex_destroy(&brfhsm->bf_lock);
4179+}
4180+#else
4181+AuStubVoid(au_br_fhsm_init, struct au_br_fhsm *brfhsm)
4182+AuStubVoid(au_br_fhsm_fin, struct au_br_fhsm *brfhsm)
4183+#endif
4184+
1facf9fc 4185+#endif /* __KERNEL__ */
4186+#endif /* __AUFS_BRANCH_H__ */
0b1ff5c3
JR
4187diff -urNp -x '*.orig' linux-4.14/fs/aufs/conf.mk linux-4.14/fs/aufs/conf.mk
4188--- linux-4.14/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
4189+++ linux-4.14/fs/aufs/conf.mk 2021-02-24 21:42:43.441114748 +0100
8b6a4947 4190@@ -0,0 +1,39 @@
4a4d8108
AM
4191+
4192+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
4193+
4194+define AuConf
4195+ifdef ${1}
4196+AuConfStr += ${1}=${${1}}
4197+endif
4198+endef
4199+
b752ccd1 4200+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe 4201+ SBILIST \
7f207e10 4202+ HNOTIFY HFSNOTIFY \
4a4d8108 4203+ EXPORT INO_T_64 \
c1595e42 4204+ XATTR \
076b876e 4205+ FHSM \
4a4d8108 4206+ RDU \
8b6a4947 4207+ DIRREN \
4a4d8108
AM
4208+ SHWH \
4209+ BR_RAMFS \
4210+ BR_FUSE POLL \
4211+ BR_HFSPLUS \
4212+ BDEV_LOOP \
b752ccd1
AM
4213+ DEBUG MAGIC_SYSRQ
4214+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
4215+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
4216+
4217+AuConfName = ${obj}/conf.str
4218+${AuConfName}.tmp: FORCE
4219+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
4220+${AuConfName}: ${AuConfName}.tmp
4221+ @diff -q $< $@ > /dev/null 2>&1 || { \
4222+ echo ' GEN ' $@; \
4223+ cp -p $< $@; \
4224+ }
4225+FORCE:
4226+clean-files += ${AuConfName} ${AuConfName}.tmp
4227+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
4228+
4229+-include ${srctree}/${src}/conf_priv.mk
0b1ff5c3
JR
4230diff -urNp -x '*.orig' linux-4.14/fs/aufs/cpup.c linux-4.14/fs/aufs/cpup.c
4231--- linux-4.14/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
4232+++ linux-4.14/fs/aufs/cpup.c 2021-02-24 21:42:43.441114748 +0100
8b6a4947 4233@@ -0,0 +1,1443 @@
1facf9fc 4234+/*
a2654f78 4235+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 4236+ *
4237+ * This program, aufs is free software; you can redistribute it and/or modify
4238+ * it under the terms of the GNU General Public License as published by
4239+ * the Free Software Foundation; either version 2 of the License, or
4240+ * (at your option) any later version.
dece6358
AM
4241+ *
4242+ * This program is distributed in the hope that it will be useful,
4243+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4244+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4245+ * GNU General Public License for more details.
4246+ *
4247+ * You should have received a copy of the GNU General Public License
523b37e3 4248+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 4249+ */
4250+
4251+/*
4252+ * copy-up functions, see wbr_policy.c for copy-down
4253+ */
4254+
4255+#include <linux/fs_stack.h>
dece6358 4256+#include <linux/mm.h>
8cdd5066 4257+#include <linux/task_work.h>
1facf9fc 4258+#include "aufs.h"
4259+
86dc4139 4260+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags)
1facf9fc 4261+{
4262+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
367653fa 4263+ | S_NOATIME | S_NOCMTIME | S_AUTOMOUNT;
1facf9fc 4264+
86dc4139
AM
4265+ BUILD_BUG_ON(sizeof(iflags) != sizeof(dst->i_flags));
4266+
4267+ dst->i_flags |= iflags & ~mask;
1facf9fc 4268+ if (au_test_fs_notime(dst->i_sb))
4269+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
4270+}
4271+
4272+void au_cpup_attr_timesizes(struct inode *inode)
4273+{
4274+ struct inode *h_inode;
4275+
5afbbe0d 4276+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 4277+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 4278+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 4279+}
4280+
4281+void au_cpup_attr_nlink(struct inode *inode, int force)
4282+{
4283+ struct inode *h_inode;
4284+ struct super_block *sb;
5afbbe0d 4285+ aufs_bindex_t bindex, bbot;
1facf9fc 4286+
4287+ sb = inode->i_sb;
5afbbe0d 4288+ bindex = au_ibtop(inode);
1facf9fc 4289+ h_inode = au_h_iptr(inode, bindex);
4290+ if (!force
4291+ && !S_ISDIR(h_inode->i_mode)
4292+ && au_opt_test(au_mntflags(sb), PLINK)
4293+ && au_plink_test(inode))
4294+ return;
4295+
7eafdf33
AM
4296+ /*
4297+ * 0 can happen in revalidating.
38d290e6
JR
4298+ * h_inode->i_mutex may not be held here, but it is harmless since once
4299+ * i_nlink reaches 0, it will never become positive except O_TMPFILE
4300+ * case.
4301+ * todo: O_TMPFILE+linkat(AT_SYMLINK_FOLLOW) bypassing aufs may cause
4302+ * the incorrect link count.
7eafdf33 4303+ */
92d182d2 4304+ set_nlink(inode, h_inode->i_nlink);
1facf9fc 4305+
4306+ /*
4307+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
4308+ * it may includes whplink directory.
4309+ */
4310+ if (S_ISDIR(h_inode->i_mode)) {
5afbbe0d
AM
4311+ bbot = au_ibbot(inode);
4312+ for (bindex++; bindex <= bbot; bindex++) {
1facf9fc 4313+ h_inode = au_h_iptr(inode, bindex);
4314+ if (h_inode)
4315+ au_add_nlink(inode, h_inode);
4316+ }
4317+ }
4318+}
4319+
4320+void au_cpup_attr_changeable(struct inode *inode)
4321+{
4322+ struct inode *h_inode;
4323+
5afbbe0d 4324+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 4325+ inode->i_mode = h_inode->i_mode;
4326+ inode->i_uid = h_inode->i_uid;
4327+ inode->i_gid = h_inode->i_gid;
4328+ au_cpup_attr_timesizes(inode);
86dc4139 4329+ au_cpup_attr_flags(inode, h_inode->i_flags);
1facf9fc 4330+}
4331+
4332+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
4333+{
4334+ struct au_iinfo *iinfo = au_ii(inode);
4335+
1308ab2a 4336+ IiMustWriteLock(inode);
4337+
1facf9fc 4338+ iinfo->ii_higen = h_inode->i_generation;
4339+ iinfo->ii_hsb1 = h_inode->i_sb;
4340+}
4341+
4342+void au_cpup_attr_all(struct inode *inode, int force)
4343+{
4344+ struct inode *h_inode;
4345+
5afbbe0d 4346+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 4347+ au_cpup_attr_changeable(inode);
4348+ if (inode->i_nlink > 0)
4349+ au_cpup_attr_nlink(inode, force);
4350+ inode->i_rdev = h_inode->i_rdev;
4351+ inode->i_blkbits = h_inode->i_blkbits;
4352+ au_cpup_igen(inode, h_inode);
4353+}
4354+
4355+/* ---------------------------------------------------------------------- */
4356+
4357+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
4358+
4359+/* keep the timestamps of the parent dir when cpup */
4360+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
4361+ struct path *h_path)
4362+{
4363+ struct inode *h_inode;
4364+
4365+ dt->dt_dentry = dentry;
4366+ dt->dt_h_path = *h_path;
5527c038 4367+ h_inode = d_inode(h_path->dentry);
1facf9fc 4368+ dt->dt_atime = h_inode->i_atime;
4369+ dt->dt_mtime = h_inode->i_mtime;
4370+ /* smp_mb(); */
4371+}
4372+
4373+void au_dtime_revert(struct au_dtime *dt)
4374+{
4375+ struct iattr attr;
4376+ int err;
4377+
4378+ attr.ia_atime = dt->dt_atime;
4379+ attr.ia_mtime = dt->dt_mtime;
4380+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
4381+ | ATTR_ATIME | ATTR_ATIME_SET;
4382+
523b37e3
AM
4383+ /* no delegation since this is a directory */
4384+ err = vfsub_notify_change(&dt->dt_h_path, &attr, /*delegated*/NULL);
1facf9fc 4385+ if (unlikely(err))
0c3ec466 4386+ pr_warn("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 4387+}
4388+
4389+/* ---------------------------------------------------------------------- */
4390+
86dc4139
AM
4391+/* internal use only */
4392+struct au_cpup_reg_attr {
4393+ int valid;
4394+ struct kstat st;
4395+ unsigned int iflags; /* inode->i_flags */
4396+};
4397+
1facf9fc 4398+static noinline_for_stack
86dc4139
AM
4399+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src,
4400+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 4401+{
c1595e42 4402+ int err, sbits, icex;
7e9cd9fe
AM
4403+ unsigned int mnt_flags;
4404+ unsigned char verbose;
1facf9fc 4405+ struct iattr ia;
4406+ struct path h_path;
1308ab2a 4407+ struct inode *h_isrc, *h_idst;
86dc4139 4408+ struct kstat *h_st;
c1595e42 4409+ struct au_branch *br;
1facf9fc 4410+
4411+ h_path.dentry = au_h_dptr(dst, bindex);
5527c038 4412+ h_idst = d_inode(h_path.dentry);
c1595e42
JR
4413+ br = au_sbr(dst->d_sb, bindex);
4414+ h_path.mnt = au_br_mnt(br);
5527c038 4415+ h_isrc = d_inode(h_src);
1308ab2a 4416+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 4417+ | ATTR_ATIME | ATTR_MTIME
4418+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
86dc4139
AM
4419+ if (h_src_attr && h_src_attr->valid) {
4420+ h_st = &h_src_attr->st;
4421+ ia.ia_uid = h_st->uid;
4422+ ia.ia_gid = h_st->gid;
4423+ ia.ia_atime = h_st->atime;
4424+ ia.ia_mtime = h_st->mtime;
4425+ if (h_idst->i_mode != h_st->mode
4426+ && !S_ISLNK(h_idst->i_mode)) {
4427+ ia.ia_valid |= ATTR_MODE;
4428+ ia.ia_mode = h_st->mode;
4429+ }
4430+ sbits = !!(h_st->mode & (S_ISUID | S_ISGID));
4431+ au_cpup_attr_flags(h_idst, h_src_attr->iflags);
4432+ } else {
4433+ ia.ia_uid = h_isrc->i_uid;
4434+ ia.ia_gid = h_isrc->i_gid;
4435+ ia.ia_atime = h_isrc->i_atime;
4436+ ia.ia_mtime = h_isrc->i_mtime;
4437+ if (h_idst->i_mode != h_isrc->i_mode
4438+ && !S_ISLNK(h_idst->i_mode)) {
4439+ ia.ia_valid |= ATTR_MODE;
4440+ ia.ia_mode = h_isrc->i_mode;
4441+ }
4442+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
4443+ au_cpup_attr_flags(h_idst, h_isrc->i_flags);
1308ab2a 4444+ }
523b37e3
AM
4445+ /* no delegation since it is just created */
4446+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL);
1facf9fc 4447+
4448+ /* is this nfs only? */
4449+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
4450+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
4451+ ia.ia_mode = h_isrc->i_mode;
523b37e3 4452+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL);
1facf9fc 4453+ }
4454+
c1595e42 4455+ icex = br->br_perm & AuBrAttr_ICEX;
7e9cd9fe
AM
4456+ if (!err) {
4457+ mnt_flags = au_mntflags(dst->d_sb);
4458+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
4459+ err = au_cpup_xattr(h_path.dentry, h_src, icex, verbose);
4460+ }
c1595e42 4461+
1facf9fc 4462+ return err;
4463+}
4464+
4465+/* ---------------------------------------------------------------------- */
4466+
4467+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
4468+ char *buf, unsigned long blksize)
4469+{
4470+ int err;
4471+ size_t sz, rbytes, wbytes;
4472+ unsigned char all_zero;
4473+ char *p, *zp;
febd17d6 4474+ struct inode *h_inode;
1facf9fc 4475+ /* reduce stack usage */
4476+ struct iattr *ia;
4477+
4478+ zp = page_address(ZERO_PAGE(0));
4479+ if (unlikely(!zp))
4480+ return -ENOMEM; /* possible? */
4481+
4482+ err = 0;
4483+ all_zero = 0;
4484+ while (len) {
4485+ AuDbg("len %lld\n", len);
4486+ sz = blksize;
4487+ if (len < blksize)
4488+ sz = len;
4489+
4490+ rbytes = 0;
4491+ /* todo: signal_pending? */
4492+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
4493+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
4494+ err = rbytes;
4495+ }
4496+ if (unlikely(err < 0))
4497+ break;
4498+
4499+ all_zero = 0;
4500+ if (len >= rbytes && rbytes == blksize)
4501+ all_zero = !memcmp(buf, zp, rbytes);
4502+ if (!all_zero) {
4503+ wbytes = rbytes;
4504+ p = buf;
4505+ while (wbytes) {
4506+ size_t b;
4507+
4508+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
4509+ err = b;
4510+ /* todo: signal_pending? */
4511+ if (unlikely(err == -EAGAIN || err == -EINTR))
4512+ continue;
4513+ if (unlikely(err < 0))
4514+ break;
4515+ wbytes -= b;
4516+ p += b;
4517+ }
392086de
AM
4518+ if (unlikely(err < 0))
4519+ break;
1facf9fc 4520+ } else {
4521+ loff_t res;
4522+
4523+ AuLabel(hole);
4524+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
4525+ err = res;
4526+ if (unlikely(res < 0))
4527+ break;
4528+ }
4529+ len -= rbytes;
4530+ err = 0;
4531+ }
4532+
4533+ /* the last block may be a hole */
4534+ if (!err && all_zero) {
4535+ AuLabel(last hole);
4536+
4537+ err = 1;
2000de60 4538+ if (au_test_nfs(dst->f_path.dentry->d_sb)) {
1facf9fc 4539+ /* nfs requires this step to make last hole */
4540+ /* is this only nfs? */
4541+ do {
4542+ /* todo: signal_pending? */
4543+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
4544+ } while (err == -EAGAIN || err == -EINTR);
4545+ if (err == 1)
4546+ dst->f_pos--;
4547+ }
4548+
4549+ if (err == 1) {
4550+ ia = (void *)buf;
4551+ ia->ia_size = dst->f_pos;
4552+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
4553+ ia->ia_file = dst;
febd17d6
JR
4554+ h_inode = file_inode(dst);
4555+ inode_lock_nested(h_inode, AuLsc_I_CHILD2);
523b37e3
AM
4556+ /* no delegation since it is just created */
4557+ err = vfsub_notify_change(&dst->f_path, ia,
4558+ /*delegated*/NULL);
febd17d6 4559+ inode_unlock(h_inode);
1facf9fc 4560+ }
4561+ }
4562+
4563+ return err;
4564+}
4565+
4566+int au_copy_file(struct file *dst, struct file *src, loff_t len)
4567+{
4568+ int err;
4569+ unsigned long blksize;
4570+ unsigned char do_kfree;
4571+ char *buf;
4572+
4573+ err = -ENOMEM;
2000de60 4574+ blksize = dst->f_path.dentry->d_sb->s_blocksize;
1facf9fc 4575+ if (!blksize || PAGE_SIZE < blksize)
4576+ blksize = PAGE_SIZE;
4577+ AuDbg("blksize %lu\n", blksize);
4578+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
4579+ if (do_kfree)
4580+ buf = kmalloc(blksize, GFP_NOFS);
4581+ else
4582+ buf = (void *)__get_free_page(GFP_NOFS);
4583+ if (unlikely(!buf))
4584+ goto out;
4585+
4586+ if (len > (1 << 22))
4587+ AuDbg("copying a large file %lld\n", (long long)len);
4588+
4589+ src->f_pos = 0;
4590+ dst->f_pos = 0;
4591+ err = au_do_copy_file(dst, src, len, buf, blksize);
4592+ if (do_kfree)
1c60b727 4593+ kfree(buf);
1facf9fc 4594+ else
1c60b727 4595+ free_page((unsigned long)buf);
1facf9fc 4596+
4f0767ce 4597+out:
1facf9fc 4598+ return err;
4599+}
4600+
1c60b727
AM
4601+static int au_do_copy(struct file *dst, struct file *src, loff_t len)
4602+{
4603+ int err;
4604+ struct super_block *h_src_sb;
4605+ struct inode *h_src_inode;
4606+
4607+ h_src_inode = file_inode(src);
4608+ h_src_sb = h_src_inode->i_sb;
4609+
4610+ /* XFS acquires inode_lock */
4611+ if (!au_test_xfs(h_src_sb))
4612+ err = au_copy_file(dst, src, len);
4613+ else {
3c1bdaff 4614+ inode_unlock_shared(h_src_inode);
1c60b727 4615+ err = au_copy_file(dst, src, len);
3c1bdaff 4616+ vfsub_inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
1c60b727
AM
4617+ }
4618+
4619+ return err;
4620+}
4621+
4622+static int au_clone_or_copy(struct file *dst, struct file *src, loff_t len)
4623+{
4624+ int err;
4625+ struct super_block *h_src_sb;
4626+ struct inode *h_src_inode;
4627+
4628+ h_src_inode = file_inode(src);
4629+ h_src_sb = h_src_inode->i_sb;
4630+ if (h_src_sb != file_inode(dst)->i_sb
4631+ || !dst->f_op->clone_file_range) {
4632+ err = au_do_copy(dst, src, len);
4633+ goto out;
4634+ }
4635+
4636+ if (!au_test_nfs(h_src_sb)) {
3c1bdaff 4637+ inode_unlock_shared(h_src_inode);
1c60b727 4638+ err = vfsub_clone_file_range(src, dst, len);
3c1bdaff 4639+ vfsub_inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
1c60b727
AM
4640+ } else
4641+ err = vfsub_clone_file_range(src, dst, len);
4642+ /* older XFS has a condition in cloning */
4643+ if (unlikely(err != -EOPNOTSUPP))
4644+ goto out;
4645+
4646+ /* the backend fs on NFS may not support cloning */
4647+ err = au_do_copy(dst, src, len);
4648+
4649+out:
4650+ AuTraceErr(err);
4651+ return err;
4652+}
4653+
1facf9fc 4654+/*
4655+ * to support a sparse file which is opened with O_APPEND,
4656+ * we need to close the file.
4657+ */
c2b27bf2 4658+static int au_cp_regular(struct au_cp_generic *cpg)
1facf9fc 4659+{
4660+ int err, i;
4661+ enum { SRC, DST };
4662+ struct {
4663+ aufs_bindex_t bindex;
4664+ unsigned int flags;
4665+ struct dentry *dentry;
392086de 4666+ int force_wr;
1facf9fc 4667+ struct file *file;
523b37e3 4668+ void *label;
1facf9fc 4669+ } *f, file[] = {
4670+ {
c2b27bf2 4671+ .bindex = cpg->bsrc,
1facf9fc 4672+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
523b37e3 4673+ .label = &&out
1facf9fc 4674+ },
4675+ {
c2b27bf2 4676+ .bindex = cpg->bdst,
1facf9fc 4677+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
392086de 4678+ .force_wr = !!au_ftest_cpup(cpg->flags, RWDST),
523b37e3 4679+ .label = &&out_src
1facf9fc 4680+ }
4681+ };
521ced18 4682+ struct super_block *sb, *h_src_sb;
e2f27e51 4683+ struct inode *h_src_inode;
8cdd5066 4684+ struct task_struct *tsk = current;
1facf9fc 4685+
4686+ /* bsrc branch can be ro/rw. */
c2b27bf2 4687+ sb = cpg->dentry->d_sb;
1facf9fc 4688+ f = file;
4689+ for (i = 0; i < 2; i++, f++) {
c2b27bf2
AM
4690+ f->dentry = au_h_dptr(cpg->dentry, f->bindex);
4691+ f->file = au_h_open(cpg->dentry, f->bindex, f->flags,
392086de 4692+ /*file*/NULL, f->force_wr);
1facf9fc 4693+ err = PTR_ERR(f->file);
4694+ if (IS_ERR(f->file))
4695+ goto *f->label;
1facf9fc 4696+ }
4697+
4698+ /* try stopping to update while we copyup */
e2f27e51 4699+ h_src_inode = d_inode(file[SRC].dentry);
521ced18
JR
4700+ h_src_sb = h_src_inode->i_sb;
4701+ if (!au_test_nfs(h_src_sb))
e2f27e51 4702+ IMustLock(h_src_inode);
1c60b727 4703+ err = au_clone_or_copy(file[DST].file, file[SRC].file, cpg->len);
1facf9fc 4704+
8cdd5066
JR
4705+ /* i wonder if we had O_NO_DELAY_FPUT flag */
4706+ if (tsk->flags & PF_KTHREAD)
4707+ __fput_sync(file[DST].file);
4708+ else {
4709+ WARN(1, "%pD\nPlease report this warning to aufs-users ML",
4710+ file[DST].file);
4711+ fput(file[DST].file);
4712+ /*
4713+ * too bad.
4714+ * we have to call both since we don't know which place the file
4715+ * was added to.
4716+ */
4717+ task_work_run();
4718+ flush_delayed_fput();
4719+ }
1facf9fc 4720+ au_sbr_put(sb, file[DST].bindex);
523b37e3 4721+
4f0767ce 4722+out_src:
1facf9fc 4723+ fput(file[SRC].file);
4724+ au_sbr_put(sb, file[SRC].bindex);
4f0767ce 4725+out:
1facf9fc 4726+ return err;
4727+}
4728+
c2b27bf2 4729+static int au_do_cpup_regular(struct au_cp_generic *cpg,
86dc4139 4730+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 4731+{
4732+ int err, rerr;
4733+ loff_t l;
86dc4139 4734+ struct path h_path;
38d290e6 4735+ struct inode *h_src_inode, *h_dst_inode;
1facf9fc 4736+
4737+ err = 0;
5527c038 4738+ h_src_inode = au_h_iptr(d_inode(cpg->dentry), cpg->bsrc);
86dc4139 4739+ l = i_size_read(h_src_inode);
c2b27bf2
AM
4740+ if (cpg->len == -1 || l < cpg->len)
4741+ cpg->len = l;
4742+ if (cpg->len) {
86dc4139 4743+ /* try stopping to update while we are referencing */
3c1bdaff 4744+ vfsub_inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
c2b27bf2 4745+ au_pin_hdir_unlock(cpg->pin);
1facf9fc 4746+
c2b27bf2
AM
4747+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bsrc);
4748+ h_path.mnt = au_sbr_mnt(cpg->dentry->d_sb, cpg->bsrc);
86dc4139 4749+ h_src_attr->iflags = h_src_inode->i_flags;
5527c038 4750+ if (!au_test_nfs(h_src_inode->i_sb))
521ced18 4751+ err = vfsub_getattr(&h_path, &h_src_attr->st);
5527c038 4752+ else {
3c1bdaff 4753+ inode_unlock_shared(h_src_inode);
521ced18 4754+ err = vfsub_getattr(&h_path, &h_src_attr->st);
8b6a4947
AM
4755+ vfsub_inode_lock_shared_nested(h_src_inode,
4756+ AuLsc_I_CHILD);
5527c038 4757+ }
86dc4139 4758+ if (unlikely(err)) {
3c1bdaff 4759+ inode_unlock_shared(h_src_inode);
86dc4139
AM
4760+ goto out;
4761+ }
4762+ h_src_attr->valid = 1;
e2f27e51
AM
4763+ if (!au_test_nfs(h_src_inode->i_sb)) {
4764+ err = au_cp_regular(cpg);
3c1bdaff 4765+ inode_unlock_shared(h_src_inode);
e2f27e51 4766+ } else {
3c1bdaff 4767+ inode_unlock_shared(h_src_inode);
e2f27e51
AM
4768+ err = au_cp_regular(cpg);
4769+ }
c2b27bf2 4770+ rerr = au_pin_hdir_relock(cpg->pin);
86dc4139
AM
4771+ if (!err && rerr)
4772+ err = rerr;
1facf9fc 4773+ }
38d290e6
JR
4774+ if (!err && (h_src_inode->i_state & I_LINKABLE)) {
4775+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bdst);
5527c038 4776+ h_dst_inode = d_inode(h_path.dentry);
38d290e6
JR
4777+ spin_lock(&h_dst_inode->i_lock);
4778+ h_dst_inode->i_state |= I_LINKABLE;
4779+ spin_unlock(&h_dst_inode->i_lock);
4780+ }
1facf9fc 4781+
4f0767ce 4782+out:
1facf9fc 4783+ return err;
4784+}
4785+
4786+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
4787+ struct inode *h_dir)
4788+{
4789+ int err, symlen;
4790+ mm_segment_t old_fs;
b752ccd1
AM
4791+ union {
4792+ char *k;
4793+ char __user *u;
4794+ } sym;
1facf9fc 4795+
4796+ err = -ENOMEM;
537831f9 4797+ sym.k = (void *)__get_free_page(GFP_NOFS);
b752ccd1 4798+ if (unlikely(!sym.k))
1facf9fc 4799+ goto out;
4800+
9dbd164d 4801+ /* unnecessary to support mmap_sem since symlink is not mmap-able */
1facf9fc 4802+ old_fs = get_fs();
4803+ set_fs(KERNEL_DS);
a2654f78 4804+ symlen = vfs_readlink(h_src, sym.u, PATH_MAX);
1facf9fc 4805+ err = symlen;
4806+ set_fs(old_fs);
4807+
4808+ if (symlen > 0) {
b752ccd1
AM
4809+ sym.k[symlen] = 0;
4810+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 4811+ }
1c60b727 4812+ free_page((unsigned long)sym.k);
1facf9fc 4813+
4f0767ce 4814+out:
1facf9fc 4815+ return err;
4816+}
4817+
8cdd5066
JR
4818+/*
4819+ * regardless 'acl' option, reset all ACL.
4820+ * All ACL will be copied up later from the original entry on the lower branch.
4821+ */
4822+static int au_reset_acl(struct inode *h_dir, struct path *h_path, umode_t mode)
4823+{
4824+ int err;
4825+ struct dentry *h_dentry;
4826+ struct inode *h_inode;
4827+
4828+ h_dentry = h_path->dentry;
4829+ h_inode = d_inode(h_dentry);
4830+ /* forget_all_cached_acls(h_inode)); */
4831+ err = vfsub_removexattr(h_dentry, XATTR_NAME_POSIX_ACL_ACCESS);
4832+ AuTraceErr(err);
4833+ if (err == -EOPNOTSUPP)
4834+ err = 0;
4835+ if (!err)
4836+ err = vfsub_acl_chmod(h_inode, mode);
4837+
4838+ AuTraceErr(err);
4839+ return err;
4840+}
4841+
4842+static int au_do_cpup_dir(struct au_cp_generic *cpg, struct dentry *dst_parent,
4843+ struct inode *h_dir, struct path *h_path)
4844+{
4845+ int err;
4846+ struct inode *dir, *inode;
4847+
4848+ err = vfsub_removexattr(h_path->dentry, XATTR_NAME_POSIX_ACL_DEFAULT);
4849+ AuTraceErr(err);
4850+ if (err == -EOPNOTSUPP)
4851+ err = 0;
4852+ if (unlikely(err))
4853+ goto out;
4854+
4855+ /*
4856+ * strange behaviour from the users view,
4857+ * particularry setattr case
4858+ */
4859+ dir = d_inode(dst_parent);
5afbbe0d 4860+ if (au_ibtop(dir) == cpg->bdst)
8cdd5066
JR
4861+ au_cpup_attr_nlink(dir, /*force*/1);
4862+ inode = d_inode(cpg->dentry);
4863+ au_cpup_attr_nlink(inode, /*force*/1);
4864+
4865+out:
4866+ return err;
4867+}
4868+
1facf9fc 4869+static noinline_for_stack
c2b27bf2 4870+int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent,
86dc4139 4871+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 4872+{
4873+ int err;
4874+ umode_t mode;
4875+ unsigned int mnt_flags;
076b876e 4876+ unsigned char isdir, isreg, force;
c2b27bf2 4877+ const unsigned char do_dt = !!au_ftest_cpup(cpg->flags, DTIME);
1facf9fc 4878+ struct au_dtime dt;
4879+ struct path h_path;
4880+ struct dentry *h_src, *h_dst, *h_parent;
8cdd5066 4881+ struct inode *h_inode, *h_dir;
1facf9fc 4882+ struct super_block *sb;
4883+
4884+ /* bsrc branch can be ro/rw. */
c2b27bf2 4885+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038
JR
4886+ h_inode = d_inode(h_src);
4887+ AuDebugOn(h_inode != au_h_iptr(d_inode(cpg->dentry), cpg->bsrc));
1facf9fc 4888+
4889+ /* try stopping to be referenced while we are creating */
c2b27bf2
AM
4890+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst);
4891+ if (au_ftest_cpup(cpg->flags, RENAME))
86dc4139
AM
4892+ AuDebugOn(strncmp(h_dst->d_name.name, AUFS_WH_PFX,
4893+ AUFS_WH_PFX_LEN));
1facf9fc 4894+ h_parent = h_dst->d_parent; /* dir inode is locked */
5527c038 4895+ h_dir = d_inode(h_parent);
1facf9fc 4896+ IMustLock(h_dir);
4897+ AuDebugOn(h_parent != h_dst->d_parent);
4898+
c2b27bf2
AM
4899+ sb = cpg->dentry->d_sb;
4900+ h_path.mnt = au_sbr_mnt(sb, cpg->bdst);
1facf9fc 4901+ if (do_dt) {
4902+ h_path.dentry = h_parent;
4903+ au_dtime_store(&dt, dst_parent, &h_path);
4904+ }
4905+ h_path.dentry = h_dst;
4906+
076b876e 4907+ isreg = 0;
1facf9fc 4908+ isdir = 0;
4909+ mode = h_inode->i_mode;
4910+ switch (mode & S_IFMT) {
4911+ case S_IFREG:
076b876e 4912+ isreg = 1;
8cdd5066 4913+ err = vfsub_create(h_dir, &h_path, S_IRUSR | S_IWUSR,
b4510431 4914+ /*want_excl*/true);
1facf9fc 4915+ if (!err)
c2b27bf2 4916+ err = au_do_cpup_regular(cpg, h_src_attr);
1facf9fc 4917+ break;
4918+ case S_IFDIR:
4919+ isdir = 1;
4920+ err = vfsub_mkdir(h_dir, &h_path, mode);
8cdd5066
JR
4921+ if (!err)
4922+ err = au_do_cpup_dir(cpg, dst_parent, h_dir, &h_path);
1facf9fc 4923+ break;
4924+ case S_IFLNK:
4925+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
4926+ break;
4927+ case S_IFCHR:
4928+ case S_IFBLK:
4929+ AuDebugOn(!capable(CAP_MKNOD));
4930+ /*FALLTHROUGH*/
4931+ case S_IFIFO:
4932+ case S_IFSOCK:
4933+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
4934+ break;
4935+ default:
4936+ AuIOErr("Unknown inode type 0%o\n", mode);
4937+ err = -EIO;
4938+ }
8cdd5066
JR
4939+ if (!err)
4940+ err = au_reset_acl(h_dir, &h_path, mode);
1facf9fc 4941+
4942+ mnt_flags = au_mntflags(sb);
4943+ if (!au_opt_test(mnt_flags, UDBA_NONE)
4944+ && !isdir
4945+ && au_opt_test(mnt_flags, XINO)
38d290e6
JR
4946+ && (h_inode->i_nlink == 1
4947+ || (h_inode->i_state & I_LINKABLE))
1facf9fc 4948+ /* todo: unnecessary? */
5527c038 4949+ /* && d_inode(cpg->dentry)->i_nlink == 1 */
c2b27bf2
AM
4950+ && cpg->bdst < cpg->bsrc
4951+ && !au_ftest_cpup(cpg->flags, KEEPLINO))
4952+ au_xino_write(sb, cpg->bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 4953+ /* ignore this error */
4954+
076b876e
AM
4955+ if (!err) {
4956+ force = 0;
4957+ if (isreg) {
4958+ force = !!cpg->len;
4959+ if (cpg->len == -1)
4960+ force = !!i_size_read(h_inode);
4961+ }
4962+ au_fhsm_wrote(sb, cpg->bdst, force);
4963+ }
4964+
1facf9fc 4965+ if (do_dt)
4966+ au_dtime_revert(&dt);
4967+ return err;
4968+}
4969+
392086de 4970+static int au_do_ren_after_cpup(struct au_cp_generic *cpg, struct path *h_path)
86dc4139
AM
4971+{
4972+ int err;
392086de 4973+ struct dentry *dentry, *h_dentry, *h_parent, *parent;
86dc4139 4974+ struct inode *h_dir;
392086de 4975+ aufs_bindex_t bdst;
86dc4139 4976+
392086de
AM
4977+ dentry = cpg->dentry;
4978+ bdst = cpg->bdst;
4979+ h_dentry = au_h_dptr(dentry, bdst);
4980+ if (!au_ftest_cpup(cpg->flags, OVERWRITE)) {
4981+ dget(h_dentry);
4982+ au_set_h_dptr(dentry, bdst, NULL);
4983+ err = au_lkup_neg(dentry, bdst, /*wh*/0);
4984+ if (!err)
4985+ h_path->dentry = dget(au_h_dptr(dentry, bdst));
86dc4139 4986+ au_set_h_dptr(dentry, bdst, h_dentry);
392086de
AM
4987+ } else {
4988+ err = 0;
4989+ parent = dget_parent(dentry);
4990+ h_parent = au_h_dptr(parent, bdst);
4991+ dput(parent);
4992+ h_path->dentry = vfsub_lkup_one(&dentry->d_name, h_parent);
4993+ if (IS_ERR(h_path->dentry))
4994+ err = PTR_ERR(h_path->dentry);
86dc4139 4995+ }
392086de
AM
4996+ if (unlikely(err))
4997+ goto out;
86dc4139 4998+
86dc4139 4999+ h_parent = h_dentry->d_parent; /* dir inode is locked */
5527c038 5000+ h_dir = d_inode(h_parent);
86dc4139 5001+ IMustLock(h_dir);
523b37e3
AM
5002+ AuDbg("%pd %pd\n", h_dentry, h_path->dentry);
5003+ /* no delegation since it is just created */
f2c43d5f
AM
5004+ err = vfsub_rename(h_dir, h_dentry, h_dir, h_path, /*delegated*/NULL,
5005+ /*flags*/0);
86dc4139
AM
5006+ dput(h_path->dentry);
5007+
5008+out:
5009+ return err;
5010+}
5011+
1facf9fc 5012+/*
5013+ * copyup the @dentry from @bsrc to @bdst.
5014+ * the caller must set the both of lower dentries.
5015+ * @len is for truncating when it is -1 copyup the entire file.
5016+ * in link/rename cases, @dst_parent may be different from the real one.
c2b27bf2 5017+ * basic->bsrc can be larger than basic->bdst.
f2c43d5f
AM
5018+ * aufs doesn't touch the credential so
5019+ * security_inode_copy_up{,_xattr}() are unnecrssary.
1facf9fc 5020+ */
c2b27bf2 5021+static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
1facf9fc 5022+{
5023+ int err, rerr;
5afbbe0d 5024+ aufs_bindex_t old_ibtop;
1facf9fc 5025+ unsigned char isdir, plink;
1facf9fc 5026+ struct dentry *h_src, *h_dst, *h_parent;
5527c038 5027+ struct inode *dst_inode, *h_dir, *inode, *delegated, *src_inode;
1facf9fc 5028+ struct super_block *sb;
86dc4139 5029+ struct au_branch *br;
c2b27bf2
AM
5030+ /* to reuduce stack size */
5031+ struct {
5032+ struct au_dtime dt;
5033+ struct path h_path;
5034+ struct au_cpup_reg_attr h_src_attr;
5035+ } *a;
1facf9fc 5036+
c2b27bf2
AM
5037+ err = -ENOMEM;
5038+ a = kmalloc(sizeof(*a), GFP_NOFS);
5039+ if (unlikely(!a))
5040+ goto out;
5041+ a->h_src_attr.valid = 0;
1facf9fc 5042+
c2b27bf2
AM
5043+ sb = cpg->dentry->d_sb;
5044+ br = au_sbr(sb, cpg->bdst);
5045+ a->h_path.mnt = au_br_mnt(br);
5046+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst);
1facf9fc 5047+ h_parent = h_dst->d_parent; /* dir inode is locked */
5527c038 5048+ h_dir = d_inode(h_parent);
1facf9fc 5049+ IMustLock(h_dir);
5050+
c2b27bf2 5051+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038 5052+ inode = d_inode(cpg->dentry);
1facf9fc 5053+
5054+ if (!dst_parent)
c2b27bf2 5055+ dst_parent = dget_parent(cpg->dentry);
1facf9fc 5056+ else
5057+ dget(dst_parent);
5058+
5059+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
c2b27bf2 5060+ dst_inode = au_h_iptr(inode, cpg->bdst);
1facf9fc 5061+ if (dst_inode) {
5062+ if (unlikely(!plink)) {
5063+ err = -EIO;
027c5e7a
AM
5064+ AuIOErr("hi%lu(i%lu) exists on b%d "
5065+ "but plink is disabled\n",
c2b27bf2
AM
5066+ dst_inode->i_ino, inode->i_ino, cpg->bdst);
5067+ goto out_parent;
1facf9fc 5068+ }
5069+
5070+ if (dst_inode->i_nlink) {
c2b27bf2 5071+ const int do_dt = au_ftest_cpup(cpg->flags, DTIME);
1facf9fc 5072+
c2b27bf2 5073+ h_src = au_plink_lkup(inode, cpg->bdst);
1facf9fc 5074+ err = PTR_ERR(h_src);
5075+ if (IS_ERR(h_src))
c2b27bf2 5076+ goto out_parent;
5527c038 5077+ if (unlikely(d_is_negative(h_src))) {
1facf9fc 5078+ err = -EIO;
79b8bda9 5079+ AuIOErr("i%lu exists on b%d "
027c5e7a 5080+ "but not pseudo-linked\n",
79b8bda9 5081+ inode->i_ino, cpg->bdst);
1facf9fc 5082+ dput(h_src);
c2b27bf2 5083+ goto out_parent;
1facf9fc 5084+ }
5085+
5086+ if (do_dt) {
c2b27bf2
AM
5087+ a->h_path.dentry = h_parent;
5088+ au_dtime_store(&a->dt, dst_parent, &a->h_path);
1facf9fc 5089+ }
86dc4139 5090+
c2b27bf2 5091+ a->h_path.dentry = h_dst;
523b37e3
AM
5092+ delegated = NULL;
5093+ err = vfsub_link(h_src, h_dir, &a->h_path, &delegated);
c2b27bf2 5094+ if (!err && au_ftest_cpup(cpg->flags, RENAME))
392086de 5095+ err = au_do_ren_after_cpup(cpg, &a->h_path);
1facf9fc 5096+ if (do_dt)
c2b27bf2 5097+ au_dtime_revert(&a->dt);
523b37e3
AM
5098+ if (unlikely(err == -EWOULDBLOCK)) {
5099+ pr_warn("cannot retry for NFSv4 delegation"
5100+ " for an internal link\n");
5101+ iput(delegated);
5102+ }
1facf9fc 5103+ dput(h_src);
c2b27bf2 5104+ goto out_parent;
1facf9fc 5105+ } else
5106+ /* todo: cpup_wh_file? */
5107+ /* udba work */
4a4d8108 5108+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 5109+ }
5110+
86dc4139 5111+ isdir = S_ISDIR(inode->i_mode);
5afbbe0d 5112+ old_ibtop = au_ibtop(inode);
c2b27bf2 5113+ err = cpup_entry(cpg, dst_parent, &a->h_src_attr);
1facf9fc 5114+ if (unlikely(err))
86dc4139 5115+ goto out_rev;
5527c038 5116+ dst_inode = d_inode(h_dst);
febd17d6 5117+ inode_lock_nested(dst_inode, AuLsc_I_CHILD2);
86dc4139 5118+ /* todo: necessary? */
c2b27bf2 5119+ /* au_pin_hdir_unlock(cpg->pin); */
1facf9fc 5120+
c2b27bf2 5121+ err = cpup_iattr(cpg->dentry, cpg->bdst, h_src, &a->h_src_attr);
86dc4139
AM
5122+ if (unlikely(err)) {
5123+ /* todo: necessary? */
c2b27bf2 5124+ /* au_pin_hdir_relock(cpg->pin); */ /* ignore an error */
febd17d6 5125+ inode_unlock(dst_inode);
86dc4139
AM
5126+ goto out_rev;
5127+ }
5128+
5afbbe0d 5129+ if (cpg->bdst < old_ibtop) {
86dc4139 5130+ if (S_ISREG(inode->i_mode)) {
c2b27bf2 5131+ err = au_dy_iaop(inode, cpg->bdst, dst_inode);
86dc4139 5132+ if (unlikely(err)) {
c2b27bf2
AM
5133+ /* ignore an error */
5134+ /* au_pin_hdir_relock(cpg->pin); */
febd17d6 5135+ inode_unlock(dst_inode);
86dc4139 5136+ goto out_rev;
4a4d8108 5137+ }
4a4d8108 5138+ }
5afbbe0d 5139+ au_set_ibtop(inode, cpg->bdst);
c2b27bf2 5140+ } else
5afbbe0d 5141+ au_set_ibbot(inode, cpg->bdst);
c2b27bf2 5142+ au_set_h_iptr(inode, cpg->bdst, au_igrab(dst_inode),
86dc4139
AM
5143+ au_hi_flags(inode, isdir));
5144+
5145+ /* todo: necessary? */
c2b27bf2 5146+ /* err = au_pin_hdir_relock(cpg->pin); */
febd17d6 5147+ inode_unlock(dst_inode);
86dc4139
AM
5148+ if (unlikely(err))
5149+ goto out_rev;
5150+
5527c038 5151+ src_inode = d_inode(h_src);
86dc4139 5152+ if (!isdir
5527c038
JR
5153+ && (src_inode->i_nlink > 1
5154+ || src_inode->i_state & I_LINKABLE)
86dc4139 5155+ && plink)
c2b27bf2 5156+ au_plink_append(inode, cpg->bdst, h_dst);
86dc4139 5157+
c2b27bf2
AM
5158+ if (au_ftest_cpup(cpg->flags, RENAME)) {
5159+ a->h_path.dentry = h_dst;
392086de 5160+ err = au_do_ren_after_cpup(cpg, &a->h_path);
86dc4139
AM
5161+ }
5162+ if (!err)
c2b27bf2 5163+ goto out_parent; /* success */
1facf9fc 5164+
5165+ /* revert */
4a4d8108 5166+out_rev:
c2b27bf2
AM
5167+ a->h_path.dentry = h_parent;
5168+ au_dtime_store(&a->dt, dst_parent, &a->h_path);
5169+ a->h_path.dentry = h_dst;
86dc4139 5170+ rerr = 0;
5527c038 5171+ if (d_is_positive(h_dst)) {
523b37e3
AM
5172+ if (!isdir) {
5173+ /* no delegation since it is just created */
5174+ rerr = vfsub_unlink(h_dir, &a->h_path,
5175+ /*delegated*/NULL, /*force*/0);
5176+ } else
c2b27bf2 5177+ rerr = vfsub_rmdir(h_dir, &a->h_path);
86dc4139 5178+ }
c2b27bf2 5179+ au_dtime_revert(&a->dt);
1facf9fc 5180+ if (rerr) {
5181+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
5182+ err = -EIO;
5183+ }
c2b27bf2 5184+out_parent:
1facf9fc 5185+ dput(dst_parent);
1c60b727 5186+ kfree(a);
c2b27bf2 5187+out:
1facf9fc 5188+ return err;
5189+}
5190+
7e9cd9fe 5191+#if 0 /* reserved */
1facf9fc 5192+struct au_cpup_single_args {
5193+ int *errp;
c2b27bf2 5194+ struct au_cp_generic *cpg;
1facf9fc 5195+ struct dentry *dst_parent;
5196+};
5197+
5198+static void au_call_cpup_single(void *args)
5199+{
5200+ struct au_cpup_single_args *a = args;
86dc4139 5201+
c2b27bf2
AM
5202+ au_pin_hdir_acquire_nest(a->cpg->pin);
5203+ *a->errp = au_cpup_single(a->cpg, a->dst_parent);
5204+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 5205+}
c2b27bf2 5206+#endif
1facf9fc 5207+
53392da6
AM
5208+/*
5209+ * prevent SIGXFSZ in copy-up.
5210+ * testing CAP_MKNOD is for generic fs,
5211+ * but CAP_FSETID is for xfs only, currently.
5212+ */
86dc4139 5213+static int au_cpup_sio_test(struct au_pin *pin, umode_t mode)
53392da6
AM
5214+{
5215+ int do_sio;
86dc4139
AM
5216+ struct super_block *sb;
5217+ struct inode *h_dir;
53392da6
AM
5218+
5219+ do_sio = 0;
86dc4139 5220+ sb = au_pinned_parent(pin)->d_sb;
53392da6
AM
5221+ if (!au_wkq_test()
5222+ && (!au_sbi(sb)->si_plink_maint_pid
5223+ || au_plink_maint(sb, AuLock_NOPLM))) {
5224+ switch (mode & S_IFMT) {
5225+ case S_IFREG:
5226+ /* no condition about RLIMIT_FSIZE and the file size */
5227+ do_sio = 1;
5228+ break;
5229+ case S_IFCHR:
5230+ case S_IFBLK:
5231+ do_sio = !capable(CAP_MKNOD);
5232+ break;
5233+ }
5234+ if (!do_sio)
5235+ do_sio = ((mode & (S_ISUID | S_ISGID))
5236+ && !capable(CAP_FSETID));
86dc4139
AM
5237+ /* this workaround may be removed in the future */
5238+ if (!do_sio) {
5239+ h_dir = au_pinned_h_dir(pin);
5240+ do_sio = h_dir->i_mode & S_ISVTX;
5241+ }
53392da6
AM
5242+ }
5243+
5244+ return do_sio;
5245+}
5246+
7e9cd9fe 5247+#if 0 /* reserved */
c2b27bf2 5248+int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
1facf9fc 5249+{
5250+ int err, wkq_err;
1facf9fc 5251+ struct dentry *h_dentry;
5252+
c2b27bf2 5253+ h_dentry = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038 5254+ if (!au_cpup_sio_test(pin, d_inode(h_dentry)->i_mode))
c2b27bf2 5255+ err = au_cpup_single(cpg, dst_parent);
1facf9fc 5256+ else {
5257+ struct au_cpup_single_args args = {
5258+ .errp = &err,
c2b27bf2
AM
5259+ .cpg = cpg,
5260+ .dst_parent = dst_parent
1facf9fc 5261+ };
5262+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
5263+ if (unlikely(wkq_err))
5264+ err = wkq_err;
5265+ }
5266+
5267+ return err;
5268+}
c2b27bf2 5269+#endif
1facf9fc 5270+
5271+/*
5272+ * copyup the @dentry from the first active lower branch to @bdst,
5273+ * using au_cpup_single().
5274+ */
c2b27bf2 5275+static int au_cpup_simple(struct au_cp_generic *cpg)
1facf9fc 5276+{
5277+ int err;
c2b27bf2
AM
5278+ unsigned int flags_orig;
5279+ struct dentry *dentry;
5280+
5281+ AuDebugOn(cpg->bsrc < 0);
1facf9fc 5282+
c2b27bf2 5283+ dentry = cpg->dentry;
86dc4139 5284+ DiMustWriteLock(dentry);
1facf9fc 5285+
c2b27bf2 5286+ err = au_lkup_neg(dentry, cpg->bdst, /*wh*/1);
1facf9fc 5287+ if (!err) {
c2b27bf2
AM
5288+ flags_orig = cpg->flags;
5289+ au_fset_cpup(cpg->flags, RENAME);
5290+ err = au_cpup_single(cpg, NULL);
5291+ cpg->flags = flags_orig;
1facf9fc 5292+ if (!err)
5293+ return 0; /* success */
5294+
5295+ /* revert */
c2b27bf2 5296+ au_set_h_dptr(dentry, cpg->bdst, NULL);
5afbbe0d 5297+ au_set_dbtop(dentry, cpg->bsrc);
1facf9fc 5298+ }
5299+
5300+ return err;
5301+}
5302+
5303+struct au_cpup_simple_args {
5304+ int *errp;
c2b27bf2 5305+ struct au_cp_generic *cpg;
1facf9fc 5306+};
5307+
5308+static void au_call_cpup_simple(void *args)
5309+{
5310+ struct au_cpup_simple_args *a = args;
86dc4139 5311+
c2b27bf2
AM
5312+ au_pin_hdir_acquire_nest(a->cpg->pin);
5313+ *a->errp = au_cpup_simple(a->cpg);
5314+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 5315+}
5316+
c2b27bf2 5317+static int au_do_sio_cpup_simple(struct au_cp_generic *cpg)
1facf9fc 5318+{
5319+ int err, wkq_err;
c2b27bf2
AM
5320+ struct dentry *dentry, *parent;
5321+ struct file *h_file;
1facf9fc 5322+ struct inode *h_dir;
5323+
c2b27bf2
AM
5324+ dentry = cpg->dentry;
5325+ h_file = NULL;
5326+ if (au_ftest_cpup(cpg->flags, HOPEN)) {
5327+ AuDebugOn(cpg->bsrc < 0);
392086de 5328+ h_file = au_h_open_pre(dentry, cpg->bsrc, /*force_wr*/0);
c2b27bf2
AM
5329+ err = PTR_ERR(h_file);
5330+ if (IS_ERR(h_file))
5331+ goto out;
5332+ }
5333+
1facf9fc 5334+ parent = dget_parent(dentry);
5527c038 5335+ h_dir = au_h_iptr(d_inode(parent), cpg->bdst);
53392da6 5336+ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE)
5527c038 5337+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode))
c2b27bf2 5338+ err = au_cpup_simple(cpg);
1facf9fc 5339+ else {
5340+ struct au_cpup_simple_args args = {
5341+ .errp = &err,
c2b27bf2 5342+ .cpg = cpg
1facf9fc 5343+ };
5344+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
5345+ if (unlikely(wkq_err))
5346+ err = wkq_err;
5347+ }
5348+
5349+ dput(parent);
c2b27bf2
AM
5350+ if (h_file)
5351+ au_h_open_post(dentry, cpg->bsrc, h_file);
5352+
5353+out:
1facf9fc 5354+ return err;
5355+}
5356+
c2b27bf2 5357+int au_sio_cpup_simple(struct au_cp_generic *cpg)
367653fa 5358+{
5afbbe0d 5359+ aufs_bindex_t bsrc, bbot;
c2b27bf2 5360+ struct dentry *dentry, *h_dentry;
367653fa 5361+
c2b27bf2
AM
5362+ if (cpg->bsrc < 0) {
5363+ dentry = cpg->dentry;
5afbbe0d
AM
5364+ bbot = au_dbbot(dentry);
5365+ for (bsrc = cpg->bdst + 1; bsrc <= bbot; bsrc++) {
c2b27bf2
AM
5366+ h_dentry = au_h_dptr(dentry, bsrc);
5367+ if (h_dentry) {
5527c038 5368+ AuDebugOn(d_is_negative(h_dentry));
c2b27bf2
AM
5369+ break;
5370+ }
5371+ }
5afbbe0d 5372+ AuDebugOn(bsrc > bbot);
c2b27bf2 5373+ cpg->bsrc = bsrc;
367653fa 5374+ }
c2b27bf2
AM
5375+ AuDebugOn(cpg->bsrc <= cpg->bdst);
5376+ return au_do_sio_cpup_simple(cpg);
5377+}
367653fa 5378+
c2b27bf2
AM
5379+int au_sio_cpdown_simple(struct au_cp_generic *cpg)
5380+{
5381+ AuDebugOn(cpg->bdst <= cpg->bsrc);
5382+ return au_do_sio_cpup_simple(cpg);
367653fa
AM
5383+}
5384+
1facf9fc 5385+/* ---------------------------------------------------------------------- */
5386+
5387+/*
5388+ * copyup the deleted file for writing.
5389+ */
c2b27bf2
AM
5390+static int au_do_cpup_wh(struct au_cp_generic *cpg, struct dentry *wh_dentry,
5391+ struct file *file)
1facf9fc 5392+{
5393+ int err;
c2b27bf2
AM
5394+ unsigned int flags_orig;
5395+ aufs_bindex_t bsrc_orig;
c2b27bf2 5396+ struct au_dinfo *dinfo;
5afbbe0d
AM
5397+ struct {
5398+ struct au_hdentry *hd;
5399+ struct dentry *h_dentry;
5400+ } hdst, hsrc;
1facf9fc 5401+
c2b27bf2 5402+ dinfo = au_di(cpg->dentry);
1308ab2a 5403+ AuRwMustWriteLock(&dinfo->di_rwsem);
5404+
c2b27bf2 5405+ bsrc_orig = cpg->bsrc;
5afbbe0d
AM
5406+ cpg->bsrc = dinfo->di_btop;
5407+ hdst.hd = au_hdentry(dinfo, cpg->bdst);
5408+ hdst.h_dentry = hdst.hd->hd_dentry;
5409+ hdst.hd->hd_dentry = wh_dentry;
5410+ dinfo->di_btop = cpg->bdst;
5411+
5412+ hsrc.h_dentry = NULL;
027c5e7a 5413+ if (file) {
5afbbe0d
AM
5414+ hsrc.hd = au_hdentry(dinfo, cpg->bsrc);
5415+ hsrc.h_dentry = hsrc.hd->hd_dentry;
5416+ hsrc.hd->hd_dentry = au_hf_top(file)->f_path.dentry;
027c5e7a 5417+ }
c2b27bf2
AM
5418+ flags_orig = cpg->flags;
5419+ cpg->flags = !AuCpup_DTIME;
5420+ err = au_cpup_single(cpg, /*h_parent*/NULL);
5421+ cpg->flags = flags_orig;
027c5e7a
AM
5422+ if (file) {
5423+ if (!err)
5424+ err = au_reopen_nondir(file);
5afbbe0d 5425+ hsrc.hd->hd_dentry = hsrc.h_dentry;
1facf9fc 5426+ }
5afbbe0d
AM
5427+ hdst.hd->hd_dentry = hdst.h_dentry;
5428+ dinfo->di_btop = cpg->bsrc;
c2b27bf2 5429+ cpg->bsrc = bsrc_orig;
1facf9fc 5430+
5431+ return err;
5432+}
5433+
c2b27bf2 5434+static int au_cpup_wh(struct au_cp_generic *cpg, struct file *file)
1facf9fc 5435+{
5436+ int err;
c2b27bf2 5437+ aufs_bindex_t bdst;
1facf9fc 5438+ struct au_dtime dt;
c2b27bf2 5439+ struct dentry *dentry, *parent, *h_parent, *wh_dentry;
1facf9fc 5440+ struct au_branch *br;
5441+ struct path h_path;
5442+
c2b27bf2
AM
5443+ dentry = cpg->dentry;
5444+ bdst = cpg->bdst;
1facf9fc 5445+ br = au_sbr(dentry->d_sb, bdst);
5446+ parent = dget_parent(dentry);
5447+ h_parent = au_h_dptr(parent, bdst);
5448+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
5449+ err = PTR_ERR(wh_dentry);
5450+ if (IS_ERR(wh_dentry))
5451+ goto out;
5452+
5453+ h_path.dentry = h_parent;
86dc4139 5454+ h_path.mnt = au_br_mnt(br);
1facf9fc 5455+ au_dtime_store(&dt, parent, &h_path);
c2b27bf2 5456+ err = au_do_cpup_wh(cpg, wh_dentry, file);
1facf9fc 5457+ if (unlikely(err))
5458+ goto out_wh;
5459+
5460+ dget(wh_dentry);
5461+ h_path.dentry = wh_dentry;
2000de60 5462+ if (!d_is_dir(wh_dentry)) {
523b37e3 5463+ /* no delegation since it is just created */
5527c038 5464+ err = vfsub_unlink(d_inode(h_parent), &h_path,
523b37e3
AM
5465+ /*delegated*/NULL, /*force*/0);
5466+ } else
5527c038 5467+ err = vfsub_rmdir(d_inode(h_parent), &h_path);
1facf9fc 5468+ if (unlikely(err)) {
523b37e3
AM
5469+ AuIOErr("failed remove copied-up tmp file %pd(%d)\n",
5470+ wh_dentry, err);
1facf9fc 5471+ err = -EIO;
5472+ }
5473+ au_dtime_revert(&dt);
5527c038 5474+ au_set_hi_wh(d_inode(dentry), bdst, wh_dentry);
1facf9fc 5475+
4f0767ce 5476+out_wh:
1facf9fc 5477+ dput(wh_dentry);
4f0767ce 5478+out:
1facf9fc 5479+ dput(parent);
5480+ return err;
5481+}
5482+
5483+struct au_cpup_wh_args {
5484+ int *errp;
c2b27bf2 5485+ struct au_cp_generic *cpg;
1facf9fc 5486+ struct file *file;
5487+};
5488+
5489+static void au_call_cpup_wh(void *args)
5490+{
5491+ struct au_cpup_wh_args *a = args;
86dc4139 5492+
c2b27bf2
AM
5493+ au_pin_hdir_acquire_nest(a->cpg->pin);
5494+ *a->errp = au_cpup_wh(a->cpg, a->file);
5495+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 5496+}
5497+
c2b27bf2 5498+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file)
1facf9fc 5499+{
5500+ int err, wkq_err;
c2b27bf2 5501+ aufs_bindex_t bdst;
c1595e42 5502+ struct dentry *dentry, *parent, *h_orph, *h_parent;
86dc4139 5503+ struct inode *dir, *h_dir, *h_tmpdir;
1facf9fc 5504+ struct au_wbr *wbr;
c2b27bf2 5505+ struct au_pin wh_pin, *pin_orig;
1facf9fc 5506+
c2b27bf2
AM
5507+ dentry = cpg->dentry;
5508+ bdst = cpg->bdst;
1facf9fc 5509+ parent = dget_parent(dentry);
5527c038 5510+ dir = d_inode(parent);
1facf9fc 5511+ h_orph = NULL;
5512+ h_parent = NULL;
5513+ h_dir = au_igrab(au_h_iptr(dir, bdst));
5514+ h_tmpdir = h_dir;
c2b27bf2 5515+ pin_orig = NULL;
1facf9fc 5516+ if (!h_dir->i_nlink) {
5517+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
5518+ h_orph = wbr->wbr_orph;
5519+
5520+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 5521+ au_set_h_dptr(parent, bdst, dget(h_orph));
5527c038 5522+ h_tmpdir = d_inode(h_orph);
1facf9fc 5523+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
5524+
febd17d6 5525+ inode_lock_nested(h_tmpdir, AuLsc_I_PARENT3);
4a4d8108 5526+ /* todo: au_h_open_pre()? */
86dc4139 5527+
c2b27bf2 5528+ pin_orig = cpg->pin;
86dc4139 5529+ au_pin_init(&wh_pin, dentry, bdst, AuLsc_DI_PARENT,
c2b27bf2
AM
5530+ AuLsc_I_PARENT3, cpg->pin->udba, AuPin_DI_LOCKED);
5531+ cpg->pin = &wh_pin;
1facf9fc 5532+ }
5533+
53392da6 5534+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE)
5527c038 5535+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode))
c2b27bf2 5536+ err = au_cpup_wh(cpg, file);
1facf9fc 5537+ else {
5538+ struct au_cpup_wh_args args = {
5539+ .errp = &err,
c2b27bf2
AM
5540+ .cpg = cpg,
5541+ .file = file
1facf9fc 5542+ };
5543+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
5544+ if (unlikely(wkq_err))
5545+ err = wkq_err;
5546+ }
5547+
5548+ if (h_orph) {
febd17d6 5549+ inode_unlock(h_tmpdir);
4a4d8108 5550+ /* todo: au_h_open_post()? */
1facf9fc 5551+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 5552+ au_set_h_dptr(parent, bdst, h_parent);
c2b27bf2
AM
5553+ AuDebugOn(!pin_orig);
5554+ cpg->pin = pin_orig;
1facf9fc 5555+ }
5556+ iput(h_dir);
5557+ dput(parent);
5558+
5559+ return err;
5560+}
5561+
5562+/* ---------------------------------------------------------------------- */
5563+
5564+/*
5565+ * generic routine for both of copy-up and copy-down.
5566+ */
5567+/* cf. revalidate function in file.c */
5568+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
5569+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 5570+ struct au_pin *pin,
1facf9fc 5571+ struct dentry *h_parent, void *arg),
5572+ void *arg)
5573+{
5574+ int err;
5575+ struct au_pin pin;
5527c038 5576+ struct dentry *d, *parent, *h_parent, *real_parent, *h_dentry;
1facf9fc 5577+
5578+ err = 0;
5579+ parent = dget_parent(dentry);
5580+ if (IS_ROOT(parent))
5581+ goto out;
5582+
5583+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
5584+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
5585+
5586+ /* do not use au_dpage */
5587+ real_parent = parent;
5588+ while (1) {
5589+ dput(parent);
5590+ parent = dget_parent(dentry);
5591+ h_parent = au_h_dptr(parent, bdst);
5592+ if (h_parent)
5593+ goto out; /* success */
5594+
5595+ /* find top dir which is necessary to cpup */
5596+ do {
5597+ d = parent;
5598+ dput(parent);
5599+ parent = dget_parent(d);
5600+ di_read_lock_parent3(parent, !AuLock_IR);
5601+ h_parent = au_h_dptr(parent, bdst);
5602+ di_read_unlock(parent, !AuLock_IR);
5603+ } while (!h_parent);
5604+
5605+ if (d != real_parent)
5606+ di_write_lock_child3(d);
5607+
5608+ /* somebody else might create while we were sleeping */
5527c038
JR
5609+ h_dentry = au_h_dptr(d, bdst);
5610+ if (!h_dentry || d_is_negative(h_dentry)) {
5611+ if (h_dentry)
5afbbe0d 5612+ au_update_dbtop(d);
1facf9fc 5613+
5614+ au_pin_set_dentry(&pin, d);
5615+ err = au_do_pin(&pin);
5616+ if (!err) {
86dc4139 5617+ err = cp(d, bdst, &pin, h_parent, arg);
1facf9fc 5618+ au_unpin(&pin);
5619+ }
5620+ }
5621+
5622+ if (d != real_parent)
5623+ di_write_unlock(d);
5624+ if (unlikely(err))
5625+ break;
5626+ }
5627+
4f0767ce 5628+out:
1facf9fc 5629+ dput(parent);
5630+ return err;
5631+}
5632+
5633+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 5634+ struct au_pin *pin,
2000de60 5635+ struct dentry *h_parent __maybe_unused,
1facf9fc 5636+ void *arg __maybe_unused)
5637+{
c2b27bf2
AM
5638+ struct au_cp_generic cpg = {
5639+ .dentry = dentry,
5640+ .bdst = bdst,
5641+ .bsrc = -1,
5642+ .len = 0,
5643+ .pin = pin,
5644+ .flags = AuCpup_DTIME
5645+ };
5646+ return au_sio_cpup_simple(&cpg);
1facf9fc 5647+}
5648+
5649+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
5650+{
5651+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
5652+}
5653+
5654+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
5655+{
5656+ int err;
5657+ struct dentry *parent;
5658+ struct inode *dir;
5659+
5660+ parent = dget_parent(dentry);
5527c038 5661+ dir = d_inode(parent);
1facf9fc 5662+ err = 0;
5663+ if (au_h_iptr(dir, bdst))
5664+ goto out;
5665+
5666+ di_read_unlock(parent, AuLock_IR);
5667+ di_write_lock_parent(parent);
5668+ /* someone else might change our inode while we were sleeping */
5669+ if (!au_h_iptr(dir, bdst))
5670+ err = au_cpup_dirs(dentry, bdst);
5671+ di_downgrade_lock(parent, AuLock_IR);
5672+
4f0767ce 5673+out:
1facf9fc 5674+ dput(parent);
5675+ return err;
5676+}
0b1ff5c3
JR
5677diff -urNp -x '*.orig' linux-4.14/fs/aufs/cpup.h linux-4.14/fs/aufs/cpup.h
5678--- linux-4.14/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
5679+++ linux-4.14/fs/aufs/cpup.h 2021-02-24 21:42:43.441114748 +0100
8b6a4947 5680@@ -0,0 +1,99 @@
1facf9fc 5681+/*
a2654f78 5682+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 5683+ *
5684+ * This program, aufs is free software; you can redistribute it and/or modify
5685+ * it under the terms of the GNU General Public License as published by
5686+ * the Free Software Foundation; either version 2 of the License, or
5687+ * (at your option) any later version.
dece6358
AM
5688+ *
5689+ * This program is distributed in the hope that it will be useful,
5690+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5691+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5692+ * GNU General Public License for more details.
5693+ *
5694+ * You should have received a copy of the GNU General Public License
523b37e3 5695+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 5696+ */
5697+
5698+/*
5699+ * copy-up/down functions
5700+ */
5701+
5702+#ifndef __AUFS_CPUP_H__
5703+#define __AUFS_CPUP_H__
5704+
5705+#ifdef __KERNEL__
5706+
dece6358 5707+#include <linux/path.h>
1facf9fc 5708+
dece6358
AM
5709+struct inode;
5710+struct file;
86dc4139 5711+struct au_pin;
dece6358 5712+
86dc4139 5713+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags);
1facf9fc 5714+void au_cpup_attr_timesizes(struct inode *inode);
5715+void au_cpup_attr_nlink(struct inode *inode, int force);
5716+void au_cpup_attr_changeable(struct inode *inode);
5717+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
5718+void au_cpup_attr_all(struct inode *inode, int force);
5719+
5720+/* ---------------------------------------------------------------------- */
5721+
c2b27bf2
AM
5722+struct au_cp_generic {
5723+ struct dentry *dentry;
5724+ aufs_bindex_t bdst, bsrc;
5725+ loff_t len;
5726+ struct au_pin *pin;
5727+ unsigned int flags;
5728+};
5729+
1facf9fc 5730+/* cpup flags */
392086de
AM
5731+#define AuCpup_DTIME 1 /* do dtime_store/revert */
5732+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
5733+ for link(2) */
5734+#define AuCpup_RENAME (1 << 2) /* rename after cpup */
5735+#define AuCpup_HOPEN (1 << 3) /* call h_open_pre/post() in
5736+ cpup */
5737+#define AuCpup_OVERWRITE (1 << 4) /* allow overwriting the
5738+ existing entry */
5739+#define AuCpup_RWDST (1 << 5) /* force write target even if
5740+ the branch is marked as RO */
c2b27bf2 5741+
8b6a4947
AM
5742+#ifndef CONFIG_AUFS_BR_HFSPLUS
5743+#undef AuCpup_HOPEN
5744+#define AuCpup_HOPEN 0
5745+#endif
5746+
1facf9fc 5747+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
7f207e10
AM
5748+#define au_fset_cpup(flags, name) \
5749+ do { (flags) |= AuCpup_##name; } while (0)
5750+#define au_fclr_cpup(flags, name) \
5751+ do { (flags) &= ~AuCpup_##name; } while (0)
1facf9fc 5752+
5753+int au_copy_file(struct file *dst, struct file *src, loff_t len);
c2b27bf2
AM
5754+int au_sio_cpup_simple(struct au_cp_generic *cpg);
5755+int au_sio_cpdown_simple(struct au_cp_generic *cpg);
5756+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file);
1facf9fc 5757+
5758+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
5759+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 5760+ struct au_pin *pin,
1facf9fc 5761+ struct dentry *h_parent, void *arg),
5762+ void *arg);
5763+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
5764+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
5765+
5766+/* ---------------------------------------------------------------------- */
5767+
5768+/* keep timestamps when copyup */
5769+struct au_dtime {
5770+ struct dentry *dt_dentry;
5771+ struct path dt_h_path;
5772+ struct timespec dt_atime, dt_mtime;
5773+};
5774+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
5775+ struct path *h_path);
5776+void au_dtime_revert(struct au_dtime *dt);
5777+
5778+#endif /* __KERNEL__ */
5779+#endif /* __AUFS_CPUP_H__ */
0b1ff5c3
JR
5780diff -urNp -x '*.orig' linux-4.14/fs/aufs/dbgaufs.c linux-4.14/fs/aufs/dbgaufs.c
5781--- linux-4.14/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
5782+++ linux-4.14/fs/aufs/dbgaufs.c 2021-02-24 21:42:43.441114748 +0100
8b6a4947 5783@@ -0,0 +1,437 @@
1facf9fc 5784+/*
a2654f78 5785+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 5786+ *
5787+ * This program, aufs is free software; you can redistribute it and/or modify
5788+ * it under the terms of the GNU General Public License as published by
5789+ * the Free Software Foundation; either version 2 of the License, or
5790+ * (at your option) any later version.
dece6358
AM
5791+ *
5792+ * This program is distributed in the hope that it will be useful,
5793+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5794+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5795+ * GNU General Public License for more details.
5796+ *
5797+ * You should have received a copy of the GNU General Public License
523b37e3 5798+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 5799+ */
5800+
5801+/*
5802+ * debugfs interface
5803+ */
5804+
5805+#include <linux/debugfs.h>
5806+#include "aufs.h"
5807+
5808+#ifndef CONFIG_SYSFS
5809+#error DEBUG_FS depends upon SYSFS
5810+#endif
5811+
5812+static struct dentry *dbgaufs;
5813+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
5814+
5815+/* 20 is max digits length of ulong 64 */
5816+struct dbgaufs_arg {
5817+ int n;
5818+ char a[20 * 4];
5819+};
5820+
5821+/*
5822+ * common function for all XINO files
5823+ */
5824+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
5825+ struct file *file)
5826+{
1c60b727 5827+ kfree(file->private_data);
1facf9fc 5828+ return 0;
5829+}
5830+
5831+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
5832+{
5833+ int err;
5834+ struct kstat st;
5835+ struct dbgaufs_arg *p;
5836+
5837+ err = -ENOMEM;
5838+ p = kmalloc(sizeof(*p), GFP_NOFS);
5839+ if (unlikely(!p))
5840+ goto out;
5841+
5842+ err = 0;
5843+ p->n = 0;
5844+ file->private_data = p;
5845+ if (!xf)
5846+ goto out;
5847+
521ced18 5848+ err = vfsub_getattr(&xf->f_path, &st);
1facf9fc 5849+ if (!err) {
5850+ if (do_fcnt)
5851+ p->n = snprintf
521ced18 5852+ (p->a, sizeof(p->a), "%ld, %llux%u %lld\n",
1facf9fc 5853+ (long)file_count(xf), st.blocks, st.blksize,
5854+ (long long)st.size);
5855+ else
521ced18 5856+ p->n = snprintf(p->a, sizeof(p->a), "%llux%u %lld\n",
1facf9fc 5857+ st.blocks, st.blksize,
5858+ (long long)st.size);
5859+ AuDebugOn(p->n >= sizeof(p->a));
5860+ } else {
5861+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
5862+ err = 0;
5863+ }
5864+
4f0767ce 5865+out:
1facf9fc 5866+ return err;
5867+
5868+}
5869+
5870+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
5871+ size_t count, loff_t *ppos)
5872+{
5873+ struct dbgaufs_arg *p;
5874+
5875+ p = file->private_data;
5876+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
5877+}
5878+
5879+/* ---------------------------------------------------------------------- */
5880+
86dc4139
AM
5881+struct dbgaufs_plink_arg {
5882+ int n;
5883+ char a[];
5884+};
5885+
5886+static int dbgaufs_plink_release(struct inode *inode __maybe_unused,
5887+ struct file *file)
5888+{
1c60b727 5889+ free_page((unsigned long)file->private_data);
86dc4139
AM
5890+ return 0;
5891+}
5892+
5893+static int dbgaufs_plink_open(struct inode *inode, struct file *file)
5894+{
5895+ int err, i, limit;
5896+ unsigned long n, sum;
5897+ struct dbgaufs_plink_arg *p;
5898+ struct au_sbinfo *sbinfo;
5899+ struct super_block *sb;
8b6a4947 5900+ struct hlist_bl_head *hbl;
86dc4139
AM
5901+
5902+ err = -ENOMEM;
5903+ p = (void *)get_zeroed_page(GFP_NOFS);
5904+ if (unlikely(!p))
5905+ goto out;
5906+
5907+ err = -EFBIG;
5908+ sbinfo = inode->i_private;
5909+ sb = sbinfo->si_sb;
5910+ si_noflush_read_lock(sb);
5911+ if (au_opt_test(au_mntflags(sb), PLINK)) {
5912+ limit = PAGE_SIZE - sizeof(p->n);
5913+
5914+ /* the number of buckets */
5915+ n = snprintf(p->a + p->n, limit, "%d\n", AuPlink_NHASH);
5916+ p->n += n;
5917+ limit -= n;
5918+
5919+ sum = 0;
8b6a4947
AM
5920+ for (i = 0, hbl = sbinfo->si_plink; i < AuPlink_NHASH;
5921+ i++, hbl++) {
5922+ n = au_hbl_count(hbl);
86dc4139
AM
5923+ sum += n;
5924+
5925+ n = snprintf(p->a + p->n, limit, "%lu ", n);
5926+ p->n += n;
5927+ limit -= n;
5928+ if (unlikely(limit <= 0))
5929+ goto out_free;
5930+ }
5931+ p->a[p->n - 1] = '\n';
5932+
5933+ /* the sum of plinks */
5934+ n = snprintf(p->a + p->n, limit, "%lu\n", sum);
5935+ p->n += n;
5936+ limit -= n;
5937+ if (unlikely(limit <= 0))
5938+ goto out_free;
5939+ } else {
5940+#define str "1\n0\n0\n"
5941+ p->n = sizeof(str) - 1;
5942+ strcpy(p->a, str);
5943+#undef str
5944+ }
5945+ si_read_unlock(sb);
5946+
5947+ err = 0;
5948+ file->private_data = p;
5949+ goto out; /* success */
5950+
5951+out_free:
1c60b727 5952+ free_page((unsigned long)p);
86dc4139
AM
5953+out:
5954+ return err;
5955+}
5956+
5957+static ssize_t dbgaufs_plink_read(struct file *file, char __user *buf,
5958+ size_t count, loff_t *ppos)
5959+{
5960+ struct dbgaufs_plink_arg *p;
5961+
5962+ p = file->private_data;
5963+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
5964+}
5965+
5966+static const struct file_operations dbgaufs_plink_fop = {
5967+ .owner = THIS_MODULE,
5968+ .open = dbgaufs_plink_open,
5969+ .release = dbgaufs_plink_release,
5970+ .read = dbgaufs_plink_read
5971+};
5972+
5973+/* ---------------------------------------------------------------------- */
5974+
1facf9fc 5975+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
5976+{
5977+ int err;
5978+ struct au_sbinfo *sbinfo;
5979+ struct super_block *sb;
5980+
5981+ sbinfo = inode->i_private;
5982+ sb = sbinfo->si_sb;
5983+ si_noflush_read_lock(sb);
5984+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
5985+ si_read_unlock(sb);
5986+ return err;
5987+}
5988+
5989+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 5990+ .owner = THIS_MODULE,
1facf9fc 5991+ .open = dbgaufs_xib_open,
5992+ .release = dbgaufs_xi_release,
5993+ .read = dbgaufs_xi_read
5994+};
5995+
5996+/* ---------------------------------------------------------------------- */
5997+
5998+#define DbgaufsXi_PREFIX "xi"
5999+
6000+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
6001+{
6002+ int err;
6003+ long l;
6004+ struct au_sbinfo *sbinfo;
6005+ struct super_block *sb;
6006+ struct file *xf;
6007+ struct qstr *name;
6008+
6009+ err = -ENOENT;
6010+ xf = NULL;
2000de60 6011+ name = &file->f_path.dentry->d_name;
1facf9fc 6012+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
6013+ || memcmp(name->name, DbgaufsXi_PREFIX,
6014+ sizeof(DbgaufsXi_PREFIX) - 1)))
6015+ goto out;
9dbd164d 6016+ err = kstrtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
1facf9fc 6017+ if (unlikely(err))
6018+ goto out;
6019+
6020+ sbinfo = inode->i_private;
6021+ sb = sbinfo->si_sb;
6022+ si_noflush_read_lock(sb);
5afbbe0d 6023+ if (l <= au_sbbot(sb)) {
1facf9fc 6024+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
6025+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
6026+ } else
6027+ err = -ENOENT;
6028+ si_read_unlock(sb);
6029+
4f0767ce 6030+out:
1facf9fc 6031+ return err;
6032+}
6033+
6034+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 6035+ .owner = THIS_MODULE,
1facf9fc 6036+ .open = dbgaufs_xino_open,
6037+ .release = dbgaufs_xi_release,
6038+ .read = dbgaufs_xi_read
6039+};
6040+
6041+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
6042+{
5afbbe0d 6043+ aufs_bindex_t bbot;
1facf9fc 6044+ struct au_branch *br;
6045+ struct au_xino_file *xi;
6046+
6047+ if (!au_sbi(sb)->si_dbgaufs)
6048+ return;
6049+
5afbbe0d
AM
6050+ bbot = au_sbbot(sb);
6051+ for (; bindex <= bbot; bindex++) {
1facf9fc 6052+ br = au_sbr(sb, bindex);
6053+ xi = &br->br_xino;
e2f27e51
AM
6054+ /* debugfs acquires the parent i_mutex */
6055+ lockdep_off();
c06a8ce3 6056+ debugfs_remove(xi->xi_dbgaufs);
e2f27e51 6057+ lockdep_on();
c06a8ce3 6058+ xi->xi_dbgaufs = NULL;
1facf9fc 6059+ }
6060+}
6061+
6062+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
6063+{
6064+ struct au_sbinfo *sbinfo;
6065+ struct dentry *parent;
6066+ struct au_branch *br;
6067+ struct au_xino_file *xi;
5afbbe0d 6068+ aufs_bindex_t bbot;
1facf9fc 6069+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
6070+
6071+ sbinfo = au_sbi(sb);
6072+ parent = sbinfo->si_dbgaufs;
6073+ if (!parent)
6074+ return;
6075+
5afbbe0d
AM
6076+ bbot = au_sbbot(sb);
6077+ for (; bindex <= bbot; bindex++) {
1facf9fc 6078+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
6079+ br = au_sbr(sb, bindex);
6080+ xi = &br->br_xino;
6081+ AuDebugOn(xi->xi_dbgaufs);
f0c0a007
AM
6082+ /* debugfs acquires the parent i_mutex */
6083+ lockdep_off();
1facf9fc 6084+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
6085+ sbinfo, &dbgaufs_xino_fop);
f0c0a007 6086+ lockdep_on();
1facf9fc 6087+ /* ignore an error */
6088+ if (unlikely(!xi->xi_dbgaufs))
6089+ AuWarn1("failed %s under debugfs\n", name);
6090+ }
6091+}
6092+
6093+/* ---------------------------------------------------------------------- */
6094+
6095+#ifdef CONFIG_AUFS_EXPORT
6096+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
6097+{
6098+ int err;
6099+ struct au_sbinfo *sbinfo;
6100+ struct super_block *sb;
6101+
6102+ sbinfo = inode->i_private;
6103+ sb = sbinfo->si_sb;
6104+ si_noflush_read_lock(sb);
6105+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
6106+ si_read_unlock(sb);
6107+ return err;
6108+}
6109+
6110+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 6111+ .owner = THIS_MODULE,
1facf9fc 6112+ .open = dbgaufs_xigen_open,
6113+ .release = dbgaufs_xi_release,
6114+ .read = dbgaufs_xi_read
6115+};
6116+
6117+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
6118+{
6119+ int err;
6120+
dece6358 6121+ /*
c1595e42 6122+ * This function is a dynamic '__init' function actually,
dece6358
AM
6123+ * so the tiny check for si_rwsem is unnecessary.
6124+ */
6125+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6126+
1facf9fc 6127+ err = -EIO;
6128+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
6129+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6130+ &dbgaufs_xigen_fop);
6131+ if (sbinfo->si_dbgaufs_xigen)
6132+ err = 0;
6133+
6134+ return err;
6135+}
6136+#else
6137+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
6138+{
6139+ return 0;
6140+}
6141+#endif /* CONFIG_AUFS_EXPORT */
6142+
6143+/* ---------------------------------------------------------------------- */
6144+
6145+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
6146+{
dece6358 6147+ /*
7e9cd9fe 6148+ * This function is a dynamic '__fin' function actually,
dece6358
AM
6149+ * so the tiny check for si_rwsem is unnecessary.
6150+ */
6151+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6152+
1facf9fc 6153+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
6154+ sbinfo->si_dbgaufs = NULL;
6155+ kobject_put(&sbinfo->si_kobj);
6156+}
6157+
6158+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
6159+{
6160+ int err;
6161+ char name[SysaufsSiNameLen];
6162+
dece6358 6163+ /*
c1595e42 6164+ * This function is a dynamic '__init' function actually,
dece6358
AM
6165+ * so the tiny check for si_rwsem is unnecessary.
6166+ */
6167+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6168+
1facf9fc 6169+ err = -ENOENT;
6170+ if (!dbgaufs) {
6171+ AuErr1("/debug/aufs is uninitialized\n");
6172+ goto out;
6173+ }
6174+
6175+ err = -EIO;
6176+ sysaufs_name(sbinfo, name);
6177+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
6178+ if (unlikely(!sbinfo->si_dbgaufs))
6179+ goto out;
6180+ kobject_get(&sbinfo->si_kobj);
6181+
6182+ sbinfo->si_dbgaufs_xib = debugfs_create_file
6183+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6184+ &dbgaufs_xib_fop);
6185+ if (unlikely(!sbinfo->si_dbgaufs_xib))
6186+ goto out_dir;
6187+
86dc4139
AM
6188+ sbinfo->si_dbgaufs_plink = debugfs_create_file
6189+ ("plink", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6190+ &dbgaufs_plink_fop);
6191+ if (unlikely(!sbinfo->si_dbgaufs_plink))
6192+ goto out_dir;
6193+
1facf9fc 6194+ err = dbgaufs_xigen_init(sbinfo);
6195+ if (!err)
6196+ goto out; /* success */
6197+
4f0767ce 6198+out_dir:
1facf9fc 6199+ dbgaufs_si_fin(sbinfo);
4f0767ce 6200+out:
1facf9fc 6201+ return err;
6202+}
6203+
6204+/* ---------------------------------------------------------------------- */
6205+
6206+void dbgaufs_fin(void)
6207+{
6208+ debugfs_remove(dbgaufs);
6209+}
6210+
6211+int __init dbgaufs_init(void)
6212+{
6213+ int err;
6214+
6215+ err = -EIO;
6216+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
6217+ if (dbgaufs)
6218+ err = 0;
6219+ return err;
6220+}
0b1ff5c3
JR
6221diff -urNp -x '*.orig' linux-4.14/fs/aufs/dbgaufs.h linux-4.14/fs/aufs/dbgaufs.h
6222--- linux-4.14/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
6223+++ linux-4.14/fs/aufs/dbgaufs.h 2021-02-24 21:42:43.441114748 +0100
523b37e3 6224@@ -0,0 +1,48 @@
1facf9fc 6225+/*
a2654f78 6226+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 6227+ *
6228+ * This program, aufs is free software; you can redistribute it and/or modify
6229+ * it under the terms of the GNU General Public License as published by
6230+ * the Free Software Foundation; either version 2 of the License, or
6231+ * (at your option) any later version.
dece6358
AM
6232+ *
6233+ * This program is distributed in the hope that it will be useful,
6234+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6235+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6236+ * GNU General Public License for more details.
6237+ *
6238+ * You should have received a copy of the GNU General Public License
523b37e3 6239+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6240+ */
6241+
6242+/*
6243+ * debugfs interface
6244+ */
6245+
6246+#ifndef __DBGAUFS_H__
6247+#define __DBGAUFS_H__
6248+
6249+#ifdef __KERNEL__
6250+
dece6358 6251+struct super_block;
1facf9fc 6252+struct au_sbinfo;
dece6358 6253+
1facf9fc 6254+#ifdef CONFIG_DEBUG_FS
6255+/* dbgaufs.c */
6256+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
6257+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
6258+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
6259+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
6260+void dbgaufs_fin(void);
6261+int __init dbgaufs_init(void);
1facf9fc 6262+#else
4a4d8108
AM
6263+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
6264+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
6265+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
6266+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
6267+AuStubVoid(dbgaufs_fin, void)
6268+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 6269+#endif /* CONFIG_DEBUG_FS */
6270+
6271+#endif /* __KERNEL__ */
6272+#endif /* __DBGAUFS_H__ */
0b1ff5c3
JR
6273diff -urNp -x '*.orig' linux-4.14/fs/aufs/dcsub.c linux-4.14/fs/aufs/dcsub.c
6274--- linux-4.14/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
6275+++ linux-4.14/fs/aufs/dcsub.c 2021-02-24 21:42:43.441114748 +0100
e2f27e51 6276@@ -0,0 +1,225 @@
1facf9fc 6277+/*
a2654f78 6278+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 6279+ *
6280+ * This program, aufs is free software; you can redistribute it and/or modify
6281+ * it under the terms of the GNU General Public License as published by
6282+ * the Free Software Foundation; either version 2 of the License, or
6283+ * (at your option) any later version.
dece6358
AM
6284+ *
6285+ * This program is distributed in the hope that it will be useful,
6286+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6287+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6288+ * GNU General Public License for more details.
6289+ *
6290+ * You should have received a copy of the GNU General Public License
523b37e3 6291+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6292+ */
6293+
6294+/*
6295+ * sub-routines for dentry cache
6296+ */
6297+
6298+#include "aufs.h"
6299+
6300+static void au_dpage_free(struct au_dpage *dpage)
6301+{
6302+ int i;
6303+ struct dentry **p;
6304+
6305+ p = dpage->dentries;
6306+ for (i = 0; i < dpage->ndentry; i++)
6307+ dput(*p++);
1c60b727 6308+ free_page((unsigned long)dpage->dentries);
1facf9fc 6309+}
6310+
6311+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
6312+{
6313+ int err;
6314+ void *p;
6315+
6316+ err = -ENOMEM;
6317+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
6318+ if (unlikely(!dpages->dpages))
6319+ goto out;
6320+
6321+ p = (void *)__get_free_page(gfp);
6322+ if (unlikely(!p))
6323+ goto out_dpages;
6324+
6325+ dpages->dpages[0].ndentry = 0;
6326+ dpages->dpages[0].dentries = p;
6327+ dpages->ndpage = 1;
6328+ return 0; /* success */
6329+
4f0767ce 6330+out_dpages:
1c60b727 6331+ kfree(dpages->dpages);
4f0767ce 6332+out:
1facf9fc 6333+ return err;
6334+}
6335+
6336+void au_dpages_free(struct au_dcsub_pages *dpages)
6337+{
6338+ int i;
6339+ struct au_dpage *p;
6340+
6341+ p = dpages->dpages;
6342+ for (i = 0; i < dpages->ndpage; i++)
6343+ au_dpage_free(p++);
1c60b727 6344+ kfree(dpages->dpages);
1facf9fc 6345+}
6346+
6347+static int au_dpages_append(struct au_dcsub_pages *dpages,
6348+ struct dentry *dentry, gfp_t gfp)
6349+{
6350+ int err, sz;
6351+ struct au_dpage *dpage;
6352+ void *p;
6353+
6354+ dpage = dpages->dpages + dpages->ndpage - 1;
6355+ sz = PAGE_SIZE / sizeof(dentry);
6356+ if (unlikely(dpage->ndentry >= sz)) {
6357+ AuLabel(new dpage);
6358+ err = -ENOMEM;
6359+ sz = dpages->ndpage * sizeof(*dpages->dpages);
6360+ p = au_kzrealloc(dpages->dpages, sz,
e2f27e51
AM
6361+ sz + sizeof(*dpages->dpages), gfp,
6362+ /*may_shrink*/0);
1facf9fc 6363+ if (unlikely(!p))
6364+ goto out;
6365+
6366+ dpages->dpages = p;
6367+ dpage = dpages->dpages + dpages->ndpage;
6368+ p = (void *)__get_free_page(gfp);
6369+ if (unlikely(!p))
6370+ goto out;
6371+
6372+ dpage->ndentry = 0;
6373+ dpage->dentries = p;
6374+ dpages->ndpage++;
6375+ }
6376+
c1595e42 6377+ AuDebugOn(au_dcount(dentry) <= 0);
027c5e7a 6378+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry);
1facf9fc 6379+ return 0; /* success */
6380+
4f0767ce 6381+out:
1facf9fc 6382+ return err;
6383+}
6384+
c1595e42
JR
6385+/* todo: BAD approach */
6386+/* copied from linux/fs/dcache.c */
6387+enum d_walk_ret {
6388+ D_WALK_CONTINUE,
6389+ D_WALK_QUIT,
6390+ D_WALK_NORETRY,
6391+ D_WALK_SKIP,
6392+};
6393+
6394+extern void d_walk(struct dentry *parent, void *data,
6395+ enum d_walk_ret (*enter)(void *, struct dentry *),
6396+ void (*finish)(void *));
6397+
6398+struct ac_dpages_arg {
1facf9fc 6399+ int err;
c1595e42
JR
6400+ struct au_dcsub_pages *dpages;
6401+ struct super_block *sb;
6402+ au_dpages_test test;
6403+ void *arg;
6404+};
1facf9fc 6405+
c1595e42
JR
6406+static enum d_walk_ret au_call_dpages_append(void *_arg, struct dentry *dentry)
6407+{
6408+ enum d_walk_ret ret;
6409+ struct ac_dpages_arg *arg = _arg;
1facf9fc 6410+
c1595e42
JR
6411+ ret = D_WALK_CONTINUE;
6412+ if (dentry->d_sb == arg->sb
6413+ && !IS_ROOT(dentry)
6414+ && au_dcount(dentry) > 0
6415+ && au_di(dentry)
6416+ && (!arg->test || arg->test(dentry, arg->arg))) {
6417+ arg->err = au_dpages_append(arg->dpages, dentry, GFP_ATOMIC);
6418+ if (unlikely(arg->err))
6419+ ret = D_WALK_QUIT;
1facf9fc 6420+ }
6421+
c1595e42
JR
6422+ return ret;
6423+}
027c5e7a 6424+
c1595e42
JR
6425+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
6426+ au_dpages_test test, void *arg)
6427+{
6428+ struct ac_dpages_arg args = {
6429+ .err = 0,
6430+ .dpages = dpages,
6431+ .sb = root->d_sb,
6432+ .test = test,
6433+ .arg = arg
6434+ };
027c5e7a 6435+
c1595e42
JR
6436+ d_walk(root, &args, au_call_dpages_append, NULL);
6437+
6438+ return args.err;
1facf9fc 6439+}
6440+
6441+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
6442+ int do_include, au_dpages_test test, void *arg)
6443+{
6444+ int err;
6445+
6446+ err = 0;
027c5e7a
AM
6447+ write_seqlock(&rename_lock);
6448+ spin_lock(&dentry->d_lock);
6449+ if (do_include
c1595e42 6450+ && au_dcount(dentry) > 0
027c5e7a 6451+ && (!test || test(dentry, arg)))
1facf9fc 6452+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
6453+ spin_unlock(&dentry->d_lock);
6454+ if (unlikely(err))
6455+ goto out;
6456+
6457+ /*
523b37e3 6458+ * RCU for vfsmount is unnecessary since this is a traverse in a single
027c5e7a
AM
6459+ * mount
6460+ */
1facf9fc 6461+ while (!IS_ROOT(dentry)) {
027c5e7a
AM
6462+ dentry = dentry->d_parent; /* rename_lock is locked */
6463+ spin_lock(&dentry->d_lock);
c1595e42 6464+ if (au_dcount(dentry) > 0
027c5e7a 6465+ && (!test || test(dentry, arg)))
1facf9fc 6466+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
6467+ spin_unlock(&dentry->d_lock);
6468+ if (unlikely(err))
6469+ break;
1facf9fc 6470+ }
6471+
4f0767ce 6472+out:
027c5e7a 6473+ write_sequnlock(&rename_lock);
1facf9fc 6474+ return err;
6475+}
6476+
027c5e7a
AM
6477+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg)
6478+{
6479+ return au_di(dentry) && dentry->d_sb == arg;
6480+}
6481+
6482+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
6483+ struct dentry *dentry, int do_include)
6484+{
6485+ return au_dcsub_pages_rev(dpages, dentry, do_include,
6486+ au_dcsub_dpages_aufs, dentry->d_sb);
6487+}
6488+
4a4d8108 6489+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 6490+{
4a4d8108
AM
6491+ struct path path[2] = {
6492+ {
6493+ .dentry = d1
6494+ },
6495+ {
6496+ .dentry = d2
6497+ }
6498+ };
1facf9fc 6499+
4a4d8108 6500+ return path_is_under(path + 0, path + 1);
1facf9fc 6501+}
0b1ff5c3
JR
6502diff -urNp -x '*.orig' linux-4.14/fs/aufs/dcsub.h linux-4.14/fs/aufs/dcsub.h
6503--- linux-4.14/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
6504+++ linux-4.14/fs/aufs/dcsub.h 2021-02-24 21:42:43.441114748 +0100
5527c038 6505@@ -0,0 +1,136 @@
1facf9fc 6506+/*
a2654f78 6507+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 6508+ *
6509+ * This program, aufs is free software; you can redistribute it and/or modify
6510+ * it under the terms of the GNU General Public License as published by
6511+ * the Free Software Foundation; either version 2 of the License, or
6512+ * (at your option) any later version.
dece6358
AM
6513+ *
6514+ * This program is distributed in the hope that it will be useful,
6515+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6516+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6517+ * GNU General Public License for more details.
6518+ *
6519+ * You should have received a copy of the GNU General Public License
523b37e3 6520+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6521+ */
6522+
6523+/*
6524+ * sub-routines for dentry cache
6525+ */
6526+
6527+#ifndef __AUFS_DCSUB_H__
6528+#define __AUFS_DCSUB_H__
6529+
6530+#ifdef __KERNEL__
6531+
7f207e10 6532+#include <linux/dcache.h>
027c5e7a 6533+#include <linux/fs.h>
dece6358 6534+
1facf9fc 6535+struct au_dpage {
6536+ int ndentry;
6537+ struct dentry **dentries;
6538+};
6539+
6540+struct au_dcsub_pages {
6541+ int ndpage;
6542+ struct au_dpage *dpages;
6543+};
6544+
6545+/* ---------------------------------------------------------------------- */
6546+
7f207e10 6547+/* dcsub.c */
1facf9fc 6548+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
6549+void au_dpages_free(struct au_dcsub_pages *dpages);
6550+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
6551+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
6552+ au_dpages_test test, void *arg);
6553+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
6554+ int do_include, au_dpages_test test, void *arg);
027c5e7a
AM
6555+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
6556+ struct dentry *dentry, int do_include);
4a4d8108 6557+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 6558+
7f207e10
AM
6559+/* ---------------------------------------------------------------------- */
6560+
523b37e3
AM
6561+/*
6562+ * todo: in linux-3.13, several similar (but faster) helpers are added to
6563+ * include/linux/dcache.h. Try them (in the future).
6564+ */
6565+
027c5e7a
AM
6566+static inline int au_d_hashed_positive(struct dentry *d)
6567+{
6568+ int err;
5527c038 6569+ struct inode *inode = d_inode(d);
076b876e 6570+
027c5e7a 6571+ err = 0;
5527c038
JR
6572+ if (unlikely(d_unhashed(d)
6573+ || d_is_negative(d)
6574+ || !inode->i_nlink))
027c5e7a
AM
6575+ err = -ENOENT;
6576+ return err;
6577+}
6578+
38d290e6
JR
6579+static inline int au_d_linkable(struct dentry *d)
6580+{
6581+ int err;
5527c038 6582+ struct inode *inode = d_inode(d);
076b876e 6583+
38d290e6
JR
6584+ err = au_d_hashed_positive(d);
6585+ if (err
5527c038 6586+ && d_is_positive(d)
38d290e6
JR
6587+ && (inode->i_state & I_LINKABLE))
6588+ err = 0;
6589+ return err;
6590+}
6591+
027c5e7a
AM
6592+static inline int au_d_alive(struct dentry *d)
6593+{
6594+ int err;
6595+ struct inode *inode;
076b876e 6596+
027c5e7a
AM
6597+ err = 0;
6598+ if (!IS_ROOT(d))
6599+ err = au_d_hashed_positive(d);
6600+ else {
5527c038
JR
6601+ inode = d_inode(d);
6602+ if (unlikely(d_unlinked(d)
6603+ || d_is_negative(d)
6604+ || !inode->i_nlink))
027c5e7a
AM
6605+ err = -ENOENT;
6606+ }
6607+ return err;
6608+}
6609+
6610+static inline int au_alive_dir(struct dentry *d)
7f207e10 6611+{
027c5e7a 6612+ int err;
076b876e 6613+
027c5e7a 6614+ err = au_d_alive(d);
5527c038 6615+ if (unlikely(err || IS_DEADDIR(d_inode(d))))
027c5e7a
AM
6616+ err = -ENOENT;
6617+ return err;
7f207e10
AM
6618+}
6619+
38d290e6
JR
6620+static inline int au_qstreq(struct qstr *a, struct qstr *b)
6621+{
6622+ return a->len == b->len
6623+ && !memcmp(a->name, b->name, a->len);
6624+}
6625+
7e9cd9fe
AM
6626+/*
6627+ * by the commit
6628+ * 360f547 2015-01-25 dcache: let the dentry count go down to zero without
6629+ * taking d_lock
6630+ * the type of d_lockref.count became int, but the inlined function d_count()
6631+ * still returns unsigned int.
6632+ * I don't know why. Maybe it is for every d_count() users?
6633+ * Anyway au_dcount() lives on.
6634+ */
c1595e42
JR
6635+static inline int au_dcount(struct dentry *d)
6636+{
6637+ return (int)d_count(d);
6638+}
6639+
1facf9fc 6640+#endif /* __KERNEL__ */
6641+#endif /* __AUFS_DCSUB_H__ */
0b1ff5c3
JR
6642diff -urNp -x '*.orig' linux-4.14/fs/aufs/debug.c linux-4.14/fs/aufs/debug.c
6643--- linux-4.14/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
6644+++ linux-4.14/fs/aufs/debug.c 2021-02-24 21:42:43.441114748 +0100
f0c0a007 6645@@ -0,0 +1,440 @@
1facf9fc 6646+/*
a2654f78 6647+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 6648+ *
6649+ * This program, aufs is free software; you can redistribute it and/or modify
6650+ * it under the terms of the GNU General Public License as published by
6651+ * the Free Software Foundation; either version 2 of the License, or
6652+ * (at your option) any later version.
dece6358
AM
6653+ *
6654+ * This program is distributed in the hope that it will be useful,
6655+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6656+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6657+ * GNU General Public License for more details.
6658+ *
6659+ * You should have received a copy of the GNU General Public License
523b37e3 6660+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6661+ */
6662+
6663+/*
6664+ * debug print functions
6665+ */
6666+
6667+#include "aufs.h"
6668+
392086de
AM
6669+/* Returns 0, or -errno. arg is in kp->arg. */
6670+static int param_atomic_t_set(const char *val, const struct kernel_param *kp)
6671+{
6672+ int err, n;
6673+
6674+ err = kstrtoint(val, 0, &n);
6675+ if (!err) {
6676+ if (n > 0)
6677+ au_debug_on();
6678+ else
6679+ au_debug_off();
6680+ }
6681+ return err;
6682+}
6683+
6684+/* Returns length written or -errno. Buffer is 4k (ie. be short!) */
6685+static int param_atomic_t_get(char *buffer, const struct kernel_param *kp)
6686+{
6687+ atomic_t *a;
6688+
6689+ a = kp->arg;
6690+ return sprintf(buffer, "%d", atomic_read(a));
6691+}
6692+
6693+static struct kernel_param_ops param_ops_atomic_t = {
6694+ .set = param_atomic_t_set,
6695+ .get = param_atomic_t_get
6696+ /* void (*free)(void *arg) */
6697+};
6698+
6699+atomic_t aufs_debug = ATOMIC_INIT(0);
1facf9fc 6700+MODULE_PARM_DESC(debug, "debug print");
392086de 6701+module_param_named(debug, aufs_debug, atomic_t, S_IRUGO | S_IWUSR | S_IWGRP);
1facf9fc 6702+
c1595e42 6703+DEFINE_MUTEX(au_dbg_mtx); /* just to serialize the dbg msgs */
1facf9fc 6704+char *au_plevel = KERN_DEBUG;
e49829fe
JR
6705+#define dpri(fmt, ...) do { \
6706+ if ((au_plevel \
6707+ && strcmp(au_plevel, KERN_DEBUG)) \
6708+ || au_debug_test()) \
6709+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 6710+} while (0)
6711+
6712+/* ---------------------------------------------------------------------- */
6713+
6714+void au_dpri_whlist(struct au_nhash *whlist)
6715+{
6716+ unsigned long ul, n;
6717+ struct hlist_head *head;
c06a8ce3 6718+ struct au_vdir_wh *pos;
1facf9fc 6719+
6720+ n = whlist->nh_num;
6721+ head = whlist->nh_head;
6722+ for (ul = 0; ul < n; ul++) {
c06a8ce3 6723+ hlist_for_each_entry(pos, head, wh_hash)
1facf9fc 6724+ dpri("b%d, %.*s, %d\n",
c06a8ce3
AM
6725+ pos->wh_bindex,
6726+ pos->wh_str.len, pos->wh_str.name,
6727+ pos->wh_str.len);
1facf9fc 6728+ head++;
6729+ }
6730+}
6731+
6732+void au_dpri_vdir(struct au_vdir *vdir)
6733+{
6734+ unsigned long ul;
6735+ union au_vdir_deblk_p p;
6736+ unsigned char *o;
6737+
6738+ if (!vdir || IS_ERR(vdir)) {
6739+ dpri("err %ld\n", PTR_ERR(vdir));
6740+ return;
6741+ }
6742+
6743+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
6744+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
6745+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
6746+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
6747+ p.deblk = vdir->vd_deblk[ul];
6748+ o = p.deblk;
6749+ dpri("[%lu]: %p\n", ul, o);
6750+ }
6751+}
6752+
53392da6 6753+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, int hn,
1facf9fc 6754+ struct dentry *wh)
6755+{
6756+ char *n = NULL;
6757+ int l = 0;
6758+
6759+ if (!inode || IS_ERR(inode)) {
6760+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
6761+ return -1;
6762+ }
6763+
c2b27bf2 6764+ /* the type of i_blocks depends upon CONFIG_LBDAF */
1facf9fc 6765+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
6766+ && sizeof(inode->i_blocks) != sizeof(u64));
6767+ if (wh) {
6768+ n = (void *)wh->d_name.name;
6769+ l = wh->d_name.len;
6770+ }
6771+
53392da6
AM
6772+ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
6773+ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
6774+ bindex, inode,
1facf9fc 6775+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
6776+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
6777+ i_size_read(inode), (unsigned long long)inode->i_blocks,
53392da6 6778+ hn, (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
1facf9fc 6779+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
b752ccd1
AM
6780+ inode->i_state, inode->i_flags, inode->i_version,
6781+ inode->i_generation,
1facf9fc 6782+ l ? ", wh " : "", l, n);
6783+ return 0;
6784+}
6785+
6786+void au_dpri_inode(struct inode *inode)
6787+{
6788+ struct au_iinfo *iinfo;
5afbbe0d 6789+ struct au_hinode *hi;
1facf9fc 6790+ aufs_bindex_t bindex;
53392da6 6791+ int err, hn;
1facf9fc 6792+
53392da6 6793+ err = do_pri_inode(-1, inode, -1, NULL);
5afbbe0d 6794+ if (err || !au_test_aufs(inode->i_sb) || au_is_bad_inode(inode))
1facf9fc 6795+ return;
6796+
6797+ iinfo = au_ii(inode);
5afbbe0d
AM
6798+ dpri("i-1: btop %d, bbot %d, gen %d\n",
6799+ iinfo->ii_btop, iinfo->ii_bbot, au_iigen(inode, NULL));
6800+ if (iinfo->ii_btop < 0)
1facf9fc 6801+ return;
53392da6 6802+ hn = 0;
5afbbe0d
AM
6803+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; bindex++) {
6804+ hi = au_hinode(iinfo, bindex);
6805+ hn = !!au_hn(hi);
6806+ do_pri_inode(bindex, hi->hi_inode, hn, hi->hi_whdentry);
53392da6 6807+ }
1facf9fc 6808+}
6809+
2cbb1c4b
JR
6810+void au_dpri_dalias(struct inode *inode)
6811+{
6812+ struct dentry *d;
6813+
6814+ spin_lock(&inode->i_lock);
c1595e42 6815+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias)
2cbb1c4b
JR
6816+ au_dpri_dentry(d);
6817+ spin_unlock(&inode->i_lock);
6818+}
6819+
1facf9fc 6820+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
6821+{
6822+ struct dentry *wh = NULL;
53392da6 6823+ int hn;
5afbbe0d 6824+ struct inode *inode;
076b876e 6825+ struct au_iinfo *iinfo;
5afbbe0d 6826+ struct au_hinode *hi;
1facf9fc 6827+
6828+ if (!dentry || IS_ERR(dentry)) {
6829+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
6830+ return -1;
6831+ }
6832+ /* do not call dget_parent() here */
027c5e7a 6833+ /* note: access d_xxx without d_lock */
523b37e3
AM
6834+ dpri("d%d: %p, %pd2?, %s, cnt %d, flags 0x%x, %shashed\n",
6835+ bindex, dentry, dentry,
1facf9fc 6836+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
c1595e42 6837+ au_dcount(dentry), dentry->d_flags,
523b37e3 6838+ d_unhashed(dentry) ? "un" : "");
53392da6 6839+ hn = -1;
5afbbe0d
AM
6840+ inode = NULL;
6841+ if (d_is_positive(dentry))
6842+ inode = d_inode(dentry);
6843+ if (inode
6844+ && au_test_aufs(dentry->d_sb)
6845+ && bindex >= 0
6846+ && !au_is_bad_inode(inode)) {
6847+ iinfo = au_ii(inode);
6848+ hi = au_hinode(iinfo, bindex);
6849+ hn = !!au_hn(hi);
6850+ wh = hi->hi_whdentry;
6851+ }
6852+ do_pri_inode(bindex, inode, hn, wh);
1facf9fc 6853+ return 0;
6854+}
6855+
6856+void au_dpri_dentry(struct dentry *dentry)
6857+{
6858+ struct au_dinfo *dinfo;
6859+ aufs_bindex_t bindex;
6860+ int err;
6861+
6862+ err = do_pri_dentry(-1, dentry);
6863+ if (err || !au_test_aufs(dentry->d_sb))
6864+ return;
6865+
6866+ dinfo = au_di(dentry);
6867+ if (!dinfo)
6868+ return;
5afbbe0d
AM
6869+ dpri("d-1: btop %d, bbot %d, bwh %d, bdiropq %d, gen %d, tmp %d\n",
6870+ dinfo->di_btop, dinfo->di_bbot,
38d290e6
JR
6871+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry),
6872+ dinfo->di_tmpfile);
5afbbe0d 6873+ if (dinfo->di_btop < 0)
1facf9fc 6874+ return;
5afbbe0d
AM
6875+ for (bindex = dinfo->di_btop; bindex <= dinfo->di_bbot; bindex++)
6876+ do_pri_dentry(bindex, au_hdentry(dinfo, bindex)->hd_dentry);
1facf9fc 6877+}
6878+
6879+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
6880+{
6881+ char a[32];
6882+
6883+ if (!file || IS_ERR(file)) {
6884+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
6885+ return -1;
6886+ }
6887+ a[0] = 0;
6888+ if (bindex < 0
b912730e 6889+ && !IS_ERR_OR_NULL(file->f_path.dentry)
2000de60 6890+ && au_test_aufs(file->f_path.dentry->d_sb)
1facf9fc 6891+ && au_fi(file))
e49829fe 6892+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
2cbb1c4b 6893+ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped));
b752ccd1 6894+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 6895+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 6896+ file->f_version, file->f_pos, a);
b912730e 6897+ if (!IS_ERR_OR_NULL(file->f_path.dentry))
2000de60 6898+ do_pri_dentry(bindex, file->f_path.dentry);
1facf9fc 6899+ return 0;
6900+}
6901+
6902+void au_dpri_file(struct file *file)
6903+{
6904+ struct au_finfo *finfo;
4a4d8108
AM
6905+ struct au_fidir *fidir;
6906+ struct au_hfile *hfile;
1facf9fc 6907+ aufs_bindex_t bindex;
6908+ int err;
6909+
6910+ err = do_pri_file(-1, file);
2000de60 6911+ if (err
b912730e 6912+ || IS_ERR_OR_NULL(file->f_path.dentry)
2000de60 6913+ || !au_test_aufs(file->f_path.dentry->d_sb))
1facf9fc 6914+ return;
6915+
6916+ finfo = au_fi(file);
6917+ if (!finfo)
6918+ return;
4a4d8108 6919+ if (finfo->fi_btop < 0)
1facf9fc 6920+ return;
4a4d8108
AM
6921+ fidir = finfo->fi_hdir;
6922+ if (!fidir)
6923+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
6924+ else
e49829fe
JR
6925+ for (bindex = finfo->fi_btop;
6926+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
6927+ bindex++) {
6928+ hfile = fidir->fd_hfile + bindex;
6929+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
6930+ }
1facf9fc 6931+}
6932+
6933+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
6934+{
6935+ struct vfsmount *mnt;
6936+ struct super_block *sb;
6937+
6938+ if (!br || IS_ERR(br))
6939+ goto out;
86dc4139 6940+ mnt = au_br_mnt(br);
1facf9fc 6941+ if (!mnt || IS_ERR(mnt))
6942+ goto out;
6943+ sb = mnt->mnt_sb;
6944+ if (!sb || IS_ERR(sb))
6945+ goto out;
6946+
5afbbe0d 6947+ dpri("s%d: {perm 0x%x, id %d, cnt %lld, wbr %p}, "
b752ccd1 6948+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 6949+ "xino %d\n",
5afbbe0d 6950+ bindex, br->br_perm, br->br_id, au_br_count(br),
1e00d052 6951+ br->br_wbr, au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 6952+ sb->s_flags, sb->s_count,
1facf9fc 6953+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
6954+ return 0;
6955+
4f0767ce 6956+out:
1facf9fc 6957+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
6958+ return -1;
6959+}
6960+
6961+void au_dpri_sb(struct super_block *sb)
6962+{
6963+ struct au_sbinfo *sbinfo;
6964+ aufs_bindex_t bindex;
6965+ int err;
6966+ /* to reuduce stack size */
6967+ struct {
6968+ struct vfsmount mnt;
6969+ struct au_branch fake;
6970+ } *a;
6971+
6972+ /* this function can be called from magic sysrq */
6973+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
6974+ if (unlikely(!a)) {
6975+ dpri("no memory\n");
6976+ return;
6977+ }
6978+
6979+ a->mnt.mnt_sb = sb;
86dc4139 6980+ a->fake.br_path.mnt = &a->mnt;
5afbbe0d 6981+ au_br_count_init(&a->fake);
1facf9fc 6982+ err = do_pri_br(-1, &a->fake);
5afbbe0d 6983+ au_br_count_fin(&a->fake);
1c60b727 6984+ kfree(a);
1facf9fc 6985+ dpri("dev 0x%x\n", sb->s_dev);
6986+ if (err || !au_test_aufs(sb))
6987+ return;
6988+
6989+ sbinfo = au_sbi(sb);
6990+ if (!sbinfo)
6991+ return;
f0c0a007
AM
6992+ dpri("nw %d, gen %u, kobj %d\n",
6993+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
521ced18 6994+ kref_read(&sbinfo->si_kobj.kref));
5afbbe0d 6995+ for (bindex = 0; bindex <= sbinfo->si_bbot; bindex++)
1facf9fc 6996+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
6997+}
6998+
6999+/* ---------------------------------------------------------------------- */
7000+
027c5e7a
AM
7001+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line)
7002+{
5527c038 7003+ struct inode *h_inode, *inode = d_inode(dentry);
027c5e7a 7004+ struct dentry *h_dentry;
5afbbe0d 7005+ aufs_bindex_t bindex, bbot, bi;
027c5e7a
AM
7006+
7007+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */)
7008+ return;
7009+
5afbbe0d
AM
7010+ bbot = au_dbbot(dentry);
7011+ bi = au_ibbot(inode);
7012+ if (bi < bbot)
7013+ bbot = bi;
7014+ bindex = au_dbtop(dentry);
7015+ bi = au_ibtop(inode);
027c5e7a
AM
7016+ if (bi > bindex)
7017+ bindex = bi;
7018+
5afbbe0d 7019+ for (; bindex <= bbot; bindex++) {
027c5e7a
AM
7020+ h_dentry = au_h_dptr(dentry, bindex);
7021+ if (!h_dentry)
7022+ continue;
7023+ h_inode = au_h_iptr(inode, bindex);
5527c038 7024+ if (unlikely(h_inode != d_inode(h_dentry))) {
392086de 7025+ au_debug_on();
027c5e7a
AM
7026+ AuDbg("b%d, %s:%d\n", bindex, func, line);
7027+ AuDbgDentry(dentry);
7028+ AuDbgInode(inode);
392086de 7029+ au_debug_off();
027c5e7a
AM
7030+ BUG();
7031+ }
7032+ }
7033+}
7034+
1facf9fc 7035+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
7036+{
7037+ int err, i, j;
7038+ struct au_dcsub_pages dpages;
7039+ struct au_dpage *dpage;
7040+ struct dentry **dentries;
7041+
7042+ err = au_dpages_init(&dpages, GFP_NOFS);
7043+ AuDebugOn(err);
027c5e7a 7044+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1);
1facf9fc 7045+ AuDebugOn(err);
7046+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
7047+ dpage = dpages.dpages + i;
7048+ dentries = dpage->dentries;
7049+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
027c5e7a 7050+ AuDebugOn(au_digen_test(dentries[j], sigen));
1facf9fc 7051+ }
7052+ au_dpages_free(&dpages);
7053+}
7054+
1facf9fc 7055+void au_dbg_verify_kthread(void)
7056+{
53392da6 7057+ if (au_wkq_test()) {
1facf9fc 7058+ au_dbg_blocked();
1e00d052
AM
7059+ /*
7060+ * It may be recursive, but udba=notify between two aufs mounts,
7061+ * where a single ro branch is shared, is not a problem.
7062+ */
7063+ /* WARN_ON(1); */
1facf9fc 7064+ }
7065+}
7066+
7067+/* ---------------------------------------------------------------------- */
7068+
1facf9fc 7069+int __init au_debug_init(void)
7070+{
7071+ aufs_bindex_t bindex;
7072+ struct au_vdir_destr destr;
7073+
7074+ bindex = -1;
7075+ AuDebugOn(bindex >= 0);
7076+
7077+ destr.len = -1;
7078+ AuDebugOn(destr.len < NAME_MAX);
7079+
7080+#ifdef CONFIG_4KSTACKS
0c3ec466 7081+ pr_warn("CONFIG_4KSTACKS is defined.\n");
1facf9fc 7082+#endif
7083+
1facf9fc 7084+ return 0;
7085+}
0b1ff5c3
JR
7086diff -urNp -x '*.orig' linux-4.14/fs/aufs/debug.h linux-4.14/fs/aufs/debug.h
7087--- linux-4.14/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
7088+++ linux-4.14/fs/aufs/debug.h 2021-02-24 21:42:43.441114748 +0100
5527c038 7089@@ -0,0 +1,225 @@
1facf9fc 7090+/*
a2654f78 7091+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 7092+ *
7093+ * This program, aufs is free software; you can redistribute it and/or modify
7094+ * it under the terms of the GNU General Public License as published by
7095+ * the Free Software Foundation; either version 2 of the License, or
7096+ * (at your option) any later version.
dece6358
AM
7097+ *
7098+ * This program is distributed in the hope that it will be useful,
7099+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7100+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7101+ * GNU General Public License for more details.
7102+ *
7103+ * You should have received a copy of the GNU General Public License
523b37e3 7104+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7105+ */
7106+
7107+/*
7108+ * debug print functions
7109+ */
7110+
7111+#ifndef __AUFS_DEBUG_H__
7112+#define __AUFS_DEBUG_H__
7113+
7114+#ifdef __KERNEL__
7115+
392086de 7116+#include <linux/atomic.h>
4a4d8108
AM
7117+#include <linux/module.h>
7118+#include <linux/kallsyms.h>
1facf9fc 7119+#include <linux/sysrq.h>
4a4d8108 7120+
1facf9fc 7121+#ifdef CONFIG_AUFS_DEBUG
7122+#define AuDebugOn(a) BUG_ON(a)
7123+
7124+/* module parameter */
392086de
AM
7125+extern atomic_t aufs_debug;
7126+static inline void au_debug_on(void)
1facf9fc 7127+{
392086de
AM
7128+ atomic_inc(&aufs_debug);
7129+}
7130+static inline void au_debug_off(void)
7131+{
7132+ atomic_dec_if_positive(&aufs_debug);
1facf9fc 7133+}
7134+
7135+static inline int au_debug_test(void)
7136+{
392086de 7137+ return atomic_read(&aufs_debug) > 0;
1facf9fc 7138+}
7139+#else
7140+#define AuDebugOn(a) do {} while (0)
392086de
AM
7141+AuStubVoid(au_debug_on, void)
7142+AuStubVoid(au_debug_off, void)
4a4d8108 7143+AuStubInt0(au_debug_test, void)
1facf9fc 7144+#endif /* CONFIG_AUFS_DEBUG */
7145+
392086de
AM
7146+#define param_check_atomic_t(name, p) __param_check(name, p, atomic_t)
7147+
1facf9fc 7148+/* ---------------------------------------------------------------------- */
7149+
7150+/* debug print */
7151+
4a4d8108 7152+#define AuDbg(fmt, ...) do { \
1facf9fc 7153+ if (au_debug_test()) \
4a4d8108 7154+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 7155+} while (0)
4a4d8108
AM
7156+#define AuLabel(l) AuDbg(#l "\n")
7157+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
7158+#define AuWarn1(fmt, ...) do { \
1facf9fc 7159+ static unsigned char _c; \
7160+ if (!_c++) \
0c3ec466 7161+ pr_warn(fmt, ##__VA_ARGS__); \
1facf9fc 7162+} while (0)
7163+
4a4d8108 7164+#define AuErr1(fmt, ...) do { \
1facf9fc 7165+ static unsigned char _c; \
7166+ if (!_c++) \
4a4d8108 7167+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 7168+} while (0)
7169+
4a4d8108 7170+#define AuIOErr1(fmt, ...) do { \
1facf9fc 7171+ static unsigned char _c; \
7172+ if (!_c++) \
4a4d8108 7173+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 7174+} while (0)
7175+
7176+#define AuUnsupportMsg "This operation is not supported." \
7177+ " Please report this application to aufs-users ML."
4a4d8108
AM
7178+#define AuUnsupport(fmt, ...) do { \
7179+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 7180+ dump_stack(); \
7181+} while (0)
7182+
7183+#define AuTraceErr(e) do { \
7184+ if (unlikely((e) < 0)) \
7185+ AuDbg("err %d\n", (int)(e)); \
7186+} while (0)
7187+
7188+#define AuTraceErrPtr(p) do { \
7189+ if (IS_ERR(p)) \
7190+ AuDbg("err %ld\n", PTR_ERR(p)); \
7191+} while (0)
7192+
7193+/* dirty macros for debug print, use with "%.*s" and caution */
7194+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
1facf9fc 7195+
7196+/* ---------------------------------------------------------------------- */
7197+
dece6358 7198+struct dentry;
1facf9fc 7199+#ifdef CONFIG_AUFS_DEBUG
c1595e42 7200+extern struct mutex au_dbg_mtx;
1facf9fc 7201+extern char *au_plevel;
7202+struct au_nhash;
7203+void au_dpri_whlist(struct au_nhash *whlist);
7204+struct au_vdir;
7205+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 7206+struct inode;
1facf9fc 7207+void au_dpri_inode(struct inode *inode);
2cbb1c4b 7208+void au_dpri_dalias(struct inode *inode);
1facf9fc 7209+void au_dpri_dentry(struct dentry *dentry);
dece6358 7210+struct file;
1facf9fc 7211+void au_dpri_file(struct file *filp);
dece6358 7212+struct super_block;
1facf9fc 7213+void au_dpri_sb(struct super_block *sb);
7214+
027c5e7a
AM
7215+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__)
7216+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
1facf9fc 7217+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 7218+void au_dbg_verify_kthread(void);
7219+
7220+int __init au_debug_init(void);
7e9cd9fe 7221+
1facf9fc 7222+#define AuDbgWhlist(w) do { \
c1595e42 7223+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7224+ AuDbg(#w "\n"); \
7225+ au_dpri_whlist(w); \
c1595e42 7226+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7227+} while (0)
7228+
7229+#define AuDbgVdir(v) do { \
c1595e42 7230+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7231+ AuDbg(#v "\n"); \
7232+ au_dpri_vdir(v); \
c1595e42 7233+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7234+} while (0)
7235+
7236+#define AuDbgInode(i) do { \
c1595e42 7237+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7238+ AuDbg(#i "\n"); \
7239+ au_dpri_inode(i); \
c1595e42 7240+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7241+} while (0)
7242+
2cbb1c4b 7243+#define AuDbgDAlias(i) do { \
c1595e42 7244+ mutex_lock(&au_dbg_mtx); \
2cbb1c4b
JR
7245+ AuDbg(#i "\n"); \
7246+ au_dpri_dalias(i); \
c1595e42 7247+ mutex_unlock(&au_dbg_mtx); \
2cbb1c4b
JR
7248+} while (0)
7249+
1facf9fc 7250+#define AuDbgDentry(d) do { \
c1595e42 7251+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7252+ AuDbg(#d "\n"); \
7253+ au_dpri_dentry(d); \
c1595e42 7254+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7255+} while (0)
7256+
7257+#define AuDbgFile(f) do { \
c1595e42 7258+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7259+ AuDbg(#f "\n"); \
7260+ au_dpri_file(f); \
c1595e42 7261+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7262+} while (0)
7263+
7264+#define AuDbgSb(sb) do { \
c1595e42 7265+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7266+ AuDbg(#sb "\n"); \
7267+ au_dpri_sb(sb); \
c1595e42 7268+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7269+} while (0)
7270+
4a4d8108
AM
7271+#define AuDbgSym(addr) do { \
7272+ char sym[KSYM_SYMBOL_LEN]; \
7273+ sprint_symbol(sym, (unsigned long)addr); \
7274+ AuDbg("%s\n", sym); \
7275+} while (0)
1facf9fc 7276+#else
027c5e7a 7277+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry)
4a4d8108
AM
7278+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
7279+AuStubVoid(au_dbg_verify_kthread, void)
7280+AuStubInt0(__init au_debug_init, void)
1facf9fc 7281+
1facf9fc 7282+#define AuDbgWhlist(w) do {} while (0)
7283+#define AuDbgVdir(v) do {} while (0)
7284+#define AuDbgInode(i) do {} while (0)
2cbb1c4b 7285+#define AuDbgDAlias(i) do {} while (0)
1facf9fc 7286+#define AuDbgDentry(d) do {} while (0)
7287+#define AuDbgFile(f) do {} while (0)
7288+#define AuDbgSb(sb) do {} while (0)
4a4d8108 7289+#define AuDbgSym(addr) do {} while (0)
1facf9fc 7290+#endif /* CONFIG_AUFS_DEBUG */
7291+
7292+/* ---------------------------------------------------------------------- */
7293+
7294+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
7295+int __init au_sysrq_init(void);
7296+void au_sysrq_fin(void);
7297+
7298+#ifdef CONFIG_HW_CONSOLE
7299+#define au_dbg_blocked() do { \
7300+ WARN_ON(1); \
0c5527e5 7301+ handle_sysrq('w'); \
1facf9fc 7302+} while (0)
7303+#else
4a4d8108 7304+AuStubVoid(au_dbg_blocked, void)
1facf9fc 7305+#endif
7306+
7307+#else
4a4d8108
AM
7308+AuStubInt0(__init au_sysrq_init, void)
7309+AuStubVoid(au_sysrq_fin, void)
7310+AuStubVoid(au_dbg_blocked, void)
1facf9fc 7311+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
7312+
7313+#endif /* __KERNEL__ */
7314+#endif /* __AUFS_DEBUG_H__ */
0b1ff5c3
JR
7315diff -urNp -x '*.orig' linux-4.14/fs/aufs/dentry.c linux-4.14/fs/aufs/dentry.c
7316--- linux-4.14/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
7317+++ linux-4.14/fs/aufs/dentry.c 2021-02-24 21:42:43.441114748 +0100
8b6a4947 7318@@ -0,0 +1,1152 @@
1facf9fc 7319+/*
a2654f78 7320+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 7321+ *
7322+ * This program, aufs is free software; you can redistribute it and/or modify
7323+ * it under the terms of the GNU General Public License as published by
7324+ * the Free Software Foundation; either version 2 of the License, or
7325+ * (at your option) any later version.
dece6358
AM
7326+ *
7327+ * This program is distributed in the hope that it will be useful,
7328+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7329+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7330+ * GNU General Public License for more details.
7331+ *
7332+ * You should have received a copy of the GNU General Public License
523b37e3 7333+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7334+ */
7335+
7336+/*
7337+ * lookup and dentry operations
7338+ */
7339+
dece6358 7340+#include <linux/namei.h>
1facf9fc 7341+#include "aufs.h"
7342+
1facf9fc 7343+/*
7344+ * returns positive/negative dentry, NULL or an error.
7345+ * NULL means whiteout-ed or not-found.
7346+ */
7347+static struct dentry*
7348+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
8b6a4947 7349+ aufs_bindex_t bindex, struct au_do_lookup_args *args)
1facf9fc 7350+{
7351+ struct dentry *h_dentry;
2000de60 7352+ struct inode *h_inode;
1facf9fc 7353+ struct au_branch *br;
7354+ int wh_found, opq;
7355+ unsigned char wh_able;
7356+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
076b876e
AM
7357+ const unsigned char ignore_perm = !!au_ftest_lkup(args->flags,
7358+ IGNORE_PERM);
1facf9fc 7359+
1facf9fc 7360+ wh_found = 0;
7361+ br = au_sbr(dentry->d_sb, bindex);
7362+ wh_able = !!au_br_whable(br->br_perm);
7363+ if (wh_able)
8b6a4947 7364+ wh_found = au_wh_test(h_parent, &args->whname, ignore_perm);
1facf9fc 7365+ h_dentry = ERR_PTR(wh_found);
7366+ if (!wh_found)
7367+ goto real_lookup;
7368+ if (unlikely(wh_found < 0))
7369+ goto out;
7370+
7371+ /* We found a whiteout */
5afbbe0d 7372+ /* au_set_dbbot(dentry, bindex); */
1facf9fc 7373+ au_set_dbwh(dentry, bindex);
7374+ if (!allow_neg)
7375+ return NULL; /* success */
7376+
4f0767ce 7377+real_lookup:
076b876e 7378+ if (!ignore_perm)
8b6a4947 7379+ h_dentry = vfsub_lkup_one(args->name, h_parent);
076b876e 7380+ else
8b6a4947 7381+ h_dentry = au_sio_lkup_one(args->name, h_parent);
2000de60
JR
7382+ if (IS_ERR(h_dentry)) {
7383+ if (PTR_ERR(h_dentry) == -ENAMETOOLONG
7384+ && !allow_neg)
7385+ h_dentry = NULL;
1facf9fc 7386+ goto out;
2000de60 7387+ }
1facf9fc 7388+
5527c038
JR
7389+ h_inode = d_inode(h_dentry);
7390+ if (d_is_negative(h_dentry)) {
1facf9fc 7391+ if (!allow_neg)
7392+ goto out_neg;
7393+ } else if (wh_found
7394+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
7395+ goto out_neg;
8b6a4947
AM
7396+ else if (au_ftest_lkup(args->flags, DIRREN)
7397+ /* && h_inode */
7398+ && !au_dr_lkup_h_ino(args, bindex, h_inode->i_ino)) {
7399+ AuDbg("b%d %pd ignored hi%llu\n", bindex, h_dentry,
7400+ (unsigned long long)h_inode->i_ino);
7401+ goto out_neg;
7402+ }
1facf9fc 7403+
5afbbe0d
AM
7404+ if (au_dbbot(dentry) <= bindex)
7405+ au_set_dbbot(dentry, bindex);
7406+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry))
7407+ au_set_dbtop(dentry, bindex);
1facf9fc 7408+ au_set_h_dptr(dentry, bindex, h_dentry);
7409+
2000de60
JR
7410+ if (!d_is_dir(h_dentry)
7411+ || !wh_able
5527c038 7412+ || (d_really_is_positive(dentry) && !d_is_dir(dentry)))
1facf9fc 7413+ goto out; /* success */
7414+
3c1bdaff 7415+ vfsub_inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
076b876e 7416+ opq = au_diropq_test(h_dentry);
3c1bdaff 7417+ inode_unlock_shared(h_inode);
1facf9fc 7418+ if (opq > 0)
7419+ au_set_dbdiropq(dentry, bindex);
7420+ else if (unlikely(opq < 0)) {
7421+ au_set_h_dptr(dentry, bindex, NULL);
7422+ h_dentry = ERR_PTR(opq);
7423+ }
7424+ goto out;
7425+
4f0767ce 7426+out_neg:
1facf9fc 7427+ dput(h_dentry);
7428+ h_dentry = NULL;
4f0767ce 7429+out:
1facf9fc 7430+ return h_dentry;
7431+}
7432+
dece6358
AM
7433+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
7434+{
7435+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
7436+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
7437+ return -EPERM;
7438+ return 0;
7439+}
7440+
1facf9fc 7441+/*
7442+ * returns the number of lower positive dentries,
7443+ * otherwise an error.
7444+ * can be called at unlinking with @type is zero.
7445+ */
5afbbe0d
AM
7446+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
7447+ unsigned int flags)
1facf9fc 7448+{
7449+ int npositive, err;
7450+ aufs_bindex_t bindex, btail, bdiropq;
8b6a4947 7451+ unsigned char isdir, dirperm1, dirren;
1facf9fc 7452+ struct au_do_lookup_args args = {
8b6a4947
AM
7453+ .flags = flags,
7454+ .name = &dentry->d_name
1facf9fc 7455+ };
1facf9fc 7456+ struct dentry *parent;
076b876e 7457+ struct super_block *sb;
1facf9fc 7458+
076b876e 7459+ sb = dentry->d_sb;
8b6a4947 7460+ err = au_test_shwh(sb, args.name);
dece6358 7461+ if (unlikely(err))
1facf9fc 7462+ goto out;
7463+
8b6a4947 7464+ err = au_wh_name_alloc(&args.whname, args.name);
1facf9fc 7465+ if (unlikely(err))
7466+ goto out;
7467+
2000de60 7468+ isdir = !!d_is_dir(dentry);
076b876e 7469+ dirperm1 = !!au_opt_test(au_mntflags(sb), DIRPERM1);
8b6a4947
AM
7470+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN);
7471+ if (dirren)
7472+ au_fset_lkup(args.flags, DIRREN);
1facf9fc 7473+
7474+ npositive = 0;
4a4d8108 7475+ parent = dget_parent(dentry);
1facf9fc 7476+ btail = au_dbtaildir(parent);
5afbbe0d 7477+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 7478+ struct dentry *h_parent, *h_dentry;
7479+ struct inode *h_inode, *h_dir;
8b6a4947 7480+ struct au_branch *br;
1facf9fc 7481+
7482+ h_dentry = au_h_dptr(dentry, bindex);
7483+ if (h_dentry) {
5527c038 7484+ if (d_is_positive(h_dentry))
1facf9fc 7485+ npositive++;
5afbbe0d 7486+ break;
1facf9fc 7487+ }
7488+ h_parent = au_h_dptr(parent, bindex);
2000de60 7489+ if (!h_parent || !d_is_dir(h_parent))
1facf9fc 7490+ continue;
7491+
8b6a4947
AM
7492+ if (dirren) {
7493+ /* if the inum matches, then use the prepared name */
7494+ err = au_dr_lkup_name(&args, bindex);
7495+ if (unlikely(err))
7496+ goto out_parent;
7497+ }
7498+
5527c038 7499+ h_dir = d_inode(h_parent);
3c1bdaff 7500+ vfsub_inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
8b6a4947 7501+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &args);
3c1bdaff 7502+ inode_unlock_shared(h_dir);
1facf9fc 7503+ err = PTR_ERR(h_dentry);
7504+ if (IS_ERR(h_dentry))
4a4d8108 7505+ goto out_parent;
2000de60
JR
7506+ if (h_dentry)
7507+ au_fclr_lkup(args.flags, ALLOW_NEG);
076b876e
AM
7508+ if (dirperm1)
7509+ au_fset_lkup(args.flags, IGNORE_PERM);
1facf9fc 7510+
79b8bda9 7511+ if (au_dbwh(dentry) == bindex)
1facf9fc 7512+ break;
7513+ if (!h_dentry)
7514+ continue;
5527c038 7515+ if (d_is_negative(h_dentry))
1facf9fc 7516+ continue;
5527c038 7517+ h_inode = d_inode(h_dentry);
1facf9fc 7518+ npositive++;
7519+ if (!args.type)
7520+ args.type = h_inode->i_mode & S_IFMT;
7521+ if (args.type != S_IFDIR)
7522+ break;
7523+ else if (isdir) {
7524+ /* the type of lower may be different */
7525+ bdiropq = au_dbdiropq(dentry);
7526+ if (bdiropq >= 0 && bdiropq <= bindex)
7527+ break;
7528+ }
8b6a4947
AM
7529+ br = au_sbr(sb, bindex);
7530+ if (dirren
7531+ && au_dr_hino_test_add(&br->br_dirren, h_inode->i_ino,
7532+ /*add_ent*/NULL)) {
7533+ /* prepare next name to lookup */
7534+ err = au_dr_lkup(&args, dentry, bindex);
7535+ if (unlikely(err))
7536+ goto out_parent;
7537+ }
1facf9fc 7538+ }
7539+
7540+ if (npositive) {
7541+ AuLabel(positive);
5afbbe0d 7542+ au_update_dbtop(dentry);
1facf9fc 7543+ }
7544+ err = npositive;
076b876e 7545+ if (unlikely(!au_opt_test(au_mntflags(sb), UDBA_NONE)
5afbbe0d 7546+ && au_dbtop(dentry) < 0)) {
1facf9fc 7547+ err = -EIO;
523b37e3
AM
7548+ AuIOErr("both of real entry and whiteout found, %pd, err %d\n",
7549+ dentry, err);
027c5e7a 7550+ }
1facf9fc 7551+
4f0767ce 7552+out_parent:
4a4d8108 7553+ dput(parent);
8b6a4947
AM
7554+ kfree(args.whname.name);
7555+ if (dirren)
7556+ au_dr_lkup_fin(&args);
4f0767ce 7557+out:
1facf9fc 7558+ return err;
7559+}
7560+
076b876e 7561+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent)
1facf9fc 7562+{
7563+ struct dentry *dentry;
7564+ int wkq_err;
7565+
5527c038 7566+ if (!au_test_h_perm_sio(d_inode(parent), MAY_EXEC))
b4510431 7567+ dentry = vfsub_lkup_one(name, parent);
1facf9fc 7568+ else {
b4510431
AM
7569+ struct vfsub_lkup_one_args args = {
7570+ .errp = &dentry,
7571+ .name = name,
7572+ .parent = parent
1facf9fc 7573+ };
7574+
b4510431 7575+ wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args);
1facf9fc 7576+ if (unlikely(wkq_err))
7577+ dentry = ERR_PTR(wkq_err);
7578+ }
7579+
7580+ return dentry;
7581+}
7582+
7583+/*
7584+ * lookup @dentry on @bindex which should be negative.
7585+ */
86dc4139 7586+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh)
1facf9fc 7587+{
7588+ int err;
7589+ struct dentry *parent, *h_parent, *h_dentry;
86dc4139 7590+ struct au_branch *br;
1facf9fc 7591+
1facf9fc 7592+ parent = dget_parent(dentry);
7593+ h_parent = au_h_dptr(parent, bindex);
86dc4139
AM
7594+ br = au_sbr(dentry->d_sb, bindex);
7595+ if (wh)
7596+ h_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
7597+ else
076b876e 7598+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent);
1facf9fc 7599+ err = PTR_ERR(h_dentry);
7600+ if (IS_ERR(h_dentry))
7601+ goto out;
5527c038 7602+ if (unlikely(d_is_positive(h_dentry))) {
1facf9fc 7603+ err = -EIO;
523b37e3 7604+ AuIOErr("%pd should be negative on b%d.\n", h_dentry, bindex);
1facf9fc 7605+ dput(h_dentry);
7606+ goto out;
7607+ }
7608+
4a4d8108 7609+ err = 0;
5afbbe0d
AM
7610+ if (bindex < au_dbtop(dentry))
7611+ au_set_dbtop(dentry, bindex);
7612+ if (au_dbbot(dentry) < bindex)
7613+ au_set_dbbot(dentry, bindex);
1facf9fc 7614+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 7615+
4f0767ce 7616+out:
1facf9fc 7617+ dput(parent);
7618+ return err;
7619+}
7620+
7621+/* ---------------------------------------------------------------------- */
7622+
7623+/* subset of struct inode */
7624+struct au_iattr {
7625+ unsigned long i_ino;
7626+ /* unsigned int i_nlink; */
0c3ec466
AM
7627+ kuid_t i_uid;
7628+ kgid_t i_gid;
1facf9fc 7629+ u64 i_version;
7630+/*
7631+ loff_t i_size;
7632+ blkcnt_t i_blocks;
7633+*/
7634+ umode_t i_mode;
7635+};
7636+
7637+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
7638+{
7639+ ia->i_ino = h_inode->i_ino;
7640+ /* ia->i_nlink = h_inode->i_nlink; */
7641+ ia->i_uid = h_inode->i_uid;
7642+ ia->i_gid = h_inode->i_gid;
7643+ ia->i_version = h_inode->i_version;
7644+/*
7645+ ia->i_size = h_inode->i_size;
7646+ ia->i_blocks = h_inode->i_blocks;
7647+*/
7648+ ia->i_mode = (h_inode->i_mode & S_IFMT);
7649+}
7650+
7651+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
7652+{
7653+ return ia->i_ino != h_inode->i_ino
7654+ /* || ia->i_nlink != h_inode->i_nlink */
0c3ec466 7655+ || !uid_eq(ia->i_uid, h_inode->i_uid)
2dfbb274 7656+ || !gid_eq(ia->i_gid, h_inode->i_gid)
1facf9fc 7657+ || ia->i_version != h_inode->i_version
7658+/*
7659+ || ia->i_size != h_inode->i_size
7660+ || ia->i_blocks != h_inode->i_blocks
7661+*/
7662+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
7663+}
7664+
7665+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
7666+ struct au_branch *br)
7667+{
7668+ int err;
7669+ struct au_iattr ia;
7670+ struct inode *h_inode;
7671+ struct dentry *h_d;
7672+ struct super_block *h_sb;
7673+
7674+ err = 0;
7675+ memset(&ia, -1, sizeof(ia));
7676+ h_sb = h_dentry->d_sb;
5527c038
JR
7677+ h_inode = NULL;
7678+ if (d_is_positive(h_dentry)) {
7679+ h_inode = d_inode(h_dentry);
1facf9fc 7680+ au_iattr_save(&ia, h_inode);
5527c038 7681+ } else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
1facf9fc 7682+ /* nfs d_revalidate may return 0 for negative dentry */
7683+ /* fuse d_revalidate always return 0 for negative dentry */
7684+ goto out;
7685+
7686+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
b4510431 7687+ h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent);
1facf9fc 7688+ err = PTR_ERR(h_d);
7689+ if (IS_ERR(h_d))
7690+ goto out;
7691+
7692+ err = 0;
7693+ if (unlikely(h_d != h_dentry
5527c038 7694+ || d_inode(h_d) != h_inode
1facf9fc 7695+ || (h_inode && au_iattr_test(&ia, h_inode))))
7696+ err = au_busy_or_stale();
7697+ dput(h_d);
7698+
4f0767ce 7699+out:
1facf9fc 7700+ AuTraceErr(err);
7701+ return err;
7702+}
7703+
7704+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
7705+ struct dentry *h_parent, struct au_branch *br)
7706+{
7707+ int err;
7708+
7709+ err = 0;
027c5e7a
AM
7710+ if (udba == AuOpt_UDBA_REVAL
7711+ && !au_test_fs_remote(h_dentry->d_sb)) {
1facf9fc 7712+ IMustLock(h_dir);
5527c038 7713+ err = (d_inode(h_dentry->d_parent) != h_dir);
027c5e7a 7714+ } else if (udba != AuOpt_UDBA_NONE)
1facf9fc 7715+ err = au_h_verify_dentry(h_dentry, h_parent, br);
7716+
7717+ return err;
7718+}
7719+
7720+/* ---------------------------------------------------------------------- */
7721+
027c5e7a 7722+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent)
1facf9fc 7723+{
027c5e7a 7724+ int err;
5afbbe0d 7725+ aufs_bindex_t new_bindex, bindex, bbot, bwh, bdiropq;
027c5e7a
AM
7726+ struct au_hdentry tmp, *p, *q;
7727+ struct au_dinfo *dinfo;
7728+ struct super_block *sb;
1facf9fc 7729+
027c5e7a 7730+ DiMustWriteLock(dentry);
1308ab2a 7731+
027c5e7a
AM
7732+ sb = dentry->d_sb;
7733+ dinfo = au_di(dentry);
5afbbe0d 7734+ bbot = dinfo->di_bbot;
1facf9fc 7735+ bwh = dinfo->di_bwh;
7736+ bdiropq = dinfo->di_bdiropq;
5afbbe0d
AM
7737+ bindex = dinfo->di_btop;
7738+ p = au_hdentry(dinfo, bindex);
7739+ for (; bindex <= bbot; bindex++, p++) {
027c5e7a 7740+ if (!p->hd_dentry)
1facf9fc 7741+ continue;
7742+
027c5e7a
AM
7743+ new_bindex = au_br_index(sb, p->hd_id);
7744+ if (new_bindex == bindex)
1facf9fc 7745+ continue;
1facf9fc 7746+
1facf9fc 7747+ if (dinfo->di_bwh == bindex)
7748+ bwh = new_bindex;
7749+ if (dinfo->di_bdiropq == bindex)
7750+ bdiropq = new_bindex;
7751+ if (new_bindex < 0) {
7752+ au_hdput(p);
7753+ p->hd_dentry = NULL;
7754+ continue;
7755+ }
7756+
7757+ /* swap two lower dentries, and loop again */
5afbbe0d 7758+ q = au_hdentry(dinfo, new_bindex);
1facf9fc 7759+ tmp = *q;
7760+ *q = *p;
7761+ *p = tmp;
7762+ if (tmp.hd_dentry) {
7763+ bindex--;
7764+ p--;
7765+ }
7766+ }
7767+
1facf9fc 7768+ dinfo->di_bwh = -1;
5afbbe0d 7769+ if (bwh >= 0 && bwh <= au_sbbot(sb) && au_sbr_whable(sb, bwh))
1facf9fc 7770+ dinfo->di_bwh = bwh;
7771+
7772+ dinfo->di_bdiropq = -1;
7773+ if (bdiropq >= 0
5afbbe0d 7774+ && bdiropq <= au_sbbot(sb)
1facf9fc 7775+ && au_sbr_whable(sb, bdiropq))
7776+ dinfo->di_bdiropq = bdiropq;
7777+
027c5e7a 7778+ err = -EIO;
5afbbe0d
AM
7779+ dinfo->di_btop = -1;
7780+ dinfo->di_bbot = -1;
7781+ bbot = au_dbbot(parent);
7782+ bindex = 0;
7783+ p = au_hdentry(dinfo, bindex);
7784+ for (; bindex <= bbot; bindex++, p++)
1facf9fc 7785+ if (p->hd_dentry) {
5afbbe0d 7786+ dinfo->di_btop = bindex;
1facf9fc 7787+ break;
7788+ }
7789+
5afbbe0d
AM
7790+ if (dinfo->di_btop >= 0) {
7791+ bindex = bbot;
7792+ p = au_hdentry(dinfo, bindex);
7793+ for (; bindex >= 0; bindex--, p--)
027c5e7a 7794+ if (p->hd_dentry) {
5afbbe0d 7795+ dinfo->di_bbot = bindex;
027c5e7a
AM
7796+ err = 0;
7797+ break;
7798+ }
7799+ }
7800+
7801+ return err;
1facf9fc 7802+}
7803+
027c5e7a 7804+static void au_do_hide(struct dentry *dentry)
1facf9fc 7805+{
027c5e7a 7806+ struct inode *inode;
1facf9fc 7807+
5527c038
JR
7808+ if (d_really_is_positive(dentry)) {
7809+ inode = d_inode(dentry);
7810+ if (!d_is_dir(dentry)) {
027c5e7a
AM
7811+ if (inode->i_nlink && !d_unhashed(dentry))
7812+ drop_nlink(inode);
7813+ } else {
7814+ clear_nlink(inode);
7815+ /* stop next lookup */
7816+ inode->i_flags |= S_DEAD;
7817+ }
7818+ smp_mb(); /* necessary? */
7819+ }
7820+ d_drop(dentry);
7821+}
1308ab2a 7822+
027c5e7a
AM
7823+static int au_hide_children(struct dentry *parent)
7824+{
7825+ int err, i, j, ndentry;
7826+ struct au_dcsub_pages dpages;
7827+ struct au_dpage *dpage;
7828+ struct dentry *dentry;
1facf9fc 7829+
027c5e7a 7830+ err = au_dpages_init(&dpages, GFP_NOFS);
1facf9fc 7831+ if (unlikely(err))
7832+ goto out;
027c5e7a
AM
7833+ err = au_dcsub_pages(&dpages, parent, NULL, NULL);
7834+ if (unlikely(err))
7835+ goto out_dpages;
1facf9fc 7836+
027c5e7a
AM
7837+ /* in reverse order */
7838+ for (i = dpages.ndpage - 1; i >= 0; i--) {
7839+ dpage = dpages.dpages + i;
7840+ ndentry = dpage->ndentry;
7841+ for (j = ndentry - 1; j >= 0; j--) {
7842+ dentry = dpage->dentries[j];
7843+ if (dentry != parent)
7844+ au_do_hide(dentry);
7845+ }
7846+ }
1facf9fc 7847+
027c5e7a
AM
7848+out_dpages:
7849+ au_dpages_free(&dpages);
4f0767ce 7850+out:
027c5e7a 7851+ return err;
1facf9fc 7852+}
7853+
027c5e7a 7854+static void au_hide(struct dentry *dentry)
1facf9fc 7855+{
027c5e7a 7856+ int err;
1facf9fc 7857+
027c5e7a 7858+ AuDbgDentry(dentry);
2000de60 7859+ if (d_is_dir(dentry)) {
027c5e7a
AM
7860+ /* shrink_dcache_parent(dentry); */
7861+ err = au_hide_children(dentry);
7862+ if (unlikely(err))
523b37e3
AM
7863+ AuIOErr("%pd, failed hiding children, ignored %d\n",
7864+ dentry, err);
027c5e7a
AM
7865+ }
7866+ au_do_hide(dentry);
7867+}
1facf9fc 7868+
027c5e7a
AM
7869+/*
7870+ * By adding a dirty branch, a cached dentry may be affected in various ways.
7871+ *
7872+ * a dirty branch is added
7873+ * - on the top of layers
7874+ * - in the middle of layers
7875+ * - to the bottom of layers
7876+ *
7877+ * on the added branch there exists
7878+ * - a whiteout
7879+ * - a diropq
7880+ * - a same named entry
7881+ * + exist
7882+ * * negative --> positive
7883+ * * positive --> positive
7884+ * - type is unchanged
7885+ * - type is changed
7886+ * + doesn't exist
7887+ * * negative --> negative
7888+ * * positive --> negative (rejected by au_br_del() for non-dir case)
7889+ * - none
7890+ */
7891+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo,
7892+ struct au_dinfo *tmp)
7893+{
7894+ int err;
5afbbe0d 7895+ aufs_bindex_t bindex, bbot;
027c5e7a
AM
7896+ struct {
7897+ struct dentry *dentry;
7898+ struct inode *inode;
7899+ mode_t mode;
be52b249
AM
7900+ } orig_h, tmp_h = {
7901+ .dentry = NULL
7902+ };
027c5e7a
AM
7903+ struct au_hdentry *hd;
7904+ struct inode *inode, *h_inode;
7905+ struct dentry *h_dentry;
7906+
7907+ err = 0;
5afbbe0d 7908+ AuDebugOn(dinfo->di_btop < 0);
027c5e7a 7909+ orig_h.mode = 0;
5afbbe0d 7910+ orig_h.dentry = au_hdentry(dinfo, dinfo->di_btop)->hd_dentry;
5527c038
JR
7911+ orig_h.inode = NULL;
7912+ if (d_is_positive(orig_h.dentry)) {
7913+ orig_h.inode = d_inode(orig_h.dentry);
027c5e7a 7914+ orig_h.mode = orig_h.inode->i_mode & S_IFMT;
5527c038 7915+ }
5afbbe0d
AM
7916+ if (tmp->di_btop >= 0) {
7917+ tmp_h.dentry = au_hdentry(tmp, tmp->di_btop)->hd_dentry;
5527c038
JR
7918+ if (d_is_positive(tmp_h.dentry)) {
7919+ tmp_h.inode = d_inode(tmp_h.dentry);
027c5e7a 7920+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT;
5527c038 7921+ }
027c5e7a
AM
7922+ }
7923+
5527c038
JR
7924+ inode = NULL;
7925+ if (d_really_is_positive(dentry))
7926+ inode = d_inode(dentry);
027c5e7a
AM
7927+ if (!orig_h.inode) {
7928+ AuDbg("nagative originally\n");
7929+ if (inode) {
7930+ au_hide(dentry);
7931+ goto out;
7932+ }
7933+ AuDebugOn(inode);
5afbbe0d 7934+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot);
027c5e7a
AM
7935+ AuDebugOn(dinfo->di_bdiropq != -1);
7936+
7937+ if (!tmp_h.inode) {
7938+ AuDbg("negative --> negative\n");
7939+ /* should have only one negative lower */
5afbbe0d
AM
7940+ if (tmp->di_btop >= 0
7941+ && tmp->di_btop < dinfo->di_btop) {
7942+ AuDebugOn(tmp->di_btop != tmp->di_bbot);
7943+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot);
7944+ au_set_h_dptr(dentry, dinfo->di_btop, NULL);
027c5e7a 7945+ au_di_cp(dinfo, tmp);
5afbbe0d
AM
7946+ hd = au_hdentry(tmp, tmp->di_btop);
7947+ au_set_h_dptr(dentry, tmp->di_btop,
027c5e7a
AM
7948+ dget(hd->hd_dentry));
7949+ }
7950+ au_dbg_verify_dinode(dentry);
7951+ } else {
7952+ AuDbg("negative --> positive\n");
7953+ /*
7954+ * similar to the behaviour of creating with bypassing
7955+ * aufs.
7956+ * unhash it in order to force an error in the
7957+ * succeeding create operation.
7958+ * we should not set S_DEAD here.
7959+ */
7960+ d_drop(dentry);
7961+ /* au_di_swap(tmp, dinfo); */
7962+ au_dbg_verify_dinode(dentry);
7963+ }
7964+ } else {
7965+ AuDbg("positive originally\n");
7966+ /* inode may be NULL */
7967+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode);
7968+ if (!tmp_h.inode) {
7969+ AuDbg("positive --> negative\n");
7970+ /* or bypassing aufs */
7971+ au_hide(dentry);
5afbbe0d 7972+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_btop)
027c5e7a
AM
7973+ dinfo->di_bwh = tmp->di_bwh;
7974+ if (inode)
7975+ err = au_refresh_hinode_self(inode);
7976+ au_dbg_verify_dinode(dentry);
7977+ } else if (orig_h.mode == tmp_h.mode) {
7978+ AuDbg("positive --> positive, same type\n");
7979+ if (!S_ISDIR(orig_h.mode)
5afbbe0d 7980+ && dinfo->di_btop > tmp->di_btop) {
027c5e7a
AM
7981+ /*
7982+ * similar to the behaviour of removing and
7983+ * creating.
7984+ */
7985+ au_hide(dentry);
7986+ if (inode)
7987+ err = au_refresh_hinode_self(inode);
7988+ au_dbg_verify_dinode(dentry);
7989+ } else {
7990+ /* fill empty slots */
5afbbe0d
AM
7991+ if (dinfo->di_btop > tmp->di_btop)
7992+ dinfo->di_btop = tmp->di_btop;
7993+ if (dinfo->di_bbot < tmp->di_bbot)
7994+ dinfo->di_bbot = tmp->di_bbot;
027c5e7a
AM
7995+ dinfo->di_bwh = tmp->di_bwh;
7996+ dinfo->di_bdiropq = tmp->di_bdiropq;
5afbbe0d
AM
7997+ bbot = dinfo->di_bbot;
7998+ bindex = tmp->di_btop;
7999+ hd = au_hdentry(tmp, bindex);
8000+ for (; bindex <= bbot; bindex++, hd++) {
027c5e7a
AM
8001+ if (au_h_dptr(dentry, bindex))
8002+ continue;
5afbbe0d 8003+ h_dentry = hd->hd_dentry;
027c5e7a
AM
8004+ if (!h_dentry)
8005+ continue;
5527c038
JR
8006+ AuDebugOn(d_is_negative(h_dentry));
8007+ h_inode = d_inode(h_dentry);
027c5e7a
AM
8008+ AuDebugOn(orig_h.mode
8009+ != (h_inode->i_mode
8010+ & S_IFMT));
8011+ au_set_h_dptr(dentry, bindex,
8012+ dget(h_dentry));
8013+ }
5afbbe0d
AM
8014+ if (inode)
8015+ err = au_refresh_hinode(inode, dentry);
027c5e7a
AM
8016+ au_dbg_verify_dinode(dentry);
8017+ }
8018+ } else {
8019+ AuDbg("positive --> positive, different type\n");
8020+ /* similar to the behaviour of removing and creating */
8021+ au_hide(dentry);
8022+ if (inode)
8023+ err = au_refresh_hinode_self(inode);
8024+ au_dbg_verify_dinode(dentry);
8025+ }
8026+ }
8027+
8028+out:
8029+ return err;
8030+}
8031+
79b8bda9
AM
8032+void au_refresh_dop(struct dentry *dentry, int force_reval)
8033+{
8034+ const struct dentry_operations *dop
8035+ = force_reval ? &aufs_dop : dentry->d_sb->s_d_op;
8036+ static const unsigned int mask
8037+ = DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE;
8038+
8039+ BUILD_BUG_ON(sizeof(mask) != sizeof(dentry->d_flags));
8040+
8041+ if (dentry->d_op == dop)
8042+ return;
8043+
8044+ AuDbg("%pd\n", dentry);
8045+ spin_lock(&dentry->d_lock);
8046+ if (dop == &aufs_dop)
8047+ dentry->d_flags |= mask;
8048+ else
8049+ dentry->d_flags &= ~mask;
8050+ dentry->d_op = dop;
8051+ spin_unlock(&dentry->d_lock);
8052+}
8053+
027c5e7a
AM
8054+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent)
8055+{
e2f27e51 8056+ int err, ebrange, nbr;
027c5e7a
AM
8057+ unsigned int sigen;
8058+ struct au_dinfo *dinfo, *tmp;
8059+ struct super_block *sb;
8060+ struct inode *inode;
8061+
8062+ DiMustWriteLock(dentry);
8063+ AuDebugOn(IS_ROOT(dentry));
5527c038 8064+ AuDebugOn(d_really_is_negative(parent));
027c5e7a
AM
8065+
8066+ sb = dentry->d_sb;
027c5e7a
AM
8067+ sigen = au_sigen(sb);
8068+ err = au_digen_test(parent, sigen);
8069+ if (unlikely(err))
8070+ goto out;
8071+
e2f27e51 8072+ nbr = au_sbbot(sb) + 1;
027c5e7a 8073+ dinfo = au_di(dentry);
e2f27e51 8074+ err = au_di_realloc(dinfo, nbr, /*may_shrink*/0);
027c5e7a
AM
8075+ if (unlikely(err))
8076+ goto out;
8077+ ebrange = au_dbrange_test(dentry);
8078+ if (!ebrange)
8079+ ebrange = au_do_refresh_hdentry(dentry, parent);
8080+
38d290e6 8081+ if (d_unhashed(dentry) || ebrange /* || dinfo->di_tmpfile */) {
5afbbe0d 8082+ AuDebugOn(au_dbtop(dentry) < 0 && au_dbbot(dentry) >= 0);
5527c038
JR
8083+ if (d_really_is_positive(dentry)) {
8084+ inode = d_inode(dentry);
027c5e7a 8085+ err = au_refresh_hinode_self(inode);
5527c038 8086+ }
027c5e7a
AM
8087+ au_dbg_verify_dinode(dentry);
8088+ if (!err)
8089+ goto out_dgen; /* success */
8090+ goto out;
8091+ }
8092+
8093+ /* temporary dinfo */
8094+ AuDbgDentry(dentry);
8095+ err = -ENOMEM;
8096+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
8097+ if (unlikely(!tmp))
8098+ goto out;
8099+ au_di_swap(tmp, dinfo);
8100+ /* returns the number of positive dentries */
8101+ /*
8102+ * if current working dir is removed, it returns an error.
8103+ * but the dentry is legal.
8104+ */
5afbbe0d 8105+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG);
027c5e7a
AM
8106+ AuDbgDentry(dentry);
8107+ au_di_swap(tmp, dinfo);
8108+ if (err == -ENOENT)
8109+ err = 0;
8110+ if (err >= 0) {
8111+ /* compare/refresh by dinfo */
8112+ AuDbgDentry(dentry);
8113+ err = au_refresh_by_dinfo(dentry, dinfo, tmp);
8114+ au_dbg_verify_dinode(dentry);
8115+ AuTraceErr(err);
8116+ }
e2f27e51 8117+ au_di_realloc(dinfo, nbr, /*may_shrink*/1); /* harmless if err */
027c5e7a
AM
8118+ au_rw_write_unlock(&tmp->di_rwsem);
8119+ au_di_free(tmp);
8120+ if (unlikely(err))
8121+ goto out;
8122+
8123+out_dgen:
8124+ au_update_digen(dentry);
8125+out:
8126+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) {
523b37e3 8127+ AuIOErr("failed refreshing %pd, %d\n", dentry, err);
027c5e7a
AM
8128+ AuDbgDentry(dentry);
8129+ }
8130+ AuTraceErr(err);
8131+ return err;
8132+}
8133+
b4510431
AM
8134+static int au_do_h_d_reval(struct dentry *h_dentry, unsigned int flags,
8135+ struct dentry *dentry, aufs_bindex_t bindex)
027c5e7a
AM
8136+{
8137+ int err, valid;
027c5e7a
AM
8138+
8139+ err = 0;
8140+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE))
8141+ goto out;
027c5e7a
AM
8142+
8143+ AuDbg("b%d\n", bindex);
b4510431
AM
8144+ /*
8145+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
8146+ * due to whiteout and branch permission.
8147+ */
8148+ flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
8149+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
8150+ /* it may return tri-state */
8151+ valid = h_dentry->d_op->d_revalidate(h_dentry, flags);
1facf9fc 8152+
8153+ if (unlikely(valid < 0))
8154+ err = valid;
8155+ else if (!valid)
8156+ err = -EINVAL;
8157+
4f0767ce 8158+out:
1facf9fc 8159+ AuTraceErr(err);
8160+ return err;
8161+}
8162+
8163+/* todo: remove this */
8164+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
8b6a4947 8165+ unsigned int flags, int do_udba, int dirren)
1facf9fc 8166+{
8167+ int err;
8168+ umode_t mode, h_mode;
5afbbe0d 8169+ aufs_bindex_t bindex, btail, btop, ibs, ibe;
38d290e6 8170+ unsigned char plus, unhashed, is_root, h_plus, h_nfs, tmpfile;
4a4d8108 8171+ struct inode *h_inode, *h_cached_inode;
1facf9fc 8172+ struct dentry *h_dentry;
8173+ struct qstr *name, *h_name;
8174+
8175+ err = 0;
8176+ plus = 0;
8177+ mode = 0;
1facf9fc 8178+ ibs = -1;
8179+ ibe = -1;
8180+ unhashed = !!d_unhashed(dentry);
8181+ is_root = !!IS_ROOT(dentry);
8182+ name = &dentry->d_name;
38d290e6 8183+ tmpfile = au_di(dentry)->di_tmpfile;
1facf9fc 8184+
8185+ /*
7f207e10
AM
8186+ * Theoretically, REVAL test should be unnecessary in case of
8187+ * {FS,I}NOTIFY.
8188+ * But {fs,i}notify doesn't fire some necessary events,
1facf9fc 8189+ * IN_ATTRIB for atime/nlink/pageio
1facf9fc 8190+ * Let's do REVAL test too.
8191+ */
8192+ if (do_udba && inode) {
8193+ mode = (inode->i_mode & S_IFMT);
8194+ plus = (inode->i_nlink > 0);
5afbbe0d
AM
8195+ ibs = au_ibtop(inode);
8196+ ibe = au_ibbot(inode);
1facf9fc 8197+ }
8198+
5afbbe0d
AM
8199+ btop = au_dbtop(dentry);
8200+ btail = btop;
1facf9fc 8201+ if (inode && S_ISDIR(inode->i_mode))
8202+ btail = au_dbtaildir(dentry);
5afbbe0d 8203+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 8204+ h_dentry = au_h_dptr(dentry, bindex);
8205+ if (!h_dentry)
8206+ continue;
8207+
523b37e3
AM
8208+ AuDbg("b%d, %pd\n", bindex, h_dentry);
8209+ h_nfs = !!au_test_nfs(h_dentry->d_sb);
027c5e7a 8210+ spin_lock(&h_dentry->d_lock);
1facf9fc 8211+ h_name = &h_dentry->d_name;
8212+ if (unlikely(do_udba
8213+ && !is_root
523b37e3
AM
8214+ && ((!h_nfs
8215+ && (unhashed != !!d_unhashed(h_dentry)
8b6a4947 8216+ || (!tmpfile && !dirren
38d290e6
JR
8217+ && !au_qstreq(name, h_name))
8218+ ))
523b37e3
AM
8219+ || (h_nfs
8220+ && !(flags & LOOKUP_OPEN)
8221+ && (h_dentry->d_flags
8222+ & DCACHE_NFSFS_RENAMED)))
1facf9fc 8223+ )) {
38d290e6
JR
8224+ int h_unhashed;
8225+
8226+ h_unhashed = d_unhashed(h_dentry);
027c5e7a 8227+ spin_unlock(&h_dentry->d_lock);
38d290e6
JR
8228+ AuDbg("unhash 0x%x 0x%x, %pd %pd\n",
8229+ unhashed, h_unhashed, dentry, h_dentry);
1facf9fc 8230+ goto err;
8231+ }
027c5e7a 8232+ spin_unlock(&h_dentry->d_lock);
1facf9fc 8233+
b4510431 8234+ err = au_do_h_d_reval(h_dentry, flags, dentry, bindex);
1facf9fc 8235+ if (unlikely(err))
8236+ /* do not goto err, to keep the errno */
8237+ break;
8238+
8239+ /* todo: plink too? */
8240+ if (!do_udba)
8241+ continue;
8242+
8243+ /* UDBA tests */
5527c038 8244+ if (unlikely(!!inode != d_is_positive(h_dentry)))
1facf9fc 8245+ goto err;
8246+
5527c038
JR
8247+ h_inode = NULL;
8248+ if (d_is_positive(h_dentry))
8249+ h_inode = d_inode(h_dentry);
1facf9fc 8250+ h_plus = plus;
8251+ h_mode = mode;
8252+ h_cached_inode = h_inode;
8253+ if (h_inode) {
8254+ h_mode = (h_inode->i_mode & S_IFMT);
8255+ h_plus = (h_inode->i_nlink > 0);
8256+ }
8257+ if (inode && ibs <= bindex && bindex <= ibe)
8258+ h_cached_inode = au_h_iptr(inode, bindex);
8259+
523b37e3 8260+ if (!h_nfs) {
38d290e6 8261+ if (unlikely(plus != h_plus && !tmpfile))
523b37e3
AM
8262+ goto err;
8263+ } else {
8264+ if (unlikely(!(h_dentry->d_flags & DCACHE_NFSFS_RENAMED)
8265+ && !is_root
8266+ && !IS_ROOT(h_dentry)
8267+ && unhashed != d_unhashed(h_dentry)))
8268+ goto err;
8269+ }
8270+ if (unlikely(mode != h_mode
1facf9fc 8271+ || h_cached_inode != h_inode))
8272+ goto err;
8273+ continue;
8274+
f6b6e03d 8275+err:
1facf9fc 8276+ err = -EINVAL;
8277+ break;
8278+ }
8279+
523b37e3 8280+ AuTraceErr(err);
1facf9fc 8281+ return err;
8282+}
8283+
027c5e7a 8284+/* todo: consolidate with do_refresh() and au_reval_for_attr() */
1facf9fc 8285+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
8286+{
8287+ int err;
8288+ struct dentry *parent;
1facf9fc 8289+
027c5e7a 8290+ if (!au_digen_test(dentry, sigen))
1facf9fc 8291+ return 0;
8292+
8293+ parent = dget_parent(dentry);
8294+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 8295+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 8296+ au_dbg_verify_gen(parent, sigen);
027c5e7a 8297+ err = au_refresh_dentry(dentry, parent);
1facf9fc 8298+ di_read_unlock(parent, AuLock_IR);
8299+ dput(parent);
027c5e7a 8300+ AuTraceErr(err);
1facf9fc 8301+ return err;
8302+}
8303+
8304+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
8305+{
8306+ int err;
8307+ struct dentry *d, *parent;
1facf9fc 8308+
027c5e7a 8309+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR))
1facf9fc 8310+ return simple_reval_dpath(dentry, sigen);
8311+
8312+ /* slow loop, keep it simple and stupid */
8313+ /* cf: au_cpup_dirs() */
8314+ err = 0;
8315+ parent = NULL;
027c5e7a 8316+ while (au_digen_test(dentry, sigen)) {
1facf9fc 8317+ d = dentry;
8318+ while (1) {
8319+ dput(parent);
8320+ parent = dget_parent(d);
027c5e7a 8321+ if (!au_digen_test(parent, sigen))
1facf9fc 8322+ break;
8323+ d = parent;
8324+ }
8325+
1facf9fc 8326+ if (d != dentry)
027c5e7a 8327+ di_write_lock_child2(d);
1facf9fc 8328+
8329+ /* someone might update our dentry while we were sleeping */
027c5e7a
AM
8330+ if (au_digen_test(d, sigen)) {
8331+ /*
8332+ * todo: consolidate with simple_reval_dpath(),
8333+ * do_refresh() and au_reval_for_attr().
8334+ */
1facf9fc 8335+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 8336+ err = au_refresh_dentry(d, parent);
1facf9fc 8337+ di_read_unlock(parent, AuLock_IR);
8338+ }
8339+
8340+ if (d != dentry)
8341+ di_write_unlock(d);
8342+ dput(parent);
8343+ if (unlikely(err))
8344+ break;
8345+ }
8346+
8347+ return err;
8348+}
8349+
8350+/*
8351+ * if valid returns 1, otherwise 0.
8352+ */
b4510431 8353+static int aufs_d_revalidate(struct dentry *dentry, unsigned int flags)
1facf9fc 8354+{
8355+ int valid, err;
8356+ unsigned int sigen;
8b6a4947 8357+ unsigned char do_udba, dirren;
1facf9fc 8358+ struct super_block *sb;
8359+ struct inode *inode;
8360+
027c5e7a 8361+ /* todo: support rcu-walk? */
b4510431 8362+ if (flags & LOOKUP_RCU)
027c5e7a
AM
8363+ return -ECHILD;
8364+
8365+ valid = 0;
8366+ if (unlikely(!au_di(dentry)))
8367+ goto out;
8368+
e49829fe 8369+ valid = 1;
1facf9fc 8370+ sb = dentry->d_sb;
e49829fe
JR
8371+ /*
8372+ * todo: very ugly
8373+ * i_mutex of parent dir may be held,
8374+ * but we should not return 'invalid' due to busy.
8375+ */
8376+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
8377+ if (unlikely(err)) {
8378+ valid = err;
027c5e7a 8379+ AuTraceErr(err);
e49829fe
JR
8380+ goto out;
8381+ }
5527c038
JR
8382+ inode = NULL;
8383+ if (d_really_is_positive(dentry))
8384+ inode = d_inode(dentry);
5afbbe0d 8385+ if (unlikely(inode && au_is_bad_inode(inode))) {
c1595e42
JR
8386+ err = -EINVAL;
8387+ AuTraceErr(err);
8388+ goto out_dgrade;
8389+ }
027c5e7a
AM
8390+ if (unlikely(au_dbrange_test(dentry))) {
8391+ err = -EINVAL;
8392+ AuTraceErr(err);
8393+ goto out_dgrade;
1facf9fc 8394+ }
027c5e7a
AM
8395+
8396+ sigen = au_sigen(sb);
8397+ if (au_digen_test(dentry, sigen)) {
1facf9fc 8398+ AuDebugOn(IS_ROOT(dentry));
027c5e7a
AM
8399+ err = au_reval_dpath(dentry, sigen);
8400+ if (unlikely(err)) {
8401+ AuTraceErr(err);
1facf9fc 8402+ goto out_dgrade;
027c5e7a 8403+ }
1facf9fc 8404+ }
8405+ di_downgrade_lock(dentry, AuLock_IR);
8406+
1facf9fc 8407+ err = -EINVAL;
c1595e42 8408+ if (!(flags & (LOOKUP_OPEN | LOOKUP_EMPTY))
523b37e3 8409+ && inode
38d290e6 8410+ && !(inode->i_state && I_LINKABLE)
79b8bda9
AM
8411+ && (IS_DEADDIR(inode) || !inode->i_nlink)) {
8412+ AuTraceErr(err);
027c5e7a 8413+ goto out_inval;
79b8bda9 8414+ }
027c5e7a 8415+
1facf9fc 8416+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
8417+ if (do_udba && inode) {
5afbbe0d 8418+ aufs_bindex_t btop = au_ibtop(inode);
027c5e7a 8419+ struct inode *h_inode;
1facf9fc 8420+
5afbbe0d
AM
8421+ if (btop >= 0) {
8422+ h_inode = au_h_iptr(inode, btop);
79b8bda9
AM
8423+ if (h_inode && au_test_higen(inode, h_inode)) {
8424+ AuTraceErr(err);
027c5e7a 8425+ goto out_inval;
79b8bda9 8426+ }
027c5e7a 8427+ }
1facf9fc 8428+ }
8429+
8b6a4947
AM
8430+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN);
8431+ err = h_d_revalidate(dentry, inode, flags, do_udba, dirren);
5afbbe0d 8432+ if (unlikely(!err && do_udba && au_dbtop(dentry) < 0)) {
1facf9fc 8433+ err = -EIO;
523b37e3
AM
8434+ AuDbg("both of real entry and whiteout found, %p, err %d\n",
8435+ dentry, err);
027c5e7a 8436+ }
e49829fe 8437+ goto out_inval;
1facf9fc 8438+
4f0767ce 8439+out_dgrade:
1facf9fc 8440+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 8441+out_inval:
1facf9fc 8442+ aufs_read_unlock(dentry, AuLock_IR);
8443+ AuTraceErr(err);
8444+ valid = !err;
e49829fe 8445+out:
027c5e7a 8446+ if (!valid) {
523b37e3 8447+ AuDbg("%pd invalid, %d\n", dentry, valid);
027c5e7a
AM
8448+ d_drop(dentry);
8449+ }
1facf9fc 8450+ return valid;
8451+}
8452+
8453+static void aufs_d_release(struct dentry *dentry)
8454+{
027c5e7a 8455+ if (au_di(dentry)) {
4a4d8108
AM
8456+ au_di_fin(dentry);
8457+ au_hn_di_reinit(dentry);
1facf9fc 8458+ }
1facf9fc 8459+}
8460+
4a4d8108 8461+const struct dentry_operations aufs_dop = {
c06a8ce3
AM
8462+ .d_revalidate = aufs_d_revalidate,
8463+ .d_weak_revalidate = aufs_d_revalidate,
8464+ .d_release = aufs_d_release
1facf9fc 8465+};
79b8bda9
AM
8466+
8467+/* aufs_dop without d_revalidate */
8468+const struct dentry_operations aufs_dop_noreval = {
8469+ .d_release = aufs_d_release
8470+};
0b1ff5c3
JR
8471diff -urNp -x '*.orig' linux-4.14/fs/aufs/dentry.h linux-4.14/fs/aufs/dentry.h
8472--- linux-4.14/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
8473+++ linux-4.14/fs/aufs/dentry.h 2021-02-24 21:42:43.441114748 +0100
8b6a4947 8474@@ -0,0 +1,266 @@
1facf9fc 8475+/*
a2654f78 8476+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 8477+ *
8478+ * This program, aufs is free software; you can redistribute it and/or modify
8479+ * it under the terms of the GNU General Public License as published by
8480+ * the Free Software Foundation; either version 2 of the License, or
8481+ * (at your option) any later version.
dece6358
AM
8482+ *
8483+ * This program is distributed in the hope that it will be useful,
8484+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8485+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8486+ * GNU General Public License for more details.
8487+ *
8488+ * You should have received a copy of the GNU General Public License
523b37e3 8489+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 8490+ */
8491+
8492+/*
8493+ * lookup and dentry operations
8494+ */
8495+
8496+#ifndef __AUFS_DENTRY_H__
8497+#define __AUFS_DENTRY_H__
8498+
8499+#ifdef __KERNEL__
8500+
dece6358 8501+#include <linux/dcache.h>
8b6a4947 8502+#include "dirren.h"
1facf9fc 8503+#include "rwsem.h"
8504+
1facf9fc 8505+struct au_hdentry {
8506+ struct dentry *hd_dentry;
027c5e7a 8507+ aufs_bindex_t hd_id;
1facf9fc 8508+};
8509+
8510+struct au_dinfo {
8511+ atomic_t di_generation;
8512+
dece6358 8513+ struct au_rwsem di_rwsem;
5afbbe0d 8514+ aufs_bindex_t di_btop, di_bbot, di_bwh, di_bdiropq;
38d290e6 8515+ unsigned char di_tmpfile; /* to allow the different name */
1c60b727 8516+ struct au_hdentry *di_hdentry;
4a4d8108 8517+} ____cacheline_aligned_in_smp;
1facf9fc 8518+
8519+/* ---------------------------------------------------------------------- */
8520+
5afbbe0d
AM
8521+/* flags for au_lkup_dentry() */
8522+#define AuLkup_ALLOW_NEG 1
8523+#define AuLkup_IGNORE_PERM (1 << 1)
8b6a4947 8524+#define AuLkup_DIRREN (1 << 2)
5afbbe0d
AM
8525+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
8526+#define au_fset_lkup(flags, name) \
8527+ do { (flags) |= AuLkup_##name; } while (0)
8528+#define au_fclr_lkup(flags, name) \
8529+ do { (flags) &= ~AuLkup_##name; } while (0)
8530+
8b6a4947
AM
8531+#ifndef CONFIG_AUFS_DIRREN
8532+#undef AuLkup_DIRREN
8533+#define AuLkup_DIRREN 0
8534+#endif
8535+
8536+struct au_do_lookup_args {
8537+ unsigned int flags;
8538+ mode_t type;
8539+ struct qstr whname, *name;
8540+ struct au_dr_lookup dirren;
8541+};
8542+
5afbbe0d
AM
8543+/* ---------------------------------------------------------------------- */
8544+
1facf9fc 8545+/* dentry.c */
79b8bda9 8546+extern const struct dentry_operations aufs_dop, aufs_dop_noreval;
1facf9fc 8547+struct au_branch;
076b876e 8548+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent);
1facf9fc 8549+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
8550+ struct dentry *h_parent, struct au_branch *br);
8551+
5afbbe0d
AM
8552+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
8553+ unsigned int flags);
86dc4139 8554+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh);
027c5e7a 8555+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
1facf9fc 8556+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
79b8bda9 8557+void au_refresh_dop(struct dentry *dentry, int force_reval);
1facf9fc 8558+
8559+/* dinfo.c */
4a4d8108 8560+void au_di_init_once(void *_di);
027c5e7a
AM
8561+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc);
8562+void au_di_free(struct au_dinfo *dinfo);
8563+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b);
8564+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src);
4a4d8108
AM
8565+int au_di_init(struct dentry *dentry);
8566+void au_di_fin(struct dentry *dentry);
e2f27e51 8567+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink);
1facf9fc 8568+
8569+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
8570+void di_read_unlock(struct dentry *d, int flags);
8571+void di_downgrade_lock(struct dentry *d, int flags);
8572+void di_write_lock(struct dentry *d, unsigned int lsc);
8573+void di_write_unlock(struct dentry *d);
8574+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
8575+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
8576+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
8577+
8578+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
2cbb1c4b 8579+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex);
1facf9fc 8580+aufs_bindex_t au_dbtail(struct dentry *dentry);
8581+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
8582+
8583+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
8584+ struct dentry *h_dentry);
027c5e7a
AM
8585+int au_digen_test(struct dentry *dentry, unsigned int sigen);
8586+int au_dbrange_test(struct dentry *dentry);
1facf9fc 8587+void au_update_digen(struct dentry *dentry);
8588+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
5afbbe0d
AM
8589+void au_update_dbtop(struct dentry *dentry);
8590+void au_update_dbbot(struct dentry *dentry);
1facf9fc 8591+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
8592+
8593+/* ---------------------------------------------------------------------- */
8594+
8595+static inline struct au_dinfo *au_di(struct dentry *dentry)
8596+{
8597+ return dentry->d_fsdata;
8598+}
8599+
8600+/* ---------------------------------------------------------------------- */
8601+
8602+/* lock subclass for dinfo */
8603+enum {
8604+ AuLsc_DI_CHILD, /* child first */
4a4d8108 8605+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 8606+ AuLsc_DI_CHILD3, /* copyup dirs */
8607+ AuLsc_DI_PARENT,
8608+ AuLsc_DI_PARENT2,
027c5e7a
AM
8609+ AuLsc_DI_PARENT3,
8610+ AuLsc_DI_TMP /* temp for replacing dinfo */
1facf9fc 8611+};
8612+
8613+/*
8614+ * di_read_lock_child, di_write_lock_child,
8615+ * di_read_lock_child2, di_write_lock_child2,
8616+ * di_read_lock_child3, di_write_lock_child3,
8617+ * di_read_lock_parent, di_write_lock_parent,
8618+ * di_read_lock_parent2, di_write_lock_parent2,
8619+ * di_read_lock_parent3, di_write_lock_parent3,
8620+ */
8621+#define AuReadLockFunc(name, lsc) \
8622+static inline void di_read_lock_##name(struct dentry *d, int flags) \
8623+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
8624+
8625+#define AuWriteLockFunc(name, lsc) \
8626+static inline void di_write_lock_##name(struct dentry *d) \
8627+{ di_write_lock(d, AuLsc_DI_##lsc); }
8628+
8629+#define AuRWLockFuncs(name, lsc) \
8630+ AuReadLockFunc(name, lsc) \
8631+ AuWriteLockFunc(name, lsc)
8632+
8633+AuRWLockFuncs(child, CHILD);
8634+AuRWLockFuncs(child2, CHILD2);
8635+AuRWLockFuncs(child3, CHILD3);
8636+AuRWLockFuncs(parent, PARENT);
8637+AuRWLockFuncs(parent2, PARENT2);
8638+AuRWLockFuncs(parent3, PARENT3);
8639+
8640+#undef AuReadLockFunc
8641+#undef AuWriteLockFunc
8642+#undef AuRWLockFuncs
8643+
8644+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
8645+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
8646+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 8647+
8648+/* ---------------------------------------------------------------------- */
8649+
8650+/* todo: memory barrier? */
8651+static inline unsigned int au_digen(struct dentry *d)
8652+{
8653+ return atomic_read(&au_di(d)->di_generation);
8654+}
8655+
8656+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
8657+{
8658+ hdentry->hd_dentry = NULL;
8659+}
8660+
5afbbe0d
AM
8661+static inline struct au_hdentry *au_hdentry(struct au_dinfo *di,
8662+ aufs_bindex_t bindex)
8663+{
8664+ return di->di_hdentry + bindex;
8665+}
8666+
1facf9fc 8667+static inline void au_hdput(struct au_hdentry *hd)
8668+{
4a4d8108
AM
8669+ if (hd)
8670+ dput(hd->hd_dentry);
1facf9fc 8671+}
8672+
5afbbe0d 8673+static inline aufs_bindex_t au_dbtop(struct dentry *dentry)
1facf9fc 8674+{
1308ab2a 8675+ DiMustAnyLock(dentry);
5afbbe0d 8676+ return au_di(dentry)->di_btop;
1facf9fc 8677+}
8678+
5afbbe0d 8679+static inline aufs_bindex_t au_dbbot(struct dentry *dentry)
1facf9fc 8680+{
1308ab2a 8681+ DiMustAnyLock(dentry);
5afbbe0d 8682+ return au_di(dentry)->di_bbot;
1facf9fc 8683+}
8684+
8685+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
8686+{
1308ab2a 8687+ DiMustAnyLock(dentry);
1facf9fc 8688+ return au_di(dentry)->di_bwh;
8689+}
8690+
8691+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
8692+{
1308ab2a 8693+ DiMustAnyLock(dentry);
1facf9fc 8694+ return au_di(dentry)->di_bdiropq;
8695+}
8696+
8697+/* todo: hard/soft set? */
5afbbe0d 8698+static inline void au_set_dbtop(struct dentry *dentry, aufs_bindex_t bindex)
1facf9fc 8699+{
1308ab2a 8700+ DiMustWriteLock(dentry);
5afbbe0d 8701+ au_di(dentry)->di_btop = bindex;
1facf9fc 8702+}
8703+
5afbbe0d 8704+static inline void au_set_dbbot(struct dentry *dentry, aufs_bindex_t bindex)
1facf9fc 8705+{
1308ab2a 8706+ DiMustWriteLock(dentry);
5afbbe0d 8707+ au_di(dentry)->di_bbot = bindex;
1facf9fc 8708+}
8709+
8710+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
8711+{
1308ab2a 8712+ DiMustWriteLock(dentry);
5afbbe0d 8713+ /* dbwh can be outside of btop - bbot range */
1facf9fc 8714+ au_di(dentry)->di_bwh = bindex;
8715+}
8716+
8717+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
8718+{
1308ab2a 8719+ DiMustWriteLock(dentry);
1facf9fc 8720+ au_di(dentry)->di_bdiropq = bindex;
8721+}
8722+
8723+/* ---------------------------------------------------------------------- */
8724+
4a4d8108 8725+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 8726+static inline void au_digen_dec(struct dentry *d)
8727+{
e49829fe 8728+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 8729+}
8730+
4a4d8108 8731+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 8732+{
8733+ dentry->d_fsdata = NULL;
8734+}
8735+#else
4a4d8108
AM
8736+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
8737+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 8738+
8739+#endif /* __KERNEL__ */
8740+#endif /* __AUFS_DENTRY_H__ */
0b1ff5c3
JR
8741diff -urNp -x '*.orig' linux-4.14/fs/aufs/dinfo.c linux-4.14/fs/aufs/dinfo.c
8742--- linux-4.14/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
8743+++ linux-4.14/fs/aufs/dinfo.c 2021-02-24 21:42:43.441114748 +0100
e2f27e51 8744@@ -0,0 +1,553 @@
1facf9fc 8745+/*
a2654f78 8746+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 8747+ *
8748+ * This program, aufs is free software; you can redistribute it and/or modify
8749+ * it under the terms of the GNU General Public License as published by
8750+ * the Free Software Foundation; either version 2 of the License, or
8751+ * (at your option) any later version.
dece6358
AM
8752+ *
8753+ * This program is distributed in the hope that it will be useful,
8754+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8755+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8756+ * GNU General Public License for more details.
8757+ *
8758+ * You should have received a copy of the GNU General Public License
523b37e3 8759+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 8760+ */
8761+
8762+/*
8763+ * dentry private data
8764+ */
8765+
8766+#include "aufs.h"
8767+
e49829fe 8768+void au_di_init_once(void *_dinfo)
4a4d8108 8769+{
e49829fe 8770+ struct au_dinfo *dinfo = _dinfo;
4a4d8108 8771+
e49829fe 8772+ au_rw_init(&dinfo->di_rwsem);
4a4d8108
AM
8773+}
8774+
027c5e7a 8775+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc)
1facf9fc 8776+{
8777+ struct au_dinfo *dinfo;
027c5e7a 8778+ int nbr, i;
1facf9fc 8779+
8780+ dinfo = au_cache_alloc_dinfo();
8781+ if (unlikely(!dinfo))
8782+ goto out;
8783+
5afbbe0d 8784+ nbr = au_sbbot(sb) + 1;
1facf9fc 8785+ if (nbr <= 0)
8786+ nbr = 1;
8787+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
027c5e7a
AM
8788+ if (dinfo->di_hdentry) {
8789+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc);
5afbbe0d
AM
8790+ dinfo->di_btop = -1;
8791+ dinfo->di_bbot = -1;
027c5e7a
AM
8792+ dinfo->di_bwh = -1;
8793+ dinfo->di_bdiropq = -1;
38d290e6 8794+ dinfo->di_tmpfile = 0;
027c5e7a
AM
8795+ for (i = 0; i < nbr; i++)
8796+ dinfo->di_hdentry[i].hd_id = -1;
8797+ goto out;
8798+ }
1facf9fc 8799+
1c60b727 8800+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
8801+ dinfo = NULL;
8802+
4f0767ce 8803+out:
027c5e7a 8804+ return dinfo;
1facf9fc 8805+}
8806+
027c5e7a 8807+void au_di_free(struct au_dinfo *dinfo)
4a4d8108 8808+{
4a4d8108 8809+ struct au_hdentry *p;
5afbbe0d 8810+ aufs_bindex_t bbot, bindex;
4a4d8108
AM
8811+
8812+ /* dentry may not be revalidated */
5afbbe0d 8813+ bindex = dinfo->di_btop;
4a4d8108 8814+ if (bindex >= 0) {
5afbbe0d
AM
8815+ bbot = dinfo->di_bbot;
8816+ p = au_hdentry(dinfo, bindex);
8817+ while (bindex++ <= bbot)
4a4d8108
AM
8818+ au_hdput(p++);
8819+ }
1c60b727
AM
8820+ kfree(dinfo->di_hdentry);
8821+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
8822+}
8823+
8824+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b)
8825+{
8826+ struct au_hdentry *p;
8827+ aufs_bindex_t bi;
8828+
8829+ AuRwMustWriteLock(&a->di_rwsem);
8830+ AuRwMustWriteLock(&b->di_rwsem);
8831+
8832+#define DiSwap(v, name) \
8833+ do { \
8834+ v = a->di_##name; \
8835+ a->di_##name = b->di_##name; \
8836+ b->di_##name = v; \
8837+ } while (0)
8838+
8839+ DiSwap(p, hdentry);
5afbbe0d
AM
8840+ DiSwap(bi, btop);
8841+ DiSwap(bi, bbot);
027c5e7a
AM
8842+ DiSwap(bi, bwh);
8843+ DiSwap(bi, bdiropq);
8844+ /* smp_mb(); */
8845+
8846+#undef DiSwap
8847+}
8848+
8849+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src)
8850+{
8851+ AuRwMustWriteLock(&dst->di_rwsem);
8852+ AuRwMustWriteLock(&src->di_rwsem);
8853+
5afbbe0d
AM
8854+ dst->di_btop = src->di_btop;
8855+ dst->di_bbot = src->di_bbot;
027c5e7a
AM
8856+ dst->di_bwh = src->di_bwh;
8857+ dst->di_bdiropq = src->di_bdiropq;
8858+ /* smp_mb(); */
8859+}
8860+
8861+int au_di_init(struct dentry *dentry)
8862+{
8863+ int err;
8864+ struct super_block *sb;
8865+ struct au_dinfo *dinfo;
8866+
8867+ err = 0;
8868+ sb = dentry->d_sb;
8869+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD);
8870+ if (dinfo) {
8871+ atomic_set(&dinfo->di_generation, au_sigen(sb));
8872+ /* smp_mb(); */ /* atomic_set */
8873+ dentry->d_fsdata = dinfo;
8874+ } else
8875+ err = -ENOMEM;
8876+
8877+ return err;
8878+}
8879+
8880+void au_di_fin(struct dentry *dentry)
8881+{
8882+ struct au_dinfo *dinfo;
8883+
8884+ dinfo = au_di(dentry);
8885+ AuRwDestroy(&dinfo->di_rwsem);
8886+ au_di_free(dinfo);
4a4d8108
AM
8887+}
8888+
e2f27e51 8889+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink)
1facf9fc 8890+{
8891+ int err, sz;
8892+ struct au_hdentry *hdp;
8893+
1308ab2a 8894+ AuRwMustWriteLock(&dinfo->di_rwsem);
8895+
1facf9fc 8896+ err = -ENOMEM;
5afbbe0d 8897+ sz = sizeof(*hdp) * (dinfo->di_bbot + 1);
1facf9fc 8898+ if (!sz)
8899+ sz = sizeof(*hdp);
e2f27e51
AM
8900+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS,
8901+ may_shrink);
1facf9fc 8902+ if (hdp) {
8903+ dinfo->di_hdentry = hdp;
8904+ err = 0;
8905+ }
8906+
8907+ return err;
8908+}
8909+
8910+/* ---------------------------------------------------------------------- */
8911+
8912+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
8913+{
8914+ switch (lsc) {
8915+ case AuLsc_DI_CHILD:
8916+ ii_write_lock_child(inode);
8917+ break;
8918+ case AuLsc_DI_CHILD2:
8919+ ii_write_lock_child2(inode);
8920+ break;
8921+ case AuLsc_DI_CHILD3:
8922+ ii_write_lock_child3(inode);
8923+ break;
8924+ case AuLsc_DI_PARENT:
8925+ ii_write_lock_parent(inode);
8926+ break;
8927+ case AuLsc_DI_PARENT2:
8928+ ii_write_lock_parent2(inode);
8929+ break;
8930+ case AuLsc_DI_PARENT3:
8931+ ii_write_lock_parent3(inode);
8932+ break;
8933+ default:
8934+ BUG();
8935+ }
8936+}
8937+
8938+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
8939+{
8940+ switch (lsc) {
8941+ case AuLsc_DI_CHILD:
8942+ ii_read_lock_child(inode);
8943+ break;
8944+ case AuLsc_DI_CHILD2:
8945+ ii_read_lock_child2(inode);
8946+ break;
8947+ case AuLsc_DI_CHILD3:
8948+ ii_read_lock_child3(inode);
8949+ break;
8950+ case AuLsc_DI_PARENT:
8951+ ii_read_lock_parent(inode);
8952+ break;
8953+ case AuLsc_DI_PARENT2:
8954+ ii_read_lock_parent2(inode);
8955+ break;
8956+ case AuLsc_DI_PARENT3:
8957+ ii_read_lock_parent3(inode);
8958+ break;
8959+ default:
8960+ BUG();
8961+ }
8962+}
8963+
8964+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
8965+{
5527c038
JR
8966+ struct inode *inode;
8967+
dece6358 8968+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
5527c038
JR
8969+ if (d_really_is_positive(d)) {
8970+ inode = d_inode(d);
1facf9fc 8971+ if (au_ftest_lock(flags, IW))
5527c038 8972+ do_ii_write_lock(inode, lsc);
1facf9fc 8973+ else if (au_ftest_lock(flags, IR))
5527c038 8974+ do_ii_read_lock(inode, lsc);
1facf9fc 8975+ }
8976+}
8977+
8978+void di_read_unlock(struct dentry *d, int flags)
8979+{
5527c038
JR
8980+ struct inode *inode;
8981+
8982+ if (d_really_is_positive(d)) {
8983+ inode = d_inode(d);
027c5e7a
AM
8984+ if (au_ftest_lock(flags, IW)) {
8985+ au_dbg_verify_dinode(d);
5527c038 8986+ ii_write_unlock(inode);
027c5e7a
AM
8987+ } else if (au_ftest_lock(flags, IR)) {
8988+ au_dbg_verify_dinode(d);
5527c038 8989+ ii_read_unlock(inode);
027c5e7a 8990+ }
1facf9fc 8991+ }
dece6358 8992+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 8993+}
8994+
8995+void di_downgrade_lock(struct dentry *d, int flags)
8996+{
5527c038
JR
8997+ if (d_really_is_positive(d) && au_ftest_lock(flags, IR))
8998+ ii_downgrade_lock(d_inode(d));
dece6358 8999+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 9000+}
9001+
9002+void di_write_lock(struct dentry *d, unsigned int lsc)
9003+{
dece6358 9004+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
5527c038
JR
9005+ if (d_really_is_positive(d))
9006+ do_ii_write_lock(d_inode(d), lsc);
1facf9fc 9007+}
9008+
9009+void di_write_unlock(struct dentry *d)
9010+{
027c5e7a 9011+ au_dbg_verify_dinode(d);
5527c038
JR
9012+ if (d_really_is_positive(d))
9013+ ii_write_unlock(d_inode(d));
dece6358 9014+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 9015+}
9016+
9017+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
9018+{
9019+ AuDebugOn(d1 == d2
5527c038 9020+ || d_inode(d1) == d_inode(d2)
1facf9fc 9021+ || d1->d_sb != d2->d_sb);
9022+
521ced18
JR
9023+ if ((isdir && au_test_subdir(d1, d2))
9024+ || d1 < d2) {
1facf9fc 9025+ di_write_lock_child(d1);
9026+ di_write_lock_child2(d2);
9027+ } else {
1facf9fc 9028+ di_write_lock_child(d2);
9029+ di_write_lock_child2(d1);
9030+ }
9031+}
9032+
9033+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
9034+{
9035+ AuDebugOn(d1 == d2
5527c038 9036+ || d_inode(d1) == d_inode(d2)
1facf9fc 9037+ || d1->d_sb != d2->d_sb);
9038+
521ced18
JR
9039+ if ((isdir && au_test_subdir(d1, d2))
9040+ || d1 < d2) {
1facf9fc 9041+ di_write_lock_parent(d1);
9042+ di_write_lock_parent2(d2);
9043+ } else {
1facf9fc 9044+ di_write_lock_parent(d2);
9045+ di_write_lock_parent2(d1);
9046+ }
9047+}
9048+
9049+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
9050+{
9051+ di_write_unlock(d1);
5527c038 9052+ if (d_inode(d1) == d_inode(d2))
dece6358 9053+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 9054+ else
9055+ di_write_unlock(d2);
9056+}
9057+
9058+/* ---------------------------------------------------------------------- */
9059+
9060+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
9061+{
9062+ struct dentry *d;
9063+
1308ab2a 9064+ DiMustAnyLock(dentry);
9065+
5afbbe0d 9066+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry))
1facf9fc 9067+ return NULL;
9068+ AuDebugOn(bindex < 0);
5afbbe0d 9069+ d = au_hdentry(au_di(dentry), bindex)->hd_dentry;
c1595e42 9070+ AuDebugOn(d && au_dcount(d) <= 0);
1facf9fc 9071+ return d;
9072+}
9073+
2cbb1c4b
JR
9074+/*
9075+ * extended version of au_h_dptr().
38d290e6
JR
9076+ * returns a hashed and positive (or linkable) h_dentry in bindex, NULL, or
9077+ * error.
2cbb1c4b
JR
9078+ */
9079+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex)
9080+{
9081+ struct dentry *h_dentry;
9082+ struct inode *inode, *h_inode;
9083+
5527c038 9084+ AuDebugOn(d_really_is_negative(dentry));
2cbb1c4b
JR
9085+
9086+ h_dentry = NULL;
5afbbe0d
AM
9087+ if (au_dbtop(dentry) <= bindex
9088+ && bindex <= au_dbbot(dentry))
2cbb1c4b 9089+ h_dentry = au_h_dptr(dentry, bindex);
38d290e6 9090+ if (h_dentry && !au_d_linkable(h_dentry)) {
2cbb1c4b
JR
9091+ dget(h_dentry);
9092+ goto out; /* success */
9093+ }
9094+
5527c038 9095+ inode = d_inode(dentry);
5afbbe0d
AM
9096+ AuDebugOn(bindex < au_ibtop(inode));
9097+ AuDebugOn(au_ibbot(inode) < bindex);
2cbb1c4b
JR
9098+ h_inode = au_h_iptr(inode, bindex);
9099+ h_dentry = d_find_alias(h_inode);
9100+ if (h_dentry) {
9101+ if (!IS_ERR(h_dentry)) {
38d290e6 9102+ if (!au_d_linkable(h_dentry))
2cbb1c4b
JR
9103+ goto out; /* success */
9104+ dput(h_dentry);
9105+ } else
9106+ goto out;
9107+ }
9108+
9109+ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) {
9110+ h_dentry = au_plink_lkup(inode, bindex);
9111+ AuDebugOn(!h_dentry);
9112+ if (!IS_ERR(h_dentry)) {
9113+ if (!au_d_hashed_positive(h_dentry))
9114+ goto out; /* success */
9115+ dput(h_dentry);
9116+ h_dentry = NULL;
9117+ }
9118+ }
9119+
9120+out:
9121+ AuDbgDentry(h_dentry);
9122+ return h_dentry;
9123+}
9124+
1facf9fc 9125+aufs_bindex_t au_dbtail(struct dentry *dentry)
9126+{
5afbbe0d 9127+ aufs_bindex_t bbot, bwh;
1facf9fc 9128+
5afbbe0d
AM
9129+ bbot = au_dbbot(dentry);
9130+ if (0 <= bbot) {
1facf9fc 9131+ bwh = au_dbwh(dentry);
9132+ if (!bwh)
9133+ return bwh;
5afbbe0d 9134+ if (0 < bwh && bwh < bbot)
1facf9fc 9135+ return bwh - 1;
9136+ }
5afbbe0d 9137+ return bbot;
1facf9fc 9138+}
9139+
9140+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
9141+{
5afbbe0d 9142+ aufs_bindex_t bbot, bopq;
1facf9fc 9143+
5afbbe0d
AM
9144+ bbot = au_dbtail(dentry);
9145+ if (0 <= bbot) {
1facf9fc 9146+ bopq = au_dbdiropq(dentry);
5afbbe0d
AM
9147+ if (0 <= bopq && bopq < bbot)
9148+ bbot = bopq;
1facf9fc 9149+ }
5afbbe0d 9150+ return bbot;
1facf9fc 9151+}
9152+
9153+/* ---------------------------------------------------------------------- */
9154+
9155+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
9156+ struct dentry *h_dentry)
9157+{
5afbbe0d
AM
9158+ struct au_dinfo *dinfo;
9159+ struct au_hdentry *hd;
027c5e7a 9160+ struct au_branch *br;
1facf9fc 9161+
1308ab2a 9162+ DiMustWriteLock(dentry);
9163+
5afbbe0d
AM
9164+ dinfo = au_di(dentry);
9165+ hd = au_hdentry(dinfo, bindex);
4a4d8108 9166+ au_hdput(hd);
1facf9fc 9167+ hd->hd_dentry = h_dentry;
027c5e7a
AM
9168+ if (h_dentry) {
9169+ br = au_sbr(dentry->d_sb, bindex);
9170+ hd->hd_id = br->br_id;
9171+ }
9172+}
9173+
9174+int au_dbrange_test(struct dentry *dentry)
9175+{
9176+ int err;
5afbbe0d 9177+ aufs_bindex_t btop, bbot;
027c5e7a
AM
9178+
9179+ err = 0;
5afbbe0d
AM
9180+ btop = au_dbtop(dentry);
9181+ bbot = au_dbbot(dentry);
9182+ if (btop >= 0)
9183+ AuDebugOn(bbot < 0 && btop > bbot);
027c5e7a
AM
9184+ else {
9185+ err = -EIO;
5afbbe0d 9186+ AuDebugOn(bbot >= 0);
027c5e7a
AM
9187+ }
9188+
9189+ return err;
9190+}
9191+
9192+int au_digen_test(struct dentry *dentry, unsigned int sigen)
9193+{
9194+ int err;
9195+
9196+ err = 0;
9197+ if (unlikely(au_digen(dentry) != sigen
5527c038 9198+ || au_iigen_test(d_inode(dentry), sigen)))
027c5e7a
AM
9199+ err = -EIO;
9200+
9201+ return err;
1facf9fc 9202+}
9203+
9204+void au_update_digen(struct dentry *dentry)
9205+{
9206+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
9207+ /* smp_mb(); */ /* atomic_set */
9208+}
9209+
9210+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
9211+{
9212+ struct au_dinfo *dinfo;
9213+ struct dentry *h_d;
4a4d8108 9214+ struct au_hdentry *hdp;
5afbbe0d 9215+ aufs_bindex_t bindex, bbot;
1facf9fc 9216+
1308ab2a 9217+ DiMustWriteLock(dentry);
9218+
1facf9fc 9219+ dinfo = au_di(dentry);
5afbbe0d 9220+ if (!dinfo || dinfo->di_btop < 0)
1facf9fc 9221+ return;
9222+
9223+ if (do_put_zero) {
5afbbe0d
AM
9224+ bbot = dinfo->di_bbot;
9225+ bindex = dinfo->di_btop;
9226+ hdp = au_hdentry(dinfo, bindex);
9227+ for (; bindex <= bbot; bindex++, hdp++) {
9228+ h_d = hdp->hd_dentry;
5527c038 9229+ if (h_d && d_is_negative(h_d))
1facf9fc 9230+ au_set_h_dptr(dentry, bindex, NULL);
9231+ }
9232+ }
9233+
5afbbe0d
AM
9234+ dinfo->di_btop = 0;
9235+ hdp = au_hdentry(dinfo, dinfo->di_btop);
9236+ for (; dinfo->di_btop <= dinfo->di_bbot; dinfo->di_btop++, hdp++)
9237+ if (hdp->hd_dentry)
1facf9fc 9238+ break;
5afbbe0d
AM
9239+ if (dinfo->di_btop > dinfo->di_bbot) {
9240+ dinfo->di_btop = -1;
9241+ dinfo->di_bbot = -1;
1facf9fc 9242+ return;
9243+ }
9244+
5afbbe0d
AM
9245+ hdp = au_hdentry(dinfo, dinfo->di_bbot);
9246+ for (; dinfo->di_bbot >= 0; dinfo->di_bbot--, hdp--)
9247+ if (hdp->hd_dentry)
1facf9fc 9248+ break;
5afbbe0d 9249+ AuDebugOn(dinfo->di_btop > dinfo->di_bbot || dinfo->di_bbot < 0);
1facf9fc 9250+}
9251+
5afbbe0d 9252+void au_update_dbtop(struct dentry *dentry)
1facf9fc 9253+{
5afbbe0d 9254+ aufs_bindex_t bindex, bbot;
1facf9fc 9255+ struct dentry *h_dentry;
9256+
5afbbe0d
AM
9257+ bbot = au_dbbot(dentry);
9258+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) {
1facf9fc 9259+ h_dentry = au_h_dptr(dentry, bindex);
9260+ if (!h_dentry)
9261+ continue;
5527c038 9262+ if (d_is_positive(h_dentry)) {
5afbbe0d 9263+ au_set_dbtop(dentry, bindex);
1facf9fc 9264+ return;
9265+ }
9266+ au_set_h_dptr(dentry, bindex, NULL);
9267+ }
9268+}
9269+
5afbbe0d 9270+void au_update_dbbot(struct dentry *dentry)
1facf9fc 9271+{
5afbbe0d 9272+ aufs_bindex_t bindex, btop;
1facf9fc 9273+ struct dentry *h_dentry;
9274+
5afbbe0d
AM
9275+ btop = au_dbtop(dentry);
9276+ for (bindex = au_dbbot(dentry); bindex >= btop; bindex--) {
1facf9fc 9277+ h_dentry = au_h_dptr(dentry, bindex);
9278+ if (!h_dentry)
9279+ continue;
5527c038 9280+ if (d_is_positive(h_dentry)) {
5afbbe0d 9281+ au_set_dbbot(dentry, bindex);
1facf9fc 9282+ return;
9283+ }
9284+ au_set_h_dptr(dentry, bindex, NULL);
9285+ }
9286+}
9287+
9288+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
9289+{
5afbbe0d 9290+ aufs_bindex_t bindex, bbot;
1facf9fc 9291+
5afbbe0d
AM
9292+ bbot = au_dbbot(dentry);
9293+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++)
1facf9fc 9294+ if (au_h_dptr(dentry, bindex) == h_dentry)
9295+ return bindex;
9296+ return -1;
9297+}
0b1ff5c3
JR
9298diff -urNp -x '*.orig' linux-4.14/fs/aufs/dir.c linux-4.14/fs/aufs/dir.c
9299--- linux-4.14/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
9300+++ linux-4.14/fs/aufs/dir.c 2021-02-24 21:42:43.441114748 +0100
1c60b727 9301@@ -0,0 +1,759 @@
1facf9fc 9302+/*
a2654f78 9303+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 9304+ *
9305+ * This program, aufs is free software; you can redistribute it and/or modify
9306+ * it under the terms of the GNU General Public License as published by
9307+ * the Free Software Foundation; either version 2 of the License, or
9308+ * (at your option) any later version.
dece6358
AM
9309+ *
9310+ * This program is distributed in the hope that it will be useful,
9311+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9312+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9313+ * GNU General Public License for more details.
9314+ *
9315+ * You should have received a copy of the GNU General Public License
523b37e3 9316+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 9317+ */
9318+
9319+/*
9320+ * directory operations
9321+ */
9322+
9323+#include <linux/fs_stack.h>
9324+#include "aufs.h"
9325+
9326+void au_add_nlink(struct inode *dir, struct inode *h_dir)
9327+{
9dbd164d
AM
9328+ unsigned int nlink;
9329+
1facf9fc 9330+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
9331+
9dbd164d
AM
9332+ nlink = dir->i_nlink;
9333+ nlink += h_dir->i_nlink - 2;
1facf9fc 9334+ if (h_dir->i_nlink < 2)
9dbd164d 9335+ nlink += 2;
f6b6e03d 9336+ smp_mb(); /* for i_nlink */
7eafdf33 9337+ /* 0 can happen in revaliding */
92d182d2 9338+ set_nlink(dir, nlink);
1facf9fc 9339+}
9340+
9341+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
9342+{
9dbd164d
AM
9343+ unsigned int nlink;
9344+
1facf9fc 9345+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
9346+
9dbd164d
AM
9347+ nlink = dir->i_nlink;
9348+ nlink -= h_dir->i_nlink - 2;
1facf9fc 9349+ if (h_dir->i_nlink < 2)
9dbd164d 9350+ nlink -= 2;
f6b6e03d 9351+ smp_mb(); /* for i_nlink */
92d182d2 9352+ /* nlink == 0 means the branch-fs is broken */
9dbd164d 9353+ set_nlink(dir, nlink);
1facf9fc 9354+}
9355+
1308ab2a 9356+loff_t au_dir_size(struct file *file, struct dentry *dentry)
9357+{
9358+ loff_t sz;
5afbbe0d 9359+ aufs_bindex_t bindex, bbot;
1308ab2a 9360+ struct file *h_file;
9361+ struct dentry *h_dentry;
9362+
9363+ sz = 0;
9364+ if (file) {
2000de60 9365+ AuDebugOn(!d_is_dir(file->f_path.dentry));
1308ab2a 9366+
5afbbe0d
AM
9367+ bbot = au_fbbot_dir(file);
9368+ for (bindex = au_fbtop(file);
9369+ bindex <= bbot && sz < KMALLOC_MAX_SIZE;
1308ab2a 9370+ bindex++) {
4a4d8108 9371+ h_file = au_hf_dir(file, bindex);
c06a8ce3
AM
9372+ if (h_file && file_inode(h_file))
9373+ sz += vfsub_f_size_read(h_file);
1308ab2a 9374+ }
9375+ } else {
9376+ AuDebugOn(!dentry);
2000de60 9377+ AuDebugOn(!d_is_dir(dentry));
1308ab2a 9378+
5afbbe0d
AM
9379+ bbot = au_dbtaildir(dentry);
9380+ for (bindex = au_dbtop(dentry);
9381+ bindex <= bbot && sz < KMALLOC_MAX_SIZE;
1308ab2a 9382+ bindex++) {
9383+ h_dentry = au_h_dptr(dentry, bindex);
5527c038
JR
9384+ if (h_dentry && d_is_positive(h_dentry))
9385+ sz += i_size_read(d_inode(h_dentry));
1308ab2a 9386+ }
9387+ }
9388+ if (sz < KMALLOC_MAX_SIZE)
9389+ sz = roundup_pow_of_two(sz);
9390+ if (sz > KMALLOC_MAX_SIZE)
9391+ sz = KMALLOC_MAX_SIZE;
9392+ else if (sz < NAME_MAX) {
9393+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
9394+ sz = AUFS_RDBLK_DEF;
9395+ }
9396+ return sz;
9397+}
9398+
b912730e
AM
9399+struct au_dir_ts_arg {
9400+ struct dentry *dentry;
9401+ aufs_bindex_t brid;
9402+};
9403+
9404+static void au_do_dir_ts(void *arg)
9405+{
9406+ struct au_dir_ts_arg *a = arg;
9407+ struct au_dtime dt;
9408+ struct path h_path;
9409+ struct inode *dir, *h_dir;
9410+ struct super_block *sb;
9411+ struct au_branch *br;
9412+ struct au_hinode *hdir;
9413+ int err;
5afbbe0d 9414+ aufs_bindex_t btop, bindex;
b912730e
AM
9415+
9416+ sb = a->dentry->d_sb;
5527c038 9417+ if (d_really_is_negative(a->dentry))
b912730e 9418+ goto out;
5527c038 9419+ /* no dir->i_mutex lock */
b95c5147
AM
9420+ aufs_read_lock(a->dentry, AuLock_DW); /* noflush */
9421+
5527c038 9422+ dir = d_inode(a->dentry);
5afbbe0d 9423+ btop = au_ibtop(dir);
b912730e 9424+ bindex = au_br_index(sb, a->brid);
5afbbe0d 9425+ if (bindex < btop)
b912730e
AM
9426+ goto out_unlock;
9427+
9428+ br = au_sbr(sb, bindex);
9429+ h_path.dentry = au_h_dptr(a->dentry, bindex);
9430+ if (!h_path.dentry)
9431+ goto out_unlock;
9432+ h_path.mnt = au_br_mnt(br);
9433+ au_dtime_store(&dt, a->dentry, &h_path);
9434+
5afbbe0d 9435+ br = au_sbr(sb, btop);
b912730e
AM
9436+ if (!au_br_writable(br->br_perm))
9437+ goto out_unlock;
5afbbe0d 9438+ h_path.dentry = au_h_dptr(a->dentry, btop);
b912730e
AM
9439+ h_path.mnt = au_br_mnt(br);
9440+ err = vfsub_mnt_want_write(h_path.mnt);
9441+ if (err)
9442+ goto out_unlock;
5afbbe0d
AM
9443+ hdir = au_hi(dir, btop);
9444+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
9445+ h_dir = au_h_iptr(dir, btop);
b912730e
AM
9446+ if (h_dir->i_nlink
9447+ && timespec_compare(&h_dir->i_mtime, &dt.dt_mtime) < 0) {
9448+ dt.dt_h_path = h_path;
9449+ au_dtime_revert(&dt);
9450+ }
5afbbe0d 9451+ au_hn_inode_unlock(hdir);
b912730e
AM
9452+ vfsub_mnt_drop_write(h_path.mnt);
9453+ au_cpup_attr_timesizes(dir);
9454+
9455+out_unlock:
9456+ aufs_read_unlock(a->dentry, AuLock_DW);
9457+out:
9458+ dput(a->dentry);
9459+ au_nwt_done(&au_sbi(sb)->si_nowait);
1c60b727 9460+ kfree(arg);
b912730e
AM
9461+}
9462+
9463+void au_dir_ts(struct inode *dir, aufs_bindex_t bindex)
9464+{
9465+ int perm, wkq_err;
5afbbe0d 9466+ aufs_bindex_t btop;
b912730e
AM
9467+ struct au_dir_ts_arg *arg;
9468+ struct dentry *dentry;
9469+ struct super_block *sb;
9470+
9471+ IMustLock(dir);
9472+
9473+ dentry = d_find_any_alias(dir);
9474+ AuDebugOn(!dentry);
9475+ sb = dentry->d_sb;
5afbbe0d
AM
9476+ btop = au_ibtop(dir);
9477+ if (btop == bindex) {
b912730e
AM
9478+ au_cpup_attr_timesizes(dir);
9479+ goto out;
9480+ }
9481+
5afbbe0d 9482+ perm = au_sbr_perm(sb, btop);
b912730e
AM
9483+ if (!au_br_writable(perm))
9484+ goto out;
9485+
9486+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
9487+ if (!arg)
9488+ goto out;
9489+
9490+ arg->dentry = dget(dentry); /* will be dput-ted by au_do_dir_ts() */
9491+ arg->brid = au_sbr_id(sb, bindex);
9492+ wkq_err = au_wkq_nowait(au_do_dir_ts, arg, sb, /*flags*/0);
9493+ if (unlikely(wkq_err)) {
9494+ pr_err("wkq %d\n", wkq_err);
9495+ dput(dentry);
1c60b727 9496+ kfree(arg);
b912730e
AM
9497+ }
9498+
9499+out:
9500+ dput(dentry);
9501+}
9502+
1facf9fc 9503+/* ---------------------------------------------------------------------- */
9504+
9505+static int reopen_dir(struct file *file)
9506+{
9507+ int err;
9508+ unsigned int flags;
5afbbe0d 9509+ aufs_bindex_t bindex, btail, btop;
1facf9fc 9510+ struct dentry *dentry, *h_dentry;
9511+ struct file *h_file;
9512+
9513+ /* open all lower dirs */
2000de60 9514+ dentry = file->f_path.dentry;
5afbbe0d
AM
9515+ btop = au_dbtop(dentry);
9516+ for (bindex = au_fbtop(file); bindex < btop; bindex++)
1facf9fc 9517+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d 9518+ au_set_fbtop(file, btop);
1facf9fc 9519+
9520+ btail = au_dbtaildir(dentry);
5afbbe0d 9521+ for (bindex = au_fbbot_dir(file); btail < bindex; bindex--)
1facf9fc 9522+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d 9523+ au_set_fbbot_dir(file, btail);
1facf9fc 9524+
4a4d8108 9525+ flags = vfsub_file_flags(file);
5afbbe0d 9526+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 9527+ h_dentry = au_h_dptr(dentry, bindex);
9528+ if (!h_dentry)
9529+ continue;
4a4d8108 9530+ h_file = au_hf_dir(file, bindex);
1facf9fc 9531+ if (h_file)
9532+ continue;
9533+
392086de 9534+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
1facf9fc 9535+ err = PTR_ERR(h_file);
9536+ if (IS_ERR(h_file))
9537+ goto out; /* close all? */
9538+ au_set_h_fptr(file, bindex, h_file);
9539+ }
9540+ au_update_figen(file);
9541+ /* todo: necessary? */
9542+ /* file->f_ra = h_file->f_ra; */
9543+ err = 0;
9544+
4f0767ce 9545+out:
1facf9fc 9546+ return err;
9547+}
9548+
b912730e 9549+static int do_open_dir(struct file *file, int flags, struct file *h_file)
1facf9fc 9550+{
9551+ int err;
9552+ aufs_bindex_t bindex, btail;
9553+ struct dentry *dentry, *h_dentry;
8cdd5066 9554+ struct vfsmount *mnt;
1facf9fc 9555+
1308ab2a 9556+ FiMustWriteLock(file);
b912730e 9557+ AuDebugOn(h_file);
1308ab2a 9558+
523b37e3 9559+ err = 0;
8cdd5066 9560+ mnt = file->f_path.mnt;
2000de60 9561+ dentry = file->f_path.dentry;
5527c038 9562+ file->f_version = d_inode(dentry)->i_version;
5afbbe0d
AM
9563+ bindex = au_dbtop(dentry);
9564+ au_set_fbtop(file, bindex);
1facf9fc 9565+ btail = au_dbtaildir(dentry);
5afbbe0d 9566+ au_set_fbbot_dir(file, btail);
1facf9fc 9567+ for (; !err && bindex <= btail; bindex++) {
9568+ h_dentry = au_h_dptr(dentry, bindex);
9569+ if (!h_dentry)
9570+ continue;
9571+
8cdd5066
JR
9572+ err = vfsub_test_mntns(mnt, h_dentry->d_sb);
9573+ if (unlikely(err))
9574+ break;
392086de 9575+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
1facf9fc 9576+ if (IS_ERR(h_file)) {
9577+ err = PTR_ERR(h_file);
9578+ break;
9579+ }
9580+ au_set_h_fptr(file, bindex, h_file);
9581+ }
9582+ au_update_figen(file);
9583+ /* todo: necessary? */
9584+ /* file->f_ra = h_file->f_ra; */
9585+ if (!err)
9586+ return 0; /* success */
9587+
9588+ /* close all */
5afbbe0d 9589+ for (bindex = au_fbtop(file); bindex <= btail; bindex++)
1facf9fc 9590+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d
AM
9591+ au_set_fbtop(file, -1);
9592+ au_set_fbbot_dir(file, -1);
4a4d8108 9593+
1facf9fc 9594+ return err;
9595+}
9596+
9597+static int aufs_open_dir(struct inode *inode __maybe_unused,
9598+ struct file *file)
9599+{
4a4d8108
AM
9600+ int err;
9601+ struct super_block *sb;
9602+ struct au_fidir *fidir;
9603+
9604+ err = -ENOMEM;
2000de60 9605+ sb = file->f_path.dentry->d_sb;
4a4d8108 9606+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 9607+ fidir = au_fidir_alloc(sb);
4a4d8108 9608+ if (fidir) {
b912730e
AM
9609+ struct au_do_open_args args = {
9610+ .open = do_open_dir,
9611+ .fidir = fidir
9612+ };
9613+ err = au_do_open(file, &args);
4a4d8108 9614+ if (unlikely(err))
1c60b727 9615+ kfree(fidir);
4a4d8108
AM
9616+ }
9617+ si_read_unlock(sb);
9618+ return err;
1facf9fc 9619+}
9620+
9621+static int aufs_release_dir(struct inode *inode __maybe_unused,
9622+ struct file *file)
9623+{
9624+ struct au_vdir *vdir_cache;
4a4d8108
AM
9625+ struct au_finfo *finfo;
9626+ struct au_fidir *fidir;
f0c0a007 9627+ struct au_hfile *hf;
5afbbe0d 9628+ aufs_bindex_t bindex, bbot;
1facf9fc 9629+
4a4d8108
AM
9630+ finfo = au_fi(file);
9631+ fidir = finfo->fi_hdir;
9632+ if (fidir) {
8b6a4947
AM
9633+ au_hbl_del(&finfo->fi_hlist,
9634+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
4a4d8108
AM
9635+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
9636+ if (vdir_cache)
1c60b727 9637+ au_vdir_free(vdir_cache);
4a4d8108
AM
9638+
9639+ bindex = finfo->fi_btop;
9640+ if (bindex >= 0) {
f0c0a007 9641+ hf = fidir->fd_hfile + bindex;
4a4d8108
AM
9642+ /*
9643+ * calls fput() instead of filp_close(),
9644+ * since no dnotify or lock for the lower file.
9645+ */
5afbbe0d 9646+ bbot = fidir->fd_bbot;
f0c0a007
AM
9647+ for (; bindex <= bbot; bindex++, hf++)
9648+ if (hf->hf_file)
1c60b727 9649+ au_hfput(hf, /*execed*/0);
4a4d8108 9650+ }
1c60b727 9651+ kfree(fidir);
4a4d8108 9652+ finfo->fi_hdir = NULL;
1facf9fc 9653+ }
1c60b727 9654+ au_finfo_fin(file);
1facf9fc 9655+ return 0;
9656+}
9657+
9658+/* ---------------------------------------------------------------------- */
9659+
4a4d8108
AM
9660+static int au_do_flush_dir(struct file *file, fl_owner_t id)
9661+{
9662+ int err;
5afbbe0d 9663+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
9664+ struct file *h_file;
9665+
9666+ err = 0;
5afbbe0d
AM
9667+ bbot = au_fbbot_dir(file);
9668+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
4a4d8108
AM
9669+ h_file = au_hf_dir(file, bindex);
9670+ if (h_file)
9671+ err = vfsub_flush(h_file, id);
9672+ }
9673+ return err;
9674+}
9675+
9676+static int aufs_flush_dir(struct file *file, fl_owner_t id)
9677+{
9678+ return au_do_flush(file, id, au_do_flush_dir);
9679+}
9680+
9681+/* ---------------------------------------------------------------------- */
9682+
1facf9fc 9683+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
9684+{
9685+ int err;
5afbbe0d 9686+ aufs_bindex_t bbot, bindex;
1facf9fc 9687+ struct inode *inode;
9688+ struct super_block *sb;
9689+
9690+ err = 0;
9691+ sb = dentry->d_sb;
5527c038 9692+ inode = d_inode(dentry);
1facf9fc 9693+ IMustLock(inode);
5afbbe0d
AM
9694+ bbot = au_dbbot(dentry);
9695+ for (bindex = au_dbtop(dentry); !err && bindex <= bbot; bindex++) {
1facf9fc 9696+ struct path h_path;
1facf9fc 9697+
9698+ if (au_test_ro(sb, bindex, inode))
9699+ continue;
9700+ h_path.dentry = au_h_dptr(dentry, bindex);
9701+ if (!h_path.dentry)
9702+ continue;
1facf9fc 9703+
1facf9fc 9704+ h_path.mnt = au_sbr_mnt(sb, bindex);
53392da6 9705+ err = vfsub_fsync(NULL, &h_path, datasync);
1facf9fc 9706+ }
9707+
9708+ return err;
9709+}
9710+
9711+static int au_do_fsync_dir(struct file *file, int datasync)
9712+{
9713+ int err;
5afbbe0d 9714+ aufs_bindex_t bbot, bindex;
1facf9fc 9715+ struct file *h_file;
9716+ struct super_block *sb;
9717+ struct inode *inode;
1facf9fc 9718+
521ced18 9719+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0);
1facf9fc 9720+ if (unlikely(err))
9721+ goto out;
9722+
c06a8ce3 9723+ inode = file_inode(file);
b912730e 9724+ sb = inode->i_sb;
5afbbe0d
AM
9725+ bbot = au_fbbot_dir(file);
9726+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
4a4d8108 9727+ h_file = au_hf_dir(file, bindex);
1facf9fc 9728+ if (!h_file || au_test_ro(sb, bindex, inode))
9729+ continue;
9730+
53392da6 9731+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
1facf9fc 9732+ }
9733+
4f0767ce 9734+out:
1facf9fc 9735+ return err;
9736+}
9737+
9738+/*
9739+ * @file may be NULL
9740+ */
1e00d052
AM
9741+static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end,
9742+ int datasync)
1facf9fc 9743+{
9744+ int err;
b752ccd1 9745+ struct dentry *dentry;
5527c038 9746+ struct inode *inode;
1facf9fc 9747+ struct super_block *sb;
1facf9fc 9748+
9749+ err = 0;
2000de60 9750+ dentry = file->f_path.dentry;
5527c038 9751+ inode = d_inode(dentry);
febd17d6 9752+ inode_lock(inode);
1facf9fc 9753+ sb = dentry->d_sb;
9754+ si_noflush_read_lock(sb);
9755+ if (file)
9756+ err = au_do_fsync_dir(file, datasync);
9757+ else {
9758+ di_write_lock_child(dentry);
9759+ err = au_do_fsync_dir_no_file(dentry, datasync);
9760+ }
5527c038 9761+ au_cpup_attr_timesizes(inode);
1facf9fc 9762+ di_write_unlock(dentry);
9763+ if (file)
9764+ fi_write_unlock(file);
9765+
9766+ si_read_unlock(sb);
febd17d6 9767+ inode_unlock(inode);
1facf9fc 9768+ return err;
9769+}
9770+
9771+/* ---------------------------------------------------------------------- */
9772+
5afbbe0d 9773+static int aufs_iterate_shared(struct file *file, struct dir_context *ctx)
1facf9fc 9774+{
9775+ int err;
9776+ struct dentry *dentry;
9dbd164d 9777+ struct inode *inode, *h_inode;
1facf9fc 9778+ struct super_block *sb;
9779+
523b37e3 9780+ AuDbg("%pD, ctx{%pf, %llu}\n", file, ctx->actor, ctx->pos);
392086de 9781+
2000de60 9782+ dentry = file->f_path.dentry;
5527c038 9783+ inode = d_inode(dentry);
1facf9fc 9784+ IMustLock(inode);
9785+
9786+ sb = dentry->d_sb;
9787+ si_read_lock(sb, AuLock_FLUSH);
521ced18 9788+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0);
1facf9fc 9789+ if (unlikely(err))
9790+ goto out;
027c5e7a
AM
9791+ err = au_alive_dir(dentry);
9792+ if (!err)
9793+ err = au_vdir_init(file);
1facf9fc 9794+ di_downgrade_lock(dentry, AuLock_IR);
9795+ if (unlikely(err))
9796+ goto out_unlock;
9797+
5afbbe0d 9798+ h_inode = au_h_iptr(inode, au_ibtop(inode));
b752ccd1 9799+ if (!au_test_nfsd()) {
392086de 9800+ err = au_vdir_fill_de(file, ctx);
9dbd164d 9801+ fsstack_copy_attr_atime(inode, h_inode);
1facf9fc 9802+ } else {
9803+ /*
9804+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
9805+ * encode_fh() and others.
9806+ */
9dbd164d 9807+ atomic_inc(&h_inode->i_count);
1facf9fc 9808+ di_read_unlock(dentry, AuLock_IR);
9809+ si_read_unlock(sb);
392086de 9810+ err = au_vdir_fill_de(file, ctx);
1facf9fc 9811+ fsstack_copy_attr_atime(inode, h_inode);
9812+ fi_write_unlock(file);
9dbd164d 9813+ iput(h_inode);
1facf9fc 9814+
9815+ AuTraceErr(err);
9816+ return err;
9817+ }
9818+
4f0767ce 9819+out_unlock:
1facf9fc 9820+ di_read_unlock(dentry, AuLock_IR);
9821+ fi_write_unlock(file);
4f0767ce 9822+out:
1facf9fc 9823+ si_read_unlock(sb);
9824+ return err;
9825+}
9826+
9827+/* ---------------------------------------------------------------------- */
9828+
9829+#define AuTestEmpty_WHONLY 1
dece6358
AM
9830+#define AuTestEmpty_CALLED (1 << 1)
9831+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 9832+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
7f207e10
AM
9833+#define au_fset_testempty(flags, name) \
9834+ do { (flags) |= AuTestEmpty_##name; } while (0)
9835+#define au_fclr_testempty(flags, name) \
9836+ do { (flags) &= ~AuTestEmpty_##name; } while (0)
1facf9fc 9837+
dece6358
AM
9838+#ifndef CONFIG_AUFS_SHWH
9839+#undef AuTestEmpty_SHWH
9840+#define AuTestEmpty_SHWH 0
9841+#endif
9842+
1facf9fc 9843+struct test_empty_arg {
392086de 9844+ struct dir_context ctx;
1308ab2a 9845+ struct au_nhash *whlist;
1facf9fc 9846+ unsigned int flags;
9847+ int err;
9848+ aufs_bindex_t bindex;
9849+};
9850+
392086de
AM
9851+static int test_empty_cb(struct dir_context *ctx, const char *__name,
9852+ int namelen, loff_t offset __maybe_unused, u64 ino,
dece6358 9853+ unsigned int d_type)
1facf9fc 9854+{
392086de
AM
9855+ struct test_empty_arg *arg = container_of(ctx, struct test_empty_arg,
9856+ ctx);
1facf9fc 9857+ char *name = (void *)__name;
9858+
9859+ arg->err = 0;
9860+ au_fset_testempty(arg->flags, CALLED);
9861+ /* smp_mb(); */
9862+ if (name[0] == '.'
9863+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
9864+ goto out; /* success */
9865+
9866+ if (namelen <= AUFS_WH_PFX_LEN
9867+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
9868+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 9869+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 9870+ arg->err = -ENOTEMPTY;
9871+ goto out;
9872+ }
9873+
9874+ name += AUFS_WH_PFX_LEN;
9875+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 9876+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 9877+ arg->err = au_nhash_append_wh
1308ab2a 9878+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 9879+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 9880+
4f0767ce 9881+out:
1facf9fc 9882+ /* smp_mb(); */
9883+ AuTraceErr(arg->err);
9884+ return arg->err;
9885+}
9886+
9887+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
9888+{
9889+ int err;
9890+ struct file *h_file;
9891+
9892+ h_file = au_h_open(dentry, arg->bindex,
9893+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
392086de 9894+ /*file*/NULL, /*force_wr*/0);
1facf9fc 9895+ err = PTR_ERR(h_file);
9896+ if (IS_ERR(h_file))
9897+ goto out;
9898+
9899+ err = 0;
9900+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
c06a8ce3 9901+ && !file_inode(h_file)->i_nlink)
1facf9fc 9902+ goto out_put;
9903+
9904+ do {
9905+ arg->err = 0;
9906+ au_fclr_testempty(arg->flags, CALLED);
9907+ /* smp_mb(); */
392086de 9908+ err = vfsub_iterate_dir(h_file, &arg->ctx);
1facf9fc 9909+ if (err >= 0)
9910+ err = arg->err;
9911+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
9912+
4f0767ce 9913+out_put:
1facf9fc 9914+ fput(h_file);
9915+ au_sbr_put(dentry->d_sb, arg->bindex);
4f0767ce 9916+out:
1facf9fc 9917+ return err;
9918+}
9919+
9920+struct do_test_empty_args {
9921+ int *errp;
9922+ struct dentry *dentry;
9923+ struct test_empty_arg *arg;
9924+};
9925+
9926+static void call_do_test_empty(void *args)
9927+{
9928+ struct do_test_empty_args *a = args;
9929+ *a->errp = do_test_empty(a->dentry, a->arg);
9930+}
9931+
9932+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
9933+{
9934+ int err, wkq_err;
9935+ struct dentry *h_dentry;
9936+ struct inode *h_inode;
9937+
9938+ h_dentry = au_h_dptr(dentry, arg->bindex);
5527c038 9939+ h_inode = d_inode(h_dentry);
53392da6 9940+ /* todo: i_mode changes anytime? */
3c1bdaff 9941+ vfsub_inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
1facf9fc 9942+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
3c1bdaff 9943+ inode_unlock_shared(h_inode);
1facf9fc 9944+ if (!err)
9945+ err = do_test_empty(dentry, arg);
9946+ else {
9947+ struct do_test_empty_args args = {
9948+ .errp = &err,
9949+ .dentry = dentry,
9950+ .arg = arg
9951+ };
9952+ unsigned int flags = arg->flags;
9953+
9954+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
9955+ if (unlikely(wkq_err))
9956+ err = wkq_err;
9957+ arg->flags = flags;
9958+ }
9959+
9960+ return err;
9961+}
9962+
9963+int au_test_empty_lower(struct dentry *dentry)
9964+{
9965+ int err;
1308ab2a 9966+ unsigned int rdhash;
5afbbe0d 9967+ aufs_bindex_t bindex, btop, btail;
1308ab2a 9968+ struct au_nhash whlist;
392086de
AM
9969+ struct test_empty_arg arg = {
9970+ .ctx = {
2000de60 9971+ .actor = test_empty_cb
392086de
AM
9972+ }
9973+ };
076b876e 9974+ int (*test_empty)(struct dentry *dentry, struct test_empty_arg *arg);
1facf9fc 9975+
dece6358
AM
9976+ SiMustAnyLock(dentry->d_sb);
9977+
1308ab2a 9978+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
9979+ if (!rdhash)
9980+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
9981+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 9982+ if (unlikely(err))
1facf9fc 9983+ goto out;
9984+
1facf9fc 9985+ arg.flags = 0;
1308ab2a 9986+ arg.whlist = &whlist;
5afbbe0d 9987+ btop = au_dbtop(dentry);
dece6358
AM
9988+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
9989+ au_fset_testempty(arg.flags, SHWH);
076b876e
AM
9990+ test_empty = do_test_empty;
9991+ if (au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1))
9992+ test_empty = sio_test_empty;
5afbbe0d 9993+ arg.bindex = btop;
076b876e 9994+ err = test_empty(dentry, &arg);
1facf9fc 9995+ if (unlikely(err))
9996+ goto out_whlist;
9997+
9998+ au_fset_testempty(arg.flags, WHONLY);
9999+ btail = au_dbtaildir(dentry);
5afbbe0d 10000+ for (bindex = btop + 1; !err && bindex <= btail; bindex++) {
1facf9fc 10001+ struct dentry *h_dentry;
10002+
10003+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 10004+ if (h_dentry && d_is_positive(h_dentry)) {
1facf9fc 10005+ arg.bindex = bindex;
076b876e 10006+ err = test_empty(dentry, &arg);
1facf9fc 10007+ }
10008+ }
10009+
4f0767ce 10010+out_whlist:
1308ab2a 10011+ au_nhash_wh_free(&whlist);
4f0767ce 10012+out:
1facf9fc 10013+ return err;
10014+}
10015+
10016+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
10017+{
10018+ int err;
392086de
AM
10019+ struct test_empty_arg arg = {
10020+ .ctx = {
2000de60 10021+ .actor = test_empty_cb
392086de
AM
10022+ }
10023+ };
1facf9fc 10024+ aufs_bindex_t bindex, btail;
10025+
10026+ err = 0;
1308ab2a 10027+ arg.whlist = whlist;
1facf9fc 10028+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
10029+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
10030+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 10031+ btail = au_dbtaildir(dentry);
5afbbe0d 10032+ for (bindex = au_dbtop(dentry); !err && bindex <= btail; bindex++) {
1facf9fc 10033+ struct dentry *h_dentry;
10034+
10035+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 10036+ if (h_dentry && d_is_positive(h_dentry)) {
1facf9fc 10037+ arg.bindex = bindex;
10038+ err = sio_test_empty(dentry, &arg);
10039+ }
10040+ }
10041+
10042+ return err;
10043+}
10044+
10045+/* ---------------------------------------------------------------------- */
10046+
10047+const struct file_operations aufs_dir_fop = {
4a4d8108 10048+ .owner = THIS_MODULE,
027c5e7a 10049+ .llseek = default_llseek,
1facf9fc 10050+ .read = generic_read_dir,
5afbbe0d 10051+ .iterate_shared = aufs_iterate_shared,
1facf9fc 10052+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
10053+#ifdef CONFIG_COMPAT
10054+ .compat_ioctl = aufs_compat_ioctl_dir,
10055+#endif
1facf9fc 10056+ .open = aufs_open_dir,
10057+ .release = aufs_release_dir,
4a4d8108 10058+ .flush = aufs_flush_dir,
1facf9fc 10059+ .fsync = aufs_fsync_dir
10060+};
0b1ff5c3
JR
10061diff -urNp -x '*.orig' linux-4.14/fs/aufs/dir.h linux-4.14/fs/aufs/dir.h
10062--- linux-4.14/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
10063+++ linux-4.14/fs/aufs/dir.h 2021-02-24 21:42:43.441114748 +0100
1c60b727 10064@@ -0,0 +1,131 @@
1facf9fc 10065+/*
a2654f78 10066+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 10067+ *
10068+ * This program, aufs is free software; you can redistribute it and/or modify
10069+ * it under the terms of the GNU General Public License as published by
10070+ * the Free Software Foundation; either version 2 of the License, or
10071+ * (at your option) any later version.
dece6358
AM
10072+ *
10073+ * This program is distributed in the hope that it will be useful,
10074+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10075+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10076+ * GNU General Public License for more details.
10077+ *
10078+ * You should have received a copy of the GNU General Public License
523b37e3 10079+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 10080+ */
10081+
10082+/*
10083+ * directory operations
10084+ */
10085+
10086+#ifndef __AUFS_DIR_H__
10087+#define __AUFS_DIR_H__
10088+
10089+#ifdef __KERNEL__
10090+
10091+#include <linux/fs.h>
1facf9fc 10092+
10093+/* ---------------------------------------------------------------------- */
10094+
10095+/* need to be faster and smaller */
10096+
10097+struct au_nhash {
dece6358
AM
10098+ unsigned int nh_num;
10099+ struct hlist_head *nh_head;
1facf9fc 10100+};
10101+
10102+struct au_vdir_destr {
10103+ unsigned char len;
10104+ unsigned char name[0];
10105+} __packed;
10106+
10107+struct au_vdir_dehstr {
10108+ struct hlist_node hash;
1c60b727 10109+ struct au_vdir_destr *str;
4a4d8108 10110+} ____cacheline_aligned_in_smp;
1facf9fc 10111+
10112+struct au_vdir_de {
10113+ ino_t de_ino;
10114+ unsigned char de_type;
10115+ /* caution: packed */
10116+ struct au_vdir_destr de_str;
10117+} __packed;
10118+
10119+struct au_vdir_wh {
10120+ struct hlist_node wh_hash;
dece6358
AM
10121+#ifdef CONFIG_AUFS_SHWH
10122+ ino_t wh_ino;
1facf9fc 10123+ aufs_bindex_t wh_bindex;
dece6358
AM
10124+ unsigned char wh_type;
10125+#else
10126+ aufs_bindex_t wh_bindex;
10127+#endif
10128+ /* caution: packed */
1facf9fc 10129+ struct au_vdir_destr wh_str;
10130+} __packed;
10131+
10132+union au_vdir_deblk_p {
10133+ unsigned char *deblk;
10134+ struct au_vdir_de *de;
10135+};
10136+
10137+struct au_vdir {
10138+ unsigned char **vd_deblk;
10139+ unsigned long vd_nblk;
1facf9fc 10140+ struct {
10141+ unsigned long ul;
10142+ union au_vdir_deblk_p p;
10143+ } vd_last;
10144+
10145+ unsigned long vd_version;
dece6358 10146+ unsigned int vd_deblk_sz;
1c60b727 10147+ unsigned long vd_jiffy;
4a4d8108 10148+} ____cacheline_aligned_in_smp;
1facf9fc 10149+
10150+/* ---------------------------------------------------------------------- */
10151+
10152+/* dir.c */
10153+extern const struct file_operations aufs_dir_fop;
10154+void au_add_nlink(struct inode *dir, struct inode *h_dir);
10155+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 10156+loff_t au_dir_size(struct file *file, struct dentry *dentry);
b912730e 10157+void au_dir_ts(struct inode *dir, aufs_bindex_t bsrc);
1facf9fc 10158+int au_test_empty_lower(struct dentry *dentry);
10159+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
10160+
10161+/* vdir.c */
1308ab2a 10162+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
10163+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
10164+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 10165+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
10166+ int limit);
dece6358
AM
10167+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
10168+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
10169+ unsigned int d_type, aufs_bindex_t bindex,
10170+ unsigned char shwh);
1c60b727 10171+void au_vdir_free(struct au_vdir *vdir);
1facf9fc 10172+int au_vdir_init(struct file *file);
392086de 10173+int au_vdir_fill_de(struct file *file, struct dir_context *ctx);
1facf9fc 10174+
10175+/* ioctl.c */
10176+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
10177+
1308ab2a 10178+#ifdef CONFIG_AUFS_RDU
10179+/* rdu.c */
10180+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
10181+#ifdef CONFIG_COMPAT
10182+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
10183+ unsigned long arg);
10184+#endif
1308ab2a 10185+#else
c1595e42
JR
10186+AuStub(long, au_rdu_ioctl, return -EINVAL, struct file *file,
10187+ unsigned int cmd, unsigned long arg)
b752ccd1 10188+#ifdef CONFIG_COMPAT
c1595e42
JR
10189+AuStub(long, au_rdu_compat_ioctl, return -EINVAL, struct file *file,
10190+ unsigned int cmd, unsigned long arg)
b752ccd1 10191+#endif
1308ab2a 10192+#endif
10193+
1facf9fc 10194+#endif /* __KERNEL__ */
10195+#endif /* __AUFS_DIR_H__ */
0b1ff5c3
JR
10196diff -urNp -x '*.orig' linux-4.14/fs/aufs/dirren.c linux-4.14/fs/aufs/dirren.c
10197--- linux-4.14/fs/aufs/dirren.c 1970-01-01 01:00:00.000000000 +0100
10198+++ linux-4.14/fs/aufs/dirren.c 2021-02-24 21:42:43.441114748 +0100
8b6a4947
AM
10199@@ -0,0 +1,1315 @@
10200+/*
10201+ * Copyright (C) 2017 Junjiro R. Okajima
10202+ *
10203+ * This program, aufs is free software; you can redistribute it and/or modify
10204+ * it under the terms of the GNU General Public License as published by
10205+ * the Free Software Foundation; either version 2 of the License, or
10206+ * (at your option) any later version.
10207+ *
10208+ * This program is distributed in the hope that it will be useful,
10209+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10210+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10211+ * GNU General Public License for more details.
10212+ *
10213+ * You should have received a copy of the GNU General Public License
10214+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
10215+ */
10216+
10217+/*
10218+ * special handling in renaming a directoy
10219+ * in order to support looking-up the before-renamed name on the lower readonly
10220+ * branches
10221+ */
10222+
10223+#include <linux/byteorder/generic.h>
10224+#include "aufs.h"
10225+
10226+static void au_dr_hino_del(struct au_dr_br *dr, struct au_dr_hino *ent)
10227+{
10228+ int idx;
10229+
10230+ idx = au_dr_ihash(ent->dr_h_ino);
10231+ au_hbl_del(&ent->dr_hnode, dr->dr_h_ino + idx);
10232+}
10233+
10234+static int au_dr_hino_test_empty(struct au_dr_br *dr)
10235+{
10236+ int ret, i;
10237+ struct hlist_bl_head *hbl;
10238+
10239+ ret = 1;
10240+ for (i = 0; ret && i < AuDirren_NHASH; i++) {
10241+ hbl = dr->dr_h_ino + i;
10242+ hlist_bl_lock(hbl);
10243+ ret &= hlist_bl_empty(hbl);
10244+ hlist_bl_unlock(hbl);
10245+ }
10246+
10247+ return ret;
10248+}
10249+
10250+static struct au_dr_hino *au_dr_hino_find(struct au_dr_br *dr, ino_t ino)
10251+{
10252+ struct au_dr_hino *found, *ent;
10253+ struct hlist_bl_head *hbl;
10254+ struct hlist_bl_node *pos;
10255+ int idx;
10256+
10257+ found = NULL;
10258+ idx = au_dr_ihash(ino);
10259+ hbl = dr->dr_h_ino + idx;
10260+ hlist_bl_lock(hbl);
10261+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode)
10262+ if (ent->dr_h_ino == ino) {
10263+ found = ent;
10264+ break;
10265+ }
10266+ hlist_bl_unlock(hbl);
10267+
10268+ return found;
10269+}
10270+
10271+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t ino,
10272+ struct au_dr_hino *add_ent)
10273+{
10274+ int found, idx;
10275+ struct hlist_bl_head *hbl;
10276+ struct hlist_bl_node *pos;
10277+ struct au_dr_hino *ent;
10278+
10279+ found = 0;
10280+ idx = au_dr_ihash(ino);
10281+ hbl = dr->dr_h_ino + idx;
10282+#if 0
10283+ {
10284+ struct hlist_bl_node *tmp;
10285+
10286+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode)
10287+ AuDbg("hi%llu\n", (unsigned long long)ent->dr_h_ino);
10288+ }
10289+#endif
10290+ hlist_bl_lock(hbl);
10291+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode)
10292+ if (ent->dr_h_ino == ino) {
10293+ found = 1;
10294+ break;
10295+ }
10296+ if (!found && add_ent)
10297+ hlist_bl_add_head(&add_ent->dr_hnode, hbl);
10298+ hlist_bl_unlock(hbl);
10299+
10300+ if (!found && add_ent)
10301+ AuDbg("i%llu added\n", (unsigned long long)add_ent->dr_h_ino);
10302+
10303+ return found;
10304+}
10305+
10306+void au_dr_hino_free(struct au_dr_br *dr)
10307+{
10308+ int i;
10309+ struct hlist_bl_head *hbl;
10310+ struct hlist_bl_node *pos, *tmp;
10311+ struct au_dr_hino *ent;
10312+
10313+ /* SiMustWriteLock(sb); */
10314+
10315+ for (i = 0; i < AuDirren_NHASH; i++) {
10316+ hbl = dr->dr_h_ino + i;
10317+ /* no spinlock since sbinfo must be write-locked */
10318+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode)
10319+ kfree(ent);
10320+ INIT_HLIST_BL_HEAD(hbl);
10321+ }
10322+}
10323+
10324+/* returns the number of inodes or an error */
10325+static int au_dr_hino_store(struct super_block *sb, struct au_branch *br,
10326+ struct file *hinofile)
10327+{
10328+ int err, i;
10329+ ssize_t ssz;
10330+ loff_t pos, oldsize;
10331+ __be64 u64;
10332+ struct inode *hinoinode;
10333+ struct hlist_bl_head *hbl;
10334+ struct hlist_bl_node *n1, *n2;
10335+ struct au_dr_hino *ent;
10336+
10337+ SiMustWriteLock(sb);
10338+ AuDebugOn(!au_br_writable(br->br_perm));
10339+
10340+ hinoinode = file_inode(hinofile);
10341+ oldsize = i_size_read(hinoinode);
10342+
10343+ err = 0;
10344+ pos = 0;
10345+ hbl = br->br_dirren.dr_h_ino;
10346+ for (i = 0; !err && i < AuDirren_NHASH; i++, hbl++) {
10347+ /* no bit-lock since sbinfo must be write-locked */
10348+ hlist_bl_for_each_entry_safe(ent, n1, n2, hbl, dr_hnode) {
10349+ AuDbg("hi%llu, %pD2\n",
10350+ (unsigned long long)ent->dr_h_ino, hinofile);
10351+ u64 = cpu_to_be64(ent->dr_h_ino);
10352+ ssz = vfsub_write_k(hinofile, &u64, sizeof(u64), &pos);
10353+ if (ssz == sizeof(u64))
10354+ continue;
10355+
10356+ /* write error */
10357+ pr_err("ssz %zd, %pD2\n", ssz, hinofile);
10358+ err = -ENOSPC;
10359+ if (ssz < 0)
10360+ err = ssz;
10361+ break;
10362+ }
10363+ }
10364+ /* regardless the error */
10365+ if (pos < oldsize) {
10366+ err = vfsub_trunc(&hinofile->f_path, pos, /*attr*/0, hinofile);
10367+ AuTraceErr(err);
10368+ }
10369+
10370+ AuTraceErr(err);
10371+ return err;
10372+}
10373+
10374+static int au_dr_hino_load(struct au_dr_br *dr, struct file *hinofile)
10375+{
10376+ int err, hidx;
10377+ ssize_t ssz;
10378+ size_t sz, n;
10379+ loff_t pos;
10380+ uint64_t u64;
10381+ struct au_dr_hino *ent;
10382+ struct inode *hinoinode;
10383+ struct hlist_bl_head *hbl;
10384+
10385+ err = 0;
10386+ pos = 0;
10387+ hbl = dr->dr_h_ino;
10388+ hinoinode = file_inode(hinofile);
10389+ sz = i_size_read(hinoinode);
10390+ AuDebugOn(sz % sizeof(u64));
10391+ n = sz / sizeof(u64);
10392+ while (n--) {
10393+ ssz = vfsub_read_k(hinofile, &u64, sizeof(u64), &pos);
10394+ if (unlikely(ssz != sizeof(u64))) {
10395+ pr_err("ssz %zd, %pD2\n", ssz, hinofile);
10396+ err = -EINVAL;
10397+ if (ssz < 0)
10398+ err = ssz;
10399+ goto out_free;
10400+ }
10401+
10402+ ent = kmalloc(sizeof(*ent), GFP_NOFS);
10403+ if (!ent) {
10404+ err = -ENOMEM;
10405+ AuTraceErr(err);
10406+ goto out_free;
10407+ }
10408+ ent->dr_h_ino = be64_to_cpu((__force __be64)u64);
10409+ AuDbg("hi%llu, %pD2\n",
10410+ (unsigned long long)ent->dr_h_ino, hinofile);
10411+ hidx = au_dr_ihash(ent->dr_h_ino);
10412+ au_hbl_add(&ent->dr_hnode, hbl + hidx);
10413+ }
10414+ goto out; /* success */
10415+
10416+out_free:
10417+ au_dr_hino_free(dr);
10418+out:
10419+ AuTraceErr(err);
10420+ return err;
10421+}
10422+
10423+/*
10424+ * @bindex/@br is a switch to distinguish whether suspending hnotify or not.
10425+ * @path is a switch to distinguish load and store.
10426+ */
10427+static int au_dr_hino(struct super_block *sb, aufs_bindex_t bindex,
10428+ struct au_branch *br, const struct path *path)
10429+{
10430+ int err, flags;
10431+ unsigned char load, suspend;
10432+ struct file *hinofile;
10433+ struct au_hinode *hdir;
10434+ struct inode *dir, *delegated;
10435+ struct path hinopath;
10436+ struct qstr hinoname = QSTR_INIT(AUFS_WH_DR_BRHINO,
10437+ sizeof(AUFS_WH_DR_BRHINO) - 1);
10438+
10439+ AuDebugOn(bindex < 0 && !br);
10440+ AuDebugOn(bindex >= 0 && br);
10441+
10442+ err = -EINVAL;
10443+ suspend = !br;
10444+ if (suspend)
10445+ br = au_sbr(sb, bindex);
10446+ load = !!path;
10447+ if (!load) {
10448+ path = &br->br_path;
10449+ AuDebugOn(!au_br_writable(br->br_perm));
10450+ if (unlikely(!au_br_writable(br->br_perm)))
10451+ goto out;
10452+ }
10453+
10454+ hdir = NULL;
10455+ if (suspend) {
10456+ dir = d_inode(sb->s_root);
10457+ hdir = au_hinode(au_ii(dir), bindex);
10458+ dir = hdir->hi_inode;
10459+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD);
10460+ } else {
10461+ dir = d_inode(path->dentry);
10462+ inode_lock_nested(dir, AuLsc_I_CHILD);
10463+ }
10464+ hinopath.dentry = vfsub_lkup_one(&hinoname, path->dentry);
10465+ err = PTR_ERR(hinopath.dentry);
10466+ if (IS_ERR(hinopath.dentry))
10467+ goto out_unlock;
10468+
10469+ err = 0;
10470+ flags = O_RDONLY;
10471+ if (load) {
10472+ if (d_is_negative(hinopath.dentry))
10473+ goto out_dput; /* success */
10474+ } else {
10475+ if (au_dr_hino_test_empty(&br->br_dirren)) {
10476+ if (d_is_positive(hinopath.dentry)) {
10477+ delegated = NULL;
10478+ err = vfsub_unlink(dir, &hinopath, &delegated,
10479+ /*force*/0);
10480+ AuTraceErr(err);
10481+ if (unlikely(err))
10482+ pr_err("ignored err %d, %pd2\n",
10483+ err, hinopath.dentry);
10484+ if (unlikely(err == -EWOULDBLOCK))
10485+ iput(delegated);
10486+ err = 0;
10487+ }
10488+ goto out_dput;
10489+ } else if (!d_is_positive(hinopath.dentry)) {
10490+ err = vfsub_create(dir, &hinopath, 0600,
10491+ /*want_excl*/false);
10492+ AuTraceErr(err);
10493+ if (unlikely(err))
10494+ goto out_dput;
10495+ }
10496+ flags = O_WRONLY;
10497+ }
10498+ hinopath.mnt = path->mnt;
10499+ hinofile = vfsub_dentry_open(&hinopath, flags);
10500+ if (suspend)
10501+ au_hn_inode_unlock(hdir);
10502+ else
10503+ inode_unlock(dir);
10504+ dput(hinopath.dentry);
10505+ AuTraceErrPtr(hinofile);
10506+ if (IS_ERR(hinofile)) {
10507+ err = PTR_ERR(hinofile);
10508+ goto out;
10509+ }
10510+
10511+ if (load)
10512+ err = au_dr_hino_load(&br->br_dirren, hinofile);
10513+ else
10514+ err = au_dr_hino_store(sb, br, hinofile);
10515+ fput(hinofile);
10516+ goto out;
10517+
10518+out_dput:
10519+ dput(hinopath.dentry);
10520+out_unlock:
10521+ if (suspend)
10522+ au_hn_inode_unlock(hdir);
10523+ else
10524+ inode_unlock(dir);
10525+out:
10526+ AuTraceErr(err);
10527+ return err;
10528+}
10529+
10530+/* ---------------------------------------------------------------------- */
10531+
10532+static int au_dr_brid_init(struct au_dr_brid *brid, const struct path *path)
10533+{
10534+ int err;
10535+ struct kstatfs kstfs;
10536+ dev_t dev;
10537+ struct dentry *dentry;
10538+ struct super_block *sb;
10539+
10540+ err = vfs_statfs((void *)path, &kstfs);
10541+ AuTraceErr(err);
10542+ if (unlikely(err))
10543+ goto out;
10544+
10545+ /* todo: support for UUID */
10546+
10547+ if (kstfs.f_fsid.val[0] || kstfs.f_fsid.val[1]) {
10548+ brid->type = AuBrid_FSID;
10549+ brid->fsid = kstfs.f_fsid;
10550+ } else {
10551+ dentry = path->dentry;
10552+ sb = dentry->d_sb;
10553+ dev = sb->s_dev;
10554+ if (dev) {
10555+ brid->type = AuBrid_DEV;
10556+ brid->dev = dev;
10557+ }
10558+ }
10559+
10560+out:
10561+ return err;
10562+}
10563+
10564+int au_dr_br_init(struct super_block *sb, struct au_branch *br,
10565+ const struct path *path)
10566+{
10567+ int err, i;
10568+ struct au_dr_br *dr;
10569+ struct hlist_bl_head *hbl;
10570+
10571+ dr = &br->br_dirren;
10572+ hbl = dr->dr_h_ino;
10573+ for (i = 0; i < AuDirren_NHASH; i++, hbl++)
10574+ INIT_HLIST_BL_HEAD(hbl);
10575+
10576+ err = au_dr_brid_init(&dr->dr_brid, path);
10577+ if (unlikely(err))
10578+ goto out;
10579+
10580+ if (au_opt_test(au_mntflags(sb), DIRREN))
10581+ err = au_dr_hino(sb, /*bindex*/-1, br, path);
10582+
10583+out:
10584+ AuTraceErr(err);
10585+ return err;
10586+}
10587+
10588+int au_dr_br_fin(struct super_block *sb, struct au_branch *br)
10589+{
10590+ int err;
10591+
10592+ err = 0;
10593+ if (au_br_writable(br->br_perm))
10594+ err = au_dr_hino(sb, /*bindex*/-1, br, /*path*/NULL);
10595+ if (!err)
10596+ au_dr_hino_free(&br->br_dirren);
10597+
10598+ return err;
10599+}
10600+
10601+/* ---------------------------------------------------------------------- */
10602+
10603+static int au_brid_str(struct au_dr_brid *brid, struct inode *h_inode,
10604+ char *buf, size_t sz)
10605+{
10606+ int err;
10607+ unsigned int major, minor;
10608+ char *p;
10609+
10610+ p = buf;
10611+ err = snprintf(p, sz, "%d_", brid->type);
10612+ AuDebugOn(err > sz);
10613+ p += err;
10614+ sz -= err;
10615+ switch (brid->type) {
10616+ case AuBrid_Unset:
10617+ return -EINVAL;
10618+ case AuBrid_UUID:
10619+ err = snprintf(p, sz, "%pU", brid->uuid.b);
10620+ break;
10621+ case AuBrid_FSID:
10622+ err = snprintf(p, sz, "%08x-%08x",
10623+ brid->fsid.val[0], brid->fsid.val[1]);
10624+ break;
10625+ case AuBrid_DEV:
10626+ major = MAJOR(brid->dev);
10627+ minor = MINOR(brid->dev);
10628+ if (major <= 0xff && minor <= 0xff)
10629+ err = snprintf(p, sz, "%02x%02x", major, minor);
10630+ else
10631+ err = snprintf(p, sz, "%03x:%05x", major, minor);
10632+ break;
10633+ }
10634+ AuDebugOn(err > sz);
10635+ p += err;
10636+ sz -= err;
10637+ err = snprintf(p, sz, "_%llu", (unsigned long long)h_inode->i_ino);
10638+ AuDebugOn(err > sz);
10639+ p += err;
10640+ sz -= err;
10641+
10642+ return p - buf;
10643+}
10644+
10645+static int au_drinfo_name(struct au_branch *br, char *name, int len)
10646+{
10647+ int rlen;
10648+ struct dentry *br_dentry;
10649+ struct inode *br_inode;
10650+
10651+ br_dentry = au_br_dentry(br);
10652+ br_inode = d_inode(br_dentry);
10653+ rlen = au_brid_str(&br->br_dirren.dr_brid, br_inode, name, len);
10654+ AuDebugOn(rlen >= AUFS_DIRREN_ENV_VAL_SZ);
10655+ AuDebugOn(rlen > len);
10656+
10657+ return rlen;
10658+}
10659+
10660+/* ---------------------------------------------------------------------- */
10661+
10662+/*
10663+ * from the given @h_dentry, construct drinfo at @*fdata.
10664+ * when the size of @*fdata is not enough, reallocate and return new @fdata and
10665+ * @allocated.
10666+ */
10667+static int au_drinfo_construct(struct au_drinfo_fdata **fdata,
10668+ struct dentry *h_dentry,
10669+ unsigned char *allocated)
10670+{
10671+ int err, v;
10672+ struct au_drinfo_fdata *f, *p;
10673+ struct au_drinfo *drinfo;
10674+ struct inode *h_inode;
10675+ struct qstr *qname;
10676+
10677+ err = 0;
10678+ f = *fdata;
10679+ h_inode = d_inode(h_dentry);
10680+ qname = &h_dentry->d_name;
10681+ drinfo = &f->drinfo;
10682+ drinfo->ino = (__force uint64_t)cpu_to_be64(h_inode->i_ino);
10683+ drinfo->oldnamelen = qname->len;
10684+ if (*allocated < sizeof(*f) + qname->len) {
10685+ v = roundup_pow_of_two(*allocated + qname->len);
10686+ p = au_krealloc(f, v, GFP_NOFS, /*may_shrink*/0);
10687+ if (unlikely(!p)) {
10688+ err = -ENOMEM;
10689+ AuTraceErr(err);
10690+ goto out;
10691+ }
10692+ f = p;
10693+ *fdata = f;
10694+ *allocated = v;
10695+ drinfo = &f->drinfo;
10696+ }
10697+ memcpy(drinfo->oldname, qname->name, qname->len);
10698+ AuDbg("i%llu, %.*s\n",
10699+ be64_to_cpu((__force __be64)drinfo->ino), drinfo->oldnamelen,
10700+ drinfo->oldname);
10701+
10702+out:
10703+ AuTraceErr(err);
10704+ return err;
10705+}
10706+
10707+/* callers have to free the return value */
10708+static struct au_drinfo *au_drinfo_read_k(struct file *file, ino_t h_ino)
10709+{
10710+ struct au_drinfo *ret, *drinfo;
10711+ struct au_drinfo_fdata fdata;
10712+ int len;
10713+ loff_t pos;
10714+ ssize_t ssz;
10715+
10716+ ret = ERR_PTR(-EIO);
10717+ pos = 0;
10718+ ssz = vfsub_read_k(file, &fdata, sizeof(fdata), &pos);
10719+ if (unlikely(ssz != sizeof(fdata))) {
10720+ AuIOErr("ssz %zd, %u, %pD2\n",
10721+ ssz, (unsigned int)sizeof(fdata), file);
10722+ goto out;
10723+ }
10724+
10725+ fdata.magic = ntohl((__force __be32)fdata.magic);
10726+ switch (fdata.magic) {
10727+ case AUFS_DRINFO_MAGIC_V1:
10728+ break;
10729+ default:
10730+ AuIOErr("magic-num 0x%x, 0x%x, %pD2\n",
10731+ fdata.magic, AUFS_DRINFO_MAGIC_V1, file);
10732+ goto out;
10733+ }
10734+
10735+ drinfo = &fdata.drinfo;
10736+ len = drinfo->oldnamelen;
10737+ if (!len) {
10738+ AuIOErr("broken drinfo %pD2\n", file);
10739+ goto out;
10740+ }
10741+
10742+ ret = NULL;
10743+ drinfo->ino = be64_to_cpu((__force __be64)drinfo->ino);
10744+ if (unlikely(h_ino && drinfo->ino != h_ino)) {
10745+ AuDbg("ignored i%llu, i%llu, %pD2\n",
10746+ (unsigned long long)drinfo->ino,
10747+ (unsigned long long)h_ino, file);
10748+ goto out; /* success */
10749+ }
10750+
10751+ ret = kmalloc(sizeof(*ret) + len, GFP_NOFS);
10752+ if (unlikely(!ret)) {
10753+ ret = ERR_PTR(-ENOMEM);
10754+ AuTraceErrPtr(ret);
10755+ goto out;
10756+ }
10757+
10758+ *ret = *drinfo;
10759+ ssz = vfsub_read_k(file, (void *)ret->oldname, len, &pos);
10760+ if (unlikely(ssz != len)) {
10761+ kfree(ret);
10762+ ret = ERR_PTR(-EIO);
10763+ AuIOErr("ssz %zd, %u, %pD2\n", ssz, len, file);
10764+ goto out;
10765+ }
10766+
10767+ AuDbg("oldname %.*s\n", ret->oldnamelen, ret->oldname);
10768+
10769+out:
10770+ return ret;
10771+}
10772+
10773+/* ---------------------------------------------------------------------- */
10774+
10775+/* in order to be revertible */
10776+struct au_drinfo_rev_elm {
10777+ int created;
10778+ struct dentry *info_dentry;
10779+ struct au_drinfo *info_last;
10780+};
10781+
10782+struct au_drinfo_rev {
10783+ unsigned char already;
10784+ aufs_bindex_t nelm;
10785+ struct au_drinfo_rev_elm elm[0];
10786+};
10787+
10788+/* todo: isn't it too large? */
10789+struct au_drinfo_store {
10790+ struct path h_ppath;
10791+ struct dentry *h_dentry;
10792+ struct au_drinfo_fdata *fdata;
10793+ char *infoname; /* inside of whname, just after PFX */
10794+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ];
10795+ aufs_bindex_t btgt, btail;
10796+ unsigned char no_sio,
10797+ allocated, /* current size of *fdata */
10798+ infonamelen, /* room size for p */
10799+ whnamelen, /* length of the genarated name */
10800+ renameback; /* renamed back */
10801+};
10802+
10803+/* on rename(2) error, the caller should revert it using @elm */
10804+static int au_drinfo_do_store(struct au_drinfo_store *w,
10805+ struct au_drinfo_rev_elm *elm)
10806+{
10807+ int err, len;
10808+ ssize_t ssz;
10809+ loff_t pos;
10810+ struct path infopath = {
10811+ .mnt = w->h_ppath.mnt
10812+ };
10813+ struct inode *h_dir, *h_inode, *delegated;
10814+ struct file *infofile;
10815+ struct qstr *qname;
10816+
10817+ AuDebugOn(elm
10818+ && memcmp(elm, page_address(ZERO_PAGE(0)), sizeof(*elm)));
10819+
10820+ infopath.dentry = vfsub_lookup_one_len(w->whname, w->h_ppath.dentry,
10821+ w->whnamelen);
10822+ AuTraceErrPtr(infopath.dentry);
10823+ if (IS_ERR(infopath.dentry)) {
10824+ err = PTR_ERR(infopath.dentry);
10825+ goto out;
10826+ }
10827+
10828+ err = 0;
10829+ h_dir = d_inode(w->h_ppath.dentry);
10830+ if (elm && d_is_negative(infopath.dentry)) {
10831+ err = vfsub_create(h_dir, &infopath, 0600, /*want_excl*/true);
10832+ AuTraceErr(err);
10833+ if (unlikely(err))
10834+ goto out_dput;
10835+ elm->created = 1;
10836+ elm->info_dentry = dget(infopath.dentry);
10837+ }
10838+
10839+ infofile = vfsub_dentry_open(&infopath, O_RDWR);
10840+ AuTraceErrPtr(infofile);
10841+ if (IS_ERR(infofile)) {
10842+ err = PTR_ERR(infofile);
10843+ goto out_dput;
10844+ }
10845+
10846+ h_inode = d_inode(infopath.dentry);
10847+ if (elm && i_size_read(h_inode)) {
10848+ h_inode = d_inode(w->h_dentry);
10849+ elm->info_last = au_drinfo_read_k(infofile, h_inode->i_ino);
10850+ AuTraceErrPtr(elm->info_last);
10851+ if (IS_ERR(elm->info_last)) {
10852+ err = PTR_ERR(elm->info_last);
10853+ elm->info_last = NULL;
10854+ AuDebugOn(elm->info_dentry);
10855+ goto out_fput;
10856+ }
10857+ }
10858+
10859+ if (elm && w->renameback) {
10860+ delegated = NULL;
10861+ err = vfsub_unlink(h_dir, &infopath, &delegated, /*force*/0);
10862+ AuTraceErr(err);
10863+ if (unlikely(err == -EWOULDBLOCK))
10864+ iput(delegated);
10865+ goto out_fput;
10866+ }
10867+
10868+ pos = 0;
10869+ qname = &w->h_dentry->d_name;
10870+ len = sizeof(*w->fdata) + qname->len;
10871+ if (!elm)
10872+ len = sizeof(*w->fdata) + w->fdata->drinfo.oldnamelen;
10873+ ssz = vfsub_write_k(infofile, w->fdata, len, &pos);
10874+ if (ssz == len) {
10875+ AuDbg("hi%llu, %.*s\n", w->fdata->drinfo.ino,
10876+ w->fdata->drinfo.oldnamelen, w->fdata->drinfo.oldname);
10877+ goto out_fput; /* success */
10878+ } else {
10879+ err = -EIO;
10880+ if (ssz < 0)
10881+ err = ssz;
10882+ /* the caller should revert it using @elm */
10883+ }
10884+
10885+out_fput:
10886+ fput(infofile);
10887+out_dput:
10888+ dput(infopath.dentry);
10889+out:
10890+ AuTraceErr(err);
10891+ return err;
10892+}
10893+
10894+struct au_call_drinfo_do_store_args {
10895+ int *errp;
10896+ struct au_drinfo_store *w;
10897+ struct au_drinfo_rev_elm *elm;
10898+};
10899+
10900+static void au_call_drinfo_do_store(void *args)
10901+{
10902+ struct au_call_drinfo_do_store_args *a = args;
10903+
10904+ *a->errp = au_drinfo_do_store(a->w, a->elm);
10905+}
10906+
10907+static int au_drinfo_store_sio(struct au_drinfo_store *w,
10908+ struct au_drinfo_rev_elm *elm)
10909+{
10910+ int err, wkq_err;
10911+
10912+ if (w->no_sio)
10913+ err = au_drinfo_do_store(w, elm);
10914+ else {
10915+ struct au_call_drinfo_do_store_args a = {
10916+ .errp = &err,
10917+ .w = w,
10918+ .elm = elm
10919+ };
10920+ wkq_err = au_wkq_wait(au_call_drinfo_do_store, &a);
10921+ if (unlikely(wkq_err))
10922+ err = wkq_err;
10923+ }
10924+ AuTraceErr(err);
10925+
10926+ return err;
10927+}
10928+
10929+static int au_drinfo_store_work_init(struct au_drinfo_store *w,
10930+ aufs_bindex_t btgt)
10931+{
10932+ int err;
10933+
10934+ memset(w, 0, sizeof(*w));
10935+ w->allocated = roundup_pow_of_two(sizeof(*w->fdata) + 40);
10936+ strcpy(w->whname, AUFS_WH_DR_INFO_PFX);
10937+ w->infoname = w->whname + sizeof(AUFS_WH_DR_INFO_PFX) - 1;
10938+ w->infonamelen = sizeof(w->whname) - sizeof(AUFS_WH_DR_INFO_PFX);
10939+ w->btgt = btgt;
10940+ w->no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID);
10941+
10942+ err = -ENOMEM;
10943+ w->fdata = kcalloc(1, w->allocated, GFP_NOFS);
10944+ if (unlikely(!w->fdata)) {
10945+ AuTraceErr(err);
10946+ goto out;
10947+ }
10948+ w->fdata->magic = (__force uint32_t)htonl(AUFS_DRINFO_MAGIC_V1);
10949+ err = 0;
10950+
10951+out:
10952+ return err;
10953+}
10954+
10955+static void au_drinfo_store_work_fin(struct au_drinfo_store *w)
10956+{
10957+ kfree(w->fdata);
10958+}
10959+
10960+static void au_drinfo_store_rev(struct au_drinfo_rev *rev,
10961+ struct au_drinfo_store *w)
10962+{
10963+ struct au_drinfo_rev_elm *elm;
10964+ struct inode *h_dir, *delegated;
10965+ int err, nelm;
10966+ struct path infopath = {
10967+ .mnt = w->h_ppath.mnt
10968+ };
10969+
10970+ h_dir = d_inode(w->h_ppath.dentry);
10971+ IMustLock(h_dir);
10972+
10973+ err = 0;
10974+ elm = rev->elm;
10975+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) {
10976+ AuDebugOn(elm->created && elm->info_last);
10977+ if (elm->created) {
10978+ AuDbg("here\n");
10979+ delegated = NULL;
10980+ infopath.dentry = elm->info_dentry;
10981+ err = vfsub_unlink(h_dir, &infopath, &delegated,
10982+ !w->no_sio);
10983+ AuTraceErr(err);
10984+ if (unlikely(err == -EWOULDBLOCK))
10985+ iput(delegated);
10986+ dput(elm->info_dentry);
10987+ } else if (elm->info_last) {
10988+ AuDbg("here\n");
10989+ w->fdata->drinfo = *elm->info_last;
10990+ memcpy(w->fdata->drinfo.oldname,
10991+ elm->info_last->oldname,
10992+ elm->info_last->oldnamelen);
10993+ err = au_drinfo_store_sio(w, /*elm*/NULL);
10994+ kfree(elm->info_last);
10995+ }
10996+ if (unlikely(err))
10997+ AuIOErr("%d, %s\n", err, w->whname);
10998+ /* go on even if err */
10999+ }
11000+}
11001+
11002+/* caller has to call au_dr_rename_fin() later */
11003+static int au_drinfo_store(struct dentry *dentry, aufs_bindex_t btgt,
11004+ struct qstr *dst_name, void *_rev)
11005+{
11006+ int err, sz, nelm;
11007+ aufs_bindex_t bindex, btail;
11008+ struct au_drinfo_store work;
11009+ struct au_drinfo_rev *rev, **p;
11010+ struct au_drinfo_rev_elm *elm;
11011+ struct super_block *sb;
11012+ struct au_branch *br;
11013+ struct au_hinode *hdir;
11014+
11015+ err = au_drinfo_store_work_init(&work, btgt);
11016+ AuTraceErr(err);
11017+ if (unlikely(err))
11018+ goto out;
11019+
11020+ err = -ENOMEM;
11021+ btail = au_dbtaildir(dentry);
11022+ nelm = btail - btgt;
11023+ sz = sizeof(*rev) + sizeof(*elm) * nelm;
11024+ rev = kcalloc(1, sz, GFP_NOFS);
11025+ if (unlikely(!rev)) {
11026+ AuTraceErr(err);
11027+ goto out_args;
11028+ }
11029+ rev->nelm = nelm;
11030+ elm = rev->elm;
11031+ p = _rev;
11032+ *p = rev;
11033+
11034+ err = 0;
11035+ sb = dentry->d_sb;
11036+ work.h_ppath.dentry = au_h_dptr(dentry, btgt);
11037+ work.h_ppath.mnt = au_sbr_mnt(sb, btgt);
11038+ hdir = au_hi(d_inode(dentry), btgt);
11039+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD);
11040+ for (bindex = btgt + 1; bindex <= btail; bindex++, elm++) {
11041+ work.h_dentry = au_h_dptr(dentry, bindex);
11042+ if (!work.h_dentry)
11043+ continue;
11044+
11045+ err = au_drinfo_construct(&work.fdata, work.h_dentry,
11046+ &work.allocated);
11047+ AuTraceErr(err);
11048+ if (unlikely(err))
11049+ break;
11050+
11051+ work.renameback = au_qstreq(&work.h_dentry->d_name, dst_name);
11052+ br = au_sbr(sb, bindex);
11053+ work.whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1;
11054+ work.whnamelen += au_drinfo_name(br, work.infoname,
11055+ work.infonamelen);
11056+ AuDbg("whname %.*s, i%llu, %.*s\n",
11057+ work.whnamelen, work.whname,
11058+ be64_to_cpu((__force __be64)work.fdata->drinfo.ino),
11059+ work.fdata->drinfo.oldnamelen,
11060+ work.fdata->drinfo.oldname);
11061+
11062+ err = au_drinfo_store_sio(&work, elm);
11063+ AuTraceErr(err);
11064+ if (unlikely(err))
11065+ break;
11066+ }
11067+ if (unlikely(err)) {
11068+ /* revert all drinfo */
11069+ au_drinfo_store_rev(rev, &work);
11070+ kfree(rev);
11071+ *p = NULL;
11072+ }
11073+ au_hn_inode_unlock(hdir);
11074+
11075+out_args:
11076+ au_drinfo_store_work_fin(&work);
11077+out:
11078+ return err;
11079+}
11080+
11081+/* ---------------------------------------------------------------------- */
11082+
11083+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex,
11084+ struct qstr *dst_name, void *_rev)
11085+{
11086+ int err, already;
11087+ ino_t ino;
11088+ struct super_block *sb;
11089+ struct au_branch *br;
11090+ struct au_dr_br *dr;
11091+ struct dentry *h_dentry;
11092+ struct inode *h_inode;
11093+ struct au_dr_hino *ent;
11094+ struct au_drinfo_rev *rev, **p;
11095+
11096+ AuDbg("bindex %d\n", bindex);
11097+
11098+ err = -ENOMEM;
11099+ ent = kmalloc(sizeof(*ent), GFP_NOFS);
11100+ if (unlikely(!ent))
11101+ goto out;
11102+
11103+ sb = src->d_sb;
11104+ br = au_sbr(sb, bindex);
11105+ dr = &br->br_dirren;
11106+ h_dentry = au_h_dptr(src, bindex);
11107+ h_inode = d_inode(h_dentry);
11108+ ino = h_inode->i_ino;
11109+ ent->dr_h_ino = ino;
11110+ already = au_dr_hino_test_add(dr, ino, ent);
11111+ AuDbg("b%d, hi%llu, already %d\n",
11112+ bindex, (unsigned long long)ino, already);
11113+
11114+ err = au_drinfo_store(src, bindex, dst_name, _rev);
11115+ AuTraceErr(err);
11116+ if (!err) {
11117+ p = _rev;
11118+ rev = *p;
11119+ rev->already = already;
11120+ goto out; /* success */
11121+ }
11122+
11123+ /* revert */
11124+ if (!already)
11125+ au_dr_hino_del(dr, ent);
11126+ kfree(ent);
11127+
11128+out:
11129+ AuTraceErr(err);
11130+ return err;
11131+}
11132+
11133+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *_rev)
11134+{
11135+ struct au_drinfo_rev *rev;
11136+ struct au_drinfo_rev_elm *elm;
11137+ int nelm;
11138+
11139+ rev = _rev;
11140+ elm = rev->elm;
11141+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) {
11142+ dput(elm->info_dentry);
11143+ kfree(elm->info_last);
11144+ }
11145+ kfree(rev);
11146+}
11147+
11148+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t btgt, void *_rev)
11149+{
11150+ int err;
11151+ struct au_drinfo_store work;
11152+ struct au_drinfo_rev *rev = _rev;
11153+ struct super_block *sb;
11154+ struct au_branch *br;
11155+ struct inode *h_inode;
11156+ struct au_dr_br *dr;
11157+ struct au_dr_hino *ent;
11158+
11159+ err = au_drinfo_store_work_init(&work, btgt);
11160+ if (unlikely(err))
11161+ goto out;
11162+
11163+ sb = src->d_sb;
11164+ br = au_sbr(sb, btgt);
11165+ work.h_ppath.dentry = au_h_dptr(src, btgt);
11166+ work.h_ppath.mnt = au_br_mnt(br);
11167+ au_drinfo_store_rev(rev, &work);
11168+ au_drinfo_store_work_fin(&work);
11169+ if (rev->already)
11170+ goto out;
11171+
11172+ dr = &br->br_dirren;
11173+ h_inode = d_inode(work.h_ppath.dentry);
11174+ ent = au_dr_hino_find(dr, h_inode->i_ino);
11175+ BUG_ON(!ent);
11176+ au_dr_hino_del(dr, ent);
11177+ kfree(ent);
11178+
11179+out:
11180+ kfree(rev);
11181+ if (unlikely(err))
11182+ pr_err("failed to remove dirren info\n");
11183+}
11184+
11185+/* ---------------------------------------------------------------------- */
11186+
11187+static struct au_drinfo *au_drinfo_do_load(struct path *h_ppath,
11188+ char *whname, int whnamelen,
11189+ struct dentry **info_dentry)
11190+{
11191+ struct au_drinfo *drinfo;
11192+ struct file *f;
11193+ struct inode *h_dir;
11194+ struct path infopath;
11195+ int unlocked;
11196+
11197+ AuDbg("%pd/%.*s\n", h_ppath->dentry, whnamelen, whname);
11198+
11199+ *info_dentry = NULL;
11200+ drinfo = NULL;
11201+ unlocked = 0;
11202+ h_dir = d_inode(h_ppath->dentry);
11203+ vfsub_inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
11204+ infopath.dentry = vfsub_lookup_one_len(whname, h_ppath->dentry,
11205+ whnamelen);
11206+ if (IS_ERR(infopath.dentry)) {
11207+ drinfo = (void *)infopath.dentry;
11208+ goto out;
11209+ }
11210+
11211+ if (d_is_negative(infopath.dentry))
11212+ goto out_dput; /* success */
11213+
11214+ infopath.mnt = h_ppath->mnt;
11215+ f = vfsub_dentry_open(&infopath, O_RDONLY);
11216+ inode_unlock_shared(h_dir);
11217+ unlocked = 1;
11218+ if (IS_ERR(f)) {
11219+ drinfo = (void *)f;
11220+ goto out_dput;
11221+ }
11222+
11223+ drinfo = au_drinfo_read_k(f, /*h_ino*/0);
11224+ if (IS_ERR_OR_NULL(drinfo))
11225+ goto out_fput;
11226+
11227+ AuDbg("oldname %.*s\n", drinfo->oldnamelen, drinfo->oldname);
11228+ *info_dentry = dget(infopath.dentry); /* keep it alive */
11229+
11230+out_fput:
11231+ fput(f);
11232+out_dput:
11233+ dput(infopath.dentry);
11234+out:
11235+ if (!unlocked)
11236+ inode_unlock_shared(h_dir);
11237+ AuTraceErrPtr(drinfo);
11238+ return drinfo;
11239+}
11240+
11241+struct au_drinfo_do_load_args {
11242+ struct au_drinfo **drinfop;
11243+ struct path *h_ppath;
11244+ char *whname;
11245+ int whnamelen;
11246+ struct dentry **info_dentry;
11247+};
11248+
11249+static void au_call_drinfo_do_load(void *args)
11250+{
11251+ struct au_drinfo_do_load_args *a = args;
11252+
11253+ *a->drinfop = au_drinfo_do_load(a->h_ppath, a->whname, a->whnamelen,
11254+ a->info_dentry);
11255+}
11256+
11257+struct au_drinfo_load {
11258+ struct path h_ppath;
11259+ struct qstr *qname;
11260+ unsigned char no_sio;
11261+
11262+ aufs_bindex_t ninfo;
11263+ struct au_drinfo **drinfo;
11264+};
11265+
11266+static int au_drinfo_load(struct au_drinfo_load *w, aufs_bindex_t bindex,
11267+ struct au_branch *br)
11268+{
11269+ int err, wkq_err, whnamelen, e;
11270+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ]
11271+ = AUFS_WH_DR_INFO_PFX;
11272+ struct au_drinfo *drinfo;
11273+ struct qstr oldname;
11274+ struct inode *h_dir, *delegated;
11275+ struct dentry *info_dentry;
11276+ struct path infopath;
11277+
11278+ whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1;
11279+ whnamelen += au_drinfo_name(br, whname + whnamelen,
11280+ sizeof(whname) - whnamelen);
11281+ if (w->no_sio)
11282+ drinfo = au_drinfo_do_load(&w->h_ppath, whname, whnamelen,
11283+ &info_dentry);
11284+ else {
11285+ struct au_drinfo_do_load_args args = {
11286+ .drinfop = &drinfo,
11287+ .h_ppath = &w->h_ppath,
11288+ .whname = whname,
11289+ .whnamelen = whnamelen,
11290+ .info_dentry = &info_dentry
11291+ };
11292+ wkq_err = au_wkq_wait(au_call_drinfo_do_load, &args);
11293+ if (unlikely(wkq_err))
11294+ drinfo = ERR_PTR(wkq_err);
11295+ }
11296+ err = PTR_ERR(drinfo);
11297+ if (IS_ERR_OR_NULL(drinfo))
11298+ goto out;
11299+
11300+ err = 0;
11301+ oldname.len = drinfo->oldnamelen;
11302+ oldname.name = drinfo->oldname;
11303+ if (au_qstreq(w->qname, &oldname)) {
11304+ /* the name is renamed back */
11305+ kfree(drinfo);
11306+ drinfo = NULL;
11307+
11308+ infopath.dentry = info_dentry;
11309+ infopath.mnt = w->h_ppath.mnt;
11310+ h_dir = d_inode(w->h_ppath.dentry);
11311+ delegated = NULL;
11312+ inode_lock_nested(h_dir, AuLsc_I_PARENT);
11313+ e = vfsub_unlink(h_dir, &infopath, &delegated, !w->no_sio);
11314+ inode_unlock(h_dir);
11315+ if (unlikely(e))
11316+ AuIOErr("ignored %d, %pd2\n", e, &infopath.dentry);
11317+ if (unlikely(e == -EWOULDBLOCK))
11318+ iput(delegated);
11319+ }
11320+ kfree(w->drinfo[bindex]);
11321+ w->drinfo[bindex] = drinfo;
11322+ dput(info_dentry);
11323+
11324+out:
11325+ AuTraceErr(err);
11326+ return err;
11327+}
11328+
11329+/* ---------------------------------------------------------------------- */
11330+
11331+static void au_dr_lkup_free(struct au_drinfo **drinfo, int n)
11332+{
11333+ struct au_drinfo **p = drinfo;
11334+
11335+ while (n-- > 0)
11336+ kfree(*drinfo++);
11337+ kfree(p);
11338+}
11339+
11340+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry,
11341+ aufs_bindex_t btgt)
11342+{
11343+ int err, ninfo;
11344+ struct au_drinfo_load w;
11345+ aufs_bindex_t bindex, bbot;
11346+ struct au_branch *br;
11347+ struct inode *h_dir;
11348+ struct au_dr_hino *ent;
11349+ struct super_block *sb;
11350+
11351+ AuDbg("%.*s, name %.*s, whname %.*s, b%d\n",
11352+ AuLNPair(&dentry->d_name), AuLNPair(&lkup->dirren.dr_name),
11353+ AuLNPair(&lkup->whname), btgt);
11354+
11355+ sb = dentry->d_sb;
11356+ bbot = au_sbbot(sb);
11357+ w.ninfo = bbot + 1;
11358+ if (!lkup->dirren.drinfo) {
11359+ lkup->dirren.drinfo = kcalloc(w.ninfo,
11360+ sizeof(*lkup->dirren.drinfo),
11361+ GFP_NOFS);
11362+ if (unlikely(!lkup->dirren.drinfo)) {
11363+ err = -ENOMEM;
11364+ goto out;
11365+ }
11366+ lkup->dirren.ninfo = w.ninfo;
11367+ }
11368+ w.drinfo = lkup->dirren.drinfo;
11369+ w.no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID);
11370+ w.h_ppath.dentry = au_h_dptr(dentry, btgt);
11371+ AuDebugOn(!w.h_ppath.dentry);
11372+ w.h_ppath.mnt = au_sbr_mnt(sb, btgt);
11373+ w.qname = &dentry->d_name;
11374+
11375+ ninfo = 0;
11376+ for (bindex = btgt + 1; bindex <= bbot; bindex++) {
11377+ br = au_sbr(sb, bindex);
11378+ err = au_drinfo_load(&w, bindex, br);
11379+ if (unlikely(err))
11380+ goto out_free;
11381+ if (w.drinfo[bindex])
11382+ ninfo++;
11383+ }
11384+ if (!ninfo) {
11385+ br = au_sbr(sb, btgt);
11386+ h_dir = d_inode(w.h_ppath.dentry);
11387+ ent = au_dr_hino_find(&br->br_dirren, h_dir->i_ino);
11388+ AuDebugOn(!ent);
11389+ au_dr_hino_del(&br->br_dirren, ent);
11390+ kfree(ent);
11391+ }
11392+ goto out; /* success */
11393+
11394+out_free:
11395+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo);
11396+ lkup->dirren.ninfo = 0;
11397+ lkup->dirren.drinfo = NULL;
11398+out:
11399+ AuTraceErr(err);
11400+ return err;
11401+}
11402+
11403+void au_dr_lkup_fin(struct au_do_lookup_args *lkup)
11404+{
11405+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo);
11406+}
11407+
11408+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt)
11409+{
11410+ int err;
11411+ struct au_drinfo *drinfo;
11412+
11413+ err = 0;
11414+ if (!lkup->dirren.drinfo)
11415+ goto out;
11416+ AuDebugOn(lkup->dirren.ninfo < btgt + 1);
11417+ drinfo = lkup->dirren.drinfo[btgt + 1];
11418+ if (!drinfo)
11419+ goto out;
11420+
11421+ kfree(lkup->whname.name);
11422+ lkup->whname.name = NULL;
11423+ lkup->dirren.dr_name.len = drinfo->oldnamelen;
11424+ lkup->dirren.dr_name.name = drinfo->oldname;
11425+ lkup->name = &lkup->dirren.dr_name;
11426+ err = au_wh_name_alloc(&lkup->whname, lkup->name);
11427+ if (!err)
11428+ AuDbg("name %.*s, whname %.*s, b%d\n",
11429+ AuLNPair(lkup->name), AuLNPair(&lkup->whname),
11430+ btgt);
11431+
11432+out:
11433+ AuTraceErr(err);
11434+ return err;
11435+}
11436+
11437+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex,
11438+ ino_t h_ino)
11439+{
11440+ int match;
11441+ struct au_drinfo *drinfo;
11442+
11443+ match = 1;
11444+ if (!lkup->dirren.drinfo)
11445+ goto out;
11446+ AuDebugOn(lkup->dirren.ninfo < bindex + 1);
11447+ drinfo = lkup->dirren.drinfo[bindex + 1];
11448+ if (!drinfo)
11449+ goto out;
11450+
11451+ match = (drinfo->ino == h_ino);
11452+ AuDbg("match %d\n", match);
11453+
11454+out:
11455+ return match;
11456+}
11457+
11458+/* ---------------------------------------------------------------------- */
11459+
11460+int au_dr_opt_set(struct super_block *sb)
11461+{
11462+ int err;
11463+ aufs_bindex_t bindex, bbot;
11464+ struct au_branch *br;
11465+
11466+ err = 0;
11467+ bbot = au_sbbot(sb);
11468+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
11469+ br = au_sbr(sb, bindex);
11470+ err = au_dr_hino(sb, bindex, /*br*/NULL, &br->br_path);
11471+ }
11472+
11473+ return err;
11474+}
11475+
11476+int au_dr_opt_flush(struct super_block *sb)
11477+{
11478+ int err;
11479+ aufs_bindex_t bindex, bbot;
11480+ struct au_branch *br;
11481+
11482+ err = 0;
11483+ bbot = au_sbbot(sb);
11484+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
11485+ br = au_sbr(sb, bindex);
11486+ if (au_br_writable(br->br_perm))
11487+ err = au_dr_hino(sb, bindex, /*br*/NULL, /*path*/NULL);
11488+ }
11489+
11490+ return err;
11491+}
11492+
11493+int au_dr_opt_clr(struct super_block *sb, int no_flush)
11494+{
11495+ int err;
11496+ aufs_bindex_t bindex, bbot;
11497+ struct au_branch *br;
11498+
11499+ err = 0;
11500+ if (!no_flush) {
11501+ err = au_dr_opt_flush(sb);
11502+ if (unlikely(err))
11503+ goto out;
11504+ }
11505+
11506+ bbot = au_sbbot(sb);
11507+ for (bindex = 0; bindex <= bbot; bindex++) {
11508+ br = au_sbr(sb, bindex);
11509+ au_dr_hino_free(&br->br_dirren);
11510+ }
11511+
11512+out:
11513+ return err;
11514+}
0b1ff5c3
JR
11515diff -urNp -x '*.orig' linux-4.14/fs/aufs/dirren.h linux-4.14/fs/aufs/dirren.h
11516--- linux-4.14/fs/aufs/dirren.h 1970-01-01 01:00:00.000000000 +0100
11517+++ linux-4.14/fs/aufs/dirren.h 2021-02-24 21:42:43.441114748 +0100
8b6a4947
AM
11518@@ -0,0 +1,139 @@
11519+/*
11520+ * Copyright (C) 2017 Junjiro R. Okajima
11521+ *
11522+ * This program, aufs is free software; you can redistribute it and/or modify
11523+ * it under the terms of the GNU General Public License as published by
11524+ * the Free Software Foundation; either version 2 of the License, or
11525+ * (at your option) any later version.
11526+ *
11527+ * This program is distributed in the hope that it will be useful,
11528+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11529+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11530+ * GNU General Public License for more details.
11531+ *
11532+ * You should have received a copy of the GNU General Public License
11533+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
11534+ */
11535+
11536+/*
11537+ * renamed dir info
11538+ */
11539+
11540+#ifndef __AUFS_DIRREN_H__
11541+#define __AUFS_DIRREN_H__
11542+
11543+#ifdef __KERNEL__
11544+
11545+#include <linux/dcache.h>
11546+#include <linux/statfs.h>
11547+#include <linux/uuid.h>
11548+#include "hbl.h"
11549+
11550+#define AuDirren_NHASH 100
11551+
11552+#ifdef CONFIG_AUFS_DIRREN
11553+enum au_brid_type {
11554+ AuBrid_Unset,
11555+ AuBrid_UUID,
11556+ AuBrid_FSID,
11557+ AuBrid_DEV
11558+};
11559+
11560+struct au_dr_brid {
11561+ enum au_brid_type type;
11562+ union {
11563+ uuid_t uuid; /* unimplemented yet */
11564+ fsid_t fsid;
11565+ dev_t dev;
11566+ };
11567+};
11568+
11569+/* 20 is the max digits length of ulong 64 */
11570+/* brid-type "_" uuid "_" inum */
11571+#define AUFS_DIRREN_FNAME_SZ (1 + 1 + UUID_STRING_LEN + 20)
11572+#define AUFS_DIRREN_ENV_VAL_SZ (AUFS_DIRREN_FNAME_SZ + 1 + 20)
11573+
11574+struct au_dr_hino {
11575+ struct hlist_bl_node dr_hnode;
11576+ ino_t dr_h_ino;
11577+};
11578+
11579+struct au_dr_br {
11580+ struct hlist_bl_head dr_h_ino[AuDirren_NHASH];
11581+ struct au_dr_brid dr_brid;
11582+};
11583+
11584+struct au_dr_lookup {
11585+ /* dr_name is pointed by struct au_do_lookup_args.name */
11586+ struct qstr dr_name; /* subset of dr_info */
11587+ aufs_bindex_t ninfo;
11588+ struct au_drinfo **drinfo;
11589+};
11590+#else
11591+struct au_dr_hino;
11592+/* empty */
11593+struct au_dr_br { };
11594+struct au_dr_lookup { };
11595+#endif
11596+
11597+/* ---------------------------------------------------------------------- */
11598+
11599+struct au_branch;
11600+struct au_do_lookup_args;
11601+struct au_hinode;
11602+#ifdef CONFIG_AUFS_DIRREN
11603+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t h_ino,
11604+ struct au_dr_hino *add_ent);
11605+void au_dr_hino_free(struct au_dr_br *dr);
11606+int au_dr_br_init(struct super_block *sb, struct au_branch *br,
11607+ const struct path *path);
11608+int au_dr_br_fin(struct super_block *sb, struct au_branch *br);
11609+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex,
11610+ struct qstr *dst_name, void *_rev);
11611+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *rev);
11612+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t bindex, void *rev);
11613+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry,
11614+ aufs_bindex_t bindex);
11615+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt);
11616+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex,
11617+ ino_t h_ino);
11618+void au_dr_lkup_fin(struct au_do_lookup_args *lkup);
11619+int au_dr_opt_set(struct super_block *sb);
11620+int au_dr_opt_flush(struct super_block *sb);
11621+int au_dr_opt_clr(struct super_block *sb, int no_flush);
11622+#else
11623+AuStubInt0(au_dr_hino_test_add, struct au_dr_br *dr, ino_t h_ino,
11624+ struct au_dr_hino *add_ent);
11625+AuStubVoid(au_dr_hino_free, struct au_dr_br *dr);
11626+AuStubInt0(au_dr_br_init, struct super_block *sb, struct au_branch *br,
11627+ const struct path *path);
11628+AuStubInt0(au_dr_br_fin, struct super_block *sb, struct au_branch *br);
11629+AuStubInt0(au_dr_rename, struct dentry *src, aufs_bindex_t bindex,
11630+ struct qstr *dst_name, void *_rev);
11631+AuStubVoid(au_dr_rename_fin, struct dentry *src, aufs_bindex_t btgt, void *rev);
11632+AuStubVoid(au_dr_rename_rev, struct dentry *src, aufs_bindex_t bindex,
11633+ void *rev);
11634+AuStubInt0(au_dr_lkup, struct au_do_lookup_args *lkup, struct dentry *dentry,
11635+ aufs_bindex_t bindex);
11636+AuStubInt0(au_dr_lkup_name, struct au_do_lookup_args *lkup, aufs_bindex_t btgt);
11637+AuStubInt0(au_dr_lkup_h_ino, struct au_do_lookup_args *lkup,
11638+ aufs_bindex_t bindex, ino_t h_ino);
11639+AuStubVoid(au_dr_lkup_fin, struct au_do_lookup_args *lkup);
11640+AuStubInt0(au_dr_opt_set, struct super_block *sb);
11641+AuStubInt0(au_dr_opt_flush, struct super_block *sb);
11642+AuStubInt0(au_dr_opt_clr, struct super_block *sb, int no_flush);
11643+#endif
11644+
11645+/* ---------------------------------------------------------------------- */
11646+
11647+#ifdef CONFIG_AUFS_DIRREN
11648+static inline int au_dr_ihash(ino_t h_ino)
11649+{
11650+ return h_ino % AuDirren_NHASH;
11651+}
11652+#else
11653+AuStubInt0(au_dr_ihash, ino_t h_ino);
11654+#endif
11655+
11656+#endif /* __KERNEL__ */
11657+#endif /* __AUFS_DIRREN_H__ */
0b1ff5c3
JR
11658diff -urNp -x '*.orig' linux-4.14/fs/aufs/dynop.c linux-4.14/fs/aufs/dynop.c
11659--- linux-4.14/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
11660+++ linux-4.14/fs/aufs/dynop.c 2021-02-24 21:42:43.441114748 +0100
8b6a4947 11661@@ -0,0 +1,369 @@
1facf9fc 11662+/*
a2654f78 11663+ * Copyright (C) 2010-2017 Junjiro R. Okajima
1facf9fc 11664+ *
11665+ * This program, aufs is free software; you can redistribute it and/or modify
11666+ * it under the terms of the GNU General Public License as published by
11667+ * the Free Software Foundation; either version 2 of the License, or
11668+ * (at your option) any later version.
dece6358
AM
11669+ *
11670+ * This program is distributed in the hope that it will be useful,
11671+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11672+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11673+ * GNU General Public License for more details.
11674+ *
11675+ * You should have received a copy of the GNU General Public License
523b37e3 11676+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 11677+ */
11678+
11679+/*
4a4d8108 11680+ * dynamically customizable operations for regular files
1facf9fc 11681+ */
11682+
1facf9fc 11683+#include "aufs.h"
11684+
4a4d8108 11685+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 11686+
4a4d8108
AM
11687+/*
11688+ * How large will these lists be?
11689+ * Usually just a few elements, 20-30 at most for each, I guess.
11690+ */
8b6a4947 11691+static struct hlist_bl_head dynop[AuDyLast];
4a4d8108 11692+
8b6a4947
AM
11693+static struct au_dykey *dy_gfind_get(struct hlist_bl_head *hbl,
11694+ const void *h_op)
1facf9fc 11695+{
4a4d8108 11696+ struct au_dykey *key, *tmp;
8b6a4947 11697+ struct hlist_bl_node *pos;
1facf9fc 11698+
4a4d8108 11699+ key = NULL;
8b6a4947
AM
11700+ hlist_bl_lock(hbl);
11701+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode)
4a4d8108
AM
11702+ if (tmp->dk_op.dy_hop == h_op) {
11703+ key = tmp;
11704+ kref_get(&key->dk_kref);
11705+ break;
11706+ }
8b6a4947 11707+ hlist_bl_unlock(hbl);
4a4d8108
AM
11708+
11709+ return key;
1facf9fc 11710+}
11711+
4a4d8108 11712+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 11713+{
4a4d8108
AM
11714+ struct au_dykey **k, *found;
11715+ const void *h_op = key->dk_op.dy_hop;
11716+ int i;
1facf9fc 11717+
4a4d8108
AM
11718+ found = NULL;
11719+ k = br->br_dykey;
11720+ for (i = 0; i < AuBrDynOp; i++)
11721+ if (k[i]) {
11722+ if (k[i]->dk_op.dy_hop == h_op) {
11723+ found = k[i];
11724+ break;
11725+ }
11726+ } else
11727+ break;
11728+ if (!found) {
11729+ spin_lock(&br->br_dykey_lock);
11730+ for (; i < AuBrDynOp; i++)
11731+ if (k[i]) {
11732+ if (k[i]->dk_op.dy_hop == h_op) {
11733+ found = k[i];
11734+ break;
11735+ }
11736+ } else {
11737+ k[i] = key;
11738+ break;
11739+ }
11740+ spin_unlock(&br->br_dykey_lock);
11741+ BUG_ON(i == AuBrDynOp); /* expand the array */
11742+ }
11743+
11744+ return found;
1facf9fc 11745+}
11746+
4a4d8108 11747+/* kref_get() if @key is already added */
8b6a4947 11748+static struct au_dykey *dy_gadd(struct hlist_bl_head *hbl, struct au_dykey *key)
4a4d8108
AM
11749+{
11750+ struct au_dykey *tmp, *found;
8b6a4947 11751+ struct hlist_bl_node *pos;
4a4d8108 11752+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 11753+
4a4d8108 11754+ found = NULL;
8b6a4947
AM
11755+ hlist_bl_lock(hbl);
11756+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode)
4a4d8108
AM
11757+ if (tmp->dk_op.dy_hop == h_op) {
11758+ kref_get(&tmp->dk_kref);
11759+ found = tmp;
11760+ break;
11761+ }
11762+ if (!found)
8b6a4947
AM
11763+ hlist_bl_add_head(&key->dk_hnode, hbl);
11764+ hlist_bl_unlock(hbl);
1facf9fc 11765+
4a4d8108
AM
11766+ if (!found)
11767+ DyPrSym(key);
11768+ return found;
11769+}
11770+
11771+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 11772+{
4a4d8108
AM
11773+ struct au_dykey *key;
11774+
11775+ key = container_of(rcu, struct au_dykey, dk_rcu);
11776+ DyPrSym(key);
1c60b727 11777+ kfree(key);
1facf9fc 11778+}
11779+
4a4d8108
AM
11780+static void dy_free(struct kref *kref)
11781+{
11782+ struct au_dykey *key;
8b6a4947 11783+ struct hlist_bl_head *hbl;
1facf9fc 11784+
4a4d8108 11785+ key = container_of(kref, struct au_dykey, dk_kref);
8b6a4947
AM
11786+ hbl = dynop + key->dk_op.dy_type;
11787+ au_hbl_del(&key->dk_hnode, hbl);
4a4d8108
AM
11788+ call_rcu(&key->dk_rcu, dy_free_rcu);
11789+}
11790+
11791+void au_dy_put(struct au_dykey *key)
1facf9fc 11792+{
4a4d8108
AM
11793+ kref_put(&key->dk_kref, dy_free);
11794+}
1facf9fc 11795+
4a4d8108
AM
11796+/* ---------------------------------------------------------------------- */
11797+
11798+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
11799+
11800+#ifdef CONFIG_AUFS_DEBUG
11801+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 11802+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
11803+#else
11804+#define DyDbgDeclare(cnt) do {} while (0)
11805+#define DyDbgInc(cnt) do {} while (0)
11806+#endif
11807+
11808+#define DySet(func, dst, src, h_op, h_sb) do { \
11809+ DyDbgInc(cnt); \
11810+ if (h_op->func) { \
11811+ if (src.func) \
11812+ dst.func = src.func; \
11813+ else \
11814+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
11815+ } \
11816+} while (0)
11817+
11818+#define DySetForce(func, dst, src) do { \
11819+ AuDebugOn(!src.func); \
11820+ DyDbgInc(cnt); \
11821+ dst.func = src.func; \
11822+} while (0)
11823+
11824+#define DySetAop(func) \
11825+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
11826+#define DySetAopForce(func) \
11827+ DySetForce(func, dyaop->da_op, aufs_aop)
11828+
11829+static void dy_aop(struct au_dykey *key, const void *h_op,
11830+ struct super_block *h_sb __maybe_unused)
11831+{
11832+ struct au_dyaop *dyaop = (void *)key;
11833+ const struct address_space_operations *h_aop = h_op;
11834+ DyDbgDeclare(cnt);
11835+
11836+ AuDbg("%s\n", au_sbtype(h_sb));
11837+
11838+ DySetAop(writepage);
11839+ DySetAopForce(readpage); /* force */
4a4d8108
AM
11840+ DySetAop(writepages);
11841+ DySetAop(set_page_dirty);
11842+ DySetAop(readpages);
11843+ DySetAop(write_begin);
11844+ DySetAop(write_end);
11845+ DySetAop(bmap);
11846+ DySetAop(invalidatepage);
11847+ DySetAop(releasepage);
027c5e7a 11848+ DySetAop(freepage);
7e9cd9fe 11849+ /* this one will be changed according to an aufs mount option */
4a4d8108 11850+ DySetAop(direct_IO);
4a4d8108 11851+ DySetAop(migratepage);
e2f27e51
AM
11852+ DySetAop(isolate_page);
11853+ DySetAop(putback_page);
4a4d8108
AM
11854+ DySetAop(launder_page);
11855+ DySetAop(is_partially_uptodate);
392086de 11856+ DySetAop(is_dirty_writeback);
4a4d8108 11857+ DySetAop(error_remove_page);
b4510431
AM
11858+ DySetAop(swap_activate);
11859+ DySetAop(swap_deactivate);
4a4d8108
AM
11860+
11861+ DyDbgSize(cnt, *h_aop);
4a4d8108
AM
11862+}
11863+
4a4d8108
AM
11864+/* ---------------------------------------------------------------------- */
11865+
11866+static void dy_bug(struct kref *kref)
11867+{
11868+ BUG();
11869+}
11870+
11871+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
11872+{
11873+ struct au_dykey *key, *old;
8b6a4947 11874+ struct hlist_bl_head *hbl;
b752ccd1 11875+ struct op {
4a4d8108 11876+ unsigned int sz;
b752ccd1
AM
11877+ void (*set)(struct au_dykey *key, const void *h_op,
11878+ struct super_block *h_sb __maybe_unused);
11879+ };
11880+ static const struct op a[] = {
4a4d8108
AM
11881+ [AuDy_AOP] = {
11882+ .sz = sizeof(struct au_dyaop),
b752ccd1 11883+ .set = dy_aop
4a4d8108 11884+ }
b752ccd1
AM
11885+ };
11886+ const struct op *p;
4a4d8108 11887+
8b6a4947
AM
11888+ hbl = dynop + op->dy_type;
11889+ key = dy_gfind_get(hbl, op->dy_hop);
4a4d8108
AM
11890+ if (key)
11891+ goto out_add; /* success */
11892+
11893+ p = a + op->dy_type;
11894+ key = kzalloc(p->sz, GFP_NOFS);
11895+ if (unlikely(!key)) {
11896+ key = ERR_PTR(-ENOMEM);
11897+ goto out;
11898+ }
11899+
11900+ key->dk_op.dy_hop = op->dy_hop;
11901+ kref_init(&key->dk_kref);
86dc4139 11902+ p->set(key, op->dy_hop, au_br_sb(br));
8b6a4947 11903+ old = dy_gadd(hbl, key);
4a4d8108 11904+ if (old) {
1c60b727 11905+ kfree(key);
4a4d8108
AM
11906+ key = old;
11907+ }
11908+
11909+out_add:
11910+ old = dy_bradd(br, key);
11911+ if (old)
11912+ /* its ref-count should never be zero here */
11913+ kref_put(&key->dk_kref, dy_bug);
11914+out:
11915+ return key;
11916+}
11917+
11918+/* ---------------------------------------------------------------------- */
11919+/*
11920+ * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
c1595e42 11921+ * This behaviour is necessary to return an error from open(O_DIRECT) instead
4a4d8108
AM
11922+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
11923+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
11924+ * See the aufs manual in detail.
4a4d8108
AM
11925+ */
11926+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
11927+{
7e9cd9fe 11928+ if (!do_dx)
4a4d8108 11929+ dyaop->da_op.direct_IO = NULL;
7e9cd9fe 11930+ else
4a4d8108 11931+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
4a4d8108
AM
11932+}
11933+
11934+static struct au_dyaop *dy_aget(struct au_branch *br,
11935+ const struct address_space_operations *h_aop,
11936+ int do_dx)
11937+{
11938+ struct au_dyaop *dyaop;
11939+ struct au_dynop op;
11940+
11941+ op.dy_type = AuDy_AOP;
11942+ op.dy_haop = h_aop;
11943+ dyaop = (void *)dy_get(&op, br);
11944+ if (IS_ERR(dyaop))
11945+ goto out;
11946+ dy_adx(dyaop, do_dx);
11947+
11948+out:
11949+ return dyaop;
11950+}
11951+
11952+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
11953+ struct inode *h_inode)
11954+{
11955+ int err, do_dx;
11956+ struct super_block *sb;
11957+ struct au_branch *br;
11958+ struct au_dyaop *dyaop;
11959+
11960+ AuDebugOn(!S_ISREG(h_inode->i_mode));
11961+ IiMustWriteLock(inode);
11962+
11963+ sb = inode->i_sb;
11964+ br = au_sbr(sb, bindex);
11965+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
11966+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
11967+ err = PTR_ERR(dyaop);
11968+ if (IS_ERR(dyaop))
11969+ /* unnecessary to call dy_fput() */
11970+ goto out;
11971+
11972+ err = 0;
11973+ inode->i_mapping->a_ops = &dyaop->da_op;
11974+
11975+out:
11976+ return err;
11977+}
11978+
b752ccd1
AM
11979+/*
11980+ * Is it safe to replace a_ops during the inode/file is in operation?
11981+ * Yes, I hope so.
11982+ */
11983+int au_dy_irefresh(struct inode *inode)
11984+{
11985+ int err;
5afbbe0d 11986+ aufs_bindex_t btop;
b752ccd1
AM
11987+ struct inode *h_inode;
11988+
11989+ err = 0;
11990+ if (S_ISREG(inode->i_mode)) {
5afbbe0d
AM
11991+ btop = au_ibtop(inode);
11992+ h_inode = au_h_iptr(inode, btop);
11993+ err = au_dy_iaop(inode, btop, h_inode);
b752ccd1
AM
11994+ }
11995+ return err;
11996+}
11997+
4a4d8108
AM
11998+void au_dy_arefresh(int do_dx)
11999+{
8b6a4947
AM
12000+ struct hlist_bl_head *hbl;
12001+ struct hlist_bl_node *pos;
4a4d8108
AM
12002+ struct au_dykey *key;
12003+
8b6a4947
AM
12004+ hbl = dynop + AuDy_AOP;
12005+ hlist_bl_lock(hbl);
12006+ hlist_bl_for_each_entry(key, pos, hbl, dk_hnode)
4a4d8108 12007+ dy_adx((void *)key, do_dx);
8b6a4947 12008+ hlist_bl_unlock(hbl);
4a4d8108
AM
12009+}
12010+
4a4d8108
AM
12011+/* ---------------------------------------------------------------------- */
12012+
12013+void __init au_dy_init(void)
12014+{
12015+ int i;
12016+
12017+ /* make sure that 'struct au_dykey *' can be any type */
12018+ BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
4a4d8108
AM
12019+
12020+ for (i = 0; i < AuDyLast; i++)
8b6a4947 12021+ INIT_HLIST_BL_HEAD(dynop + i);
4a4d8108
AM
12022+}
12023+
12024+void au_dy_fin(void)
12025+{
12026+ int i;
12027+
12028+ for (i = 0; i < AuDyLast; i++)
8b6a4947 12029+ WARN_ON(!hlist_bl_empty(dynop + i));
4a4d8108 12030+}
0b1ff5c3
JR
12031diff -urNp -x '*.orig' linux-4.14/fs/aufs/dynop.h linux-4.14/fs/aufs/dynop.h
12032--- linux-4.14/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
12033+++ linux-4.14/fs/aufs/dynop.h 2021-02-24 21:42:43.441114748 +0100
7e9cd9fe 12034@@ -0,0 +1,74 @@
4a4d8108 12035+/*
a2654f78 12036+ * Copyright (C) 2010-2017 Junjiro R. Okajima
4a4d8108
AM
12037+ *
12038+ * This program, aufs is free software; you can redistribute it and/or modify
12039+ * it under the terms of the GNU General Public License as published by
12040+ * the Free Software Foundation; either version 2 of the License, or
12041+ * (at your option) any later version.
12042+ *
12043+ * This program is distributed in the hope that it will be useful,
12044+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12045+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12046+ * GNU General Public License for more details.
12047+ *
12048+ * You should have received a copy of the GNU General Public License
523b37e3 12049+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
12050+ */
12051+
12052+/*
12053+ * dynamically customizable operations (for regular files only)
12054+ */
12055+
12056+#ifndef __AUFS_DYNOP_H__
12057+#define __AUFS_DYNOP_H__
12058+
12059+#ifdef __KERNEL__
12060+
7e9cd9fe
AM
12061+#include <linux/fs.h>
12062+#include <linux/kref.h>
4a4d8108 12063+
2cbb1c4b 12064+enum {AuDy_AOP, AuDyLast};
4a4d8108
AM
12065+
12066+struct au_dynop {
12067+ int dy_type;
12068+ union {
12069+ const void *dy_hop;
12070+ const struct address_space_operations *dy_haop;
4a4d8108
AM
12071+ };
12072+};
12073+
12074+struct au_dykey {
12075+ union {
8b6a4947 12076+ struct hlist_bl_node dk_hnode;
4a4d8108
AM
12077+ struct rcu_head dk_rcu;
12078+ };
12079+ struct au_dynop dk_op;
12080+
12081+ /*
12082+ * during I am in the branch local array, kref is gotten. when the
12083+ * branch is removed, kref is put.
12084+ */
12085+ struct kref dk_kref;
12086+};
12087+
12088+/* stop unioning since their sizes are very different from each other */
12089+struct au_dyaop {
12090+ struct au_dykey da_key;
12091+ struct address_space_operations da_op; /* not const */
4a4d8108
AM
12092+};
12093+
4a4d8108
AM
12094+/* ---------------------------------------------------------------------- */
12095+
12096+/* dynop.c */
12097+struct au_branch;
12098+void au_dy_put(struct au_dykey *key);
12099+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
12100+ struct inode *h_inode);
b752ccd1 12101+int au_dy_irefresh(struct inode *inode);
4a4d8108 12102+void au_dy_arefresh(int do_dio);
4a4d8108
AM
12103+
12104+void __init au_dy_init(void);
12105+void au_dy_fin(void);
12106+
4a4d8108
AM
12107+#endif /* __KERNEL__ */
12108+#endif /* __AUFS_DYNOP_H__ */
0b1ff5c3
JR
12109diff -urNp -x '*.orig' linux-4.14/fs/aufs/export.c linux-4.14/fs/aufs/export.c
12110--- linux-4.14/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
12111+++ linux-4.14/fs/aufs/export.c 2021-02-24 21:42:43.441114748 +0100
f2c43d5f 12112@@ -0,0 +1,836 @@
4a4d8108 12113+/*
a2654f78 12114+ * Copyright (C) 2005-2017 Junjiro R. Okajima
4a4d8108
AM
12115+ *
12116+ * This program, aufs is free software; you can redistribute it and/or modify
12117+ * it under the terms of the GNU General Public License as published by
12118+ * the Free Software Foundation; either version 2 of the License, or
12119+ * (at your option) any later version.
12120+ *
12121+ * This program is distributed in the hope that it will be useful,
12122+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12123+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12124+ * GNU General Public License for more details.
12125+ *
12126+ * You should have received a copy of the GNU General Public License
523b37e3 12127+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
12128+ */
12129+
12130+/*
12131+ * export via nfs
12132+ */
12133+
12134+#include <linux/exportfs.h>
7eafdf33 12135+#include <linux/fs_struct.h>
4a4d8108
AM
12136+#include <linux/namei.h>
12137+#include <linux/nsproxy.h>
12138+#include <linux/random.h>
12139+#include <linux/writeback.h>
12140+#include "aufs.h"
12141+
12142+union conv {
12143+#ifdef CONFIG_AUFS_INO_T_64
12144+ __u32 a[2];
12145+#else
12146+ __u32 a[1];
12147+#endif
12148+ ino_t ino;
12149+};
12150+
12151+static ino_t decode_ino(__u32 *a)
12152+{
12153+ union conv u;
12154+
12155+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
12156+ u.a[0] = a[0];
12157+#ifdef CONFIG_AUFS_INO_T_64
12158+ u.a[1] = a[1];
12159+#endif
12160+ return u.ino;
12161+}
12162+
12163+static void encode_ino(__u32 *a, ino_t ino)
12164+{
12165+ union conv u;
12166+
12167+ u.ino = ino;
12168+ a[0] = u.a[0];
12169+#ifdef CONFIG_AUFS_INO_T_64
12170+ a[1] = u.a[1];
12171+#endif
12172+}
12173+
12174+/* NFS file handle */
12175+enum {
12176+ Fh_br_id,
12177+ Fh_sigen,
12178+#ifdef CONFIG_AUFS_INO_T_64
12179+ /* support 64bit inode number */
12180+ Fh_ino1,
12181+ Fh_ino2,
12182+ Fh_dir_ino1,
12183+ Fh_dir_ino2,
12184+#else
12185+ Fh_ino1,
12186+ Fh_dir_ino1,
12187+#endif
12188+ Fh_igen,
12189+ Fh_h_type,
12190+ Fh_tail,
12191+
12192+ Fh_ino = Fh_ino1,
12193+ Fh_dir_ino = Fh_dir_ino1
12194+};
12195+
12196+static int au_test_anon(struct dentry *dentry)
12197+{
027c5e7a 12198+ /* note: read d_flags without d_lock */
4a4d8108
AM
12199+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
12200+}
12201+
a2a7ad62
AM
12202+int au_test_nfsd(void)
12203+{
12204+ int ret;
12205+ struct task_struct *tsk = current;
12206+ char comm[sizeof(tsk->comm)];
12207+
12208+ ret = 0;
12209+ if (tsk->flags & PF_KTHREAD) {
12210+ get_task_comm(comm, tsk);
12211+ ret = !strcmp(comm, "nfsd");
12212+ }
12213+
12214+ return ret;
12215+}
12216+
4a4d8108
AM
12217+/* ---------------------------------------------------------------------- */
12218+/* inode generation external table */
12219+
b752ccd1 12220+void au_xigen_inc(struct inode *inode)
4a4d8108 12221+{
4a4d8108
AM
12222+ loff_t pos;
12223+ ssize_t sz;
12224+ __u32 igen;
12225+ struct super_block *sb;
12226+ struct au_sbinfo *sbinfo;
12227+
4a4d8108 12228+ sb = inode->i_sb;
b752ccd1 12229+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 12230+
b752ccd1 12231+ sbinfo = au_sbi(sb);
1facf9fc 12232+ pos = inode->i_ino;
12233+ pos *= sizeof(igen);
12234+ igen = inode->i_generation + 1;
1facf9fc 12235+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
12236+ sizeof(igen), &pos);
12237+ if (sz == sizeof(igen))
b752ccd1 12238+ return; /* success */
1facf9fc 12239+
b752ccd1 12240+ if (unlikely(sz >= 0))
1facf9fc 12241+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 12242+}
12243+
12244+int au_xigen_new(struct inode *inode)
12245+{
12246+ int err;
12247+ loff_t pos;
12248+ ssize_t sz;
12249+ struct super_block *sb;
12250+ struct au_sbinfo *sbinfo;
12251+ struct file *file;
12252+
12253+ err = 0;
12254+ /* todo: dirty, at mount time */
12255+ if (inode->i_ino == AUFS_ROOT_INO)
12256+ goto out;
12257+ sb = inode->i_sb;
dece6358 12258+ SiMustAnyLock(sb);
1facf9fc 12259+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
12260+ goto out;
12261+
12262+ err = -EFBIG;
12263+ pos = inode->i_ino;
12264+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
12265+ AuIOErr1("too large i%lld\n", pos);
12266+ goto out;
12267+ }
12268+ pos *= sizeof(inode->i_generation);
12269+
12270+ err = 0;
12271+ sbinfo = au_sbi(sb);
12272+ file = sbinfo->si_xigen;
12273+ BUG_ON(!file);
12274+
c06a8ce3 12275+ if (vfsub_f_size_read(file)
1facf9fc 12276+ < pos + sizeof(inode->i_generation)) {
12277+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
12278+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
12279+ sizeof(inode->i_generation), &pos);
12280+ } else
12281+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
12282+ sizeof(inode->i_generation), &pos);
12283+ if (sz == sizeof(inode->i_generation))
12284+ goto out; /* success */
12285+
12286+ err = sz;
12287+ if (unlikely(sz >= 0)) {
12288+ err = -EIO;
12289+ AuIOErr("xigen error (%zd)\n", sz);
12290+ }
12291+
4f0767ce 12292+out:
1facf9fc 12293+ return err;
12294+}
12295+
12296+int au_xigen_set(struct super_block *sb, struct file *base)
12297+{
12298+ int err;
12299+ struct au_sbinfo *sbinfo;
12300+ struct file *file;
12301+
dece6358
AM
12302+ SiMustWriteLock(sb);
12303+
1facf9fc 12304+ sbinfo = au_sbi(sb);
12305+ file = au_xino_create2(base, sbinfo->si_xigen);
12306+ err = PTR_ERR(file);
12307+ if (IS_ERR(file))
12308+ goto out;
12309+ err = 0;
12310+ if (sbinfo->si_xigen)
12311+ fput(sbinfo->si_xigen);
12312+ sbinfo->si_xigen = file;
12313+
4f0767ce 12314+out:
1facf9fc 12315+ return err;
12316+}
12317+
12318+void au_xigen_clr(struct super_block *sb)
12319+{
12320+ struct au_sbinfo *sbinfo;
12321+
dece6358
AM
12322+ SiMustWriteLock(sb);
12323+
1facf9fc 12324+ sbinfo = au_sbi(sb);
12325+ if (sbinfo->si_xigen) {
12326+ fput(sbinfo->si_xigen);
12327+ sbinfo->si_xigen = NULL;
12328+ }
12329+}
12330+
12331+/* ---------------------------------------------------------------------- */
12332+
12333+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
12334+ ino_t dir_ino)
12335+{
12336+ struct dentry *dentry, *d;
12337+ struct inode *inode;
12338+ unsigned int sigen;
12339+
12340+ dentry = NULL;
12341+ inode = ilookup(sb, ino);
12342+ if (!inode)
12343+ goto out;
12344+
12345+ dentry = ERR_PTR(-ESTALE);
12346+ sigen = au_sigen(sb);
5afbbe0d 12347+ if (unlikely(au_is_bad_inode(inode)
1facf9fc 12348+ || IS_DEADDIR(inode)
537831f9 12349+ || sigen != au_iigen(inode, NULL)))
1facf9fc 12350+ goto out_iput;
12351+
12352+ dentry = NULL;
12353+ if (!dir_ino || S_ISDIR(inode->i_mode))
12354+ dentry = d_find_alias(inode);
12355+ else {
027c5e7a 12356+ spin_lock(&inode->i_lock);
c1595e42 12357+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) {
027c5e7a 12358+ spin_lock(&d->d_lock);
1facf9fc 12359+ if (!au_test_anon(d)
5527c038 12360+ && d_inode(d->d_parent)->i_ino == dir_ino) {
027c5e7a
AM
12361+ dentry = dget_dlock(d);
12362+ spin_unlock(&d->d_lock);
1facf9fc 12363+ break;
12364+ }
027c5e7a
AM
12365+ spin_unlock(&d->d_lock);
12366+ }
12367+ spin_unlock(&inode->i_lock);
1facf9fc 12368+ }
027c5e7a 12369+ if (unlikely(dentry && au_digen_test(dentry, sigen))) {
2cbb1c4b 12370+ /* need to refresh */
1facf9fc 12371+ dput(dentry);
2cbb1c4b 12372+ dentry = NULL;
1facf9fc 12373+ }
12374+
4f0767ce 12375+out_iput:
1facf9fc 12376+ iput(inode);
4f0767ce 12377+out:
2cbb1c4b 12378+ AuTraceErrPtr(dentry);
1facf9fc 12379+ return dentry;
12380+}
12381+
12382+/* ---------------------------------------------------------------------- */
12383+
12384+/* todo: dirty? */
12385+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
12386+
12387+struct au_compare_mnt_args {
12388+ /* input */
12389+ struct super_block *sb;
12390+
12391+ /* output */
12392+ struct vfsmount *mnt;
12393+};
12394+
12395+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
12396+{
12397+ struct au_compare_mnt_args *a = arg;
12398+
12399+ if (mnt->mnt_sb != a->sb)
12400+ return 0;
12401+ a->mnt = mntget(mnt);
12402+ return 1;
12403+}
12404+
1facf9fc 12405+static struct vfsmount *au_mnt_get(struct super_block *sb)
12406+{
4a4d8108 12407+ int err;
7eafdf33 12408+ struct path root;
4a4d8108
AM
12409+ struct au_compare_mnt_args args = {
12410+ .sb = sb
12411+ };
1facf9fc 12412+
7eafdf33 12413+ get_fs_root(current->fs, &root);
523b37e3 12414+ rcu_read_lock();
7eafdf33 12415+ err = iterate_mounts(au_compare_mnt, &args, root.mnt);
523b37e3 12416+ rcu_read_unlock();
7eafdf33 12417+ path_put(&root);
4a4d8108
AM
12418+ AuDebugOn(!err);
12419+ AuDebugOn(!args.mnt);
12420+ return args.mnt;
1facf9fc 12421+}
12422+
12423+struct au_nfsd_si_lock {
4a4d8108 12424+ unsigned int sigen;
027c5e7a 12425+ aufs_bindex_t bindex, br_id;
1facf9fc 12426+ unsigned char force_lock;
12427+};
12428+
027c5e7a
AM
12429+static int si_nfsd_read_lock(struct super_block *sb,
12430+ struct au_nfsd_si_lock *nsi_lock)
1facf9fc 12431+{
027c5e7a 12432+ int err;
1facf9fc 12433+ aufs_bindex_t bindex;
12434+
12435+ si_read_lock(sb, AuLock_FLUSH);
12436+
12437+ /* branch id may be wrapped around */
027c5e7a 12438+ err = 0;
1facf9fc 12439+ bindex = au_br_index(sb, nsi_lock->br_id);
12440+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
12441+ goto out; /* success */
12442+
027c5e7a
AM
12443+ err = -ESTALE;
12444+ bindex = -1;
1facf9fc 12445+ if (!nsi_lock->force_lock)
12446+ si_read_unlock(sb);
1facf9fc 12447+
4f0767ce 12448+out:
027c5e7a
AM
12449+ nsi_lock->bindex = bindex;
12450+ return err;
1facf9fc 12451+}
12452+
12453+struct find_name_by_ino {
392086de 12454+ struct dir_context ctx;
1facf9fc 12455+ int called, found;
12456+ ino_t ino;
12457+ char *name;
12458+ int namelen;
12459+};
12460+
12461+static int
392086de
AM
12462+find_name_by_ino(struct dir_context *ctx, const char *name, int namelen,
12463+ loff_t offset, u64 ino, unsigned int d_type)
1facf9fc 12464+{
392086de
AM
12465+ struct find_name_by_ino *a = container_of(ctx, struct find_name_by_ino,
12466+ ctx);
1facf9fc 12467+
12468+ a->called++;
12469+ if (a->ino != ino)
12470+ return 0;
12471+
12472+ memcpy(a->name, name, namelen);
12473+ a->namelen = namelen;
12474+ a->found = 1;
12475+ return 1;
12476+}
12477+
12478+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
12479+ struct au_nfsd_si_lock *nsi_lock)
12480+{
12481+ struct dentry *dentry, *parent;
12482+ struct file *file;
12483+ struct inode *dir;
392086de
AM
12484+ struct find_name_by_ino arg = {
12485+ .ctx = {
2000de60 12486+ .actor = find_name_by_ino
392086de
AM
12487+ }
12488+ };
1facf9fc 12489+ int err;
12490+
12491+ parent = path->dentry;
12492+ if (nsi_lock)
12493+ si_read_unlock(parent->d_sb);
4a4d8108 12494+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 12495+ dentry = (void *)file;
12496+ if (IS_ERR(file))
12497+ goto out;
12498+
12499+ dentry = ERR_PTR(-ENOMEM);
537831f9 12500+ arg.name = (void *)__get_free_page(GFP_NOFS);
1facf9fc 12501+ if (unlikely(!arg.name))
12502+ goto out_file;
12503+ arg.ino = ino;
12504+ arg.found = 0;
12505+ do {
12506+ arg.called = 0;
12507+ /* smp_mb(); */
392086de 12508+ err = vfsub_iterate_dir(file, &arg.ctx);
1facf9fc 12509+ } while (!err && !arg.found && arg.called);
12510+ dentry = ERR_PTR(err);
12511+ if (unlikely(err))
12512+ goto out_name;
1716fcea
AM
12513+ /* instead of ENOENT */
12514+ dentry = ERR_PTR(-ESTALE);
1facf9fc 12515+ if (!arg.found)
12516+ goto out_name;
12517+
b4510431 12518+ /* do not call vfsub_lkup_one() */
5527c038 12519+ dir = d_inode(parent);
febd17d6 12520+ dentry = vfsub_lookup_one_len_unlocked(arg.name, parent, arg.namelen);
1facf9fc 12521+ AuTraceErrPtr(dentry);
12522+ if (IS_ERR(dentry))
12523+ goto out_name;
12524+ AuDebugOn(au_test_anon(dentry));
5527c038 12525+ if (unlikely(d_really_is_negative(dentry))) {
1facf9fc 12526+ dput(dentry);
12527+ dentry = ERR_PTR(-ENOENT);
12528+ }
12529+
4f0767ce 12530+out_name:
1c60b727 12531+ free_page((unsigned long)arg.name);
4f0767ce 12532+out_file:
1facf9fc 12533+ fput(file);
4f0767ce 12534+out:
1facf9fc 12535+ if (unlikely(nsi_lock
12536+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
12537+ if (!IS_ERR(dentry)) {
12538+ dput(dentry);
12539+ dentry = ERR_PTR(-ESTALE);
12540+ }
12541+ AuTraceErrPtr(dentry);
12542+ return dentry;
12543+}
12544+
12545+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
12546+ ino_t dir_ino,
12547+ struct au_nfsd_si_lock *nsi_lock)
12548+{
12549+ struct dentry *dentry;
12550+ struct path path;
12551+
12552+ if (dir_ino != AUFS_ROOT_INO) {
12553+ path.dentry = decode_by_ino(sb, dir_ino, 0);
12554+ dentry = path.dentry;
12555+ if (!path.dentry || IS_ERR(path.dentry))
12556+ goto out;
12557+ AuDebugOn(au_test_anon(path.dentry));
12558+ } else
12559+ path.dentry = dget(sb->s_root);
12560+
12561+ path.mnt = au_mnt_get(sb);
12562+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
12563+ path_put(&path);
12564+
4f0767ce 12565+out:
1facf9fc 12566+ AuTraceErrPtr(dentry);
12567+ return dentry;
12568+}
12569+
12570+/* ---------------------------------------------------------------------- */
12571+
12572+static int h_acceptable(void *expv, struct dentry *dentry)
12573+{
12574+ return 1;
12575+}
12576+
12577+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
12578+ char *buf, int len, struct super_block *sb)
12579+{
12580+ char *p;
12581+ int n;
12582+ struct path path;
12583+
12584+ p = d_path(h_rootpath, buf, len);
12585+ if (IS_ERR(p))
12586+ goto out;
12587+ n = strlen(p);
12588+
12589+ path.mnt = h_rootpath->mnt;
12590+ path.dentry = h_parent;
12591+ p = d_path(&path, buf, len);
12592+ if (IS_ERR(p))
12593+ goto out;
12594+ if (n != 1)
12595+ p += n;
12596+
12597+ path.mnt = au_mnt_get(sb);
12598+ path.dentry = sb->s_root;
12599+ p = d_path(&path, buf, len - strlen(p));
12600+ mntput(path.mnt);
12601+ if (IS_ERR(p))
12602+ goto out;
12603+ if (n != 1)
12604+ p[strlen(p)] = '/';
12605+
4f0767ce 12606+out:
1facf9fc 12607+ AuTraceErrPtr(p);
12608+ return p;
12609+}
12610+
12611+static
027c5e7a
AM
12612+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh,
12613+ int fh_len, struct au_nfsd_si_lock *nsi_lock)
1facf9fc 12614+{
12615+ struct dentry *dentry, *h_parent, *root;
12616+ struct super_block *h_sb;
12617+ char *pathname, *p;
12618+ struct vfsmount *h_mnt;
12619+ struct au_branch *br;
12620+ int err;
12621+ struct path path;
12622+
027c5e7a 12623+ br = au_sbr(sb, nsi_lock->bindex);
86dc4139 12624+ h_mnt = au_br_mnt(br);
1facf9fc 12625+ h_sb = h_mnt->mnt_sb;
12626+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
5afbbe0d 12627+ lockdep_off();
1facf9fc 12628+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
12629+ fh_len - Fh_tail, fh[Fh_h_type],
12630+ h_acceptable, /*context*/NULL);
5afbbe0d 12631+ lockdep_on();
1facf9fc 12632+ dentry = h_parent;
12633+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
12634+ AuWarn1("%s decode_fh failed, %ld\n",
12635+ au_sbtype(h_sb), PTR_ERR(h_parent));
12636+ goto out;
12637+ }
12638+ dentry = NULL;
12639+ if (unlikely(au_test_anon(h_parent))) {
12640+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
12641+ au_sbtype(h_sb));
12642+ goto out_h_parent;
12643+ }
12644+
12645+ dentry = ERR_PTR(-ENOMEM);
12646+ pathname = (void *)__get_free_page(GFP_NOFS);
12647+ if (unlikely(!pathname))
12648+ goto out_h_parent;
12649+
12650+ root = sb->s_root;
12651+ path.mnt = h_mnt;
12652+ di_read_lock_parent(root, !AuLock_IR);
027c5e7a 12653+ path.dentry = au_h_dptr(root, nsi_lock->bindex);
1facf9fc 12654+ di_read_unlock(root, !AuLock_IR);
12655+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
12656+ dentry = (void *)p;
12657+ if (IS_ERR(p))
12658+ goto out_pathname;
12659+
12660+ si_read_unlock(sb);
12661+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
12662+ dentry = ERR_PTR(err);
12663+ if (unlikely(err))
12664+ goto out_relock;
12665+
12666+ dentry = ERR_PTR(-ENOENT);
12667+ AuDebugOn(au_test_anon(path.dentry));
5527c038 12668+ if (unlikely(d_really_is_negative(path.dentry)))
1facf9fc 12669+ goto out_path;
12670+
5527c038 12671+ if (ino != d_inode(path.dentry)->i_ino)
1facf9fc 12672+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
12673+ else
12674+ dentry = dget(path.dentry);
12675+
4f0767ce 12676+out_path:
1facf9fc 12677+ path_put(&path);
4f0767ce 12678+out_relock:
1facf9fc 12679+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
12680+ if (!IS_ERR(dentry)) {
12681+ dput(dentry);
12682+ dentry = ERR_PTR(-ESTALE);
12683+ }
4f0767ce 12684+out_pathname:
1c60b727 12685+ free_page((unsigned long)pathname);
4f0767ce 12686+out_h_parent:
1facf9fc 12687+ dput(h_parent);
4f0767ce 12688+out:
1facf9fc 12689+ AuTraceErrPtr(dentry);
12690+ return dentry;
12691+}
12692+
12693+/* ---------------------------------------------------------------------- */
12694+
12695+static struct dentry *
12696+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
12697+ int fh_type)
12698+{
12699+ struct dentry *dentry;
12700+ __u32 *fh = fid->raw;
027c5e7a 12701+ struct au_branch *br;
1facf9fc 12702+ ino_t ino, dir_ino;
1facf9fc 12703+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 12704+ .force_lock = 0
12705+ };
12706+
1facf9fc 12707+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
12708+ /* it should never happen, but the file handle is unreliable */
12709+ if (unlikely(fh_len < Fh_tail))
12710+ goto out;
12711+ nsi_lock.sigen = fh[Fh_sigen];
12712+ nsi_lock.br_id = fh[Fh_br_id];
12713+
1facf9fc 12714+ /* branch id may be wrapped around */
027c5e7a
AM
12715+ br = NULL;
12716+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock)))
0b1ff5c3
JR
12717+ goto out;
12718+ nsi_lock.force_lock = 1;
076b876e 12719+
0b1ff5c3
JR
12720+ /* is this inode still cached? */
12721+ ino = decode_ino(fh + Fh_ino);
12722+ /* it should never happen */
12723+ if (unlikely(ino == AUFS_ROOT_INO))
12724+ goto out_unlock;
076b876e 12725+
0b1ff5c3
JR
12726+ dir_ino = decode_ino(fh + Fh_dir_ino);
12727+ dentry = decode_by_ino(sb, ino, dir_ino);
12728+ if (IS_ERR(dentry))
12729+ goto out_unlock;
12730+ if (dentry)
12731+ goto accept;
076b876e 12732+
0b1ff5c3
JR
12733+ /* is the parent dir cached? */
12734+ br = au_sbr(sb, nsi_lock.bindex);
12735+ au_br_get(br);
12736+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
12737+ if (IS_ERR(dentry))
12738+ goto out_unlock;
12739+ if (dentry)
12740+ goto accept;
076b876e 12741+
0b1ff5c3
JR
12742+ /* lookup path */
12743+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock);
12744+ if (IS_ERR(dentry))
12745+ goto out_unlock;
12746+ if (unlikely(!dentry))
12747+ /* todo?: make it ESTALE */
12748+ goto out_unlock;
076b876e 12749+
0b1ff5c3
JR
12750+accept:
12751+ if (!au_digen_test(dentry, au_sigen(sb))
12752+ && d_inode(dentry)->i_generation == fh[Fh_igen])
12753+ goto out_unlock; /* success */
12754+
12755+ dput(dentry);
12756+ dentry = ERR_PTR(-ESTALE);
12757+out_unlock:
12758+ if (br)
12759+ au_br_put(br);
12760+ si_read_unlock(sb);
076b876e 12761+out:
0b1ff5c3
JR
12762+ AuTraceErrPtr(dentry);
12763+ return dentry;
076b876e
AM
12764+}
12765+
0b1ff5c3
JR
12766+#if 0 /* reserved for future use */
12767+/* support subtreecheck option */
12768+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
12769+ int fh_len, int fh_type)
076b876e 12770+{
0b1ff5c3
JR
12771+ struct dentry *parent;
12772+ __u32 *fh = fid->raw;
12773+ ino_t dir_ino;
076b876e 12774+
0b1ff5c3
JR
12775+ dir_ino = decode_ino(fh + Fh_dir_ino);
12776+ parent = decode_by_ino(sb, dir_ino, 0);
12777+ if (IS_ERR(parent))
12778+ goto out;
12779+ if (!parent)
12780+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
12781+ dir_ino, fh, fh_len);
076b876e 12782+
0b1ff5c3
JR
12783+out:
12784+ AuTraceErrPtr(parent);
12785+ return parent;
076b876e 12786+}
0b1ff5c3 12787+#endif
076b876e 12788+
0b1ff5c3 12789+/* ---------------------------------------------------------------------- */
076b876e 12790+
0b1ff5c3
JR
12791+static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len,
12792+ struct inode *dir)
076b876e 12793+{
0b1ff5c3
JR
12794+ int err;
12795+ aufs_bindex_t bindex;
12796+ struct super_block *sb, *h_sb;
12797+ struct dentry *dentry, *parent, *h_parent;
12798+ struct inode *h_dir;
12799+ struct au_branch *br;
076b876e 12800+
0b1ff5c3
JR
12801+ err = -ENOSPC;
12802+ if (unlikely(*max_len <= Fh_tail)) {
12803+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
076b876e 12804+ goto out;
0b1ff5c3 12805+ }
076b876e 12806+
0b1ff5c3
JR
12807+ err = FILEID_ROOT;
12808+ if (inode->i_ino == AUFS_ROOT_INO) {
12809+ AuDebugOn(inode->i_ino != AUFS_ROOT_INO);
076b876e 12810+ goto out;
0b1ff5c3 12811+ }
076b876e 12812+
0b1ff5c3
JR
12813+ h_parent = NULL;
12814+ sb = inode->i_sb;
12815+ err = si_read_lock(sb, AuLock_FLUSH);
076b876e
AM
12816+ if (unlikely(err))
12817+ goto out;
12818+
0b1ff5c3
JR
12819+#ifdef CONFIG_AUFS_DEBUG
12820+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
12821+ AuWarn1("NFS-exporting requires xino\n");
12822+#endif
12823+ err = -EIO;
12824+ parent = NULL;
12825+ ii_read_lock_child(inode);
12826+ bindex = au_ibtop(inode);
12827+ if (!dir) {
12828+ dentry = d_find_any_alias(inode);
12829+ if (unlikely(!dentry))
12830+ goto out_unlock;
12831+ AuDebugOn(au_test_anon(dentry));
12832+ parent = dget_parent(dentry);
12833+ dput(dentry);
12834+ if (unlikely(!parent))
12835+ goto out_unlock;
12836+ if (d_really_is_positive(parent))
12837+ dir = d_inode(parent);
12838+ }
076b876e 12839+
0b1ff5c3
JR
12840+ ii_read_lock_parent(dir);
12841+ h_dir = au_h_iptr(dir, bindex);
12842+ ii_read_unlock(dir);
12843+ if (unlikely(!h_dir))
12844+ goto out_parent;
12845+ h_parent = d_find_any_alias(h_dir);
12846+ if (unlikely(!h_parent))
12847+ goto out_hparent;
076b876e 12848+
0b1ff5c3
JR
12849+ err = -EPERM;
12850+ br = au_sbr(sb, bindex);
12851+ h_sb = au_br_sb(br);
12852+ if (unlikely(!h_sb->s_export_op)) {
12853+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
12854+ goto out_hparent;
12855+ }
12856+
12857+ fh[Fh_br_id] = br->br_id;
12858+ fh[Fh_sigen] = au_sigen(sb);
12859+ encode_ino(fh + Fh_ino, inode->i_ino);
12860+ encode_ino(fh + Fh_dir_ino, dir->i_ino);
12861+ fh[Fh_igen] = inode->i_generation;
12862+
12863+ *max_len -= Fh_tail;
12864+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
12865+ max_len,
12866+ /*connectable or subtreecheck*/0);
12867+ err = fh[Fh_h_type];
12868+ *max_len += Fh_tail;
12869+ /* todo: macros? */
12870+ if (err != FILEID_INVALID)
12871+ err = 99;
12872+ else
12873+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
12874+
12875+out_hparent:
12876+ dput(h_parent);
12877+out_parent:
12878+ dput(parent);
12879+out_unlock:
12880+ ii_read_unlock(inode);
12881+ si_read_unlock(sb);
076b876e 12882+out:
0b1ff5c3
JR
12883+ if (unlikely(err < 0))
12884+ err = FILEID_INVALID;
076b876e
AM
12885+ return err;
12886+}
12887+
12888+/* ---------------------------------------------------------------------- */
12889+
0b1ff5c3 12890+static int aufs_commit_metadata(struct inode *inode)
076b876e
AM
12891+{
12892+ int err;
0b1ff5c3
JR
12893+ aufs_bindex_t bindex;
12894+ struct super_block *sb;
12895+ struct inode *h_inode;
12896+ int (*f)(struct inode *inode);
076b876e 12897+
0b1ff5c3
JR
12898+ sb = inode->i_sb;
12899+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
12900+ ii_write_lock_child(inode);
12901+ bindex = au_ibtop(inode);
12902+ AuDebugOn(bindex < 0);
12903+ h_inode = au_h_iptr(inode, bindex);
076b876e 12904+
0b1ff5c3
JR
12905+ f = h_inode->i_sb->s_export_op->commit_metadata;
12906+ if (f)
12907+ err = f(h_inode);
12908+ else {
12909+ struct writeback_control wbc = {
12910+ .sync_mode = WB_SYNC_ALL,
12911+ .nr_to_write = 0 /* metadata only */
12912+ };
076b876e 12913+
0b1ff5c3
JR
12914+ err = sync_inode(h_inode, &wbc);
12915+ }
076b876e 12916+
0b1ff5c3
JR
12917+ au_cpup_attr_timesizes(inode);
12918+ ii_write_unlock(inode);
12919+ si_read_unlock(sb);
12920+ return err;
076b876e
AM
12921+}
12922+
0b1ff5c3 12923+/* ---------------------------------------------------------------------- */
076b876e 12924+
0b1ff5c3
JR
12925+static struct export_operations aufs_export_op = {
12926+ .fh_to_dentry = aufs_fh_to_dentry,
12927+ /* .fh_to_parent = aufs_fh_to_parent, */
12928+ .encode_fh = aufs_encode_fh,
12929+ .commit_metadata = aufs_commit_metadata
12930+};
076b876e 12931+
0b1ff5c3 12932+void au_export_init(struct super_block *sb)
076b876e 12933+{
0b1ff5c3
JR
12934+ struct au_sbinfo *sbinfo;
12935+ __u32 u;
076b876e 12936+
0b1ff5c3
JR
12937+ BUILD_BUG_ON_MSG(IS_BUILTIN(CONFIG_AUFS_FS)
12938+ && IS_MODULE(CONFIG_EXPORTFS),
12939+ AUFS_NAME ": unsupported configuration "
12940+ "CONFIG_EXPORTFS=m and CONFIG_AUFS_FS=y");
076b876e 12941+
0b1ff5c3
JR
12942+ sb->s_export_op = &aufs_export_op;
12943+ sbinfo = au_sbi(sb);
12944+ sbinfo->si_xigen = NULL;
12945+ get_random_bytes(&u, sizeof(u));
12946+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
12947+ atomic_set(&sbinfo->si_xigen_next, u);
076b876e 12948+}
0b1ff5c3
JR
12949diff -urNp -x '*.orig' linux-4.14/fs/aufs/f_op.c linux-4.14/fs/aufs/f_op.c
12950--- linux-4.14/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
12951+++ linux-4.14/fs/aufs/f_op.c 2021-02-24 21:42:43.447781402 +0100
12952@@ -0,0 +1,817 @@
1facf9fc 12953+/*
a2654f78 12954+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 12955+ *
12956+ * This program, aufs is free software; you can redistribute it and/or modify
12957+ * it under the terms of the GNU General Public License as published by
12958+ * the Free Software Foundation; either version 2 of the License, or
12959+ * (at your option) any later version.
dece6358
AM
12960+ *
12961+ * This program is distributed in the hope that it will be useful,
12962+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12963+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12964+ * GNU General Public License for more details.
12965+ *
12966+ * You should have received a copy of the GNU General Public License
523b37e3 12967+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 12968+ */
12969+
12970+/*
0b1ff5c3 12971+ * file and vm operations
1facf9fc 12972+ */
12973+
0b1ff5c3
JR
12974+#include <linux/aio.h>
12975+#include <linux/fs_stack.h>
12976+#include <linux/mman.h>
12977+#include <linux/security.h>
1facf9fc 12978+#include "aufs.h"
12979+
0b1ff5c3 12980+int au_do_open_nondir(struct file *file, int flags, struct file *h_file)
4a4d8108 12981+{
0b1ff5c3
JR
12982+ int err;
12983+ aufs_bindex_t bindex;
12984+ struct dentry *dentry, *h_dentry;
12985+ struct au_finfo *finfo;
12986+ struct inode *h_inode;
12987+
12988+ FiMustWriteLock(file);
12989+
12990+ err = 0;
12991+ dentry = file->f_path.dentry;
12992+ AuDebugOn(IS_ERR_OR_NULL(dentry));
12993+ finfo = au_fi(file);
12994+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
12995+ atomic_set(&finfo->fi_mmapped, 0);
12996+ bindex = au_dbtop(dentry);
12997+ if (!h_file) {
12998+ h_dentry = au_h_dptr(dentry, bindex);
12999+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb);
13000+ if (unlikely(err))
13001+ goto out;
13002+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
13003+ } else {
13004+ h_dentry = h_file->f_path.dentry;
13005+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb);
13006+ if (unlikely(err))
13007+ goto out;
13008+ get_file(h_file);
13009+ }
13010+ if (IS_ERR(h_file))
13011+ err = PTR_ERR(h_file);
13012+ else {
13013+ if ((flags & __O_TMPFILE)
13014+ && !(flags & O_EXCL)) {
13015+ h_inode = file_inode(h_file);
13016+ spin_lock(&h_inode->i_lock);
13017+ h_inode->i_state |= I_LINKABLE;
13018+ spin_unlock(&h_inode->i_lock);
13019+ }
13020+ au_set_fbtop(file, bindex);
13021+ au_set_h_fptr(file, bindex, h_file);
13022+ au_update_figen(file);
13023+ /* todo: necessary? */
13024+ /* file->f_ra = h_file->f_ra; */
13025+ }
13026+
13027+out:
13028+ return err;
4a4d8108
AM
13029+}
13030+
0b1ff5c3
JR
13031+static int aufs_open_nondir(struct inode *inode __maybe_unused,
13032+ struct file *file)
1facf9fc 13033+{
0b1ff5c3 13034+ int err;
4a4d8108 13035+ struct super_block *sb;
0b1ff5c3
JR
13036+ struct au_do_open_args args = {
13037+ .open = au_do_open_nondir
13038+ };
13039+
13040+ AuDbg("%pD, f_flags 0x%x, f_mode 0x%x\n",
13041+ file, vfsub_file_flags(file), file->f_mode);
13042+
13043+ sb = file->f_path.dentry->d_sb;
13044+ si_read_lock(sb, AuLock_FLUSH);
13045+ err = au_do_open(file, &args);
13046+ si_read_unlock(sb);
13047+ return err;
13048+}
13049+
13050+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
13051+{
13052+ struct au_finfo *finfo;
13053+ aufs_bindex_t bindex;
13054+
13055+ finfo = au_fi(file);
13056+ au_hbl_del(&finfo->fi_hlist,
13057+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
13058+ bindex = finfo->fi_btop;
13059+ if (bindex >= 0)
13060+ au_set_h_fptr(file, bindex, NULL);
13061+
13062+ au_finfo_fin(file);
13063+ return 0;
13064+}
13065+
13066+/* ---------------------------------------------------------------------- */
13067+
13068+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
13069+{
b912730e 13070+ int err;
0b1ff5c3 13071+ struct file *h_file;
1facf9fc 13072+
0b1ff5c3
JR
13073+ err = 0;
13074+ h_file = au_hf_top(file);
13075+ if (h_file)
13076+ err = vfsub_flush(h_file, id);
13077+ return err;
13078+}
13079+
13080+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
13081+{
13082+ return au_do_flush(file, id, au_do_flush_nondir);
13083+}
13084+
13085+/* ---------------------------------------------------------------------- */
13086+/*
13087+ * read and write functions acquire [fdi]_rwsem once, but release before
13088+ * mmap_sem. This is because to stop a race condition between mmap(2).
13089+ * Releasing these aufs-rwsem should be safe, no branch-mamagement (by keeping
13090+ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in
13091+ * read functions after [fdi]_rwsem are released, but it should be harmless.
13092+ */
13093+
13094+/* Callers should call au_read_post() or fput() in the end */
13095+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc)
13096+{
13097+ struct file *h_file;
13098+ int err;
13099+
13100+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, lsc);
13101+ if (!err) {
13102+ di_read_unlock(file->f_path.dentry, AuLock_IR);
13103+ h_file = au_hf_top(file);
13104+ get_file(h_file);
13105+ if (!keep_fi)
13106+ fi_read_unlock(file);
13107+ } else
13108+ h_file = ERR_PTR(err);
13109+
13110+ return h_file;
13111+}
13112+
13113+static void au_read_post(struct inode *inode, struct file *h_file)
13114+{
13115+ /* update without lock, I don't think it a problem */
13116+ fsstack_copy_attr_atime(inode, file_inode(h_file));
13117+ fput(h_file);
13118+}
13119+
13120+struct au_write_pre {
13121+ /* input */
13122+ unsigned int lsc;
13123+
13124+ /* output */
13125+ blkcnt_t blks;
13126+ aufs_bindex_t btop;
13127+};
13128+
13129+/*
13130+ * return with iinfo is write-locked
13131+ * callers should call au_write_post() or iinfo_write_unlock() + fput() in the
13132+ * end
13133+ */
13134+static struct file *au_write_pre(struct file *file, int do_ready,
13135+ struct au_write_pre *wpre)
13136+{
13137+ struct file *h_file;
13138+ struct dentry *dentry;
13139+ int err;
13140+ unsigned int lsc;
13141+ struct au_pin pin;
1facf9fc 13142+
0b1ff5c3
JR
13143+ lsc = 0;
13144+ if (wpre)
13145+ lsc = wpre->lsc;
13146+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, lsc);
b912730e
AM
13147+ h_file = ERR_PTR(err);
13148+ if (unlikely(err))
027c5e7a 13149+ goto out;
1facf9fc 13150+
0b1ff5c3
JR
13151+ dentry = file->f_path.dentry;
13152+ if (do_ready) {
13153+ err = au_ready_to_write(file, -1, &pin);
4a4d8108 13154+ if (unlikely(err)) {
4a4d8108 13155+ h_file = ERR_PTR(err);
0b1ff5c3
JR
13156+ di_write_unlock(dentry);
13157+ goto out_fi;
4a4d8108
AM
13158+ }
13159+ }
1facf9fc 13160+
0b1ff5c3
JR
13161+ di_downgrade_lock(dentry, /*flags*/0);
13162+ if (wpre)
13163+ wpre->btop = au_fbtop(file);
13164+ h_file = au_hf_top(file);
13165+ get_file(h_file);
13166+ if (wpre)
13167+ wpre->blks = file_inode(h_file)->i_blocks;
13168+ if (do_ready)
13169+ au_unpin(&pin);
13170+ di_read_unlock(dentry, /*flags*/0);
13171+
13172+out_fi:
13173+ fi_write_unlock(file);
4f0767ce 13174+out:
4a4d8108
AM
13175+ return h_file;
13176+}
1308ab2a 13177+
0b1ff5c3
JR
13178+static void au_write_post(struct inode *inode, struct file *h_file,
13179+ struct au_write_pre *wpre, ssize_t written)
076b876e 13180+{
0b1ff5c3
JR
13181+ struct inode *h_inode;
13182+
13183+ au_cpup_attr_timesizes(inode);
13184+ AuDebugOn(au_ibtop(inode) != wpre->btop);
13185+ h_inode = file_inode(h_file);
13186+ inode->i_mode = h_inode->i_mode;
13187+ ii_write_unlock(inode);
13188+ /* AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); */
13189+ if (written > 0)
13190+ au_fhsm_wrote(inode->i_sb, wpre->btop,
13191+ /*force*/h_inode->i_blocks > wpre->blks);
13192+ fput(h_file);
13193+}
13194+
13195+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
13196+ loff_t *ppos)
13197+{
13198+ ssize_t err;
13199+ struct inode *inode;
13200+ struct file *h_file;
076b876e 13201+ struct super_block *sb;
076b876e 13202+
0b1ff5c3
JR
13203+ inode = file_inode(file);
13204+ sb = inode->i_sb;
13205+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
076b876e 13206+
0b1ff5c3
JR
13207+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
13208+ err = PTR_ERR(h_file);
13209+ if (IS_ERR(h_file))
076b876e
AM
13210+ goto out;
13211+
0b1ff5c3
JR
13212+ /* filedata may be obsoleted by concurrent copyup, but no problem */
13213+ err = vfsub_read_u(h_file, buf, count, ppos);
13214+ /* todo: necessary? */
13215+ /* file->f_ra = h_file->f_ra; */
13216+ au_read_post(inode, h_file);
076b876e 13217+
0b1ff5c3
JR
13218+out:
13219+ si_read_unlock(sb);
13220+ return err;
13221+}
076b876e 13222+
0b1ff5c3
JR
13223+/*
13224+ * todo: very ugly
13225+ * it locks both of i_mutex and si_rwsem for read in safe.
13226+ * if the plink maintenance mode continues forever (that is the problem),
13227+ * may loop forever.
13228+ */
13229+static void au_mtx_and_read_lock(struct inode *inode)
13230+{
13231+ int err;
13232+ struct super_block *sb = inode->i_sb;
076b876e 13233+
0b1ff5c3
JR
13234+ while (1) {
13235+ inode_lock(inode);
13236+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
13237+ if (!err)
13238+ break;
13239+ inode_unlock(inode);
13240+ si_read_lock(sb, AuLock_NOPLMW);
13241+ si_read_unlock(sb);
13242+ }
13243+}
076b876e 13244+
0b1ff5c3
JR
13245+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
13246+ size_t count, loff_t *ppos)
13247+{
13248+ ssize_t err;
13249+ struct au_write_pre wpre;
13250+ struct inode *inode;
13251+ struct file *h_file;
13252+ char __user *buf = (char __user *)ubuf;
076b876e 13253+
0b1ff5c3
JR
13254+ inode = file_inode(file);
13255+ au_mtx_and_read_lock(inode);
076b876e 13256+
0b1ff5c3
JR
13257+ wpre.lsc = 0;
13258+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
13259+ err = PTR_ERR(h_file);
13260+ if (IS_ERR(h_file))
13261+ goto out;
076b876e 13262+
0b1ff5c3
JR
13263+ err = vfsub_write_u(h_file, buf, count, ppos);
13264+ au_write_post(inode, h_file, &wpre, err);
076b876e 13265+
076b876e 13266+out:
0b1ff5c3
JR
13267+ si_read_unlock(inode->i_sb);
13268+ inode_unlock(inode);
076b876e
AM
13269+ return err;
13270+}
13271+
0b1ff5c3
JR
13272+static ssize_t au_do_iter(struct file *h_file, int rw, struct kiocb *kio,
13273+ struct iov_iter *iov_iter)
1facf9fc 13274+{
0b1ff5c3
JR
13275+ ssize_t err;
13276+ struct file *file;
13277+ ssize_t (*iter)(struct kiocb *, struct iov_iter *);
1308ab2a 13278+
0b1ff5c3 13279+ err = security_file_permission(h_file, rw);
4a4d8108
AM
13280+ if (unlikely(err))
13281+ goto out;
1facf9fc 13282+
0b1ff5c3
JR
13283+ err = -ENOSYS;
13284+ iter = NULL;
13285+ if (rw == MAY_READ)
13286+ iter = h_file->f_op->read_iter;
13287+ else if (rw == MAY_WRITE)
13288+ iter = h_file->f_op->write_iter;
1facf9fc 13289+
0b1ff5c3
JR
13290+ file = kio->ki_filp;
13291+ kio->ki_filp = h_file;
13292+ if (iter) {
b912730e 13293+ lockdep_off();
0b1ff5c3 13294+ err = iter(kio, iov_iter);
b912730e 13295+ lockdep_on();
0b1ff5c3
JR
13296+ } else
13297+ /* currently there is no such fs */
13298+ WARN_ON_ONCE(1);
13299+ kio->ki_filp = file;
4a4d8108 13300+
4f0767ce 13301+out:
1308ab2a 13302+ return err;
13303+}
dece6358 13304+
0b1ff5c3 13305+static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
1308ab2a 13306+{
0b1ff5c3
JR
13307+ ssize_t err;
13308+ struct file *file, *h_file;
13309+ struct inode *inode;
13310+ struct super_block *sb;
1308ab2a 13311+
0b1ff5c3
JR
13312+ file = kio->ki_filp;
13313+ inode = file_inode(file);
13314+ sb = inode->i_sb;
13315+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
1308ab2a 13316+
0b1ff5c3 13317+ h_file = au_read_pre(file, /*keep_fi*/1, /*lsc*/0);
4a4d8108 13318+ err = PTR_ERR(h_file);
0b1ff5c3
JR
13319+ if (IS_ERR(h_file))
13320+ goto out;
13321+
13322+ if (0 && au_test_loopback_kthread()) {
13323+ au_warn_loopback(h_file->f_path.dentry->d_sb);
13324+ if (file->f_mapping != h_file->f_mapping) {
13325+ file->f_mapping = h_file->f_mapping;
13326+ smp_mb(); /* unnecessary? */
86dc4139 13327+ }
86dc4139 13328+ }
0b1ff5c3 13329+ fi_read_unlock(file);
4a4d8108 13330+
0b1ff5c3 13331+ err = au_do_iter(h_file, MAY_READ, kio, iov_iter);
4a4d8108
AM
13332+ /* todo: necessary? */
13333+ /* file->f_ra = h_file->f_ra; */
0b1ff5c3 13334+ au_read_post(inode, h_file);
4a4d8108 13335+
4f0767ce 13336+out:
0b1ff5c3 13337+ si_read_unlock(sb);
4a4d8108 13338+ return err;
1facf9fc 13339+}
13340+
0b1ff5c3
JR
13341+static ssize_t aufs_write_iter(struct kiocb *kio, struct iov_iter *iov_iter)
13342+{
13343+ ssize_t err;
13344+ struct au_write_pre wpre;
13345+ struct inode *inode;
13346+ struct file *file, *h_file;
1308ab2a 13347+
0b1ff5c3
JR
13348+ file = kio->ki_filp;
13349+ inode = file_inode(file);
13350+ au_mtx_and_read_lock(inode);
13351+
13352+ wpre.lsc = 0;
13353+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
13354+ err = PTR_ERR(h_file);
13355+ if (IS_ERR(h_file))
13356+ goto out;
13357+
13358+ err = au_do_iter(h_file, MAY_WRITE, kio, iov_iter);
13359+ au_write_post(inode, h_file, &wpre, err);
13360+
13361+out:
13362+ si_read_unlock(inode->i_sb);
13363+ inode_unlock(inode);
13364+ return err;
13365+}
13366+
13367+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
13368+ struct pipe_inode_info *pipe, size_t len,
13369+ unsigned int flags)
1facf9fc 13370+{
0b1ff5c3
JR
13371+ ssize_t err;
13372+ struct file *h_file;
13373+ struct inode *inode;
13374+ struct super_block *sb;
1facf9fc 13375+
0b1ff5c3
JR
13376+ inode = file_inode(file);
13377+ sb = inode->i_sb;
13378+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
dece6358 13379+
0b1ff5c3
JR
13380+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
13381+ err = PTR_ERR(h_file);
13382+ if (IS_ERR(h_file))
13383+ goto out;
13384+
13385+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
13386+ /* todo: necessasry? */
13387+ /* file->f_ra = h_file->f_ra; */
13388+ au_read_post(inode, h_file);
1facf9fc 13389+
0b1ff5c3
JR
13390+out:
13391+ si_read_unlock(sb);
1facf9fc 13392+ return err;
13393+}
13394+
0b1ff5c3
JR
13395+static ssize_t
13396+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
13397+ size_t len, unsigned int flags)
1facf9fc 13398+{
0b1ff5c3
JR
13399+ ssize_t err;
13400+ struct au_write_pre wpre;
13401+ struct inode *inode;
13402+ struct file *h_file;
1facf9fc 13403+
0b1ff5c3
JR
13404+ inode = file_inode(file);
13405+ au_mtx_and_read_lock(inode);
1facf9fc 13406+
0b1ff5c3
JR
13407+ wpre.lsc = 0;
13408+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
13409+ err = PTR_ERR(h_file);
13410+ if (IS_ERR(h_file))
13411+ goto out;
13412+
13413+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
13414+ au_write_post(inode, h_file, &wpre, err);
13415+
13416+out:
13417+ si_read_unlock(inode->i_sb);
13418+ inode_unlock(inode);
13419+ return err;
13420+}
13421+
13422+static long aufs_fallocate(struct file *file, int mode, loff_t offset,
13423+ loff_t len)
13424+{
13425+ long err;
13426+ struct au_write_pre wpre;
13427+ struct inode *inode;
13428+ struct file *h_file;
13429+
13430+ inode = file_inode(file);
13431+ au_mtx_and_read_lock(inode);
13432+
13433+ wpre.lsc = 0;
13434+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
13435+ err = PTR_ERR(h_file);
13436+ if (IS_ERR(h_file))
13437+ goto out;
1308ab2a 13438+
0b1ff5c3
JR
13439+ lockdep_off();
13440+ err = vfs_fallocate(h_file, mode, offset, len);
13441+ lockdep_on();
13442+ au_write_post(inode, h_file, &wpre, /*written*/1);
13443+
13444+out:
13445+ si_read_unlock(inode->i_sb);
13446+ inode_unlock(inode);
dece6358 13447+ return err;
1facf9fc 13448+}
13449+
0b1ff5c3
JR
13450+static ssize_t aufs_copy_file_range(struct file *src, loff_t src_pos,
13451+ struct file *dst, loff_t dst_pos,
13452+ size_t len, unsigned int flags)
1facf9fc 13453+{
0b1ff5c3
JR
13454+ ssize_t err;
13455+ struct au_write_pre wpre;
13456+ enum { SRC, DST };
13457+ struct {
13458+ struct inode *inode;
13459+ struct file *h_file;
13460+ struct super_block *h_sb;
13461+ } a[2];
13462+#define a_src a[SRC]
13463+#define a_dst a[DST]
1facf9fc 13464+
0b1ff5c3
JR
13465+ err = -EINVAL;
13466+ a_src.inode = file_inode(src);
13467+ if (unlikely(!S_ISREG(a_src.inode->i_mode)))
13468+ goto out;
13469+ a_dst.inode = file_inode(dst);
13470+ if (unlikely(!S_ISREG(a_dst.inode->i_mode)))
1facf9fc 13471+ goto out;
4a4d8108 13472+
0b1ff5c3
JR
13473+ au_mtx_and_read_lock(a_dst.inode);
13474+ /*
13475+ * in order to match the order in di_write_lock2_{child,parent}(),
13476+ * use f_path.dentry for this comparision.
13477+ */
13478+ if (src->f_path.dentry < dst->f_path.dentry) {
13479+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_1);
13480+ err = PTR_ERR(a_src.h_file);
13481+ if (IS_ERR(a_src.h_file))
13482+ goto out_si;
4a4d8108 13483+
0b1ff5c3
JR
13484+ wpre.lsc = AuLsc_FI_2;
13485+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre);
13486+ err = PTR_ERR(a_dst.h_file);
13487+ if (IS_ERR(a_dst.h_file)) {
13488+ au_read_post(a_src.inode, a_src.h_file);
13489+ goto out_si;
13490+ }
13491+ } else {
13492+ wpre.lsc = AuLsc_FI_1;
13493+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre);
13494+ err = PTR_ERR(a_dst.h_file);
13495+ if (IS_ERR(a_dst.h_file))
13496+ goto out_si;
027c5e7a 13497+
0b1ff5c3
JR
13498+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_2);
13499+ err = PTR_ERR(a_src.h_file);
13500+ if (IS_ERR(a_src.h_file)) {
13501+ au_write_post(a_dst.inode, a_dst.h_file, &wpre,
13502+ /*written*/0);
13503+ goto out_si;
027c5e7a 13504+ }
4a4d8108 13505+ }
4a4d8108 13506+
0b1ff5c3
JR
13507+ err = -EXDEV;
13508+ a_src.h_sb = file_inode(a_src.h_file)->i_sb;
13509+ a_dst.h_sb = file_inode(a_dst.h_file)->i_sb;
13510+ if (unlikely(a_src.h_sb != a_dst.h_sb)) {
13511+ AuDbgFile(src);
13512+ AuDbgFile(dst);
13513+ goto out_file;
4a4d8108 13514+ }
1facf9fc 13515+
0b1ff5c3
JR
13516+ err = vfsub_copy_file_range(a_src.h_file, src_pos, a_dst.h_file,
13517+ dst_pos, len, flags);
13518+
13519+out_file:
13520+ au_write_post(a_dst.inode, a_dst.h_file, &wpre, err);
13521+ fi_read_unlock(src);
13522+ au_read_post(a_src.inode, a_src.h_file);
13523+out_si:
13524+ si_read_unlock(a_dst.inode->i_sb);
13525+ inode_unlock(a_dst.inode);
4f0767ce 13526+out:
1facf9fc 13527+ return err;
0b1ff5c3
JR
13528+#undef a_src
13529+#undef a_dst
1facf9fc 13530+}
13531+
4a4d8108
AM
13532+/* ---------------------------------------------------------------------- */
13533+
0b1ff5c3
JR
13534+/*
13535+ * The locking order around current->mmap_sem.
13536+ * - in most and regular cases
13537+ * file I/O syscall -- aufs_read() or something
13538+ * -- si_rwsem for read -- mmap_sem
13539+ * (Note that [fdi]i_rwsem are released before mmap_sem).
13540+ * - in mmap case
13541+ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem
13542+ * This AB-BA order is definitly bad, but is not a problem since "si_rwsem for
13543+ * read" allows muliple processes to acquire it and [fdi]i_rwsem are not held in
13544+ * file I/O. Aufs needs to stop lockdep in aufs_mmap() though.
13545+ * It means that when aufs acquires si_rwsem for write, the process should never
13546+ * acquire mmap_sem.
13547+ *
13548+ * Actually aufs_iterate() holds [fdi]i_rwsem before mmap_sem, but this is not a
13549+ * problem either since any directory is not able to be mmap-ed.
13550+ * The similar scenario is applied to aufs_readlink() too.
13551+ */
13552+
13553+#if 0 /* stop calling security_file_mmap() */
13554+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
13555+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
13556+
13557+static unsigned long au_arch_prot_conv(unsigned long flags)
13558+{
13559+ /* currently ppc64 only */
13560+#ifdef CONFIG_PPC64
13561+ /* cf. linux/arch/powerpc/include/asm/mman.h */
13562+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
13563+ return AuConv_VM_PROT(flags, SAO);
13564+#else
13565+ AuDebugOn(arch_calc_vm_prot_bits(-1));
13566+ return 0;
13567+#endif
13568+}
13569+
13570+static unsigned long au_prot_conv(unsigned long flags)
13571+{
13572+ return AuConv_VM_PROT(flags, READ)
13573+ | AuConv_VM_PROT(flags, WRITE)
13574+ | AuConv_VM_PROT(flags, EXEC)
13575+ | au_arch_prot_conv(flags);
13576+}
13577+
13578+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
13579+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
13580+
13581+static unsigned long au_flag_conv(unsigned long flags)
13582+{
13583+ return AuConv_VM_MAP(flags, GROWSDOWN)
13584+ | AuConv_VM_MAP(flags, DENYWRITE)
13585+ | AuConv_VM_MAP(flags, LOCKED);
13586+}
13587+#endif
13588+
13589+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
1facf9fc 13590+{
4a4d8108 13591+ int err;
0b1ff5c3
JR
13592+ const unsigned char wlock
13593+ = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
1facf9fc 13594+ struct super_block *sb;
0b1ff5c3 13595+ struct file *h_file;
4a4d8108 13596+ struct inode *inode;
1facf9fc 13597+
0b1ff5c3
JR
13598+ AuDbgVmRegion(file, vma);
13599+
c06a8ce3
AM
13600+ inode = file_inode(file);
13601+ sb = inode->i_sb;
0b1ff5c3
JR
13602+ lockdep_off();
13603+ si_read_lock(sb, AuLock_NOPLMW);
1facf9fc 13604+
0b1ff5c3
JR
13605+ h_file = au_write_pre(file, wlock, /*wpre*/NULL);
13606+ lockdep_on();
13607+ err = PTR_ERR(h_file);
13608+ if (IS_ERR(h_file))
13609+ goto out;
1facf9fc 13610+
0b1ff5c3
JR
13611+ err = 0;
13612+ au_set_mmapped(file);
13613+ au_vm_file_reset(vma, h_file);
13614+ /*
13615+ * we cannot call security_mmap_file() here since it may acquire
13616+ * mmap_sem or i_mutex.
13617+ *
13618+ * err = security_mmap_file(h_file, au_prot_conv(vma->vm_flags),
13619+ * au_flag_conv(vma->vm_flags));
13620+ */
13621+ if (!err)
13622+ err = call_mmap(h_file, vma);
13623+ if (!err) {
13624+ au_vm_prfile_set(vma, file);
13625+ fsstack_copy_attr_atime(inode, file_inode(h_file));
13626+ goto out_fput; /* success */
13627+ }
13628+ au_unset_mmapped(file);
13629+ au_vm_file_reset(vma, file);
13630+
13631+out_fput:
13632+ lockdep_off();
13633+ ii_write_unlock(inode);
13634+ lockdep_on();
13635+ fput(h_file);
13636+out:
13637+ lockdep_off();
1308ab2a 13638+ si_read_unlock(sb);
0b1ff5c3
JR
13639+ lockdep_on();
13640+ AuTraceErr(err);
dece6358 13641+ return err;
1facf9fc 13642+}
13643+
4a4d8108
AM
13644+/* ---------------------------------------------------------------------- */
13645+
0b1ff5c3
JR
13646+static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end,
13647+ int datasync)
1facf9fc 13648+{
4a4d8108 13649+ int err;
0b1ff5c3 13650+ struct au_write_pre wpre;
4a4d8108 13651+ struct inode *inode;
0b1ff5c3 13652+ struct file *h_file;
4a4d8108 13653+
0b1ff5c3
JR
13654+ err = 0; /* -EBADF; */ /* posix? */
13655+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
1308ab2a 13656+ goto out;
dece6358 13657+
0b1ff5c3
JR
13658+ inode = file_inode(file);
13659+ au_mtx_and_read_lock(inode);
1facf9fc 13660+
0b1ff5c3
JR
13661+ wpre.lsc = 0;
13662+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
13663+ err = PTR_ERR(h_file);
13664+ if (IS_ERR(h_file))
13665+ goto out_unlock;
4a4d8108 13666+
0b1ff5c3
JR
13667+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
13668+ au_write_post(inode, h_file, &wpre, /*written*/0);
1facf9fc 13669+
4f0767ce 13670+out_unlock:
0b1ff5c3
JR
13671+ si_read_unlock(inode->i_sb);
13672+ inode_unlock(inode);
4f0767ce 13673+out:
1308ab2a 13674+ return err;
dece6358 13675+}
1facf9fc 13676+
0b1ff5c3 13677+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 13678+{
0b1ff5c3
JR
13679+ int err;
13680+ struct file *h_file;
1308ab2a 13681+ struct super_block *sb;
1facf9fc 13682+
2000de60 13683+ sb = file->f_path.dentry->d_sb;
0b1ff5c3 13684+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
1308ab2a 13685+
0b1ff5c3
JR
13686+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
13687+ err = PTR_ERR(h_file);
13688+ if (IS_ERR(h_file))
13689+ goto out;
1308ab2a 13690+
0b1ff5c3
JR
13691+ if (h_file->f_op->fasync)
13692+ err = h_file->f_op->fasync(fd, h_file, flag);
13693+ fput(h_file); /* instead of au_read_post() */
1308ab2a 13694+
0b1ff5c3
JR
13695+out:
13696+ si_read_unlock(sb);
13697+ return err;
1308ab2a 13698+}
13699+
0b1ff5c3 13700+static int aufs_setfl(struct file *file, unsigned long arg)
1facf9fc 13701+{
0b1ff5c3
JR
13702+ int err;
13703+ struct file *h_file;
e2f27e51 13704+ struct super_block *sb;
1facf9fc 13705+
0b1ff5c3
JR
13706+ sb = file->f_path.dentry->d_sb;
13707+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 13708+
0b1ff5c3
JR
13709+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
13710+ err = PTR_ERR(h_file);
13711+ if (IS_ERR(h_file))
13712+ goto out;
4a4d8108 13713+
0b1ff5c3
JR
13714+ /* stop calling h_file->fasync */
13715+ arg |= vfsub_file_flags(file) & FASYNC;
13716+ err = setfl(/*unused fd*/-1, h_file, arg);
13717+ fput(h_file); /* instead of au_read_post() */
1facf9fc 13718+
4f0767ce 13719+out:
0b1ff5c3 13720+ si_read_unlock(sb);
1facf9fc 13721+ return err;
13722+}
13723+
0b1ff5c3 13724+/* ---------------------------------------------------------------------- */
1facf9fc 13725+
0b1ff5c3
JR
13726+/* no one supports this operation, currently */
13727+#if 0
13728+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
13729+ size_t len, loff_t *pos, int more)
13730+{
1308ab2a 13731+}
0b1ff5c3 13732+#endif
1facf9fc 13733+
4a4d8108
AM
13734+/* ---------------------------------------------------------------------- */
13735+
0b1ff5c3
JR
13736+const struct file_operations aufs_file_fop = {
13737+ .owner = THIS_MODULE,
1facf9fc 13738+
0b1ff5c3 13739+ .llseek = default_llseek,
1facf9fc 13740+
0b1ff5c3
JR
13741+ .read = aufs_read,
13742+ .write = aufs_write,
13743+ .read_iter = aufs_read_iter,
13744+ .write_iter = aufs_write_iter,
1308ab2a 13745+
0b1ff5c3
JR
13746+#ifdef CONFIG_AUFS_POLL
13747+ .poll = aufs_poll,
79b8bda9 13748+#endif
0b1ff5c3
JR
13749+ .unlocked_ioctl = aufs_ioctl_nondir,
13750+#ifdef CONFIG_COMPAT
13751+ .compat_ioctl = aufs_compat_ioctl_nondir,
13752+#endif
13753+ .mmap = aufs_mmap,
13754+ .open = aufs_open_nondir,
13755+ .flush = aufs_flush_nondir,
13756+ .release = aufs_release_nondir,
13757+ .fsync = aufs_fsync_nondir,
13758+ .fasync = aufs_fasync,
13759+ /* .sendpage = aufs_sendpage, */
13760+ .setfl = aufs_setfl,
13761+ .splice_write = aufs_splice_write,
13762+ .splice_read = aufs_splice_read,
13763+#if 0
13764+ .aio_splice_write = aufs_aio_splice_write,
13765+ .aio_splice_read = aufs_aio_splice_read,
13766+#endif
13767+ .fallocate = aufs_fallocate,
13768+ .copy_file_range = aufs_copy_file_range
dece6358 13769+};
0b1ff5c3
JR
13770diff -urNp -x '*.orig' linux-4.14/fs/aufs/fhsm.c linux-4.14/fs/aufs/fhsm.c
13771--- linux-4.14/fs/aufs/fhsm.c 1970-01-01 01:00:00.000000000 +0100
13772+++ linux-4.14/fs/aufs/fhsm.c 2021-02-24 21:42:43.441114748 +0100
13773@@ -0,0 +1,426 @@
4a4d8108 13774+/*
0b1ff5c3 13775+ * Copyright (C) 2011-2017 Junjiro R. Okajima
4a4d8108
AM
13776+ *
13777+ * This program, aufs is free software; you can redistribute it and/or modify
13778+ * it under the terms of the GNU General Public License as published by
13779+ * the Free Software Foundation; either version 2 of the License, or
13780+ * (at your option) any later version.
13781+ *
13782+ * This program is distributed in the hope that it will be useful,
13783+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13784+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13785+ * GNU General Public License for more details.
13786+ *
13787+ * You should have received a copy of the GNU General Public License
0b1ff5c3
JR
13788+ * along with this program; if not, write to the Free Software
13789+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
4a4d8108 13790+ */
1facf9fc 13791+
4a4d8108 13792+/*
0b1ff5c3 13793+ * File-based Hierarchy Storage Management
4a4d8108 13794+ */
1facf9fc 13795+
0b1ff5c3 13796+#include <linux/anon_inodes.h>
4a4d8108 13797+#include <linux/poll.h>
0b1ff5c3
JR
13798+#include <linux/seq_file.h>
13799+#include <linux/statfs.h>
13800+#include "aufs.h"
1facf9fc 13801+
0b1ff5c3
JR
13802+static aufs_bindex_t au_fhsm_bottom(struct super_block *sb)
13803+{
13804+ struct au_sbinfo *sbinfo;
13805+ struct au_fhsm *fhsm;
1facf9fc 13806+
0b1ff5c3 13807+ SiMustAnyLock(sb);
1facf9fc 13808+
0b1ff5c3
JR
13809+ sbinfo = au_sbi(sb);
13810+ fhsm = &sbinfo->si_fhsm;
13811+ AuDebugOn(!fhsm);
13812+ return fhsm->fhsm_bottom;
13813+}
13814+
13815+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex)
dece6358 13816+{
0b1ff5c3
JR
13817+ struct au_sbinfo *sbinfo;
13818+ struct au_fhsm *fhsm;
13819+
13820+ SiMustWriteLock(sb);
13821+
13822+ sbinfo = au_sbi(sb);
13823+ fhsm = &sbinfo->si_fhsm;
13824+ AuDebugOn(!fhsm);
13825+ fhsm->fhsm_bottom = bindex;
4a4d8108 13826+}
1facf9fc 13827+
0b1ff5c3 13828+/* ---------------------------------------------------------------------- */
dece6358 13829+
0b1ff5c3
JR
13830+static int au_fhsm_test_jiffy(struct au_sbinfo *sbinfo, struct au_branch *br)
13831+{
13832+ struct au_br_fhsm *bf;
4a4d8108 13833+
0b1ff5c3
JR
13834+ bf = br->br_fhsm;
13835+ MtxMustLock(&bf->bf_lock);
523b37e3 13836+
0b1ff5c3
JR
13837+ return !bf->bf_readable
13838+ || time_after(jiffies,
13839+ bf->bf_jiffy + sbinfo->si_fhsm.fhsm_expire);
13840+}
1facf9fc 13841+
4a4d8108 13842+/* ---------------------------------------------------------------------- */
1facf9fc 13843+
0b1ff5c3
JR
13844+static void au_fhsm_notify(struct super_block *sb, int val)
13845+{
13846+ struct au_sbinfo *sbinfo;
13847+ struct au_fhsm *fhsm;
1facf9fc 13848+
0b1ff5c3 13849+ SiMustAnyLock(sb);
1facf9fc 13850+
0b1ff5c3
JR
13851+ sbinfo = au_sbi(sb);
13852+ fhsm = &sbinfo->si_fhsm;
13853+ if (au_fhsm_pid(fhsm)
13854+ && atomic_read(&fhsm->fhsm_readable) != -1) {
13855+ atomic_set(&fhsm->fhsm_readable, val);
13856+ if (val)
13857+ wake_up(&fhsm->fhsm_wqh);
13858+ }
13859+}
1facf9fc 13860+
0b1ff5c3
JR
13861+static int au_fhsm_stfs(struct super_block *sb, aufs_bindex_t bindex,
13862+ struct aufs_stfs *rstfs, int do_lock, int do_notify)
13863+{
13864+ int err;
13865+ struct au_branch *br;
13866+ struct au_br_fhsm *bf;
4a4d8108 13867+
0b1ff5c3
JR
13868+ br = au_sbr(sb, bindex);
13869+ AuDebugOn(au_br_rdonly(br));
13870+ bf = br->br_fhsm;
13871+ AuDebugOn(!bf);
1facf9fc 13872+
0b1ff5c3
JR
13873+ if (do_lock)
13874+ mutex_lock(&bf->bf_lock);
13875+ else
13876+ MtxMustLock(&bf->bf_lock);
1facf9fc 13877+
0b1ff5c3
JR
13878+ /* sb->s_root for NFS is unreliable */
13879+ err = au_br_stfs(br, &bf->bf_stfs);
13880+ if (unlikely(err)) {
13881+ AuErr1("FHSM failed (%d), b%d, ignored.\n", bindex, err);
13882+ goto out;
13883+ }
1facf9fc 13884+
0b1ff5c3
JR
13885+ bf->bf_jiffy = jiffies;
13886+ bf->bf_readable = 1;
13887+ if (do_notify)
13888+ au_fhsm_notify(sb, /*val*/1);
13889+ if (rstfs)
13890+ *rstfs = bf->bf_stfs;
1facf9fc 13891+
0b1ff5c3
JR
13892+out:
13893+ if (do_lock)
13894+ mutex_unlock(&bf->bf_lock);
13895+ au_fhsm_notify(sb, /*val*/1);
1facf9fc 13896+
0b1ff5c3 13897+ return err;
4a4d8108 13898+}
1facf9fc 13899+
0b1ff5c3
JR
13900+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force)
13901+{
13902+ int err;
13903+ struct au_sbinfo *sbinfo;
13904+ struct au_fhsm *fhsm;
13905+ struct au_branch *br;
13906+ struct au_br_fhsm *bf;
8b6a4947 13907+
0b1ff5c3
JR
13908+ AuDbg("b%d, force %d\n", bindex, force);
13909+ SiMustAnyLock(sb);
1308ab2a 13910+
0b1ff5c3
JR
13911+ sbinfo = au_sbi(sb);
13912+ fhsm = &sbinfo->si_fhsm;
13913+ if (!au_ftest_si(sbinfo, FHSM)
13914+ || fhsm->fhsm_bottom == bindex)
13915+ return;
521ced18 13916+
0b1ff5c3
JR
13917+ br = au_sbr(sb, bindex);
13918+ bf = br->br_fhsm;
13919+ AuDebugOn(!bf);
13920+ mutex_lock(&bf->bf_lock);
13921+ if (force
13922+ || au_fhsm_pid(fhsm)
13923+ || au_fhsm_test_jiffy(sbinfo, br))
13924+ err = au_fhsm_stfs(sb, bindex, /*rstfs*/NULL, /*do_lock*/0,
13925+ /*do_notify*/1);
13926+ mutex_unlock(&bf->bf_lock);
521ced18
JR
13927+}
13928+
0b1ff5c3 13929+void au_fhsm_wrote_all(struct super_block *sb, int force)
521ced18 13930+{
0b1ff5c3
JR
13931+ aufs_bindex_t bindex, bbot;
13932+ struct au_branch *br;
521ced18 13933+
0b1ff5c3
JR
13934+ /* exclude the bottom */
13935+ bbot = au_fhsm_bottom(sb);
13936+ for (bindex = 0; bindex < bbot; bindex++) {
13937+ br = au_sbr(sb, bindex);
13938+ if (au_br_fhsm(br->br_perm))
13939+ au_fhsm_wrote(sb, bindex, force);
13940+ }
13941+}
521ced18 13942+
0b1ff5c3 13943+/* ---------------------------------------------------------------------- */
521ced18 13944+
0b1ff5c3
JR
13945+static unsigned int au_fhsm_poll(struct file *file,
13946+ struct poll_table_struct *wait)
13947+{
13948+ unsigned int mask;
13949+ struct au_sbinfo *sbinfo;
13950+ struct au_fhsm *fhsm;
521ced18 13951+
0b1ff5c3
JR
13952+ mask = 0;
13953+ sbinfo = file->private_data;
13954+ fhsm = &sbinfo->si_fhsm;
13955+ poll_wait(file, &fhsm->fhsm_wqh, wait);
13956+ if (atomic_read(&fhsm->fhsm_readable))
13957+ mask = POLLIN /* | POLLRDNORM */;
521ced18 13958+
0b1ff5c3
JR
13959+ AuTraceErr((int)mask);
13960+ return mask;
13961+}
521ced18 13962+
0b1ff5c3
JR
13963+static int au_fhsm_do_read_one(struct aufs_stbr __user *stbr,
13964+ struct aufs_stfs *stfs, __s16 brid)
13965+{
13966+ int err;
1facf9fc 13967+
0b1ff5c3
JR
13968+ err = copy_to_user(&stbr->stfs, stfs, sizeof(*stfs));
13969+ if (!err)
13970+ err = __put_user(brid, &stbr->brid);
13971+ if (unlikely(err))
13972+ err = -EFAULT;
1308ab2a 13973+
0b1ff5c3 13974+ return err;
4a4d8108 13975+}
dece6358 13976+
0b1ff5c3
JR
13977+static ssize_t au_fhsm_do_read(struct super_block *sb,
13978+ struct aufs_stbr __user *stbr, size_t count)
4a4d8108 13979+{
0b1ff5c3
JR
13980+ ssize_t err;
13981+ int nstbr;
13982+ aufs_bindex_t bindex, bbot;
13983+ struct au_branch *br;
13984+ struct au_br_fhsm *bf;
13985+
13986+ /* except the bottom branch */
13987+ err = 0;
13988+ nstbr = 0;
13989+ bbot = au_fhsm_bottom(sb);
13990+ for (bindex = 0; !err && bindex < bbot; bindex++) {
13991+ br = au_sbr(sb, bindex);
13992+ if (!au_br_fhsm(br->br_perm))
13993+ continue;
13994+
13995+ bf = br->br_fhsm;
13996+ mutex_lock(&bf->bf_lock);
13997+ if (bf->bf_readable) {
13998+ err = -EFAULT;
13999+ if (count >= sizeof(*stbr))
14000+ err = au_fhsm_do_read_one(stbr++, &bf->bf_stfs,
14001+ br->br_id);
14002+ if (!err) {
14003+ bf->bf_readable = 0;
14004+ count -= sizeof(*stbr);
14005+ nstbr++;
14006+ }
14007+ }
14008+ mutex_unlock(&bf->bf_lock);
14009+ }
14010+ if (!err)
14011+ err = sizeof(*stbr) * nstbr;
14012+
14013+ return err;
4a4d8108 14014+}
1facf9fc 14015+
0b1ff5c3
JR
14016+static ssize_t au_fhsm_read(struct file *file, char __user *buf, size_t count,
14017+ loff_t *pos)
4a4d8108 14018+{
0b1ff5c3
JR
14019+ ssize_t err;
14020+ int readable;
14021+ aufs_bindex_t nfhsm, bindex, bbot;
14022+ struct au_sbinfo *sbinfo;
14023+ struct au_fhsm *fhsm;
14024+ struct au_branch *br;
14025+ struct super_block *sb;
14026+
14027+ err = 0;
14028+ sbinfo = file->private_data;
14029+ fhsm = &sbinfo->si_fhsm;
14030+need_data:
14031+ spin_lock_irq(&fhsm->fhsm_wqh.lock);
14032+ if (!atomic_read(&fhsm->fhsm_readable)) {
14033+ if (vfsub_file_flags(file) & O_NONBLOCK)
14034+ err = -EAGAIN;
14035+ else
14036+ err = wait_event_interruptible_locked_irq
14037+ (fhsm->fhsm_wqh,
14038+ atomic_read(&fhsm->fhsm_readable));
14039+ }
14040+ spin_unlock_irq(&fhsm->fhsm_wqh.lock);
14041+ if (unlikely(err))
14042+ goto out;
14043+
14044+ /* sb may already be dead */
14045+ au_rw_read_lock(&sbinfo->si_rwsem);
14046+ readable = atomic_read(&fhsm->fhsm_readable);
14047+ if (readable > 0) {
14048+ sb = sbinfo->si_sb;
14049+ AuDebugOn(!sb);
14050+ /* exclude the bottom branch */
14051+ nfhsm = 0;
14052+ bbot = au_fhsm_bottom(sb);
14053+ for (bindex = 0; bindex < bbot; bindex++) {
14054+ br = au_sbr(sb, bindex);
14055+ if (au_br_fhsm(br->br_perm))
14056+ nfhsm++;
14057+ }
14058+ err = -EMSGSIZE;
14059+ if (nfhsm * sizeof(struct aufs_stbr) <= count) {
14060+ atomic_set(&fhsm->fhsm_readable, 0);
14061+ err = au_fhsm_do_read(sbinfo->si_sb, (void __user *)buf,
14062+ count);
14063+ }
14064+ }
14065+ au_rw_read_unlock(&sbinfo->si_rwsem);
14066+ if (!readable)
14067+ goto need_data;
1facf9fc 14068+
0b1ff5c3
JR
14069+out:
14070+ return err;
4a4d8108 14071+}
1facf9fc 14072+
0b1ff5c3 14073+static int au_fhsm_release(struct inode *inode, struct file *file)
4a4d8108 14074+{
0b1ff5c3
JR
14075+ struct au_sbinfo *sbinfo;
14076+ struct au_fhsm *fhsm;
1308ab2a 14077+
0b1ff5c3
JR
14078+ /* sb may already be dead */
14079+ sbinfo = file->private_data;
14080+ fhsm = &sbinfo->si_fhsm;
14081+ spin_lock(&fhsm->fhsm_spin);
14082+ fhsm->fhsm_pid = 0;
14083+ spin_unlock(&fhsm->fhsm_spin);
14084+ kobject_put(&sbinfo->si_kobj);
dece6358 14085+
0b1ff5c3 14086+ return 0;
4a4d8108 14087+}
1facf9fc 14088+
0b1ff5c3
JR
14089+static const struct file_operations au_fhsm_fops = {
14090+ .owner = THIS_MODULE,
14091+ .llseek = noop_llseek,
14092+ .read = au_fhsm_read,
14093+ .poll = au_fhsm_poll,
14094+ .release = au_fhsm_release
14095+};
dece6358 14096+
0b1ff5c3 14097+int au_fhsm_fd(struct super_block *sb, int oflags)
dece6358 14098+{
0b1ff5c3
JR
14099+ int err, fd;
14100+ struct au_sbinfo *sbinfo;
14101+ struct au_fhsm *fhsm;
dece6358 14102+
0b1ff5c3
JR
14103+ err = -EPERM;
14104+ if (unlikely(!capable(CAP_SYS_ADMIN)))
14105+ goto out;
2cbb1c4b 14106+
0b1ff5c3
JR
14107+ err = -EINVAL;
14108+ if (unlikely(oflags & ~(O_CLOEXEC | O_NONBLOCK)))
14109+ goto out;
2cbb1c4b 14110+
0b1ff5c3
JR
14111+ err = 0;
14112+ sbinfo = au_sbi(sb);
14113+ fhsm = &sbinfo->si_fhsm;
14114+ spin_lock(&fhsm->fhsm_spin);
14115+ if (!fhsm->fhsm_pid)
14116+ fhsm->fhsm_pid = current->pid;
14117+ else
14118+ err = -EBUSY;
14119+ spin_unlock(&fhsm->fhsm_spin);
14120+ if (unlikely(err))
14121+ goto out;
14122+
14123+ oflags |= O_RDONLY;
14124+ /* oflags |= FMODE_NONOTIFY; */
14125+ fd = anon_inode_getfd("[aufs_fhsm]", &au_fhsm_fops, sbinfo, oflags);
14126+ err = fd;
14127+ if (unlikely(fd < 0))
14128+ goto out_pid;
14129+
14130+ /* succeed reglardless 'fhsm' status */
14131+ kobject_get(&sbinfo->si_kobj);
14132+ si_noflush_read_lock(sb);
14133+ if (au_ftest_si(sbinfo, FHSM))
14134+ au_fhsm_wrote_all(sb, /*force*/0);
14135+ si_read_unlock(sb);
14136+ goto out; /* success */
14137+
14138+out_pid:
14139+ spin_lock(&fhsm->fhsm_spin);
14140+ fhsm->fhsm_pid = 0;
14141+ spin_unlock(&fhsm->fhsm_spin);
14142+out:
14143+ AuTraceErr(err);
14144+ return err;
2cbb1c4b
JR
14145+}
14146+
0b1ff5c3 14147+/* ---------------------------------------------------------------------- */
2cbb1c4b 14148+
0b1ff5c3 14149+int au_fhsm_br_alloc(struct au_branch *br)
2cbb1c4b 14150+{
0b1ff5c3 14151+ int err;
53392da6 14152+
0b1ff5c3
JR
14153+ err = 0;
14154+ br->br_fhsm = kmalloc(sizeof(*br->br_fhsm), GFP_NOFS);
14155+ if (br->br_fhsm)
14156+ au_br_fhsm_init(br->br_fhsm);
14157+ else
14158+ err = -ENOMEM;
14159+
14160+ return err;
2cbb1c4b
JR
14161+}
14162+
0b1ff5c3 14163+/* ---------------------------------------------------------------------- */
2cbb1c4b 14164+
0b1ff5c3 14165+void au_fhsm_fin(struct super_block *sb)
2cbb1c4b 14166+{
0b1ff5c3 14167+ au_fhsm_notify(sb, /*val*/-1);
2cbb1c4b 14168+}
2cbb1c4b 14169+
0b1ff5c3 14170+void au_fhsm_init(struct au_sbinfo *sbinfo)
2cbb1c4b 14171+{
0b1ff5c3 14172+ struct au_fhsm *fhsm;
53392da6 14173+
0b1ff5c3
JR
14174+ fhsm = &sbinfo->si_fhsm;
14175+ spin_lock_init(&fhsm->fhsm_spin);
14176+ init_waitqueue_head(&fhsm->fhsm_wqh);
14177+ atomic_set(&fhsm->fhsm_readable, 0);
14178+ fhsm->fhsm_expire
14179+ = msecs_to_jiffies(AUFS_FHSM_CACHE_DEF_SEC * MSEC_PER_SEC);
14180+ fhsm->fhsm_bottom = -1;
2cbb1c4b 14181+}
2cbb1c4b 14182+
0b1ff5c3 14183+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec)
2cbb1c4b 14184+{
0b1ff5c3
JR
14185+ sbinfo->si_fhsm.fhsm_expire
14186+ = msecs_to_jiffies(sec * MSEC_PER_SEC);
fb47a38f 14187+}
1308ab2a 14188+
0b1ff5c3
JR
14189+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo)
14190+{
14191+ unsigned int u;
14192+
14193+ if (!au_ftest_si(sbinfo, FHSM))
14194+ return;
14195+
14196+ u = jiffies_to_msecs(sbinfo->si_fhsm.fhsm_expire) / MSEC_PER_SEC;
14197+ if (u != AUFS_FHSM_CACHE_DEF_SEC)
14198+ seq_printf(seq, ",fhsm_sec=%u", u);
14199+}
14200diff -urNp -x '*.orig' linux-4.14/fs/aufs/file.c linux-4.14/fs/aufs/file.c
14201--- linux-4.14/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
14202+++ linux-4.14/fs/aufs/file.c 2021-02-24 21:42:43.441114748 +0100
14203@@ -0,0 +1,856 @@
4a4d8108 14204+/*
a2654f78 14205+ * Copyright (C) 2005-2017 Junjiro R. Okajima
4a4d8108
AM
14206+ *
14207+ * This program, aufs is free software; you can redistribute it and/or modify
14208+ * it under the terms of the GNU General Public License as published by
14209+ * the Free Software Foundation; either version 2 of the License, or
14210+ * (at your option) any later version.
14211+ *
14212+ * This program is distributed in the hope that it will be useful,
14213+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14214+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14215+ * GNU General Public License for more details.
14216+ *
14217+ * You should have received a copy of the GNU General Public License
523b37e3 14218+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 14219+ */
1308ab2a 14220+
4a4d8108 14221+/*
0b1ff5c3 14222+ * handling file/dir, and address_space operation
4a4d8108 14223+ */
1facf9fc 14224+
0b1ff5c3
JR
14225+#ifdef CONFIG_AUFS_DEBUG
14226+#include <linux/migrate.h>
14227+#endif
14228+#include <linux/pagemap.h>
4a4d8108 14229+#include "aufs.h"
1facf9fc 14230+
0b1ff5c3
JR
14231+/* drop flags for writing */
14232+unsigned int au_file_roflags(unsigned int flags)
4a4d8108 14233+{
0b1ff5c3
JR
14234+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
14235+ flags |= O_RDONLY | O_NOATIME;
14236+ return flags;
4a4d8108 14237+}
1facf9fc 14238+
0b1ff5c3
JR
14239+/* common functions to regular file and dir */
14240+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
14241+ struct file *file, int force_wr)
4a4d8108 14242+{
0b1ff5c3
JR
14243+ struct file *h_file;
14244+ struct dentry *h_dentry;
14245+ struct inode *h_inode;
14246+ struct super_block *sb;
14247+ struct au_branch *br;
14248+ struct path h_path;
14249+ int err;
4a4d8108 14250+
0b1ff5c3
JR
14251+ /* a race condition can happen between open and unlink/rmdir */
14252+ h_file = ERR_PTR(-ENOENT);
14253+ h_dentry = au_h_dptr(dentry, bindex);
14254+ if (au_test_nfsd() && (!h_dentry || d_is_negative(h_dentry)))
14255+ goto out;
14256+ h_inode = d_inode(h_dentry);
14257+ spin_lock(&h_dentry->d_lock);
14258+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry))
14259+ /* || !d_inode(dentry)->i_nlink */
14260+ ;
14261+ spin_unlock(&h_dentry->d_lock);
14262+ if (unlikely(err))
14263+ goto out;
4a4d8108 14264+
0b1ff5c3
JR
14265+ sb = dentry->d_sb;
14266+ br = au_sbr(sb, bindex);
14267+ err = au_br_test_oflag(flags, br);
14268+ h_file = ERR_PTR(err);
14269+ if (unlikely(err))
14270+ goto out;
14271+
14272+ /* drop flags for writing */
14273+ if (au_test_ro(sb, bindex, d_inode(dentry))) {
14274+ if (force_wr && !(flags & O_WRONLY))
14275+ force_wr = 0;
14276+ flags = au_file_roflags(flags);
14277+ if (force_wr) {
14278+ h_file = ERR_PTR(-EROFS);
14279+ flags = au_file_roflags(flags);
14280+ if (unlikely(vfsub_native_ro(h_inode)
14281+ || IS_APPEND(h_inode)))
14282+ goto out;
14283+ flags &= ~O_ACCMODE;
14284+ flags |= O_WRONLY;
14285+ }
14286+ }
14287+ flags &= ~O_CREAT;
14288+ au_br_get(br);
14289+ h_path.dentry = h_dentry;
14290+ h_path.mnt = au_br_mnt(br);
14291+ h_file = vfsub_dentry_open(&h_path, flags);
14292+ if (IS_ERR(h_file))
14293+ goto out_br;
14294+
14295+ if (flags & __FMODE_EXEC) {
14296+ err = deny_write_access(h_file);
14297+ if (unlikely(err)) {
14298+ fput(h_file);
14299+ h_file = ERR_PTR(err);
14300+ goto out_br;
14301+ }
1308ab2a 14302+ }
0b1ff5c3
JR
14303+ fsnotify_open(h_file);
14304+ goto out; /* success */
14305+
14306+out_br:
14307+ au_br_put(br);
14308+out:
14309+ return h_file;
4a4d8108 14310+}
1facf9fc 14311+
0b1ff5c3 14312+static int au_cmoo(struct dentry *dentry)
4a4d8108 14313+{
0b1ff5c3
JR
14314+ int err, cmoo, matched;
14315+ unsigned int udba;
14316+ struct path h_path;
14317+ struct au_pin pin;
14318+ struct au_cp_generic cpg = {
14319+ .dentry = dentry,
14320+ .bdst = -1,
14321+ .bsrc = -1,
14322+ .len = -1,
14323+ .pin = &pin,
14324+ .flags = AuCpup_DTIME | AuCpup_HOPEN
14325+ };
14326+ struct inode *delegated;
14327+ struct super_block *sb;
14328+ struct au_sbinfo *sbinfo;
14329+ struct au_fhsm *fhsm;
14330+ pid_t pid;
14331+ struct au_branch *br;
14332+ struct dentry *parent;
14333+ struct au_hinode *hdir;
14334+
14335+ DiMustWriteLock(dentry);
14336+ IiMustWriteLock(d_inode(dentry));
14337+
14338+ err = 0;
14339+ if (IS_ROOT(dentry))
14340+ goto out;
14341+ cpg.bsrc = au_dbtop(dentry);
14342+ if (!cpg.bsrc)
14343+ goto out;
14344+
14345+ sb = dentry->d_sb;
14346+ sbinfo = au_sbi(sb);
14347+ fhsm = &sbinfo->si_fhsm;
14348+ pid = au_fhsm_pid(fhsm);
14349+ rcu_read_lock();
14350+ matched = (pid
14351+ && (current->pid == pid
14352+ || rcu_dereference(current->real_parent)->pid == pid));
14353+ rcu_read_unlock();
14354+ if (matched)
14355+ goto out;
14356+
14357+ br = au_sbr(sb, cpg.bsrc);
14358+ cmoo = au_br_cmoo(br->br_perm);
14359+ if (!cmoo)
14360+ goto out;
14361+ if (!d_is_reg(dentry))
14362+ cmoo &= AuBrAttr_COO_ALL;
14363+ if (!cmoo)
14364+ goto out;
14365+
14366+ parent = dget_parent(dentry);
14367+ di_write_lock_parent(parent);
14368+ err = au_wbr_do_copyup_bu(dentry, cpg.bsrc - 1);
14369+ cpg.bdst = err;
14370+ if (unlikely(err < 0)) {
14371+ err = 0; /* there is no upper writable branch */
14372+ goto out_dgrade;
14373+ }
14374+ AuDbg("bsrc %d, bdst %d\n", cpg.bsrc, cpg.bdst);
14375+
14376+ /* do not respect the coo attrib for the target branch */
14377+ err = au_cpup_dirs(dentry, cpg.bdst);
14378+ if (unlikely(err))
14379+ goto out_dgrade;
14380+
14381+ di_downgrade_lock(parent, AuLock_IR);
14382+ udba = au_opt_udba(sb);
14383+ err = au_pin(&pin, dentry, cpg.bdst, udba,
14384+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14385+ if (unlikely(err))
14386+ goto out_parent;
14387+
14388+ err = au_sio_cpup_simple(&cpg);
14389+ au_unpin(&pin);
14390+ if (unlikely(err))
14391+ goto out_parent;
14392+ if (!(cmoo & AuBrWAttr_MOO))
14393+ goto out_parent; /* success */
14394+
14395+ err = au_pin(&pin, dentry, cpg.bsrc, udba,
14396+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14397+ if (unlikely(err))
14398+ goto out_parent;
14399+
14400+ h_path.mnt = au_br_mnt(br);
14401+ h_path.dentry = au_h_dptr(dentry, cpg.bsrc);
14402+ hdir = au_hi(d_inode(parent), cpg.bsrc);
14403+ delegated = NULL;
14404+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, /*force*/1);
14405+ au_unpin(&pin);
14406+ /* todo: keep h_dentry or not? */
14407+ if (unlikely(err == -EWOULDBLOCK)) {
14408+ pr_warn("cannot retry for NFSv4 delegation"
14409+ " for an internal unlink\n");
14410+ iput(delegated);
14411+ }
14412+ if (unlikely(err)) {
14413+ pr_err("unlink %pd after coo failed (%d), ignored\n",
14414+ dentry, err);
14415+ err = 0;
14416+ }
14417+ goto out_parent; /* success */
14418+
14419+out_dgrade:
14420+ di_downgrade_lock(parent, AuLock_IR);
14421+out_parent:
14422+ di_read_unlock(parent, AuLock_IR);
14423+ dput(parent);
14424+out:
14425+ AuTraceErr(err);
14426+ return err;
14427+}
14428+
14429+int au_do_open(struct file *file, struct au_do_open_args *args)
14430+{
14431+ int err, aopen = args->aopen;
14432+ struct dentry *dentry;
14433+ struct au_finfo *finfo;
14434+
14435+ if (!aopen)
14436+ err = au_finfo_init(file, args->fidir);
14437+ else {
14438+ lockdep_off();
14439+ err = au_finfo_init(file, args->fidir);
14440+ lockdep_on();
14441+ }
14442+ if (unlikely(err))
14443+ goto out;
14444+
14445+ dentry = file->f_path.dentry;
14446+ AuDebugOn(IS_ERR_OR_NULL(dentry));
14447+ di_write_lock_child(dentry);
14448+ err = au_cmoo(dentry);
14449+ di_downgrade_lock(dentry, AuLock_IR);
14450+ if (!err) {
14451+ if (!aopen)
14452+ err = args->open(file, vfsub_file_flags(file), NULL);
14453+ else {
14454+ lockdep_off();
14455+ err = args->open(file, vfsub_file_flags(file), NULL);
14456+ lockdep_on();
14457+ }
14458+ }
14459+ di_read_unlock(dentry, AuLock_IR);
14460+
14461+ finfo = au_fi(file);
14462+ if (!err) {
14463+ finfo->fi_file = file;
14464+ au_hbl_add(&finfo->fi_hlist,
14465+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
14466+ }
14467+ if (!aopen)
14468+ fi_write_unlock(file);
14469+ else {
14470+ lockdep_off();
14471+ fi_write_unlock(file);
14472+ lockdep_on();
14473+ }
14474+ if (unlikely(err)) {
14475+ finfo->fi_hdir = NULL;
14476+ au_finfo_fin(file);
14477+ }
14478+
14479+out:
14480+ AuTraceErr(err);
14481+ return err;
14482+}
14483+
14484+int au_reopen_nondir(struct file *file)
14485+{
14486+ int err;
14487+ aufs_bindex_t btop;
14488+ struct dentry *dentry;
14489+ struct file *h_file, *h_file_tmp;
14490+
14491+ dentry = file->f_path.dentry;
14492+ btop = au_dbtop(dentry);
14493+ h_file_tmp = NULL;
14494+ if (au_fbtop(file) == btop) {
14495+ h_file = au_hf_top(file);
14496+ if (file->f_mode == h_file->f_mode)
14497+ return 0; /* success */
14498+ h_file_tmp = h_file;
14499+ get_file(h_file_tmp);
14500+ au_set_h_fptr(file, btop, NULL);
14501+ }
14502+ AuDebugOn(au_fi(file)->fi_hdir);
14503+ /*
14504+ * it can happen
14505+ * file exists on both of rw and ro
14506+ * open --> dbtop and fbtop are both 0
14507+ * prepend a branch as rw, "rw" become ro
14508+ * remove rw/file
14509+ * delete the top branch, "rw" becomes rw again
14510+ * --> dbtop is 1, fbtop is still 0
14511+ * write --> fbtop is 0 but dbtop is 1
14512+ */
14513+ /* AuDebugOn(au_fbtop(file) < btop); */
14514+
14515+ h_file = au_h_open(dentry, btop, vfsub_file_flags(file) & ~O_TRUNC,
14516+ file, /*force_wr*/0);
14517+ err = PTR_ERR(h_file);
14518+ if (IS_ERR(h_file)) {
14519+ if (h_file_tmp) {
14520+ au_sbr_get(dentry->d_sb, btop);
14521+ au_set_h_fptr(file, btop, h_file_tmp);
14522+ h_file_tmp = NULL;
14523+ }
14524+ goto out; /* todo: close all? */
14525+ }
14526+
14527+ err = 0;
14528+ au_set_fbtop(file, btop);
14529+ au_set_h_fptr(file, btop, h_file);
14530+ au_update_figen(file);
14531+ /* todo: necessary? */
14532+ /* file->f_ra = h_file->f_ra; */
14533+
14534+out:
14535+ if (h_file_tmp)
14536+ fput(h_file_tmp);
14537+ return err;
1facf9fc 14538+}
14539+
4a4d8108
AM
14540+/* ---------------------------------------------------------------------- */
14541+
0b1ff5c3
JR
14542+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
14543+ struct dentry *hi_wh)
4a4d8108 14544+{
0b1ff5c3
JR
14545+ int err;
14546+ aufs_bindex_t btop;
14547+ struct au_dinfo *dinfo;
14548+ struct dentry *h_dentry;
14549+ struct au_hdentry *hdp;
4a4d8108 14550+
0b1ff5c3
JR
14551+ dinfo = au_di(file->f_path.dentry);
14552+ AuRwMustWriteLock(&dinfo->di_rwsem);
4a4d8108 14553+
0b1ff5c3
JR
14554+ btop = dinfo->di_btop;
14555+ dinfo->di_btop = btgt;
14556+ hdp = au_hdentry(dinfo, btgt);
14557+ h_dentry = hdp->hd_dentry;
14558+ hdp->hd_dentry = hi_wh;
14559+ err = au_reopen_nondir(file);
14560+ hdp->hd_dentry = h_dentry;
14561+ dinfo->di_btop = btop;
14562+
14563+ return err;
4a4d8108
AM
14564+}
14565+
0b1ff5c3
JR
14566+static int au_ready_to_write_wh(struct file *file, loff_t len,
14567+ aufs_bindex_t bcpup, struct au_pin *pin)
4a4d8108
AM
14568+{
14569+ int err;
0b1ff5c3
JR
14570+ struct inode *inode, *h_inode;
14571+ struct dentry *h_dentry, *hi_wh;
14572+ struct au_cp_generic cpg = {
14573+ .dentry = file->f_path.dentry,
14574+ .bdst = bcpup,
14575+ .bsrc = -1,
14576+ .len = len,
14577+ .pin = pin
14578+ };
4a4d8108 14579+
0b1ff5c3
JR
14580+ au_update_dbtop(cpg.dentry);
14581+ inode = d_inode(cpg.dentry);
14582+ h_inode = NULL;
14583+ if (au_dbtop(cpg.dentry) <= bcpup
14584+ && au_dbbot(cpg.dentry) >= bcpup) {
14585+ h_dentry = au_h_dptr(cpg.dentry, bcpup);
14586+ if (h_dentry && d_is_positive(h_dentry))
14587+ h_inode = d_inode(h_dentry);
4a4d8108 14588+ }
0b1ff5c3
JR
14589+ hi_wh = au_hi_wh(inode, bcpup);
14590+ if (!hi_wh && !h_inode)
14591+ err = au_sio_cpup_wh(&cpg, file);
14592+ else
14593+ /* already copied-up after unlink */
14594+ err = au_reopen_wh(file, bcpup, hi_wh);
14595+
14596+ if (!err
14597+ && (inode->i_nlink > 1
14598+ || (inode->i_state & I_LINKABLE))
14599+ && au_opt_test(au_mntflags(cpg.dentry->d_sb), PLINK))
14600+ au_plink_append(inode, bcpup, au_h_dptr(cpg.dentry, bcpup));
1facf9fc 14601+
dece6358 14602+ return err;
1facf9fc 14603+}
1308ab2a 14604+
0b1ff5c3
JR
14605+/*
14606+ * prepare the @file for writing.
14607+ */
14608+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1308ab2a 14609+{
0b1ff5c3
JR
14610+ int err;
14611+ aufs_bindex_t dbtop;
14612+ struct dentry *parent;
14613+ struct inode *inode;
14614+ struct super_block *sb;
14615+ struct file *h_file;
14616+ struct au_cp_generic cpg = {
14617+ .dentry = file->f_path.dentry,
14618+ .bdst = -1,
14619+ .bsrc = -1,
14620+ .len = len,
14621+ .pin = pin,
14622+ .flags = AuCpup_DTIME
14623+ };
4a4d8108 14624+
0b1ff5c3
JR
14625+ sb = cpg.dentry->d_sb;
14626+ inode = d_inode(cpg.dentry);
14627+ cpg.bsrc = au_fbtop(file);
14628+ err = au_test_ro(sb, cpg.bsrc, inode);
14629+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
14630+ err = au_pin(pin, cpg.dentry, cpg.bsrc, AuOpt_UDBA_NONE,
14631+ /*flags*/0);
14632+ goto out;
14633+ }
7f207e10 14634+
0b1ff5c3
JR
14635+ /* need to cpup or reopen */
14636+ parent = dget_parent(cpg.dentry);
14637+ di_write_lock_parent(parent);
14638+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry);
14639+ cpg.bdst = err;
14640+ if (unlikely(err < 0))
14641+ goto out_dgrade;
14642+ err = 0;
1308ab2a 14643+
0b1ff5c3
JR
14644+ if (!d_unhashed(cpg.dentry) && !au_h_dptr(parent, cpg.bdst)) {
14645+ err = au_cpup_dirs(cpg.dentry, cpg.bdst);
14646+ if (unlikely(err))
14647+ goto out_dgrade;
14648+ }
1308ab2a 14649+
0b1ff5c3
JR
14650+ err = au_pin(pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE,
14651+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14652+ if (unlikely(err))
14653+ goto out_dgrade;
14654+
14655+ dbtop = au_dbtop(cpg.dentry);
14656+ if (dbtop <= cpg.bdst)
14657+ cpg.bsrc = cpg.bdst;
14658+
14659+ if (dbtop <= cpg.bdst /* just reopen */
14660+ || !d_unhashed(cpg.dentry) /* copyup and reopen */
14661+ ) {
14662+ h_file = au_h_open_pre(cpg.dentry, cpg.bsrc, /*force_wr*/0);
14663+ if (IS_ERR(h_file))
14664+ err = PTR_ERR(h_file);
14665+ else {
14666+ di_downgrade_lock(parent, AuLock_IR);
14667+ if (dbtop > cpg.bdst)
14668+ err = au_sio_cpup_simple(&cpg);
14669+ if (!err)
14670+ err = au_reopen_nondir(file);
14671+ au_h_open_post(cpg.dentry, cpg.bsrc, h_file);
14672+ }
14673+ } else { /* copyup as wh and reopen */
14674+ /*
14675+ * since writable hfsplus branch is not supported,
14676+ * h_open_pre/post() are unnecessary.
14677+ */
14678+ err = au_ready_to_write_wh(file, len, cpg.bdst, pin);
14679+ di_downgrade_lock(parent, AuLock_IR);
14680+ }
14681+
14682+ if (!err) {
14683+ au_pin_set_parent_lflag(pin, /*lflag*/0);
14684+ goto out_dput; /* success */
14685+ }
14686+ au_unpin(pin);
14687+ goto out_unlock;
14688+
14689+out_dgrade:
14690+ di_downgrade_lock(parent, AuLock_IR);
14691+out_unlock:
14692+ di_read_unlock(parent, AuLock_IR);
14693+out_dput:
14694+ dput(parent);
14695+out:
14696+ return err;
4a4d8108 14697+}
1308ab2a 14698+
0b1ff5c3
JR
14699+/* ---------------------------------------------------------------------- */
14700+
14701+int au_do_flush(struct file *file, fl_owner_t id,
14702+ int (*flush)(struct file *file, fl_owner_t id))
4a4d8108 14703+{
1716fcea 14704+ int err;
0b1ff5c3
JR
14705+ struct super_block *sb;
14706+ struct inode *inode;
4a4d8108 14707+
0b1ff5c3
JR
14708+ inode = file_inode(file);
14709+ sb = inode->i_sb;
14710+ si_noflush_read_lock(sb);
14711+ fi_read_lock(file);
14712+ ii_read_lock_child(inode);
4a4d8108 14713+
0b1ff5c3
JR
14714+ err = flush(file, id);
14715+ au_cpup_attr_timesizes(inode);
4a4d8108 14716+
0b1ff5c3
JR
14717+ ii_read_unlock(inode);
14718+ fi_read_unlock(file);
14719+ si_read_unlock(sb);
4a4d8108
AM
14720+ return err;
14721+}
dece6358 14722+
0b1ff5c3 14723+/* ---------------------------------------------------------------------- */
dece6358 14724+
0b1ff5c3 14725+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 14726+{
4a4d8108 14727+ int err;
0b1ff5c3 14728+ struct au_pin pin;
4a4d8108 14729+ struct au_finfo *finfo;
0b1ff5c3
JR
14730+ struct dentry *parent, *hi_wh;
14731+ struct inode *inode;
14732+ struct super_block *sb;
14733+ struct au_cp_generic cpg = {
14734+ .dentry = file->f_path.dentry,
14735+ .bdst = -1,
14736+ .bsrc = -1,
14737+ .len = -1,
14738+ .pin = &pin,
14739+ .flags = AuCpup_DTIME
14740+ };
4a4d8108
AM
14741+
14742+ FiMustWriteLock(file);
14743+
523b37e3 14744+ err = 0;
4a4d8108 14745+ finfo = au_fi(file);
0b1ff5c3
JR
14746+ sb = cpg.dentry->d_sb;
14747+ inode = d_inode(cpg.dentry);
14748+ cpg.bdst = au_ibtop(inode);
14749+ if (cpg.bdst == finfo->fi_btop || IS_ROOT(cpg.dentry))
14750+ goto out;
14751+
14752+ parent = dget_parent(cpg.dentry);
14753+ if (au_test_ro(sb, cpg.bdst, inode)) {
14754+ di_read_lock_parent(parent, !AuLock_IR);
14755+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry);
14756+ cpg.bdst = err;
14757+ di_read_unlock(parent, !AuLock_IR);
14758+ if (unlikely(err < 0))
14759+ goto out_parent;
14760+ err = 0;
8cdd5066 14761+ }
0b1ff5c3
JR
14762+
14763+ di_read_lock_parent(parent, AuLock_IR);
14764+ hi_wh = au_hi_wh(inode, cpg.bdst);
14765+ if (!S_ISDIR(inode->i_mode)
14766+ && au_opt_test(au_mntflags(sb), PLINK)
14767+ && au_plink_test(inode)
14768+ && !d_unhashed(cpg.dentry)
14769+ && cpg.bdst < au_dbtop(cpg.dentry)) {
14770+ err = au_test_and_cpup_dirs(cpg.dentry, cpg.bdst);
14771+ if (unlikely(err))
14772+ goto out_unlock;
14773+
14774+ /* always superio. */
14775+ err = au_pin(&pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE,
14776+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14777+ if (!err) {
14778+ err = au_sio_cpup_simple(&cpg);
14779+ au_unpin(&pin);
38d290e6 14780+ }
0b1ff5c3
JR
14781+ } else if (hi_wh) {
14782+ /* already copied-up after unlink */
14783+ err = au_reopen_wh(file, cpg.bdst, hi_wh);
14784+ *need_reopen = 0;
4a4d8108 14785+ }
027c5e7a 14786+
0b1ff5c3
JR
14787+out_unlock:
14788+ di_read_unlock(parent, AuLock_IR);
14789+out_parent:
14790+ dput(parent);
8cdd5066 14791+out:
4a4d8108 14792+ return err;
1facf9fc 14793+}
14794+
0b1ff5c3 14795+static void au_do_refresh_dir(struct file *file)
1facf9fc 14796+{
0b1ff5c3
JR
14797+ aufs_bindex_t bindex, bbot, new_bindex, brid;
14798+ struct au_hfile *p, tmp, *q;
14799+ struct au_finfo *finfo;
1308ab2a 14800+ struct super_block *sb;
0b1ff5c3 14801+ struct au_fidir *fidir;
1facf9fc 14802+
0b1ff5c3 14803+ FiMustWriteLock(file);
1facf9fc 14804+
2000de60 14805+ sb = file->f_path.dentry->d_sb;
0b1ff5c3
JR
14806+ finfo = au_fi(file);
14807+ fidir = finfo->fi_hdir;
14808+ AuDebugOn(!fidir);
14809+ p = fidir->fd_hfile + finfo->fi_btop;
14810+ brid = p->hf_br->br_id;
14811+ bbot = fidir->fd_bbot;
14812+ for (bindex = finfo->fi_btop; bindex <= bbot; bindex++, p++) {
14813+ if (!p->hf_file)
14814+ continue;
14815+
14816+ new_bindex = au_br_index(sb, p->hf_br->br_id);
14817+ if (new_bindex == bindex)
14818+ continue;
14819+ if (new_bindex < 0) {
14820+ au_set_h_fptr(file, bindex, NULL);
14821+ continue;
14822+ }
14823+
14824+ /* swap two lower inode, and loop again */
14825+ q = fidir->fd_hfile + new_bindex;
14826+ tmp = *q;
14827+ *q = *p;
14828+ *p = tmp;
14829+ if (tmp.hf_file) {
14830+ bindex--;
14831+ p--;
14832+ }
14833+ }
14834+
14835+ p = fidir->fd_hfile;
14836+ if (!au_test_mmapped(file) && !d_unlinked(file->f_path.dentry)) {
14837+ bbot = au_sbbot(sb);
14838+ for (finfo->fi_btop = 0; finfo->fi_btop <= bbot;
14839+ finfo->fi_btop++, p++)
14840+ if (p->hf_file) {
14841+ if (file_inode(p->hf_file))
14842+ break;
14843+ au_hfput(p, /*execed*/0);
14844+ }
14845+ } else {
14846+ bbot = au_br_index(sb, brid);
14847+ for (finfo->fi_btop = 0; finfo->fi_btop < bbot;
14848+ finfo->fi_btop++, p++)
14849+ if (p->hf_file)
14850+ au_hfput(p, /*execed*/0);
14851+ bbot = au_sbbot(sb);
14852+ }
14853+
14854+ p = fidir->fd_hfile + bbot;
14855+ for (fidir->fd_bbot = bbot; fidir->fd_bbot >= finfo->fi_btop;
14856+ fidir->fd_bbot--, p--)
14857+ if (p->hf_file) {
14858+ if (file_inode(p->hf_file))
14859+ break;
14860+ au_hfput(p, /*execed*/0);
14861+ }
14862+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
4a4d8108 14863+}
1facf9fc 14864+
0b1ff5c3
JR
14865+/*
14866+ * after branch manipulating, refresh the file.
14867+ */
14868+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
4a4d8108 14869+{
0b1ff5c3
JR
14870+ int err, need_reopen, nbr;
14871+ aufs_bindex_t bbot, bindex;
14872+ struct dentry *dentry;
14873+ struct super_block *sb;
4a4d8108 14874+ struct au_finfo *finfo;
0b1ff5c3 14875+ struct au_hfile *hfile;
1facf9fc 14876+
0b1ff5c3
JR
14877+ dentry = file->f_path.dentry;
14878+ sb = dentry->d_sb;
14879+ nbr = au_sbbot(sb) + 1;
4a4d8108 14880+ finfo = au_fi(file);
0b1ff5c3
JR
14881+ if (!finfo->fi_hdir) {
14882+ hfile = &finfo->fi_htop;
14883+ AuDebugOn(!hfile->hf_file);
14884+ bindex = au_br_index(sb, hfile->hf_br->br_id);
14885+ AuDebugOn(bindex < 0);
14886+ if (bindex != finfo->fi_btop)
14887+ au_set_fbtop(file, bindex);
14888+ } else {
14889+ err = au_fidir_realloc(finfo, nbr, /*may_shrink*/0);
14890+ if (unlikely(err))
14891+ goto out;
14892+ au_do_refresh_dir(file);
14893+ }
7f207e10 14894+
0b1ff5c3
JR
14895+ err = 0;
14896+ need_reopen = 1;
14897+ if (!au_test_mmapped(file))
14898+ err = au_file_refresh_by_inode(file, &need_reopen);
14899+ if (finfo->fi_hdir)
14900+ /* harmless if err */
14901+ au_fidir_realloc(finfo, nbr, /*may_shrink*/1);
14902+ if (!err && need_reopen && !d_unlinked(dentry))
14903+ err = reopen(file);
14904+ if (!err) {
14905+ au_update_figen(file);
14906+ goto out; /* success */
14907+ }
1facf9fc 14908+
0b1ff5c3
JR
14909+ /* error, close all lower files */
14910+ if (finfo->fi_hdir) {
14911+ bbot = au_fbbot_dir(file);
14912+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++)
14913+ au_set_h_fptr(file, bindex, NULL);
14914+ }
4a4d8108 14915+
0b1ff5c3
JR
14916+out:
14917+ return err;
14918+}
14919+
14920+/* common function to regular file and dir */
14921+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
14922+ int wlock, unsigned int fi_lsc)
dece6358 14923+{
1308ab2a 14924+ int err;
0b1ff5c3
JR
14925+ unsigned int sigen, figen;
14926+ aufs_bindex_t btop;
14927+ unsigned char pseudo_link;
14928+ struct dentry *dentry;
14929+ struct inode *inode;
4a4d8108
AM
14930+
14931+ err = 0;
0b1ff5c3
JR
14932+ dentry = file->f_path.dentry;
14933+ inode = d_inode(dentry);
14934+ sigen = au_sigen(dentry->d_sb);
14935+ fi_write_lock_nested(file, fi_lsc);
14936+ figen = au_figen(file);
14937+ if (!fi_lsc)
14938+ di_write_lock_child(dentry);
14939+ else
14940+ di_write_lock_child2(dentry);
14941+ btop = au_dbtop(dentry);
14942+ pseudo_link = (btop != au_ibtop(inode));
14943+ if (sigen == figen && !pseudo_link && au_fbtop(file) == btop) {
14944+ if (!wlock) {
14945+ di_downgrade_lock(dentry, AuLock_IR);
14946+ fi_downgrade_lock(file);
14947+ }
14948+ goto out; /* success */
14949+ }
14950+
14951+ AuDbg("sigen %d, figen %d\n", sigen, figen);
14952+ if (au_digen_test(dentry, sigen)) {
14953+ err = au_reval_dpath(dentry, sigen);
14954+ AuDebugOn(!err && au_digen_test(dentry, sigen));
14955+ }
14956+
14957+ if (!err)
14958+ err = refresh_file(file, reopen);
14959+ if (!err) {
14960+ if (!wlock) {
14961+ di_downgrade_lock(dentry, AuLock_IR);
14962+ fi_downgrade_lock(file);
14963+ }
14964+ } else {
14965+ di_write_unlock(dentry);
14966+ fi_write_unlock(file);
14967+ }
4a4d8108 14968+
0b1ff5c3
JR
14969+out:
14970+ return err;
4a4d8108
AM
14971+}
14972+
14973+/* ---------------------------------------------------------------------- */
14974+
0b1ff5c3
JR
14975+/* cf. aufs_nopage() */
14976+/* for madvise(2) */
14977+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
4a4d8108 14978+{
0b1ff5c3
JR
14979+ unlock_page(page);
14980+ return 0;
b912730e
AM
14981+}
14982+
0b1ff5c3
JR
14983+/* it will never be called, but necessary to support O_DIRECT */
14984+static ssize_t aufs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
14985+{ BUG(); return 0; }
b912730e 14986+
0b1ff5c3
JR
14987+/* they will never be called. */
14988+#ifdef CONFIG_AUFS_DEBUG
14989+static int aufs_write_begin(struct file *file, struct address_space *mapping,
14990+ loff_t pos, unsigned len, unsigned flags,
14991+ struct page **pagep, void **fsdata)
14992+{ AuUnsupport(); return 0; }
14993+static int aufs_write_end(struct file *file, struct address_space *mapping,
14994+ loff_t pos, unsigned len, unsigned copied,
14995+ struct page *page, void *fsdata)
14996+{ AuUnsupport(); return 0; }
14997+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
14998+{ AuUnsupport(); return 0; }
521ced18 14999+
0b1ff5c3
JR
15000+static int aufs_set_page_dirty(struct page *page)
15001+{ AuUnsupport(); return 0; }
15002+static void aufs_invalidatepage(struct page *page, unsigned int offset,
15003+ unsigned int length)
15004+{ AuUnsupport(); }
15005+static int aufs_releasepage(struct page *page, gfp_t gfp)
15006+{ AuUnsupport(); return 0; }
15007+#if 0 /* called by memory compaction regardless file */
15008+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
15009+ struct page *page, enum migrate_mode mode)
15010+{ AuUnsupport(); return 0; }
15011+#endif
15012+static bool aufs_isolate_page(struct page *page, isolate_mode_t mode)
15013+{ AuUnsupport(); return true; }
15014+static void aufs_putback_page(struct page *page)
15015+{ AuUnsupport(); }
15016+static int aufs_launder_page(struct page *page)
15017+{ AuUnsupport(); return 0; }
15018+static int aufs_is_partially_uptodate(struct page *page,
15019+ unsigned long from,
15020+ unsigned long count)
15021+{ AuUnsupport(); return 0; }
15022+static void aufs_is_dirty_writeback(struct page *page, bool *dirty,
15023+ bool *writeback)
15024+{ AuUnsupport(); }
15025+static int aufs_error_remove_page(struct address_space *mapping,
15026+ struct page *page)
15027+{ AuUnsupport(); return 0; }
15028+static int aufs_swap_activate(struct swap_info_struct *sis, struct file *file,
15029+ sector_t *span)
15030+{ AuUnsupport(); return 0; }
15031+static void aufs_swap_deactivate(struct file *file)
15032+{ AuUnsupport(); }
15033+#endif /* CONFIG_AUFS_DEBUG */
b912730e 15034+
0b1ff5c3
JR
15035+const struct address_space_operations aufs_aop = {
15036+ .readpage = aufs_readpage,
15037+ .direct_IO = aufs_direct_IO,
15038+#ifdef CONFIG_AUFS_DEBUG
15039+ .writepage = aufs_writepage,
15040+ /* no writepages, because of writepage */
15041+ .set_page_dirty = aufs_set_page_dirty,
15042+ /* no readpages, because of readpage */
15043+ .write_begin = aufs_write_begin,
15044+ .write_end = aufs_write_end,
15045+ /* no bmap, no block device */
15046+ .invalidatepage = aufs_invalidatepage,
15047+ .releasepage = aufs_releasepage,
15048+ /* is fallback_migrate_page ok? */
15049+ /* .migratepage = aufs_migratepage, */
15050+ .isolate_page = aufs_isolate_page,
15051+ .putback_page = aufs_putback_page,
15052+ .launder_page = aufs_launder_page,
15053+ .is_partially_uptodate = aufs_is_partially_uptodate,
15054+ .is_dirty_writeback = aufs_is_dirty_writeback,
15055+ .error_remove_page = aufs_error_remove_page,
15056+ .swap_activate = aufs_swap_activate,
15057+ .swap_deactivate = aufs_swap_deactivate
15058+#endif /* CONFIG_AUFS_DEBUG */
15059+};
15060diff -urNp -x '*.orig' linux-4.14/fs/aufs/file.h linux-4.14/fs/aufs/file.h
15061--- linux-4.14/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
15062+++ linux-4.14/fs/aufs/file.h 2021-02-24 21:42:43.441114748 +0100
15063@@ -0,0 +1,340 @@
b912730e 15064+/*
0b1ff5c3
JR
15065+ * Copyright (C) 2005-2017 Junjiro R. Okajima
15066+ *
15067+ * This program, aufs is free software; you can redistribute it and/or modify
15068+ * it under the terms of the GNU General Public License as published by
15069+ * the Free Software Foundation; either version 2 of the License, or
15070+ * (at your option) any later version.
15071+ *
15072+ * This program is distributed in the hope that it will be useful,
15073+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15074+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15075+ * GNU General Public License for more details.
15076+ *
15077+ * You should have received a copy of the GNU General Public License
15078+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
b912730e 15079+ */
b912730e 15080+
0b1ff5c3
JR
15081+/*
15082+ * file operations
15083+ */
1facf9fc 15084+
0b1ff5c3
JR
15085+#ifndef __AUFS_FILE_H__
15086+#define __AUFS_FILE_H__
b912730e 15087+
0b1ff5c3 15088+#ifdef __KERNEL__
b912730e 15089+
0b1ff5c3
JR
15090+#include <linux/file.h>
15091+#include <linux/fs.h>
15092+#include <linux/mm_types.h>
15093+#include <linux/poll.h>
15094+#include "rwsem.h"
b912730e 15095+
0b1ff5c3
JR
15096+struct au_branch;
15097+struct au_hfile {
15098+ struct file *hf_file;
15099+ struct au_branch *hf_br;
15100+};
b912730e 15101+
0b1ff5c3
JR
15102+struct au_vdir;
15103+struct au_fidir {
15104+ aufs_bindex_t fd_bbot;
15105+ aufs_bindex_t fd_nent;
15106+ struct au_vdir *fd_vdir_cache;
15107+ struct au_hfile fd_hfile[];
15108+};
b912730e 15109+
0b1ff5c3 15110+static inline int au_fidir_sz(int nent)
b912730e 15111+{
0b1ff5c3
JR
15112+ AuDebugOn(nent < 0);
15113+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
15114+}
9dbd164d 15115+
0b1ff5c3
JR
15116+struct au_finfo {
15117+ atomic_t fi_generation;
1308ab2a 15118+
0b1ff5c3
JR
15119+ struct au_rwsem fi_rwsem;
15120+ aufs_bindex_t fi_btop;
1facf9fc 15121+
0b1ff5c3
JR
15122+ /* do not union them */
15123+ struct { /* for non-dir */
15124+ struct au_hfile fi_htop;
15125+ atomic_t fi_mmapped;
15126+ };
15127+ struct au_fidir *fi_hdir; /* for dir only */
e49829fe 15128+
0b1ff5c3
JR
15129+ struct hlist_bl_node fi_hlist;
15130+ struct file *fi_file; /* very ugly */
15131+} ____cacheline_aligned_in_smp;
e49829fe 15132+
0b1ff5c3 15133+/* ---------------------------------------------------------------------- */
1facf9fc 15134+
0b1ff5c3
JR
15135+/* file.c */
15136+extern const struct address_space_operations aufs_aop;
15137+unsigned int au_file_roflags(unsigned int flags);
15138+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
15139+ struct file *file, int force_wr);
15140+struct au_do_open_args {
15141+ int aopen;
15142+ int (*open)(struct file *file, int flags,
15143+ struct file *h_file);
15144+ struct au_fidir *fidir;
15145+ struct file *h_file;
15146+};
15147+int au_do_open(struct file *file, struct au_do_open_args *args);
15148+int au_reopen_nondir(struct file *file);
15149+struct au_pin;
15150+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
15151+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
15152+ int wlock, unsigned int fi_lsc);
15153+int au_do_flush(struct file *file, fl_owner_t id,
15154+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 15155+
0b1ff5c3
JR
15156+/* poll.c */
15157+#ifdef CONFIG_AUFS_POLL
15158+unsigned int aufs_poll(struct file *file, poll_table *wait);
15159+#endif
9dbd164d 15160+
0b1ff5c3
JR
15161+#ifdef CONFIG_AUFS_BR_HFSPLUS
15162+/* hfsplus.c */
15163+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
15164+ int force_wr);
15165+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
15166+ struct file *h_file);
15167+#else
15168+AuStub(struct file *, au_h_open_pre, return NULL, struct dentry *dentry,
15169+ aufs_bindex_t bindex, int force_wr)
15170+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
15171+ struct file *h_file);
15172+#endif
1facf9fc 15173+
0b1ff5c3
JR
15174+/* f_op.c */
15175+extern const struct file_operations aufs_file_fop;
15176+int au_do_open_nondir(struct file *file, int flags, struct file *h_file);
15177+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
15178+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc);
1facf9fc 15179+
0b1ff5c3
JR
15180+/* finfo.c */
15181+void au_hfput(struct au_hfile *hf, int execed);
15182+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
15183+ struct file *h_file);
1facf9fc 15184+
0b1ff5c3
JR
15185+void au_update_figen(struct file *file);
15186+struct au_fidir *au_fidir_alloc(struct super_block *sb);
15187+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink);
1facf9fc 15188+
0b1ff5c3
JR
15189+void au_fi_init_once(void *_fi);
15190+void au_finfo_fin(struct file *file);
15191+int au_finfo_init(struct file *file, struct au_fidir *fidir);
076b876e 15192+
0b1ff5c3
JR
15193+/* ioctl.c */
15194+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
15195+#ifdef CONFIG_COMPAT
15196+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
15197+ unsigned long arg);
15198+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
15199+ unsigned long arg);
15200+#endif
1facf9fc 15201+
0b1ff5c3 15202+/* ---------------------------------------------------------------------- */
1facf9fc 15203+
0b1ff5c3 15204+static inline struct au_finfo *au_fi(struct file *file)
1facf9fc 15205+{
0b1ff5c3
JR
15206+ return file->private_data;
15207+}
1facf9fc 15208+
0b1ff5c3 15209+/* ---------------------------------------------------------------------- */
4a4d8108 15210+
0b1ff5c3
JR
15211+#define fi_read_lock(f) au_rw_read_lock(&au_fi(f)->fi_rwsem)
15212+#define fi_write_lock(f) au_rw_write_lock(&au_fi(f)->fi_rwsem)
15213+#define fi_read_trylock(f) au_rw_read_trylock(&au_fi(f)->fi_rwsem)
15214+#define fi_write_trylock(f) au_rw_write_trylock(&au_fi(f)->fi_rwsem)
15215+/*
15216+#define fi_read_trylock_nested(f) \
15217+ au_rw_read_trylock_nested(&au_fi(f)->fi_rwsem)
15218+#define fi_write_trylock_nested(f) \
15219+ au_rw_write_trylock_nested(&au_fi(f)->fi_rwsem)
15220+*/
9dbd164d 15221+
0b1ff5c3
JR
15222+#define fi_read_unlock(f) au_rw_read_unlock(&au_fi(f)->fi_rwsem)
15223+#define fi_write_unlock(f) au_rw_write_unlock(&au_fi(f)->fi_rwsem)
15224+#define fi_downgrade_lock(f) au_rw_dgrade_lock(&au_fi(f)->fi_rwsem)
5afbbe0d 15225+
0b1ff5c3
JR
15226+/* lock subclass for finfo */
15227+enum {
15228+ AuLsc_FI_1,
15229+ AuLsc_FI_2
15230+};
1facf9fc 15231+
0b1ff5c3
JR
15232+static inline void fi_read_lock_nested(struct file *f, unsigned int lsc)
15233+{
15234+ au_rw_read_lock_nested(&au_fi(f)->fi_rwsem, lsc);
1308ab2a 15235+}
1facf9fc 15236+
0b1ff5c3 15237+static inline void fi_write_lock_nested(struct file *f, unsigned int lsc)
1308ab2a 15238+{
0b1ff5c3
JR
15239+ au_rw_write_lock_nested(&au_fi(f)->fi_rwsem, lsc);
15240+}
e49829fe 15241+
0b1ff5c3
JR
15242+/*
15243+ * fi_read_lock_1, fi_write_lock_1,
15244+ * fi_read_lock_2, fi_write_lock_2
15245+ */
15246+#define AuReadLockFunc(name) \
15247+static inline void fi_read_lock_##name(struct file *f) \
15248+{ fi_read_lock_nested(f, AuLsc_FI_##name); }
9dbd164d 15249+
0b1ff5c3
JR
15250+#define AuWriteLockFunc(name) \
15251+static inline void fi_write_lock_##name(struct file *f) \
15252+{ fi_write_lock_nested(f, AuLsc_FI_##name); }
1facf9fc 15253+
0b1ff5c3
JR
15254+#define AuRWLockFuncs(name) \
15255+ AuReadLockFunc(name) \
15256+ AuWriteLockFunc(name)
1facf9fc 15257+
0b1ff5c3
JR
15258+AuRWLockFuncs(1);
15259+AuRWLockFuncs(2);
1facf9fc 15260+
0b1ff5c3
JR
15261+#undef AuReadLockFunc
15262+#undef AuWriteLockFunc
15263+#undef AuRWLockFuncs
b912730e 15264+
0b1ff5c3
JR
15265+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
15266+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
15267+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 15268+
0b1ff5c3 15269+/* ---------------------------------------------------------------------- */
1facf9fc 15270+
0b1ff5c3
JR
15271+/* todo: hard/soft set? */
15272+static inline aufs_bindex_t au_fbtop(struct file *file)
15273+{
15274+ FiMustAnyLock(file);
15275+ return au_fi(file)->fi_btop;
1facf9fc 15276+}
15277+
0b1ff5c3 15278+static inline aufs_bindex_t au_fbbot_dir(struct file *file)
1facf9fc 15279+{
0b1ff5c3
JR
15280+ FiMustAnyLock(file);
15281+ AuDebugOn(!au_fi(file)->fi_hdir);
15282+ return au_fi(file)->fi_hdir->fd_bbot;
15283+}
1facf9fc 15284+
0b1ff5c3
JR
15285+static inline struct au_vdir *au_fvdir_cache(struct file *file)
15286+{
15287+ FiMustAnyLock(file);
15288+ AuDebugOn(!au_fi(file)->fi_hdir);
15289+ return au_fi(file)->fi_hdir->fd_vdir_cache;
15290+}
9dbd164d 15291+
0b1ff5c3
JR
15292+static inline void au_set_fbtop(struct file *file, aufs_bindex_t bindex)
15293+{
15294+ FiMustWriteLock(file);
15295+ au_fi(file)->fi_btop = bindex;
15296+}
9dbd164d 15297+
0b1ff5c3
JR
15298+static inline void au_set_fbbot_dir(struct file *file, aufs_bindex_t bindex)
15299+{
15300+ FiMustWriteLock(file);
15301+ AuDebugOn(!au_fi(file)->fi_hdir);
15302+ au_fi(file)->fi_hdir->fd_bbot = bindex;
15303+}
1facf9fc 15304+
0b1ff5c3
JR
15305+static inline void au_set_fvdir_cache(struct file *file,
15306+ struct au_vdir *vdir_cache)
15307+{
15308+ FiMustWriteLock(file);
15309+ AuDebugOn(!au_fi(file)->fi_hdir);
15310+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
4a4d8108 15311+}
1facf9fc 15312+
0b1ff5c3 15313+static inline struct file *au_hf_top(struct file *file)
38d290e6 15314+{
0b1ff5c3
JR
15315+ FiMustAnyLock(file);
15316+ AuDebugOn(au_fi(file)->fi_hdir);
15317+ return au_fi(file)->fi_htop.hf_file;
15318+}
38d290e6 15319+
0b1ff5c3
JR
15320+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
15321+{
15322+ FiMustAnyLock(file);
15323+ AuDebugOn(!au_fi(file)->fi_hdir);
15324+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
15325+}
38d290e6 15326+
0b1ff5c3
JR
15327+/* todo: memory barrier? */
15328+static inline unsigned int au_figen(struct file *f)
15329+{
15330+ return atomic_read(&au_fi(f)->fi_generation);
15331+}
38d290e6 15332+
0b1ff5c3
JR
15333+static inline void au_set_mmapped(struct file *f)
15334+{
15335+ if (atomic_inc_return(&au_fi(f)->fi_mmapped))
15336+ return;
15337+ pr_warn("fi_mmapped wrapped around\n");
15338+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
15339+ ;
15340+}
38d290e6 15341+
0b1ff5c3
JR
15342+static inline void au_unset_mmapped(struct file *f)
15343+{
15344+ atomic_dec(&au_fi(f)->fi_mmapped);
38d290e6
JR
15345+}
15346+
0b1ff5c3 15347+static inline int au_test_mmapped(struct file *f)
521ced18 15348+{
0b1ff5c3
JR
15349+ return atomic_read(&au_fi(f)->fi_mmapped);
15350+}
521ced18 15351+
0b1ff5c3 15352+/* customize vma->vm_file */
521ced18 15353+
0b1ff5c3
JR
15354+static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
15355+ struct file *file)
15356+{
15357+ struct file *f;
521ced18 15358+
0b1ff5c3
JR
15359+ f = vma->vm_file;
15360+ get_file(file);
15361+ vma->vm_file = file;
15362+ fput(f);
15363+}
521ced18 15364+
0b1ff5c3
JR
15365+#ifdef CONFIG_MMU
15366+#define AuDbgVmRegion(file, vma) do {} while (0)
521ced18 15367+
0b1ff5c3
JR
15368+static inline void au_vm_file_reset(struct vm_area_struct *vma,
15369+ struct file *file)
15370+{
15371+ au_do_vm_file_reset(vma, file);
15372+}
15373+#else
15374+#define AuDbgVmRegion(file, vma) \
15375+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
521ced18 15376+
0b1ff5c3
JR
15377+static inline void au_vm_file_reset(struct vm_area_struct *vma,
15378+ struct file *file)
15379+{
15380+ struct file *f;
521ced18 15381+
0b1ff5c3
JR
15382+ au_do_vm_file_reset(vma, file);
15383+ f = vma->vm_region->vm_file;
15384+ get_file(file);
15385+ vma->vm_region->vm_file = file;
15386+ fput(f);
521ced18 15387+}
0b1ff5c3 15388+#endif /* CONFIG_MMU */
521ced18 15389+
0b1ff5c3
JR
15390+/* handle vma->vm_prfile */
15391+static inline void au_vm_prfile_set(struct vm_area_struct *vma,
15392+ struct file *file)
15393+{
15394+ get_file(file);
15395+ vma->vm_prfile = file;
15396+#ifndef CONFIG_MMU
15397+ get_file(file);
15398+ vma->vm_region->vm_prfile = file;
15399+#endif
15400+}
4a4d8108 15401+
0b1ff5c3
JR
15402+#endif /* __KERNEL__ */
15403+#endif /* __AUFS_FILE_H__ */
15404diff -urNp -x '*.orig' linux-4.14/fs/aufs/finfo.c linux-4.14/fs/aufs/finfo.c
15405--- linux-4.14/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
15406+++ linux-4.14/fs/aufs/finfo.c 2021-02-24 21:42:43.441114748 +0100
15407@@ -0,0 +1,148 @@
9dbd164d 15408+/*
0b1ff5c3 15409+ * Copyright (C) 2005-2017 Junjiro R. Okajima
9dbd164d 15410+ *
0b1ff5c3
JR
15411+ * This program, aufs is free software; you can redistribute it and/or modify
15412+ * it under the terms of the GNU General Public License as published by
15413+ * the Free Software Foundation; either version 2 of the License, or
15414+ * (at your option) any later version.
15415+ *
15416+ * This program is distributed in the hope that it will be useful,
15417+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15418+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15419+ * GNU General Public License for more details.
15420+ *
15421+ * You should have received a copy of the GNU General Public License
15422+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
9dbd164d
AM
15423+ */
15424+
0b1ff5c3
JR
15425+/*
15426+ * file private data
15427+ */
2dfbb274 15428+
0b1ff5c3
JR
15429+#include "aufs.h"
15430+
15431+void au_hfput(struct au_hfile *hf, int execed)
2dfbb274 15432+{
0b1ff5c3
JR
15433+ if (execed)
15434+ allow_write_access(hf->hf_file);
15435+ fput(hf->hf_file);
15436+ hf->hf_file = NULL;
15437+ au_br_put(hf->hf_br);
15438+ hf->hf_br = NULL;
2dfbb274
AM
15439+}
15440+
0b1ff5c3 15441+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
2dfbb274 15442+{
0b1ff5c3
JR
15443+ struct au_finfo *finfo = au_fi(file);
15444+ struct au_hfile *hf;
15445+ struct au_fidir *fidir;
2dfbb274 15446+
0b1ff5c3
JR
15447+ fidir = finfo->fi_hdir;
15448+ if (!fidir) {
15449+ AuDebugOn(finfo->fi_btop != bindex);
15450+ hf = &finfo->fi_htop;
15451+ } else
15452+ hf = fidir->fd_hfile + bindex;
2dfbb274 15453+
0b1ff5c3
JR
15454+ if (hf && hf->hf_file)
15455+ au_hfput(hf, vfsub_file_execed(file));
15456+ if (val) {
15457+ FiMustWriteLock(file);
15458+ AuDebugOn(IS_ERR_OR_NULL(file->f_path.dentry));
15459+ hf->hf_file = val;
15460+ hf->hf_br = au_sbr(file->f_path.dentry->d_sb, bindex);
15461+ }
2dfbb274
AM
15462+}
15463+
0b1ff5c3 15464+void au_update_figen(struct file *file)
dece6358 15465+{
0b1ff5c3
JR
15466+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_path.dentry));
15467+ /* smp_mb(); */ /* atomic_set */
15468+}
1308ab2a 15469+
0b1ff5c3 15470+/* ---------------------------------------------------------------------- */
4a4d8108 15471+
0b1ff5c3
JR
15472+struct au_fidir *au_fidir_alloc(struct super_block *sb)
15473+{
15474+ struct au_fidir *fidir;
15475+ int nbr;
1308ab2a 15476+
0b1ff5c3
JR
15477+ nbr = au_sbbot(sb) + 1;
15478+ if (nbr < 2)
15479+ nbr = 2; /* initial allocate for 2 branches */
15480+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
15481+ if (fidir) {
15482+ fidir->fd_bbot = -1;
15483+ fidir->fd_nent = nbr;
b912730e 15484+ }
b912730e 15485+
0b1ff5c3 15486+ return fidir;
4a4d8108
AM
15487+}
15488+
0b1ff5c3 15489+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink)
4a4d8108
AM
15490+{
15491+ int err;
0b1ff5c3 15492+ struct au_fidir *fidir, *p;
b912730e 15493+
0b1ff5c3
JR
15494+ AuRwMustWriteLock(&finfo->fi_rwsem);
15495+ fidir = finfo->fi_hdir;
15496+ AuDebugOn(!fidir);
4a4d8108 15497+
0b1ff5c3
JR
15498+ err = -ENOMEM;
15499+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
15500+ GFP_NOFS, may_shrink);
15501+ if (p) {
15502+ p->fd_nent = nbr;
15503+ finfo->fi_hdir = p;
15504+ err = 0;
15505+ }
4a4d8108 15506+
4a4d8108 15507+ return err;
dece6358
AM
15508+}
15509+
0b1ff5c3
JR
15510+/* ---------------------------------------------------------------------- */
15511+
15512+void au_finfo_fin(struct file *file)
dece6358 15513+{
0b1ff5c3 15514+ struct au_finfo *finfo;
1308ab2a 15515+
0b1ff5c3 15516+ au_nfiles_dec(file->f_path.dentry->d_sb);
b912730e 15517+
0b1ff5c3
JR
15518+ finfo = au_fi(file);
15519+ AuDebugOn(finfo->fi_hdir);
15520+ AuRwDestroy(&finfo->fi_rwsem);
15521+ au_cache_free_finfo(finfo);
15522+}
4a4d8108 15523+
0b1ff5c3
JR
15524+void au_fi_init_once(void *_finfo)
15525+{
15526+ struct au_finfo *finfo = _finfo;
1308ab2a 15527+
0b1ff5c3 15528+ au_rw_init(&finfo->fi_rwsem);
dece6358 15529+}
4a4d8108 15530+
0b1ff5c3 15531+int au_finfo_init(struct file *file, struct au_fidir *fidir)
febd17d6
JR
15532+{
15533+ int err;
0b1ff5c3
JR
15534+ struct au_finfo *finfo;
15535+ struct dentry *dentry;
febd17d6 15536+
0b1ff5c3
JR
15537+ err = -ENOMEM;
15538+ dentry = file->f_path.dentry;
15539+ finfo = au_cache_alloc_finfo();
15540+ if (unlikely(!finfo))
febd17d6
JR
15541+ goto out;
15542+
0b1ff5c3
JR
15543+ err = 0;
15544+ au_nfiles_inc(dentry->d_sb);
15545+ au_rw_write_lock(&finfo->fi_rwsem);
15546+ finfo->fi_btop = -1;
15547+ finfo->fi_hdir = fidir;
15548+ atomic_set(&finfo->fi_generation, au_digen(dentry));
15549+ /* smp_mb(); */ /* atomic_set */
15550+
15551+ file->private_data = finfo;
febd17d6
JR
15552+
15553+out:
febd17d6
JR
15554+ return err;
15555+}
0b1ff5c3
JR
15556diff -urNp -x '*.orig' linux-4.14/fs/aufs/fstype.h linux-4.14/fs/aufs/fstype.h
15557--- linux-4.14/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
15558+++ linux-4.14/fs/aufs/fstype.h 2021-02-24 21:42:43.441114748 +0100
b912730e 15559@@ -0,0 +1,400 @@
4a4d8108 15560+/*
a2654f78 15561+ * Copyright (C) 2005-2017 Junjiro R. Okajima
4a4d8108
AM
15562+ *
15563+ * This program, aufs is free software; you can redistribute it and/or modify
15564+ * it under the terms of the GNU General Public License as published by
15565+ * the Free Software Foundation; either version 2 of the License, or
15566+ * (at your option) any later version.
15567+ *
15568+ * This program is distributed in the hope that it will be useful,
15569+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15570+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15571+ * GNU General Public License for more details.
15572+ *
15573+ * You should have received a copy of the GNU General Public License
523b37e3 15574+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
15575+ */
15576+
15577+/*
15578+ * judging filesystem type
15579+ */
15580+
15581+#ifndef __AUFS_FSTYPE_H__
15582+#define __AUFS_FSTYPE_H__
15583+
15584+#ifdef __KERNEL__
15585+
15586+#include <linux/fs.h>
15587+#include <linux/magic.h>
b912730e 15588+#include <linux/nfs_fs.h>
b95c5147 15589+#include <linux/romfs_fs.h>
4a4d8108
AM
15590+
15591+static inline int au_test_aufs(struct super_block *sb)
15592+{
15593+ return sb->s_magic == AUFS_SUPER_MAGIC;
15594+}
15595+
15596+static inline const char *au_sbtype(struct super_block *sb)
15597+{
15598+ return sb->s_type->name;
15599+}
1308ab2a 15600+
15601+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
15602+{
f0c0a007 15603+#if IS_ENABLED(CONFIG_ISO9660_FS)
2000de60 15604+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
15605+#else
15606+ return 0;
15607+#endif
15608+}
15609+
1308ab2a 15610+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 15611+{
f0c0a007 15612+#if IS_ENABLED(CONFIG_ROMFS_FS)
2000de60 15613+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
15614+#else
15615+ return 0;
15616+#endif
15617+}
15618+
1308ab2a 15619+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 15620+{
f0c0a007 15621+#if IS_ENABLED(CONFIG_CRAMFS)
1308ab2a 15622+ return sb->s_magic == CRAMFS_MAGIC;
15623+#endif
15624+ return 0;
15625+}
15626+
15627+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
15628+{
f0c0a007 15629+#if IS_ENABLED(CONFIG_NFS_FS)
1308ab2a 15630+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
15631+#else
15632+ return 0;
15633+#endif
15634+}
15635+
1308ab2a 15636+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 15637+{
f0c0a007 15638+#if IS_ENABLED(CONFIG_FUSE_FS)
1308ab2a 15639+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
15640+#else
15641+ return 0;
15642+#endif
15643+}
15644+
1308ab2a 15645+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 15646+{
f0c0a007 15647+#if IS_ENABLED(CONFIG_XFS_FS)
1308ab2a 15648+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
15649+#else
15650+ return 0;
15651+#endif
15652+}
15653+
1308ab2a 15654+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 15655+{
1308ab2a 15656+#ifdef CONFIG_TMPFS
15657+ return sb->s_magic == TMPFS_MAGIC;
15658+#else
15659+ return 0;
dece6358 15660+#endif
dece6358
AM
15661+}
15662+
1308ab2a 15663+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 15664+{
f0c0a007 15665+#if IS_ENABLED(CONFIG_ECRYPT_FS)
1308ab2a 15666+ return !strcmp(au_sbtype(sb), "ecryptfs");
15667+#else
15668+ return 0;
15669+#endif
1facf9fc 15670+}
15671+
1308ab2a 15672+static inline int au_test_ramfs(struct super_block *sb)
15673+{
15674+ return sb->s_magic == RAMFS_MAGIC;
15675+}
15676+
15677+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
15678+{
f0c0a007 15679+#if IS_ENABLED(CONFIG_UBIFS_FS)
1308ab2a 15680+ return sb->s_magic == UBIFS_SUPER_MAGIC;
15681+#else
15682+ return 0;
15683+#endif
15684+}
15685+
15686+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
15687+{
15688+#ifdef CONFIG_PROC_FS
15689+ return sb->s_magic == PROC_SUPER_MAGIC;
15690+#else
15691+ return 0;
15692+#endif
15693+}
15694+
15695+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
15696+{
15697+#ifdef CONFIG_SYSFS
15698+ return sb->s_magic == SYSFS_MAGIC;
15699+#else
15700+ return 0;
15701+#endif
15702+}
15703+
15704+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
15705+{
f0c0a007 15706+#if IS_ENABLED(CONFIG_CONFIGFS_FS)
1308ab2a 15707+ return sb->s_magic == CONFIGFS_MAGIC;
15708+#else
15709+ return 0;
15710+#endif
15711+}
15712+
15713+static inline int au_test_minix(struct super_block *sb __maybe_unused)
15714+{
f0c0a007 15715+#if IS_ENABLED(CONFIG_MINIX_FS)
1308ab2a 15716+ return sb->s_magic == MINIX3_SUPER_MAGIC
15717+ || sb->s_magic == MINIX2_SUPER_MAGIC
15718+ || sb->s_magic == MINIX2_SUPER_MAGIC2
15719+ || sb->s_magic == MINIX_SUPER_MAGIC
15720+ || sb->s_magic == MINIX_SUPER_MAGIC2;
15721+#else
15722+ return 0;
15723+#endif
15724+}
15725+
1308ab2a 15726+static inline int au_test_fat(struct super_block *sb __maybe_unused)
15727+{
f0c0a007 15728+#if IS_ENABLED(CONFIG_FAT_FS)
1308ab2a 15729+ return sb->s_magic == MSDOS_SUPER_MAGIC;
15730+#else
15731+ return 0;
15732+#endif
15733+}
15734+
15735+static inline int au_test_msdos(struct super_block *sb)
15736+{
15737+ return au_test_fat(sb);
15738+}
15739+
15740+static inline int au_test_vfat(struct super_block *sb)
15741+{
15742+ return au_test_fat(sb);
15743+}
15744+
15745+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
15746+{
15747+#ifdef CONFIG_SECURITYFS
15748+ return sb->s_magic == SECURITYFS_MAGIC;
15749+#else
15750+ return 0;
15751+#endif
15752+}
15753+
15754+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
15755+{
f0c0a007 15756+#if IS_ENABLED(CONFIG_SQUASHFS)
1308ab2a 15757+ return sb->s_magic == SQUASHFS_MAGIC;
15758+#else
15759+ return 0;
15760+#endif
15761+}
15762+
15763+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
15764+{
f0c0a007 15765+#if IS_ENABLED(CONFIG_BTRFS_FS)
1308ab2a 15766+ return sb->s_magic == BTRFS_SUPER_MAGIC;
15767+#else
15768+ return 0;
15769+#endif
15770+}
15771+
15772+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
15773+{
f0c0a007 15774+#if IS_ENABLED(CONFIG_XENFS)
1308ab2a 15775+ return sb->s_magic == XENFS_SUPER_MAGIC;
15776+#else
15777+ return 0;
15778+#endif
15779+}
15780+
15781+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
15782+{
15783+#ifdef CONFIG_DEBUG_FS
15784+ return sb->s_magic == DEBUGFS_MAGIC;
15785+#else
15786+ return 0;
15787+#endif
15788+}
15789+
15790+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
15791+{
f0c0a007 15792+#if IS_ENABLED(CONFIG_NILFS)
1308ab2a 15793+ return sb->s_magic == NILFS_SUPER_MAGIC;
15794+#else
15795+ return 0;
15796+#endif
15797+}
15798+
4a4d8108
AM
15799+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
15800+{
f0c0a007 15801+#if IS_ENABLED(CONFIG_HFSPLUS_FS)
4a4d8108
AM
15802+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
15803+#else
15804+ return 0;
15805+#endif
15806+}
15807+
1308ab2a 15808+/* ---------------------------------------------------------------------- */
15809+/*
15810+ * they can't be an aufs branch.
15811+ */
15812+static inline int au_test_fs_unsuppoted(struct super_block *sb)
15813+{
15814+ return
15815+#ifndef CONFIG_AUFS_BR_RAMFS
15816+ au_test_ramfs(sb) ||
15817+#endif
15818+ au_test_procfs(sb)
15819+ || au_test_sysfs(sb)
15820+ || au_test_configfs(sb)
15821+ || au_test_debugfs(sb)
15822+ || au_test_securityfs(sb)
15823+ || au_test_xenfs(sb)
15824+ || au_test_ecryptfs(sb)
15825+ /* || !strcmp(au_sbtype(sb), "unionfs") */
15826+ || au_test_aufs(sb); /* will be supported in next version */
15827+}
15828+
1308ab2a 15829+static inline int au_test_fs_remote(struct super_block *sb)
15830+{
15831+ return !au_test_tmpfs(sb)
15832+#ifdef CONFIG_AUFS_BR_RAMFS
15833+ && !au_test_ramfs(sb)
15834+#endif
15835+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
15836+}
15837+
15838+/* ---------------------------------------------------------------------- */
15839+
15840+/*
15841+ * Note: these functions (below) are created after reading ->getattr() in all
15842+ * filesystems under linux/fs. it means we have to do so in every update...
15843+ */
15844+
15845+/*
15846+ * some filesystems require getattr to refresh the inode attributes before
15847+ * referencing.
15848+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
15849+ * and leave the work for d_revalidate()
15850+ */
15851+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
15852+{
15853+ return au_test_nfs(sb)
15854+ || au_test_fuse(sb)
1308ab2a 15855+ /* || au_test_btrfs(sb) */ /* untested */
1308ab2a 15856+ ;
15857+}
15858+
15859+/*
15860+ * filesystems which don't maintain i_size or i_blocks.
15861+ */
15862+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
15863+{
15864+ return au_test_xfs(sb)
4a4d8108
AM
15865+ || au_test_btrfs(sb)
15866+ || au_test_ubifs(sb)
15867+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 15868+ /* || au_test_minix(sb) */ /* untested */
15869+ ;
15870+}
15871+
15872+/*
15873+ * filesystems which don't store the correct value in some of their inode
15874+ * attributes.
15875+ */
15876+static inline int au_test_fs_bad_iattr(struct super_block *sb)
15877+{
15878+ return au_test_fs_bad_iattr_size(sb)
1308ab2a 15879+ || au_test_fat(sb)
15880+ || au_test_msdos(sb)
15881+ || au_test_vfat(sb);
1facf9fc 15882+}
15883+
15884+/* they don't check i_nlink in link(2) */
15885+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
15886+{
15887+ return au_test_tmpfs(sb)
15888+#ifdef CONFIG_AUFS_BR_RAMFS
15889+ || au_test_ramfs(sb)
15890+#endif
4a4d8108 15891+ || au_test_ubifs(sb)
4a4d8108 15892+ || au_test_hfsplus(sb);
1facf9fc 15893+}
15894+
15895+/*
15896+ * filesystems which sets S_NOATIME and S_NOCMTIME.
15897+ */
15898+static inline int au_test_fs_notime(struct super_block *sb)
15899+{
15900+ return au_test_nfs(sb)
15901+ || au_test_fuse(sb)
dece6358 15902+ || au_test_ubifs(sb)
1facf9fc 15903+ ;
15904+}
15905+
1facf9fc 15906+/* temporary support for i#1 in cramfs */
15907+static inline int au_test_fs_unique_ino(struct inode *inode)
15908+{
15909+ if (au_test_cramfs(inode->i_sb))
15910+ return inode->i_ino != 1;
15911+ return 1;
15912+}
15913+
15914+/* ---------------------------------------------------------------------- */
15915+
15916+/*
15917+ * the filesystem where the xino files placed must support i/o after unlink and
15918+ * maintain i_size and i_blocks.
15919+ */
15920+static inline int au_test_fs_bad_xino(struct super_block *sb)
15921+{
15922+ return au_test_fs_remote(sb)
15923+ || au_test_fs_bad_iattr_size(sb)
1facf9fc 15924+ /* don't want unnecessary work for xino */
15925+ || au_test_aufs(sb)
1308ab2a 15926+ || au_test_ecryptfs(sb)
15927+ || au_test_nilfs(sb);
1facf9fc 15928+}
15929+
15930+static inline int au_test_fs_trunc_xino(struct super_block *sb)
15931+{
15932+ return au_test_tmpfs(sb)
15933+ || au_test_ramfs(sb);
15934+}
15935+
15936+/*
15937+ * test if the @sb is real-readonly.
15938+ */
15939+static inline int au_test_fs_rr(struct super_block *sb)
15940+{
15941+ return au_test_squashfs(sb)
15942+ || au_test_iso9660(sb)
15943+ || au_test_cramfs(sb)
15944+ || au_test_romfs(sb);
15945+}
15946+
b912730e
AM
15947+/*
15948+ * test if the @inode is nfs with 'noacl' option
15949+ * NFS always sets MS_POSIXACL regardless its mount option 'noacl.'
15950+ */
15951+static inline int au_test_nfs_noacl(struct inode *inode)
15952+{
15953+ return au_test_nfs(inode->i_sb)
15954+ /* && IS_POSIXACL(inode) */
15955+ && !nfs_server_capable(inode, NFS_CAP_ACLS);
15956+}
15957+
1facf9fc 15958+#endif /* __KERNEL__ */
15959+#endif /* __AUFS_FSTYPE_H__ */
0b1ff5c3
JR
15960diff -urNp -x '*.orig' linux-4.14/fs/aufs/hbl.h linux-4.14/fs/aufs/hbl.h
15961--- linux-4.14/fs/aufs/hbl.h 1970-01-01 01:00:00.000000000 +0100
15962+++ linux-4.14/fs/aufs/hbl.h 2021-02-24 21:42:43.441114748 +0100
8b6a4947
AM
15963@@ -0,0 +1,64 @@
15964+/*
15965+ * Copyright (C) 2017 Junjiro R. Okajima
15966+ *
15967+ * This program, aufs is free software; you can redistribute it and/or modify
15968+ * it under the terms of the GNU General Public License as published by
15969+ * the Free Software Foundation; either version 2 of the License, or
15970+ * (at your option) any later version.
15971+ *
15972+ * This program is distributed in the hope that it will be useful,
15973+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15974+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15975+ * GNU General Public License for more details.
15976+ *
15977+ * You should have received a copy of the GNU General Public License
15978+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15979+ */
15980+
15981+/*
15982+ * helpers for hlist_bl.h
15983+ */
15984+
15985+#ifndef __AUFS_HBL_H__
15986+#define __AUFS_HBL_H__
15987+
15988+#ifdef __KERNEL__
15989+
15990+#include <linux/list_bl.h>
15991+
15992+static inline void au_hbl_add(struct hlist_bl_node *node,
15993+ struct hlist_bl_head *hbl)
15994+{
15995+ hlist_bl_lock(hbl);
15996+ hlist_bl_add_head(node, hbl);
15997+ hlist_bl_unlock(hbl);
15998+}
15999+
16000+static inline void au_hbl_del(struct hlist_bl_node *node,
16001+ struct hlist_bl_head *hbl)
16002+{
16003+ hlist_bl_lock(hbl);
16004+ hlist_bl_del(node);
16005+ hlist_bl_unlock(hbl);
16006+}
16007+
16008+#define au_hbl_for_each(pos, head) \
16009+ for (pos = hlist_bl_first(head); \
16010+ pos; \
16011+ pos = pos->next)
16012+
16013+static inline unsigned long au_hbl_count(struct hlist_bl_head *hbl)
16014+{
16015+ unsigned long cnt;
16016+ struct hlist_bl_node *pos;
16017+
16018+ cnt = 0;
16019+ hlist_bl_lock(hbl);
16020+ au_hbl_for_each(pos, hbl)
16021+ cnt++;
16022+ hlist_bl_unlock(hbl);
16023+ return cnt;
16024+}
16025+
16026+#endif /* __KERNEL__ */
16027+#endif /* __AUFS_HBL_H__ */
0b1ff5c3
JR
16028diff -urNp -x '*.orig' linux-4.14/fs/aufs/hfsnotify.c linux-4.14/fs/aufs/hfsnotify.c
16029--- linux-4.14/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
16030+++ linux-4.14/fs/aufs/hfsnotify.c 2021-02-24 21:42:43.441114748 +0100
ffa93bbd 16031@@ -0,0 +1,289 @@
1facf9fc 16032+/*
a2654f78 16033+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 16034+ *
16035+ * This program, aufs is free software; you can redistribute it and/or modify
16036+ * it under the terms of the GNU General Public License as published by
16037+ * the Free Software Foundation; either version 2 of the License, or
16038+ * (at your option) any later version.
dece6358
AM
16039+ *
16040+ * This program is distributed in the hope that it will be useful,
16041+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16042+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16043+ * GNU General Public License for more details.
16044+ *
16045+ * You should have received a copy of the GNU General Public License
523b37e3 16046+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 16047+ */
16048+
16049+/*
4a4d8108 16050+ * fsnotify for the lower directories
1facf9fc 16051+ */
16052+
16053+#include "aufs.h"
16054+
4a4d8108
AM
16055+/* FS_IN_IGNORED is unnecessary */
16056+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
16057+ | FS_CREATE | FS_EVENT_ON_CHILD);
7f207e10 16058+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
7eafdf33 16059+static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0);
1facf9fc 16060+
0c5527e5 16061+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 16062+{
0c5527e5
AM
16063+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
16064+ hn_mark);
5afbbe0d 16065+ /* AuDbg("here\n"); */
1c60b727 16066+ au_cache_free_hnotify(hn);
8b6a4947 16067+ smp_mb__before_atomic(); /* for atomic64_dec */
1716fcea
AM
16068+ if (atomic64_dec_and_test(&au_hfsn_ifree))
16069+ wake_up(&au_hfsn_wq);
4a4d8108 16070+}
1facf9fc 16071+
027c5e7a 16072+static int au_hfsn_alloc(struct au_hinode *hinode)
4a4d8108 16073+{
1716fcea 16074+ int err;
027c5e7a
AM
16075+ struct au_hnotify *hn;
16076+ struct super_block *sb;
16077+ struct au_branch *br;
0c5527e5 16078+ struct fsnotify_mark *mark;
027c5e7a 16079+ aufs_bindex_t bindex;
1facf9fc 16080+
027c5e7a
AM
16081+ hn = hinode->hi_notify;
16082+ sb = hn->hn_aufs_inode->i_sb;
16083+ bindex = au_br_index(sb, hinode->hi_id);
16084+ br = au_sbr(sb, bindex);
1716fcea
AM
16085+ AuDebugOn(!br->br_hfsn);
16086+
0c5527e5 16087+ mark = &hn->hn_mark;
ffa93bbd 16088+ fsnotify_init_mark(mark, br->br_hfsn->hfsn_group);
0c5527e5 16089+ mark->mask = AuHfsnMask;
7f207e10
AM
16090+ /*
16091+ * by udba rename or rmdir, aufs assign a new inode to the known
16092+ * h_inode, so specify 1 to allow dups.
16093+ */
c1595e42 16094+ lockdep_off();
ffa93bbd
AM
16095+ err = fsnotify_add_mark(mark, hinode->hi_inode, /*mnt*/NULL,
16096+ /*allow_dups*/1);
c1595e42 16097+ lockdep_on();
1716fcea
AM
16098+
16099+ return err;
1facf9fc 16100+}
16101+
7eafdf33 16102+static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn)
1facf9fc 16103+{
0c5527e5 16104+ struct fsnotify_mark *mark;
7eafdf33 16105+ unsigned long long ull;
1716fcea 16106+ struct fsnotify_group *group;
7eafdf33
AM
16107+
16108+ ull = atomic64_inc_return(&au_hfsn_ifree);
16109+ BUG_ON(!ull);
953406b4 16110+
0c5527e5 16111+ mark = &hn->hn_mark;
1716fcea
AM
16112+ spin_lock(&mark->lock);
16113+ group = mark->group;
16114+ fsnotify_get_group(group);
16115+ spin_unlock(&mark->lock);
c1595e42 16116+ lockdep_off();
1716fcea 16117+ fsnotify_destroy_mark(mark, group);
5afbbe0d 16118+ fsnotify_put_mark(mark);
1716fcea 16119+ fsnotify_put_group(group);
c1595e42 16120+ lockdep_on();
7f207e10 16121+
7eafdf33
AM
16122+ /* free hn by myself */
16123+ return 0;
1facf9fc 16124+}
16125+
16126+/* ---------------------------------------------------------------------- */
16127+
4a4d8108 16128+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 16129+{
0c5527e5 16130+ struct fsnotify_mark *mark;
1facf9fc 16131+
0c5527e5
AM
16132+ mark = &hinode->hi_notify->hn_mark;
16133+ spin_lock(&mark->lock);
1facf9fc 16134+ if (do_set) {
0c5527e5
AM
16135+ AuDebugOn(mark->mask & AuHfsnMask);
16136+ mark->mask |= AuHfsnMask;
1facf9fc 16137+ } else {
0c5527e5
AM
16138+ AuDebugOn(!(mark->mask & AuHfsnMask));
16139+ mark->mask &= ~AuHfsnMask;
1facf9fc 16140+ }
0c5527e5 16141+ spin_unlock(&mark->lock);
4a4d8108 16142+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 16143+}
16144+
4a4d8108 16145+/* ---------------------------------------------------------------------- */
1facf9fc 16146+
4a4d8108
AM
16147+/* #define AuDbgHnotify */
16148+#ifdef AuDbgHnotify
16149+static char *au_hfsn_name(u32 mask)
16150+{
16151+#ifdef CONFIG_AUFS_DEBUG
c06a8ce3
AM
16152+#define test_ret(flag) \
16153+ do { \
16154+ if (mask & flag) \
16155+ return #flag; \
16156+ } while (0)
4a4d8108
AM
16157+ test_ret(FS_ACCESS);
16158+ test_ret(FS_MODIFY);
16159+ test_ret(FS_ATTRIB);
16160+ test_ret(FS_CLOSE_WRITE);
16161+ test_ret(FS_CLOSE_NOWRITE);
16162+ test_ret(FS_OPEN);
16163+ test_ret(FS_MOVED_FROM);
16164+ test_ret(FS_MOVED_TO);
16165+ test_ret(FS_CREATE);
16166+ test_ret(FS_DELETE);
16167+ test_ret(FS_DELETE_SELF);
16168+ test_ret(FS_MOVE_SELF);
16169+ test_ret(FS_UNMOUNT);
16170+ test_ret(FS_Q_OVERFLOW);
16171+ test_ret(FS_IN_IGNORED);
b912730e 16172+ test_ret(FS_ISDIR);
4a4d8108
AM
16173+ test_ret(FS_IN_ONESHOT);
16174+ test_ret(FS_EVENT_ON_CHILD);
16175+ return "";
16176+#undef test_ret
16177+#else
16178+ return "??";
16179+#endif
1facf9fc 16180+}
4a4d8108 16181+#endif
1facf9fc 16182+
16183+/* ---------------------------------------------------------------------- */
16184+
1716fcea
AM
16185+static void au_hfsn_free_group(struct fsnotify_group *group)
16186+{
16187+ struct au_br_hfsnotify *hfsn = group->private;
16188+
5afbbe0d 16189+ /* AuDbg("here\n"); */
1c60b727 16190+ kfree(hfsn);
1716fcea
AM
16191+}
16192+
4a4d8108 16193+static int au_hfsn_handle_event(struct fsnotify_group *group,
fb47a38f 16194+ struct inode *inode,
0c5527e5
AM
16195+ struct fsnotify_mark *inode_mark,
16196+ struct fsnotify_mark *vfsmount_mark,
a2654f78 16197+ u32 mask, const void *data, int data_type,
ffa93bbd
AM
16198+ const unsigned char *file_name, u32 cookie,
16199+ struct fsnotify_iter_info *iter_info)
1facf9fc 16200+{
16201+ int err;
4a4d8108
AM
16202+ struct au_hnotify *hnotify;
16203+ struct inode *h_dir, *h_inode;
fb47a38f 16204+ struct qstr h_child_qstr = QSTR_INIT(file_name, strlen(file_name));
4a4d8108 16205+
fb47a38f 16206+ AuDebugOn(data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 16207+
16208+ err = 0;
0c5527e5 16209+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108 16210+ AuDebugOn(mask & FS_UNMOUNT);
0c5527e5 16211+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 16212+ goto out;
1facf9fc 16213+
fb47a38f
JR
16214+ h_dir = inode;
16215+ h_inode = NULL;
4a4d8108 16216+#ifdef AuDbgHnotify
392086de 16217+ au_debug_on();
4a4d8108
AM
16218+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
16219+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
16220+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
16221+ h_dir->i_ino, mask, au_hfsn_name(mask),
16222+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
16223+ /* WARN_ON(1); */
1facf9fc 16224+ }
392086de 16225+ au_debug_off();
1facf9fc 16226+#endif
4a4d8108 16227+
0c5527e5
AM
16228+ AuDebugOn(!inode_mark);
16229+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
16230+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
1facf9fc 16231+
4a4d8108
AM
16232+out:
16233+ return err;
16234+}
1facf9fc 16235+
4a4d8108 16236+static struct fsnotify_ops au_hfsn_ops = {
1716fcea 16237+ .handle_event = au_hfsn_handle_event,
ffa93bbd
AM
16238+ .free_group_priv = au_hfsn_free_group,
16239+ .free_mark = au_hfsn_free_mark
4a4d8108
AM
16240+};
16241+
16242+/* ---------------------------------------------------------------------- */
16243+
027c5e7a
AM
16244+static void au_hfsn_fin_br(struct au_branch *br)
16245+{
1716fcea 16246+ struct au_br_hfsnotify *hfsn;
027c5e7a 16247+
1716fcea 16248+ hfsn = br->br_hfsn;
c1595e42
JR
16249+ if (hfsn) {
16250+ lockdep_off();
1716fcea 16251+ fsnotify_put_group(hfsn->hfsn_group);
c1595e42
JR
16252+ lockdep_on();
16253+ }
027c5e7a
AM
16254+}
16255+
1716fcea 16256+static int au_hfsn_init_br(struct au_branch *br, int perm)
4a4d8108
AM
16257+{
16258+ int err;
1716fcea
AM
16259+ struct fsnotify_group *group;
16260+ struct au_br_hfsnotify *hfsn;
1facf9fc 16261+
4a4d8108 16262+ err = 0;
1716fcea
AM
16263+ br->br_hfsn = NULL;
16264+ if (!au_br_hnotifyable(perm))
027c5e7a 16265+ goto out;
027c5e7a 16266+
1716fcea
AM
16267+ err = -ENOMEM;
16268+ hfsn = kmalloc(sizeof(*hfsn), GFP_NOFS);
16269+ if (unlikely(!hfsn))
027c5e7a
AM
16270+ goto out;
16271+
1716fcea
AM
16272+ err = 0;
16273+ group = fsnotify_alloc_group(&au_hfsn_ops);
16274+ if (IS_ERR(group)) {
16275+ err = PTR_ERR(group);
0c5527e5 16276+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
1716fcea 16277+ goto out_hfsn;
4a4d8108 16278+ }
1facf9fc 16279+
1716fcea
AM
16280+ group->private = hfsn;
16281+ hfsn->hfsn_group = group;
16282+ br->br_hfsn = hfsn;
16283+ goto out; /* success */
16284+
16285+out_hfsn:
1c60b727 16286+ kfree(hfsn);
027c5e7a 16287+out:
1716fcea
AM
16288+ return err;
16289+}
16290+
16291+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm)
16292+{
16293+ int err;
16294+
16295+ err = 0;
16296+ if (!br->br_hfsn)
16297+ err = au_hfsn_init_br(br, perm);
16298+
1facf9fc 16299+ return err;
16300+}
16301+
7eafdf33
AM
16302+/* ---------------------------------------------------------------------- */
16303+
16304+static void au_hfsn_fin(void)
16305+{
16306+ AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree));
16307+ wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree));
16308+}
16309+
4a4d8108
AM
16310+const struct au_hnotify_op au_hnotify_op = {
16311+ .ctl = au_hfsn_ctl,
16312+ .alloc = au_hfsn_alloc,
16313+ .free = au_hfsn_free,
1facf9fc 16314+
7eafdf33
AM
16315+ .fin = au_hfsn_fin,
16316+
027c5e7a
AM
16317+ .reset_br = au_hfsn_reset_br,
16318+ .fin_br = au_hfsn_fin_br,
16319+ .init_br = au_hfsn_init_br
4a4d8108 16320+};
0b1ff5c3
JR
16321diff -urNp -x '*.orig' linux-4.14/fs/aufs/hfsplus.c linux-4.14/fs/aufs/hfsplus.c
16322--- linux-4.14/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
16323+++ linux-4.14/fs/aufs/hfsplus.c 2021-02-24 21:42:43.441114748 +0100
523b37e3 16324@@ -0,0 +1,56 @@
4a4d8108 16325+/*
a2654f78 16326+ * Copyright (C) 2010-2017 Junjiro R. Okajima
4a4d8108
AM
16327+ *
16328+ * This program, aufs is free software; you can redistribute it and/or modify
16329+ * it under the terms of the GNU General Public License as published by
16330+ * the Free Software Foundation; either version 2 of the License, or
16331+ * (at your option) any later version.
16332+ *
16333+ * This program is distributed in the hope that it will be useful,
16334+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16335+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16336+ * GNU General Public License for more details.
16337+ *
16338+ * You should have received a copy of the GNU General Public License
523b37e3 16339+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 16340+ */
1facf9fc 16341+
4a4d8108
AM
16342+/*
16343+ * special support for filesystems which aqucires an inode mutex
16344+ * at final closing a file, eg, hfsplus.
16345+ *
16346+ * This trick is very simple and stupid, just to open the file before really
16347+ * neceeary open to tell hfsplus that this is not the final closing.
16348+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
16349+ * and au_h_open_post() after releasing it.
16350+ */
1facf9fc 16351+
4a4d8108 16352+#include "aufs.h"
1facf9fc 16353+
392086de
AM
16354+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
16355+ int force_wr)
4a4d8108
AM
16356+{
16357+ struct file *h_file;
16358+ struct dentry *h_dentry;
1facf9fc 16359+
4a4d8108
AM
16360+ h_dentry = au_h_dptr(dentry, bindex);
16361+ AuDebugOn(!h_dentry);
5527c038 16362+ AuDebugOn(d_is_negative(h_dentry));
4a4d8108
AM
16363+
16364+ h_file = NULL;
16365+ if (au_test_hfsplus(h_dentry->d_sb)
7e9cd9fe 16366+ && d_is_reg(h_dentry))
4a4d8108
AM
16367+ h_file = au_h_open(dentry, bindex,
16368+ O_RDONLY | O_NOATIME | O_LARGEFILE,
392086de 16369+ /*file*/NULL, force_wr);
4a4d8108 16370+ return h_file;
1facf9fc 16371+}
16372+
4a4d8108
AM
16373+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
16374+ struct file *h_file)
16375+{
16376+ if (h_file) {
16377+ fput(h_file);
16378+ au_sbr_put(dentry->d_sb, bindex);
16379+ }
16380+}
0b1ff5c3
JR
16381diff -urNp -x '*.orig' linux-4.14/fs/aufs/hnotify.c linux-4.14/fs/aufs/hnotify.c
16382--- linux-4.14/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
16383+++ linux-4.14/fs/aufs/hnotify.c 2021-02-24 21:42:43.444448075 +0100
8b6a4947 16384@@ -0,0 +1,719 @@
e49829fe 16385+/*
a2654f78 16386+ * Copyright (C) 2005-2017 Junjiro R. Okajima
e49829fe
JR
16387+ *
16388+ * This program, aufs is free software; you can redistribute it and/or modify
16389+ * it under the terms of the GNU General Public License as published by
16390+ * the Free Software Foundation; either version 2 of the License, or
16391+ * (at your option) any later version.
16392+ *
16393+ * This program is distributed in the hope that it will be useful,
16394+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16395+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16396+ * GNU General Public License for more details.
16397+ *
16398+ * You should have received a copy of the GNU General Public License
523b37e3 16399+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
e49829fe
JR
16400+ */
16401+
16402+/*
7f207e10 16403+ * abstraction to notify the direct changes on lower directories
e49829fe
JR
16404+ */
16405+
16406+#include "aufs.h"
16407+
027c5e7a 16408+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode)
e49829fe
JR
16409+{
16410+ int err;
7f207e10 16411+ struct au_hnotify *hn;
1facf9fc 16412+
4a4d8108
AM
16413+ err = -ENOMEM;
16414+ hn = au_cache_alloc_hnotify();
16415+ if (hn) {
16416+ hn->hn_aufs_inode = inode;
027c5e7a
AM
16417+ hinode->hi_notify = hn;
16418+ err = au_hnotify_op.alloc(hinode);
16419+ AuTraceErr(err);
16420+ if (unlikely(err)) {
16421+ hinode->hi_notify = NULL;
1c60b727 16422+ au_cache_free_hnotify(hn);
4a4d8108
AM
16423+ /*
16424+ * The upper dir was removed by udba, but the same named
16425+ * dir left. In this case, aufs assignes a new inode
16426+ * number and set the monitor again.
16427+ * For the lower dir, the old monitnor is still left.
16428+ */
16429+ if (err == -EEXIST)
16430+ err = 0;
16431+ }
1308ab2a 16432+ }
1308ab2a 16433+
027c5e7a 16434+ AuTraceErr(err);
1308ab2a 16435+ return err;
dece6358 16436+}
1facf9fc 16437+
4a4d8108 16438+void au_hn_free(struct au_hinode *hinode)
dece6358 16439+{
4a4d8108 16440+ struct au_hnotify *hn;
1facf9fc 16441+
4a4d8108
AM
16442+ hn = hinode->hi_notify;
16443+ if (hn) {
4a4d8108 16444+ hinode->hi_notify = NULL;
7eafdf33 16445+ if (au_hnotify_op.free(hinode, hn))
1c60b727 16446+ au_cache_free_hnotify(hn);
4a4d8108
AM
16447+ }
16448+}
dece6358 16449+
4a4d8108 16450+/* ---------------------------------------------------------------------- */
dece6358 16451+
4a4d8108
AM
16452+void au_hn_ctl(struct au_hinode *hinode, int do_set)
16453+{
16454+ if (hinode->hi_notify)
16455+ au_hnotify_op.ctl(hinode, do_set);
16456+}
16457+
16458+void au_hn_reset(struct inode *inode, unsigned int flags)
16459+{
5afbbe0d 16460+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
16461+ struct inode *hi;
16462+ struct dentry *iwhdentry;
1facf9fc 16463+
5afbbe0d
AM
16464+ bbot = au_ibbot(inode);
16465+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) {
4a4d8108
AM
16466+ hi = au_h_iptr(inode, bindex);
16467+ if (!hi)
16468+ continue;
1308ab2a 16469+
febd17d6 16470+ /* inode_lock_nested(hi, AuLsc_I_CHILD); */
4a4d8108
AM
16471+ iwhdentry = au_hi_wh(inode, bindex);
16472+ if (iwhdentry)
16473+ dget(iwhdentry);
16474+ au_igrab(hi);
16475+ au_set_h_iptr(inode, bindex, NULL, 0);
16476+ au_set_h_iptr(inode, bindex, au_igrab(hi),
16477+ flags & ~AuHi_XINO);
16478+ iput(hi);
16479+ dput(iwhdentry);
febd17d6 16480+ /* inode_unlock(hi); */
1facf9fc 16481+ }
1facf9fc 16482+}
16483+
1308ab2a 16484+/* ---------------------------------------------------------------------- */
1facf9fc 16485+
4a4d8108 16486+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 16487+{
4a4d8108 16488+ int err;
5afbbe0d 16489+ aufs_bindex_t bindex, bbot, bfound, btop;
4a4d8108 16490+ struct inode *h_i;
1facf9fc 16491+
4a4d8108
AM
16492+ err = 0;
16493+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 16494+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
16495+ goto out;
16496+ }
1facf9fc 16497+
4a4d8108 16498+ bfound = -1;
5afbbe0d
AM
16499+ bbot = au_ibbot(inode);
16500+ btop = au_ibtop(inode);
4a4d8108 16501+#if 0 /* reserved for future use */
5afbbe0d 16502+ if (bindex == bbot) {
4a4d8108
AM
16503+ /* keep this ino in rename case */
16504+ goto out;
16505+ }
16506+#endif
5afbbe0d 16507+ for (bindex = btop; bindex <= bbot; bindex++)
4a4d8108
AM
16508+ if (au_h_iptr(inode, bindex) == h_inode) {
16509+ bfound = bindex;
16510+ break;
16511+ }
16512+ if (bfound < 0)
1308ab2a 16513+ goto out;
1facf9fc 16514+
5afbbe0d 16515+ for (bindex = btop; bindex <= bbot; bindex++) {
4a4d8108
AM
16516+ h_i = au_h_iptr(inode, bindex);
16517+ if (!h_i)
16518+ continue;
1facf9fc 16519+
4a4d8108
AM
16520+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
16521+ /* ignore this error */
16522+ /* bad action? */
1facf9fc 16523+ }
1facf9fc 16524+
4a4d8108 16525+ /* children inode number will be broken */
1facf9fc 16526+
4f0767ce 16527+out:
4a4d8108
AM
16528+ AuTraceErr(err);
16529+ return err;
1facf9fc 16530+}
16531+
4a4d8108 16532+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 16533+{
4a4d8108
AM
16534+ int err, i, j, ndentry;
16535+ struct au_dcsub_pages dpages;
16536+ struct au_dpage *dpage;
16537+ struct dentry **dentries;
1facf9fc 16538+
4a4d8108
AM
16539+ err = au_dpages_init(&dpages, GFP_NOFS);
16540+ if (unlikely(err))
16541+ goto out;
16542+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
16543+ if (unlikely(err))
16544+ goto out_dpages;
1facf9fc 16545+
4a4d8108
AM
16546+ for (i = 0; i < dpages.ndpage; i++) {
16547+ dpage = dpages.dpages + i;
16548+ dentries = dpage->dentries;
16549+ ndentry = dpage->ndentry;
16550+ for (j = 0; j < ndentry; j++) {
16551+ struct dentry *d;
16552+
16553+ d = dentries[j];
16554+ if (IS_ROOT(d))
16555+ continue;
16556+
4a4d8108 16557+ au_digen_dec(d);
5527c038 16558+ if (d_really_is_positive(d))
4a4d8108
AM
16559+ /* todo: reset children xino?
16560+ cached children only? */
5527c038 16561+ au_iigen_dec(d_inode(d));
1308ab2a 16562+ }
dece6358 16563+ }
1facf9fc 16564+
4f0767ce 16565+out_dpages:
4a4d8108 16566+ au_dpages_free(&dpages);
dece6358 16567+
027c5e7a 16568+#if 0
4a4d8108
AM
16569+ /* discard children */
16570+ dentry_unhash(dentry);
16571+ dput(dentry);
027c5e7a 16572+#endif
4f0767ce 16573+out:
dece6358
AM
16574+ return err;
16575+}
16576+
1308ab2a 16577+/*
4a4d8108 16578+ * return 0 if processed.
1308ab2a 16579+ */
4a4d8108
AM
16580+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
16581+ const unsigned int isdir)
dece6358 16582+{
1308ab2a 16583+ int err;
4a4d8108
AM
16584+ struct dentry *d;
16585+ struct qstr *dname;
1facf9fc 16586+
4a4d8108
AM
16587+ err = 1;
16588+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 16589+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
16590+ err = 0;
16591+ goto out;
16592+ }
dece6358 16593+
4a4d8108
AM
16594+ if (!isdir) {
16595+ AuDebugOn(!name);
16596+ au_iigen_dec(inode);
027c5e7a 16597+ spin_lock(&inode->i_lock);
c1595e42 16598+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) {
027c5e7a 16599+ spin_lock(&d->d_lock);
4a4d8108
AM
16600+ dname = &d->d_name;
16601+ if (dname->len != nlen
027c5e7a
AM
16602+ && memcmp(dname->name, name, nlen)) {
16603+ spin_unlock(&d->d_lock);
4a4d8108 16604+ continue;
027c5e7a 16605+ }
4a4d8108 16606+ err = 0;
4a4d8108
AM
16607+ au_digen_dec(d);
16608+ spin_unlock(&d->d_lock);
16609+ break;
1facf9fc 16610+ }
027c5e7a 16611+ spin_unlock(&inode->i_lock);
1308ab2a 16612+ } else {
027c5e7a 16613+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR);
c1595e42 16614+ d = d_find_any_alias(inode);
4a4d8108
AM
16615+ if (!d) {
16616+ au_iigen_dec(inode);
16617+ goto out;
16618+ }
1facf9fc 16619+
027c5e7a 16620+ spin_lock(&d->d_lock);
4a4d8108 16621+ dname = &d->d_name;
027c5e7a
AM
16622+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) {
16623+ spin_unlock(&d->d_lock);
4a4d8108 16624+ err = hn_gen_tree(d);
027c5e7a
AM
16625+ spin_lock(&d->d_lock);
16626+ }
16627+ spin_unlock(&d->d_lock);
4a4d8108
AM
16628+ dput(d);
16629+ }
1facf9fc 16630+
4f0767ce 16631+out:
4a4d8108 16632+ AuTraceErr(err);
1308ab2a 16633+ return err;
16634+}
dece6358 16635+
4a4d8108 16636+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 16637+{
4a4d8108 16638+ int err;
1facf9fc 16639+
5527c038 16640+ if (IS_ROOT(dentry)) {
0c3ec466 16641+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
16642+ return 0;
16643+ }
1308ab2a 16644+
4a4d8108
AM
16645+ err = 0;
16646+ if (!isdir) {
4a4d8108 16647+ au_digen_dec(dentry);
5527c038
JR
16648+ if (d_really_is_positive(dentry))
16649+ au_iigen_dec(d_inode(dentry));
4a4d8108 16650+ } else {
027c5e7a 16651+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR);
5527c038 16652+ if (d_really_is_positive(dentry))
4a4d8108
AM
16653+ err = hn_gen_tree(dentry);
16654+ }
16655+
16656+ AuTraceErr(err);
16657+ return err;
1facf9fc 16658+}
16659+
4a4d8108 16660+/* ---------------------------------------------------------------------- */
1facf9fc 16661+
4a4d8108
AM
16662+/* hnotify job flags */
16663+#define AuHnJob_XINO0 1
16664+#define AuHnJob_GEN (1 << 1)
16665+#define AuHnJob_DIRENT (1 << 2)
16666+#define AuHnJob_ISDIR (1 << 3)
16667+#define AuHnJob_TRYXINO0 (1 << 4)
16668+#define AuHnJob_MNTPNT (1 << 5)
16669+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
7f207e10
AM
16670+#define au_fset_hnjob(flags, name) \
16671+ do { (flags) |= AuHnJob_##name; } while (0)
16672+#define au_fclr_hnjob(flags, name) \
16673+ do { (flags) &= ~AuHnJob_##name; } while (0)
1facf9fc 16674+
4a4d8108
AM
16675+enum {
16676+ AuHn_CHILD,
16677+ AuHn_PARENT,
16678+ AuHnLast
16679+};
1facf9fc 16680+
4a4d8108
AM
16681+struct au_hnotify_args {
16682+ struct inode *h_dir, *dir, *h_child_inode;
16683+ u32 mask;
16684+ unsigned int flags[AuHnLast];
16685+ unsigned int h_child_nlen;
16686+ char h_child_name[];
16687+};
1facf9fc 16688+
4a4d8108
AM
16689+struct hn_job_args {
16690+ unsigned int flags;
16691+ struct inode *inode, *h_inode, *dir, *h_dir;
16692+ struct dentry *dentry;
16693+ char *h_name;
16694+ int h_nlen;
16695+};
1308ab2a 16696+
4a4d8108
AM
16697+static int hn_job(struct hn_job_args *a)
16698+{
16699+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
076b876e 16700+ int e;
1308ab2a 16701+
4a4d8108
AM
16702+ /* reset xino */
16703+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
16704+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 16705+
4a4d8108
AM
16706+ if (au_ftest_hnjob(a->flags, TRYXINO0)
16707+ && a->inode
16708+ && a->h_inode) {
3c1bdaff 16709+ vfsub_inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD);
38d290e6
JR
16710+ if (!a->h_inode->i_nlink
16711+ && !(a->h_inode->i_state & I_LINKABLE))
4a4d8108 16712+ hn_xino(a->inode, a->h_inode); /* ignore this error */
3c1bdaff 16713+ inode_unlock_shared(a->h_inode);
1308ab2a 16714+ }
1facf9fc 16715+
4a4d8108
AM
16716+ /* make the generation obsolete */
16717+ if (au_ftest_hnjob(a->flags, GEN)) {
076b876e 16718+ e = -1;
4a4d8108 16719+ if (a->inode)
076b876e 16720+ e = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
4a4d8108 16721+ isdir);
076b876e 16722+ if (e && a->dentry)
4a4d8108
AM
16723+ hn_gen_by_name(a->dentry, isdir);
16724+ /* ignore this error */
1facf9fc 16725+ }
1facf9fc 16726+
4a4d8108
AM
16727+ /* make dir entries obsolete */
16728+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
16729+ struct au_vdir *vdir;
1facf9fc 16730+
4a4d8108
AM
16731+ vdir = au_ivdir(a->inode);
16732+ if (vdir)
16733+ vdir->vd_jiffy = 0;
16734+ /* IMustLock(a->inode); */
16735+ /* a->inode->i_version++; */
16736+ }
1facf9fc 16737+
4a4d8108
AM
16738+ /* can do nothing but warn */
16739+ if (au_ftest_hnjob(a->flags, MNTPNT)
16740+ && a->dentry
16741+ && d_mountpoint(a->dentry))
523b37e3 16742+ pr_warn("mount-point %pd is removed or renamed\n", a->dentry);
1facf9fc 16743+
4a4d8108 16744+ return 0;
1308ab2a 16745+}
1facf9fc 16746+
1308ab2a 16747+/* ---------------------------------------------------------------------- */
1facf9fc 16748+
4a4d8108
AM
16749+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
16750+ struct inode *dir)
1308ab2a 16751+{
4a4d8108
AM
16752+ struct dentry *dentry, *d, *parent;
16753+ struct qstr *dname;
1308ab2a 16754+
c1595e42 16755+ parent = d_find_any_alias(dir);
4a4d8108
AM
16756+ if (!parent)
16757+ return NULL;
1308ab2a 16758+
4a4d8108 16759+ dentry = NULL;
027c5e7a 16760+ spin_lock(&parent->d_lock);
c1595e42 16761+ list_for_each_entry(d, &parent->d_subdirs, d_child) {
523b37e3 16762+ /* AuDbg("%pd\n", d); */
027c5e7a 16763+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
4a4d8108
AM
16764+ dname = &d->d_name;
16765+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
027c5e7a
AM
16766+ goto cont_unlock;
16767+ if (au_di(d))
16768+ au_digen_dec(d);
16769+ else
16770+ goto cont_unlock;
c1595e42 16771+ if (au_dcount(d) > 0) {
027c5e7a 16772+ dentry = dget_dlock(d);
4a4d8108 16773+ spin_unlock(&d->d_lock);
027c5e7a 16774+ break;
dece6358 16775+ }
1facf9fc 16776+
f6b6e03d 16777+cont_unlock:
027c5e7a 16778+ spin_unlock(&d->d_lock);
1308ab2a 16779+ }
027c5e7a 16780+ spin_unlock(&parent->d_lock);
4a4d8108 16781+ dput(parent);
1facf9fc 16782+
4a4d8108
AM
16783+ if (dentry)
16784+ di_write_lock_child(dentry);
1308ab2a 16785+
4a4d8108
AM
16786+ return dentry;
16787+}
dece6358 16788+
4a4d8108
AM
16789+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
16790+ aufs_bindex_t bindex, ino_t h_ino)
16791+{
16792+ struct inode *inode;
16793+ ino_t ino;
16794+ int err;
16795+
16796+ inode = NULL;
16797+ err = au_xino_read(sb, bindex, h_ino, &ino);
16798+ if (!err && ino)
16799+ inode = ilookup(sb, ino);
16800+ if (!inode)
16801+ goto out;
16802+
16803+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 16804+ pr_warn("wrong root branch\n");
4a4d8108
AM
16805+ iput(inode);
16806+ inode = NULL;
16807+ goto out;
1308ab2a 16808+ }
16809+
4a4d8108 16810+ ii_write_lock_child(inode);
1308ab2a 16811+
4f0767ce 16812+out:
4a4d8108 16813+ return inode;
dece6358
AM
16814+}
16815+
4a4d8108 16816+static void au_hn_bh(void *_args)
1facf9fc 16817+{
4a4d8108
AM
16818+ struct au_hnotify_args *a = _args;
16819+ struct super_block *sb;
5afbbe0d 16820+ aufs_bindex_t bindex, bbot, bfound;
4a4d8108 16821+ unsigned char xino, try_iput;
1facf9fc 16822+ int err;
1308ab2a 16823+ struct inode *inode;
4a4d8108
AM
16824+ ino_t h_ino;
16825+ struct hn_job_args args;
16826+ struct dentry *dentry;
16827+ struct au_sbinfo *sbinfo;
1facf9fc 16828+
4a4d8108
AM
16829+ AuDebugOn(!_args);
16830+ AuDebugOn(!a->h_dir);
16831+ AuDebugOn(!a->dir);
16832+ AuDebugOn(!a->mask);
16833+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
16834+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
16835+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 16836+
4a4d8108
AM
16837+ inode = NULL;
16838+ dentry = NULL;
16839+ /*
16840+ * do not lock a->dir->i_mutex here
16841+ * because of d_revalidate() may cause a deadlock.
16842+ */
16843+ sb = a->dir->i_sb;
16844+ AuDebugOn(!sb);
16845+ sbinfo = au_sbi(sb);
16846+ AuDebugOn(!sbinfo);
7f207e10 16847+ si_write_lock(sb, AuLock_NOPLMW);
1facf9fc 16848+
8b6a4947
AM
16849+ if (au_opt_test(sbinfo->si_mntflags, DIRREN))
16850+ switch (a->mask & FS_EVENTS_POSS_ON_CHILD) {
16851+ case FS_MOVED_FROM:
16852+ case FS_MOVED_TO:
16853+ AuWarn1("DIRREN with UDBA may not work correctly "
16854+ "for the direct rename(2)\n");
16855+ }
16856+
4a4d8108
AM
16857+ ii_read_lock_parent(a->dir);
16858+ bfound = -1;
5afbbe0d
AM
16859+ bbot = au_ibbot(a->dir);
16860+ for (bindex = au_ibtop(a->dir); bindex <= bbot; bindex++)
4a4d8108
AM
16861+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
16862+ bfound = bindex;
16863+ break;
16864+ }
16865+ ii_read_unlock(a->dir);
16866+ if (unlikely(bfound < 0))
16867+ goto out;
1facf9fc 16868+
4a4d8108
AM
16869+ xino = !!au_opt_test(au_mntflags(sb), XINO);
16870+ h_ino = 0;
16871+ if (a->h_child_inode)
16872+ h_ino = a->h_child_inode->i_ino;
1facf9fc 16873+
4a4d8108
AM
16874+ if (a->h_child_nlen
16875+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
16876+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
16877+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
16878+ a->dir);
16879+ try_iput = 0;
5527c038
JR
16880+ if (dentry && d_really_is_positive(dentry))
16881+ inode = d_inode(dentry);
4a4d8108
AM
16882+ if (xino && !inode && h_ino
16883+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
16884+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
16885+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
16886+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
16887+ try_iput = 1;
f0c0a007 16888+ }
1facf9fc 16889+
4a4d8108
AM
16890+ args.flags = a->flags[AuHn_CHILD];
16891+ args.dentry = dentry;
16892+ args.inode = inode;
16893+ args.h_inode = a->h_child_inode;
16894+ args.dir = a->dir;
16895+ args.h_dir = a->h_dir;
16896+ args.h_name = a->h_child_name;
16897+ args.h_nlen = a->h_child_nlen;
16898+ err = hn_job(&args);
16899+ if (dentry) {
027c5e7a 16900+ if (au_di(dentry))
4a4d8108
AM
16901+ di_write_unlock(dentry);
16902+ dput(dentry);
16903+ }
16904+ if (inode && try_iput) {
16905+ ii_write_unlock(inode);
16906+ iput(inode);
16907+ }
1facf9fc 16908+
4a4d8108
AM
16909+ ii_write_lock_parent(a->dir);
16910+ args.flags = a->flags[AuHn_PARENT];
16911+ args.dentry = NULL;
16912+ args.inode = a->dir;
16913+ args.h_inode = a->h_dir;
16914+ args.dir = NULL;
16915+ args.h_dir = NULL;
16916+ args.h_name = NULL;
16917+ args.h_nlen = 0;
16918+ err = hn_job(&args);
16919+ ii_write_unlock(a->dir);
1facf9fc 16920+
4f0767ce 16921+out:
4a4d8108
AM
16922+ iput(a->h_child_inode);
16923+ iput(a->h_dir);
16924+ iput(a->dir);
027c5e7a
AM
16925+ si_write_unlock(sb);
16926+ au_nwt_done(&sbinfo->si_nowait);
1c60b727 16927+ kfree(a);
dece6358 16928+}
1facf9fc 16929+
4a4d8108
AM
16930+/* ---------------------------------------------------------------------- */
16931+
16932+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
16933+ struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 16934+{
4a4d8108 16935+ int err, len;
53392da6 16936+ unsigned int flags[AuHnLast], f;
4a4d8108
AM
16937+ unsigned char isdir, isroot, wh;
16938+ struct inode *dir;
16939+ struct au_hnotify_args *args;
16940+ char *p, *h_child_name;
dece6358 16941+
1308ab2a 16942+ err = 0;
4a4d8108
AM
16943+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
16944+ dir = igrab(hnotify->hn_aufs_inode);
16945+ if (!dir)
16946+ goto out;
1facf9fc 16947+
4a4d8108
AM
16948+ isroot = (dir->i_ino == AUFS_ROOT_INO);
16949+ wh = 0;
16950+ h_child_name = (void *)h_child_qstr->name;
16951+ len = h_child_qstr->len;
16952+ if (h_child_name) {
16953+ if (len > AUFS_WH_PFX_LEN
16954+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
16955+ h_child_name += AUFS_WH_PFX_LEN;
16956+ len -= AUFS_WH_PFX_LEN;
16957+ wh = 1;
16958+ }
1facf9fc 16959+ }
dece6358 16960+
4a4d8108
AM
16961+ isdir = 0;
16962+ if (h_child_inode)
16963+ isdir = !!S_ISDIR(h_child_inode->i_mode);
16964+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
16965+ flags[AuHn_CHILD] = 0;
16966+ if (isdir)
16967+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
16968+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
16969+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
16970+ switch (mask & FS_EVENTS_POSS_ON_CHILD) {
16971+ case FS_MOVED_FROM:
16972+ case FS_MOVED_TO:
16973+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
16974+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
16975+ /*FALLTHROUGH*/
16976+ case FS_CREATE:
fb47a38f 16977+ AuDebugOn(!h_child_name);
4a4d8108 16978+ break;
1facf9fc 16979+
4a4d8108
AM
16980+ case FS_DELETE:
16981+ /*
16982+ * aufs never be able to get this child inode.
16983+ * revalidation should be in d_revalidate()
16984+ * by checking i_nlink, i_generation or d_unhashed().
16985+ */
16986+ AuDebugOn(!h_child_name);
16987+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
16988+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
16989+ break;
dece6358 16990+
4a4d8108
AM
16991+ default:
16992+ AuDebugOn(1);
16993+ }
1308ab2a 16994+
4a4d8108
AM
16995+ if (wh)
16996+ h_child_inode = NULL;
1308ab2a 16997+
4a4d8108
AM
16998+ err = -ENOMEM;
16999+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 17000+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
17001+ if (unlikely(!args)) {
17002+ AuErr1("no memory\n");
17003+ iput(dir);
17004+ goto out;
17005+ }
17006+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
17007+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
17008+ args->mask = mask;
17009+ args->dir = dir;
17010+ args->h_dir = igrab(h_dir);
17011+ if (h_child_inode)
17012+ h_child_inode = igrab(h_child_inode); /* can be NULL */
17013+ args->h_child_inode = h_child_inode;
17014+ args->h_child_nlen = len;
17015+ if (len) {
17016+ p = (void *)args;
0b1ff5c3
JR
17017+ p += sizeof(*args);
17018+ memcpy(p, h_child_name, len);
17019+ p[len] = 0;
17020+ }
17021+
17022+ /* NFS fires the event for silly-renamed one from kworker */
17023+ f = 0;
17024+ if (!dir->i_nlink
17025+ || (au_test_nfs(h_dir->i_sb) && (mask & FS_DELETE)))
17026+ f = AuWkq_NEST;
17027+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb, f);
17028+ if (unlikely(err)) {
17029+ pr_err("wkq %d\n", err);
17030+ iput(args->h_child_inode);
17031+ iput(args->h_dir);
17032+ iput(args->dir);
17033+ kfree(args);
1308ab2a 17034+ }
1facf9fc 17035+
4f0767ce 17036+out:
027c5e7a
AM
17037+ return err;
17038+}
17039+
0b1ff5c3
JR
17040+/* ---------------------------------------------------------------------- */
17041+
17042+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm)
b95c5147 17043+{
0b1ff5c3 17044+ int err;
b95c5147 17045+
0b1ff5c3 17046+ AuDebugOn(!(udba & AuOptMask_UDBA));
b95c5147 17047+
0b1ff5c3
JR
17048+ err = 0;
17049+ if (au_hnotify_op.reset_br)
17050+ err = au_hnotify_op.reset_br(udba, br, perm);
b95c5147 17051+
0b1ff5c3 17052+ return err;
b95c5147
AM
17053+}
17054+
0b1ff5c3 17055+int au_hnotify_init_br(struct au_branch *br, int perm)
027c5e7a 17056+{
0b1ff5c3 17057+ int err;
027c5e7a 17058+
0b1ff5c3
JR
17059+ err = 0;
17060+ if (au_hnotify_op.init_br)
17061+ err = au_hnotify_op.init_br(br, perm);
027c5e7a 17062+
4a4d8108
AM
17063+ return err;
17064+}
1facf9fc 17065+
0b1ff5c3 17066+void au_hnotify_fin_br(struct au_branch *br)
4a4d8108 17067+{
0b1ff5c3
JR
17068+ if (au_hnotify_op.fin_br)
17069+ au_hnotify_op.fin_br(br);
17070+}
4a4d8108 17071+
0b1ff5c3
JR
17072+static void au_hn_destroy_cache(void)
17073+{
17074+ kmem_cache_destroy(au_cache[AuCache_HNOTIFY]);
17075+ au_cache[AuCache_HNOTIFY] = NULL;
dece6358
AM
17076+}
17077+
0b1ff5c3 17078+int __init au_hnotify_init(void)
dece6358 17079+{
4a4d8108 17080+ int err;
dece6358 17081+
0b1ff5c3
JR
17082+ err = -ENOMEM;
17083+ au_cache[AuCache_HNOTIFY] = AuCache(au_hnotify);
17084+ if (au_cache[AuCache_HNOTIFY]) {
17085+ err = 0;
17086+ if (au_hnotify_op.init)
17087+ err = au_hnotify_op.init();
4a4d8108 17088+ if (unlikely(err))
0b1ff5c3 17089+ au_hn_destroy_cache();
4a4d8108 17090+ }
0b1ff5c3
JR
17091+ AuTraceErr(err);
17092+ return err;
17093+}
dece6358 17094+
0b1ff5c3
JR
17095+void au_hnotify_fin(void)
17096+{
17097+ if (au_hnotify_op.fin)
17098+ au_hnotify_op.fin();
dece6358 17099+
0b1ff5c3
JR
17100+ /* cf. au_cache_fin() */
17101+ if (au_cache[AuCache_HNOTIFY])
17102+ au_hn_destroy_cache();
4a4d8108 17103+}
0b1ff5c3
JR
17104diff -urNp -x '*.orig' linux-4.14/fs/aufs/i_op.c linux-4.14/fs/aufs/i_op.c
17105--- linux-4.14/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
17106+++ linux-4.14/fs/aufs/i_op.c 2021-02-24 21:42:43.444448075 +0100
17107@@ -0,0 +1,1459 @@
17108+/*
17109+ * Copyright (C) 2005-2017 Junjiro R. Okajima
17110+ *
17111+ * This program, aufs is free software; you can redistribute it and/or modify
17112+ * it under the terms of the GNU General Public License as published by
17113+ * the Free Software Foundation; either version 2 of the License, or
17114+ * (at your option) any later version.
17115+ *
17116+ * This program is distributed in the hope that it will be useful,
17117+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17118+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17119+ * GNU General Public License for more details.
17120+ *
17121+ * You should have received a copy of the GNU General Public License
17122+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
17123+ */
dece6358 17124+
027c5e7a 17125+/*
0b1ff5c3 17126+ * inode operations (except add/del/rename)
027c5e7a 17127+ */
0b1ff5c3
JR
17128+
17129+#include <linux/device_cgroup.h>
17130+#include <linux/fs_stack.h>
17131+#include <linux/namei.h>
17132+#include <linux/security.h>
17133+#include "aufs.h"
17134+
17135+static int h_permission(struct inode *h_inode, int mask,
17136+ struct path *h_path, int brperm)
4a4d8108
AM
17137+{
17138+ int err;
0b1ff5c3 17139+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
dece6358 17140+
0b1ff5c3
JR
17141+ err = -EPERM;
17142+ if (write_mask && IS_IMMUTABLE(h_inode))
4a4d8108
AM
17143+ goto out;
17144+
0b1ff5c3
JR
17145+ err = -EACCES;
17146+ if (((mask & MAY_EXEC)
17147+ && S_ISREG(h_inode->i_mode)
17148+ && (path_noexec(h_path)
17149+ || !(h_inode->i_mode & S_IXUGO))))
17150+ goto out;
1facf9fc 17151+
0b1ff5c3
JR
17152+ /*
17153+ * - skip the lower fs test in the case of write to ro branch.
17154+ * - nfs dir permission write check is optimized, but a policy for
17155+ * link/rename requires a real check.
17156+ * - nfs always sets MS_POSIXACL regardless its mount option 'noacl.'
17157+ * in this case, generic_permission() returns -EOPNOTSUPP.
17158+ */
17159+ if ((write_mask && !au_br_writable(brperm))
17160+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
17161+ && write_mask && !(mask & MAY_READ))
17162+ || !h_inode->i_op->permission) {
17163+ /* AuLabel(generic_permission); */
17164+ /* AuDbg("get_acl %pf\n", h_inode->i_op->get_acl); */
17165+ err = generic_permission(h_inode, mask);
17166+ if (err == -EOPNOTSUPP && au_test_nfs_noacl(h_inode))
17167+ err = h_inode->i_op->permission(h_inode, mask);
17168+ AuTraceErr(err);
17169+ } else {
17170+ /* AuLabel(h_inode->permission); */
17171+ err = h_inode->i_op->permission(h_inode, mask);
17172+ AuTraceErr(err);
4a4d8108 17173+ }
521ced18 17174+
0b1ff5c3
JR
17175+ if (!err)
17176+ err = devcgroup_inode_permission(h_inode, mask);
17177+ if (!err)
17178+ err = security_inode_permission(h_inode, mask);
1308ab2a 17179+
0b1ff5c3
JR
17180+#if 0
17181+ if (!err) {
17182+ /* todo: do we need to call ima_path_check()? */
17183+ struct path h_path = {
17184+ .dentry =
17185+ .mnt = h_mnt
17186+ };
17187+ err = ima_path_check(&h_path,
17188+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
17189+ IMA_COUNT_LEAVE);
1308ab2a 17190+ }
0b1ff5c3 17191+#endif
1facf9fc 17192+
4f0767ce 17193+out:
1facf9fc 17194+ return err;
17195+}
17196+
0b1ff5c3 17197+static int aufs_permission(struct inode *inode, int mask)
1facf9fc 17198+{
0b1ff5c3
JR
17199+ int err;
17200+ aufs_bindex_t bindex, bbot;
17201+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
17202+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
17203+ struct inode *h_inode;
4a4d8108 17204+ struct super_block *sb;
0b1ff5c3 17205+ struct au_branch *br;
b752ccd1 17206+
0b1ff5c3
JR
17207+ /* todo: support rcu-walk? */
17208+ if (mask & MAY_NOT_BLOCK)
17209+ return -ECHILD;
b752ccd1 17210+
0b1ff5c3
JR
17211+ sb = inode->i_sb;
17212+ si_read_lock(sb, AuLock_FLUSH);
17213+ ii_read_lock_child(inode);
17214+#if 0
17215+ err = au_iigen_test(inode, au_sigen(sb));
4a4d8108 17216+ if (unlikely(err))
0b1ff5c3
JR
17217+ goto out;
17218+#endif
b752ccd1 17219+
0b1ff5c3
JR
17220+ if (!isdir
17221+ || write_mask
17222+ || au_opt_test(au_mntflags(sb), DIRPERM1)) {
17223+ err = au_busy_or_stale();
17224+ h_inode = au_h_iptr(inode, au_ibtop(inode));
17225+ if (unlikely(!h_inode
17226+ || (h_inode->i_mode & S_IFMT)
17227+ != (inode->i_mode & S_IFMT)))
17228+ goto out;
17229+
17230+ err = 0;
17231+ bindex = au_ibtop(inode);
17232+ br = au_sbr(sb, bindex);
17233+ err = h_permission(h_inode, mask, &br->br_path, br->br_perm);
17234+ if (write_mask
17235+ && !err
17236+ && !special_file(h_inode->i_mode)) {
17237+ /* test whether the upper writable branch exists */
17238+ err = -EROFS;
17239+ for (; bindex >= 0; bindex--)
17240+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
17241+ err = 0;
17242+ break;
17243+ }
dece6358 17244+ }
0b1ff5c3 17245+ goto out;
dece6358 17246+ }
1facf9fc 17247+
0b1ff5c3
JR
17248+ /* non-write to dir */
17249+ err = 0;
17250+ bbot = au_ibbot(inode);
17251+ for (bindex = au_ibtop(inode); !err && bindex <= bbot; bindex++) {
17252+ h_inode = au_h_iptr(inode, bindex);
17253+ if (h_inode) {
17254+ err = au_busy_or_stale();
17255+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
17256+ break;
1308ab2a 17257+
0b1ff5c3
JR
17258+ br = au_sbr(sb, bindex);
17259+ err = h_permission(h_inode, mask, &br->br_path,
17260+ br->br_perm);
521ced18 17261+ }
4a4d8108
AM
17262+ }
17263+
4f0767ce 17264+out:
0b1ff5c3
JR
17265+ ii_read_unlock(inode);
17266+ si_read_unlock(sb);
17267+ return err;
1facf9fc 17268+}
17269+
4a4d8108 17270+/* ---------------------------------------------------------------------- */
1facf9fc 17271+
0b1ff5c3
JR
17272+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
17273+ unsigned int flags)
4a4d8108 17274+{
0b1ff5c3
JR
17275+ struct dentry *ret, *parent;
17276+ struct inode *inode;
17277+ struct super_block *sb;
17278+ int err, npositive;
1facf9fc 17279+
0b1ff5c3 17280+ IMustLock(dir);
1facf9fc 17281+
0b1ff5c3
JR
17282+ /* todo: support rcu-walk? */
17283+ ret = ERR_PTR(-ECHILD);
17284+ if (flags & LOOKUP_RCU)
17285+ goto out;
17286+
17287+ ret = ERR_PTR(-ENAMETOOLONG);
17288+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
17289+ goto out;
17290+
17291+ sb = dir->i_sb;
17292+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
17293+ ret = ERR_PTR(err);
17294+ if (unlikely(err))
17295+ goto out;
17296+
17297+ err = au_di_init(dentry);
17298+ ret = ERR_PTR(err);
17299+ if (unlikely(err))
17300+ goto out_si;
17301+
17302+ inode = NULL;
17303+ npositive = 0; /* suppress a warning */
17304+ parent = dentry->d_parent; /* dir inode is locked */
17305+ di_read_lock_parent(parent, AuLock_IR);
17306+ err = au_alive_dir(parent);
17307+ if (!err)
17308+ err = au_digen_test(parent, au_sigen(sb));
17309+ if (!err) {
17310+ /* regardless LOOKUP_CREATE, always ALLOW_NEG */
17311+ npositive = au_lkup_dentry(dentry, au_dbtop(parent),
17312+ AuLkup_ALLOW_NEG);
17313+ err = npositive;
1facf9fc 17314+ }
0b1ff5c3
JR
17315+ di_read_unlock(parent, AuLock_IR);
17316+ ret = ERR_PTR(err);
17317+ if (unlikely(err < 0))
17318+ goto out_unlock;
1facf9fc 17319+
0b1ff5c3
JR
17320+ if (npositive) {
17321+ inode = au_new_inode(dentry, /*must_new*/0);
17322+ if (IS_ERR(inode)) {
17323+ ret = (void *)inode;
17324+ inode = NULL;
17325+ goto out_unlock;
17326+ }
17327+ }
dece6358 17328+
0b1ff5c3
JR
17329+ if (inode)
17330+ atomic_inc(&inode->i_count);
17331+ ret = d_splice_alias(inode, dentry);
17332+#if 0
17333+ if (unlikely(d_need_lookup(dentry))) {
17334+ spin_lock(&dentry->d_lock);
17335+ dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
17336+ spin_unlock(&dentry->d_lock);
17337+ } else
17338+#endif
17339+ if (inode) {
17340+ if (!IS_ERR(ret)) {
17341+ iput(inode);
17342+ if (ret && ret != dentry)
17343+ ii_write_unlock(inode);
17344+ } else {
17345+ ii_write_unlock(inode);
17346+ iput(inode);
17347+ inode = NULL;
17348+ }
17349+ }
1facf9fc 17350+
0b1ff5c3
JR
17351+out_unlock:
17352+ di_write_unlock(dentry);
17353+out_si:
17354+ si_read_unlock(sb);
17355+out:
17356+ return ret;
1facf9fc 17357+}
dece6358 17358+
0b1ff5c3 17359+/* ---------------------------------------------------------------------- */
dece6358 17360+
0b1ff5c3
JR
17361+struct aopen_node {
17362+ struct hlist_bl_node hblist;
17363+ struct file *file, *h_file;
17364+};
1308ab2a 17365+
0b1ff5c3
JR
17366+static int au_do_aopen(struct inode *inode, struct file *file)
17367+{
17368+ struct hlist_bl_head *aopen;
17369+ struct hlist_bl_node *pos;
17370+ struct aopen_node *node;
17371+ struct au_do_open_args args = {
17372+ .aopen = 1,
17373+ .open = au_do_open_nondir
17374+ };
1308ab2a 17375+
0b1ff5c3
JR
17376+ aopen = &au_sbi(inode->i_sb)->si_aopen;
17377+ hlist_bl_lock(aopen);
17378+ hlist_bl_for_each_entry(node, pos, aopen, hblist)
17379+ if (node->file == file) {
17380+ args.h_file = node->h_file;
17381+ break;
17382+ }
17383+ hlist_bl_unlock(aopen);
17384+ /* AuDebugOn(!args.h_file); */
1facf9fc 17385+
0b1ff5c3
JR
17386+ return au_do_open(file, &args);
17387+}
1facf9fc 17388+
0b1ff5c3
JR
17389+static int aufs_atomic_open(struct inode *dir, struct dentry *dentry,
17390+ struct file *file, unsigned int open_flag,
17391+ umode_t create_mode, int *opened)
17392+{
17393+ int err, unlocked, h_opened = *opened;
17394+ unsigned int lkup_flags;
17395+ struct dentry *parent, *d;
17396+ struct hlist_bl_head *aopen;
17397+ struct vfsub_aopen_args args = {
17398+ .open_flag = open_flag,
17399+ .create_mode = create_mode,
17400+ .opened = &h_opened
17401+ };
17402+ struct aopen_node aopen_node = {
17403+ .file = file
17404+ };
dece6358 17405+
0b1ff5c3
JR
17406+ IMustLock(dir);
17407+ AuDbg("open_flag 0%o\n", open_flag);
17408+ AuDbgDentry(dentry);
dece6358 17409+
0b1ff5c3
JR
17410+ err = 0;
17411+ if (!au_di(dentry)) {
17412+ lkup_flags = LOOKUP_OPEN;
17413+ if (open_flag & O_CREAT)
17414+ lkup_flags |= LOOKUP_CREATE;
17415+ d = aufs_lookup(dir, dentry, lkup_flags);
17416+ if (IS_ERR(d)) {
17417+ err = PTR_ERR(d);
17418+ AuTraceErr(err);
17419+ goto out;
17420+ } else if (d) {
17421+ /*
17422+ * obsoleted dentry found.
17423+ * another error will be returned later.
17424+ */
17425+ d_drop(d);
17426+ AuDbgDentry(d);
17427+ dput(d);
17428+ }
17429+ AuDbgDentry(dentry);
17430+ }
537831f9 17431+
0b1ff5c3
JR
17432+ if (d_is_positive(dentry)
17433+ || d_unhashed(dentry)
17434+ || d_unlinked(dentry)
17435+ || !(open_flag & O_CREAT))
17436+ goto out_no_open;
537831f9 17437+
0b1ff5c3
JR
17438+ unlocked = 0;
17439+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
17440+ if (unlikely(err))
17441+ goto out;
1facf9fc 17442+
0b1ff5c3
JR
17443+ parent = dentry->d_parent; /* dir is locked */
17444+ di_write_lock_parent(parent);
17445+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG);
17446+ if (unlikely(err))
17447+ goto out_unlock;
1facf9fc 17448+
0b1ff5c3
JR
17449+ AuDbgDentry(dentry);
17450+ if (d_is_positive(dentry))
17451+ goto out_unlock;
1308ab2a 17452+
0b1ff5c3
JR
17453+ args.file = get_empty_filp();
17454+ err = PTR_ERR(args.file);
17455+ if (IS_ERR(args.file))
17456+ goto out_unlock;
4a4d8108 17457+
0b1ff5c3
JR
17458+ args.file->f_flags = file->f_flags;
17459+ err = au_aopen_or_create(dir, dentry, &args);
17460+ AuTraceErr(err);
17461+ AuDbgFile(args.file);
17462+ if (unlikely(err < 0)) {
17463+ if (h_opened & FILE_OPENED)
17464+ fput(args.file);
17465+ else
17466+ put_filp(args.file);
17467+ goto out_unlock;
17468+ }
17469+ di_write_unlock(parent);
17470+ di_write_unlock(dentry);
17471+ unlocked = 1;
4a4d8108 17472+
0b1ff5c3
JR
17473+ /* some filesystems don't set FILE_CREATED while succeeded? */
17474+ *opened |= FILE_CREATED;
17475+ if (h_opened & FILE_OPENED)
17476+ aopen_node.h_file = args.file;
17477+ else {
17478+ put_filp(args.file);
17479+ args.file = NULL;
17480+ }
17481+ aopen = &au_sbi(dir->i_sb)->si_aopen;
17482+ au_hbl_add(&aopen_node.hblist, aopen);
17483+ err = finish_open(file, dentry, au_do_aopen, opened);
17484+ au_hbl_del(&aopen_node.hblist, aopen);
17485+ AuTraceErr(err);
17486+ AuDbgFile(file);
17487+ if (aopen_node.h_file)
17488+ fput(aopen_node.h_file);
86dc4139 17489+
0b1ff5c3
JR
17490+out_unlock:
17491+ if (unlocked)
17492+ si_read_unlock(dentry->d_sb);
17493+ else {
17494+ di_write_unlock(parent);
17495+ aufs_read_unlock(dentry, AuLock_DW);
17496+ }
17497+ AuDbgDentry(dentry);
17498+ if (unlikely(err < 0))
17499+ goto out;
17500+out_no_open:
17501+ if (err >= 0 && !(*opened & FILE_CREATED)) {
17502+ AuLabel(out_no_open);
17503+ dget(dentry);
17504+ err = finish_no_open(file, dentry);
17505+ }
17506+out:
17507+ AuDbg("%pd%s%s\n", dentry,
17508+ (*opened & FILE_CREATED) ? " created" : "",
17509+ (*opened & FILE_OPENED) ? " opened" : "");
17510+ AuTraceErr(err);
17511+ return err;
17512+}
1facf9fc 17513+
86dc4139 17514+
1308ab2a 17515+/* ---------------------------------------------------------------------- */
17516+
0b1ff5c3
JR
17517+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
17518+ const unsigned char add_entry, aufs_bindex_t bcpup,
17519+ aufs_bindex_t btop)
1facf9fc 17520+{
0b1ff5c3
JR
17521+ int err;
17522+ struct dentry *h_parent;
17523+ struct inode *h_dir;
1facf9fc 17524+
0b1ff5c3
JR
17525+ if (add_entry)
17526+ IMustLock(d_inode(parent));
17527+ else
17528+ di_write_lock_parent(parent);
1facf9fc 17529+
0b1ff5c3
JR
17530+ err = 0;
17531+ if (!au_h_dptr(parent, bcpup)) {
17532+ if (btop > bcpup)
17533+ err = au_cpup_dirs(dentry, bcpup);
17534+ else if (btop < bcpup)
17535+ err = au_cpdown_dirs(dentry, bcpup);
17536+ else
17537+ BUG();
17538+ }
17539+ if (!err && add_entry && !au_ftest_wrdir(add_entry, TMPFILE)) {
17540+ h_parent = au_h_dptr(parent, bcpup);
17541+ h_dir = d_inode(h_parent);
17542+ vfsub_inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
17543+ err = au_lkup_neg(dentry, bcpup, /*wh*/0);
17544+ /* todo: no unlock here */
17545+ inode_unlock_shared(h_dir);
1facf9fc 17546+
0b1ff5c3
JR
17547+ AuDbg("bcpup %d\n", bcpup);
17548+ if (!err) {
17549+ if (d_really_is_negative(dentry))
17550+ au_set_h_dptr(dentry, btop, NULL);
17551+ au_update_dbrange(dentry, /*do_put_zero*/0);
17552+ }
17553+ }
1facf9fc 17554+
0b1ff5c3
JR
17555+ if (!add_entry)
17556+ di_write_unlock(parent);
17557+ if (!err)
17558+ err = bcpup; /* success */
1308ab2a 17559+
0b1ff5c3
JR
17560+ AuTraceErr(err);
17561+ return err;
17562+}
1facf9fc 17563+
0b1ff5c3
JR
17564+/*
17565+ * decide the branch and the parent dir where we will create a new entry.
17566+ * returns new bindex or an error.
17567+ * copyup the parent dir if needed.
17568+ */
4a4d8108 17569+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
0b1ff5c3
JR
17570+ struct au_wr_dir_args *args)
17571+{
17572+ int err;
17573+ unsigned int flags;
17574+ aufs_bindex_t bcpup, btop, src_btop;
17575+ const unsigned char add_entry
17576+ = au_ftest_wrdir(args->flags, ADD_ENTRY)
17577+ | au_ftest_wrdir(args->flags, TMPFILE);
17578+ struct super_block *sb;
17579+ struct dentry *parent;
17580+ struct au_sbinfo *sbinfo;
c1595e42 17581+
0b1ff5c3
JR
17582+ sb = dentry->d_sb;
17583+ sbinfo = au_sbi(sb);
17584+ parent = dget_parent(dentry);
17585+ btop = au_dbtop(dentry);
17586+ bcpup = btop;
17587+ if (args->force_btgt < 0) {
17588+ if (src_dentry) {
17589+ src_btop = au_dbtop(src_dentry);
17590+ if (src_btop < btop)
17591+ bcpup = src_btop;
17592+ } else if (add_entry) {
17593+ flags = 0;
17594+ if (au_ftest_wrdir(args->flags, ISDIR))
17595+ au_fset_wbr(flags, DIR);
17596+ err = AuWbrCreate(sbinfo, dentry, flags);
17597+ bcpup = err;
17598+ }
c1595e42 17599+
0b1ff5c3
JR
17600+ if (bcpup < 0 || au_test_ro(sb, bcpup, d_inode(dentry))) {
17601+ if (add_entry)
17602+ err = AuWbrCopyup(sbinfo, dentry);
17603+ else {
17604+ if (!IS_ROOT(dentry)) {
17605+ di_read_lock_parent(parent, !AuLock_IR);
17606+ err = AuWbrCopyup(sbinfo, dentry);
17607+ di_read_unlock(parent, !AuLock_IR);
17608+ } else
17609+ err = AuWbrCopyup(sbinfo, dentry);
17610+ }
17611+ bcpup = err;
17612+ if (unlikely(err < 0))
17613+ goto out;
17614+ }
17615+ } else {
17616+ bcpup = args->force_btgt;
17617+ AuDebugOn(au_test_ro(sb, bcpup, d_inode(dentry)));
17618+ }
c1595e42 17619+
0b1ff5c3
JR
17620+ AuDbg("btop %d, bcpup %d\n", btop, bcpup);
17621+ err = bcpup;
17622+ if (bcpup == btop)
17623+ goto out; /* success */
c1595e42 17624+
0b1ff5c3
JR
17625+ /* copyup the new parent into the branch we process */
17626+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, btop);
17627+ if (err >= 0) {
17628+ if (d_really_is_negative(dentry)) {
17629+ au_set_h_dptr(dentry, btop, NULL);
17630+ au_set_dbtop(dentry, bcpup);
17631+ au_set_dbbot(dentry, bcpup);
17632+ }
17633+ AuDebugOn(add_entry
17634+ && !au_ftest_wrdir(args->flags, TMPFILE)
17635+ && !au_h_dptr(dentry, bcpup));
17636+ }
1facf9fc 17637+
0b1ff5c3
JR
17638+out:
17639+ dput(parent);
17640+ return err;
17641+}
1facf9fc 17642+
0b1ff5c3 17643+/* ---------------------------------------------------------------------- */
1308ab2a 17644+
0b1ff5c3
JR
17645+void au_pin_hdir_unlock(struct au_pin *p)
17646+{
17647+ if (p->hdir)
17648+ au_hn_inode_unlock(p->hdir);
17649+}
1facf9fc 17650+
0b1ff5c3
JR
17651+int au_pin_hdir_lock(struct au_pin *p)
17652+{
17653+ int err;
1308ab2a 17654+
0b1ff5c3
JR
17655+ err = 0;
17656+ if (!p->hdir)
17657+ goto out;
1facf9fc 17658+
0b1ff5c3
JR
17659+ /* even if an error happens later, keep this lock */
17660+ au_hn_inode_lock_nested(p->hdir, p->lsc_hi);
1facf9fc 17661+
0b1ff5c3
JR
17662+ err = -EBUSY;
17663+ if (unlikely(p->hdir->hi_inode != d_inode(p->h_parent)))
17664+ goto out;
1facf9fc 17665+
0b1ff5c3
JR
17666+ err = 0;
17667+ if (p->h_dentry)
17668+ err = au_h_verify(p->h_dentry, p->udba, p->hdir->hi_inode,
17669+ p->h_parent, p->br);
1facf9fc 17670+
0b1ff5c3
JR
17671+out:
17672+ return err;
17673+}
1308ab2a 17674+
0b1ff5c3
JR
17675+int au_pin_hdir_relock(struct au_pin *p)
17676+{
17677+ int err, i;
17678+ struct inode *h_i;
17679+ struct dentry *h_d[] = {
17680+ p->h_dentry,
17681+ p->h_parent
17682+ };
1facf9fc 17683+
0b1ff5c3
JR
17684+ err = au_pin_hdir_lock(p);
17685+ if (unlikely(err))
17686+ goto out;
c1595e42 17687+
0b1ff5c3
JR
17688+ for (i = 0; !err && i < sizeof(h_d)/sizeof(*h_d); i++) {
17689+ if (!h_d[i])
17690+ continue;
17691+ if (d_is_positive(h_d[i])) {
17692+ h_i = d_inode(h_d[i]);
17693+ err = !h_i->i_nlink;
17694+ }
17695+ }
c1595e42 17696+
0b1ff5c3
JR
17697+out:
17698+ return err;
17699+}
c1595e42 17700+
0b1ff5c3
JR
17701+static void au_pin_hdir_set_owner(struct au_pin *p, struct task_struct *task)
17702+{
17703+#if !defined(CONFIG_RWSEM_GENERIC_SPINLOCK) && defined(CONFIG_RWSEM_SPIN_ON_OWNER)
17704+ p->hdir->hi_inode->i_rwsem.owner = task;
c1595e42 17705+#endif
0b1ff5c3 17706+}
c1595e42 17707+
0b1ff5c3
JR
17708+void au_pin_hdir_acquire_nest(struct au_pin *p)
17709+{
17710+ if (p->hdir) {
17711+ rwsem_acquire_nest(&p->hdir->hi_inode->i_rwsem.dep_map,
17712+ p->lsc_hi, 0, NULL, _RET_IP_);
17713+ au_pin_hdir_set_owner(p, current);
17714+ }
17715+}
1308ab2a 17716+
0b1ff5c3
JR
17717+void au_pin_hdir_release(struct au_pin *p)
17718+{
17719+ if (p->hdir) {
17720+ au_pin_hdir_set_owner(p, p->task);
17721+ rwsem_release(&p->hdir->hi_inode->i_rwsem.dep_map, 1, _RET_IP_);
17722+ }
17723+}
1308ab2a 17724+
0b1ff5c3
JR
17725+struct dentry *au_pinned_h_parent(struct au_pin *pin)
17726+{
17727+ if (pin && pin->parent)
17728+ return au_h_dptr(pin->parent, pin->bindex);
17729+ return NULL;
4a4d8108
AM
17730+}
17731+
0b1ff5c3
JR
17732+void au_unpin(struct au_pin *p)
17733+{
17734+ if (p->hdir)
17735+ au_pin_hdir_unlock(p);
17736+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
17737+ vfsub_mnt_drop_write(p->h_mnt);
17738+ if (!p->hdir)
17739+ return;
17740+
17741+ if (!au_ftest_pin(p->flags, DI_LOCKED))
17742+ di_read_unlock(p->parent, AuLock_IR);
17743+ iput(p->hdir->hi_inode);
17744+ dput(p->parent);
17745+ p->parent = NULL;
17746+ p->hdir = NULL;
17747+ p->h_mnt = NULL;
17748+ /* do not clear p->task */
4a4d8108
AM
17749+}
17750+
0b1ff5c3
JR
17751+int au_do_pin(struct au_pin *p)
17752+{
17753+ int err;
17754+ struct super_block *sb;
17755+ struct inode *h_dir;
4a4d8108 17756+
0b1ff5c3
JR
17757+ err = 0;
17758+ sb = p->dentry->d_sb;
17759+ p->br = au_sbr(sb, p->bindex);
17760+ if (IS_ROOT(p->dentry)) {
17761+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
17762+ p->h_mnt = au_br_mnt(p->br);
17763+ err = vfsub_mnt_want_write(p->h_mnt);
17764+ if (unlikely(err)) {
17765+ au_fclr_pin(p->flags, MNT_WRITE);
17766+ goto out_err;
17767+ }
17768+ }
17769+ goto out;
17770+ }
4a4d8108 17771+
0b1ff5c3
JR
17772+ p->h_dentry = NULL;
17773+ if (p->bindex <= au_dbbot(p->dentry))
17774+ p->h_dentry = au_h_dptr(p->dentry, p->bindex);
1facf9fc 17775+
0b1ff5c3
JR
17776+ p->parent = dget_parent(p->dentry);
17777+ if (!au_ftest_pin(p->flags, DI_LOCKED))
17778+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
1facf9fc 17779+
0b1ff5c3
JR
17780+ h_dir = NULL;
17781+ p->h_parent = au_h_dptr(p->parent, p->bindex);
17782+ p->hdir = au_hi(d_inode(p->parent), p->bindex);
17783+ if (p->hdir)
17784+ h_dir = p->hdir->hi_inode;
1facf9fc 17785+
0b1ff5c3
JR
17786+ /*
17787+ * udba case, or
17788+ * if DI_LOCKED is not set, then p->parent may be different
17789+ * and h_parent can be NULL.
17790+ */
17791+ if (unlikely(!p->hdir || !h_dir || !p->h_parent)) {
17792+ err = -EBUSY;
17793+ if (!au_ftest_pin(p->flags, DI_LOCKED))
17794+ di_read_unlock(p->parent, AuLock_IR);
17795+ dput(p->parent);
17796+ p->parent = NULL;
17797+ goto out_err;
17798+ }
1308ab2a 17799+
0b1ff5c3
JR
17800+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
17801+ p->h_mnt = au_br_mnt(p->br);
17802+ err = vfsub_mnt_want_write(p->h_mnt);
17803+ if (unlikely(err)) {
17804+ au_fclr_pin(p->flags, MNT_WRITE);
17805+ if (!au_ftest_pin(p->flags, DI_LOCKED))
17806+ di_read_unlock(p->parent, AuLock_IR);
17807+ dput(p->parent);
17808+ p->parent = NULL;
17809+ goto out_err;
17810+ }
17811+ }
17812+
17813+ au_igrab(h_dir);
17814+ err = au_pin_hdir_lock(p);
17815+ if (!err)
17816+ goto out; /* success */
17817+
17818+ au_unpin(p);
17819+
17820+out_err:
17821+ pr_err("err %d\n", err);
17822+ err = au_busy_or_stale();
17823+out:
17824+ return err;
027c5e7a
AM
17825+}
17826+
0b1ff5c3
JR
17827+void au_pin_init(struct au_pin *p, struct dentry *dentry,
17828+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
17829+ unsigned int udba, unsigned char flags)
4a4d8108 17830+{
0b1ff5c3
JR
17831+ p->dentry = dentry;
17832+ p->udba = udba;
17833+ p->lsc_di = lsc_di;
17834+ p->lsc_hi = lsc_hi;
17835+ p->flags = flags;
17836+ p->bindex = bindex;
537831f9 17837+
0b1ff5c3
JR
17838+ p->parent = NULL;
17839+ p->hdir = NULL;
17840+ p->h_mnt = NULL;
537831f9 17841+
0b1ff5c3
JR
17842+ p->h_dentry = NULL;
17843+ p->h_parent = NULL;
17844+ p->br = NULL;
17845+ p->task = current;
4a4d8108 17846+}
1308ab2a 17847+
0b1ff5c3
JR
17848+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
17849+ unsigned int udba, unsigned char flags)
4a4d8108 17850+{
0b1ff5c3
JR
17851+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
17852+ udba, flags);
17853+ return au_do_pin(pin);
17854+}
1308ab2a 17855+
0b1ff5c3
JR
17856+/* ---------------------------------------------------------------------- */
17857+
17858+/*
17859+ * ->setattr() and ->getattr() are called in various cases.
17860+ * chmod, stat: dentry is revalidated.
17861+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
17862+ * unhashed.
17863+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
17864+ */
17865+/* todo: consolidate with do_refresh() and simple_reval_dpath() */
17866+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
17867+{
17868+ int err;
17869+ struct dentry *parent;
17870+
17871+ err = 0;
17872+ if (au_digen_test(dentry, sigen)) {
17873+ parent = dget_parent(dentry);
17874+ di_read_lock_parent(parent, AuLock_IR);
17875+ err = au_refresh_dentry(dentry, parent);
17876+ di_read_unlock(parent, AuLock_IR);
17877+ dput(parent);
17878+ }
17879+
17880+ AuTraceErr(err);
17881+ return err;
4a4d8108 17882+}
1308ab2a 17883+
0b1ff5c3
JR
17884+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
17885+ struct au_icpup_args *a)
4a4d8108 17886+{
0b1ff5c3
JR
17887+ int err;
17888+ loff_t sz;
17889+ aufs_bindex_t btop, ibtop;
17890+ struct dentry *hi_wh, *parent;
17891+ struct inode *inode;
17892+ struct au_wr_dir_args wr_dir_args = {
17893+ .force_btgt = -1,
17894+ .flags = 0
17895+ };
17896+
17897+ if (d_is_dir(dentry))
17898+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
17899+ /* plink or hi_wh() case */
17900+ btop = au_dbtop(dentry);
17901+ inode = d_inode(dentry);
17902+ ibtop = au_ibtop(inode);
17903+ if (btop != ibtop && !au_test_ro(inode->i_sb, ibtop, inode))
17904+ wr_dir_args.force_btgt = ibtop;
17905+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
17906+ if (unlikely(err < 0))
17907+ goto out;
17908+ a->btgt = err;
17909+ if (err != btop)
17910+ au_fset_icpup(a->flags, DID_CPUP);
17911+
17912+ err = 0;
17913+ a->pin_flags = AuPin_MNT_WRITE;
17914+ parent = NULL;
17915+ if (!IS_ROOT(dentry)) {
17916+ au_fset_pin(a->pin_flags, DI_LOCKED);
17917+ parent = dget_parent(dentry);
17918+ di_write_lock_parent(parent);
17919+ }
17920+
17921+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
17922+ if (unlikely(err))
17923+ goto out_parent;
17924+
17925+ sz = -1;
17926+ a->h_path.dentry = au_h_dptr(dentry, btop);
17927+ a->h_inode = d_inode(a->h_path.dentry);
17928+ if (ia && (ia->ia_valid & ATTR_SIZE)) {
17929+ vfsub_inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD);
17930+ if (ia->ia_size < i_size_read(a->h_inode))
17931+ sz = ia->ia_size;
17932+ inode_unlock_shared(a->h_inode);
17933+ }
17934+
17935+ hi_wh = NULL;
17936+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
17937+ hi_wh = au_hi_wh(inode, a->btgt);
17938+ if (!hi_wh) {
17939+ struct au_cp_generic cpg = {
17940+ .dentry = dentry,
17941+ .bdst = a->btgt,
17942+ .bsrc = -1,
17943+ .len = sz,
17944+ .pin = &a->pin
17945+ };
17946+ err = au_sio_cpup_wh(&cpg, /*file*/NULL);
17947+ if (unlikely(err))
17948+ goto out_unlock;
17949+ hi_wh = au_hi_wh(inode, a->btgt);
17950+ /* todo: revalidate hi_wh? */
17951+ }
17952+ }
17953+
17954+ if (parent) {
17955+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
17956+ di_downgrade_lock(parent, AuLock_IR);
17957+ dput(parent);
17958+ parent = NULL;
17959+ }
17960+ if (!au_ftest_icpup(a->flags, DID_CPUP))
17961+ goto out; /* success */
17962+
17963+ if (!d_unhashed(dentry)) {
17964+ struct au_cp_generic cpg = {
17965+ .dentry = dentry,
17966+ .bdst = a->btgt,
17967+ .bsrc = btop,
17968+ .len = sz,
17969+ .pin = &a->pin,
17970+ .flags = AuCpup_DTIME | AuCpup_HOPEN
17971+ };
17972+ err = au_sio_cpup_simple(&cpg);
17973+ if (!err)
17974+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
17975+ } else if (!hi_wh)
17976+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
17977+ else
17978+ a->h_path.dentry = hi_wh; /* do not dget here */
537831f9 17979+
0b1ff5c3
JR
17980+out_unlock:
17981+ a->h_inode = d_inode(a->h_path.dentry);
17982+ if (!err)
17983+ goto out; /* success */
17984+ au_unpin(&a->pin);
17985+out_parent:
17986+ if (parent) {
17987+ di_write_unlock(parent);
17988+ dput(parent);
17989+ }
17990+out:
17991+ if (!err)
17992+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD);
17993+ return err;
027c5e7a
AM
17994+}
17995+
0b1ff5c3 17996+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
027c5e7a
AM
17997+{
17998+ int err;
0b1ff5c3
JR
17999+ struct inode *inode, *delegated;
18000+ struct super_block *sb;
18001+ struct file *file;
18002+ struct au_icpup_args *a;
027c5e7a 18003+
0b1ff5c3
JR
18004+ inode = d_inode(dentry);
18005+ IMustLock(inode);
027c5e7a 18006+
0b1ff5c3
JR
18007+ err = setattr_prepare(dentry, ia);
18008+ if (unlikely(err))
18009+ goto out;
1308ab2a 18010+
0b1ff5c3
JR
18011+ err = -ENOMEM;
18012+ a = kzalloc(sizeof(*a), GFP_NOFS);
18013+ if (unlikely(!a))
18014+ goto out;
1308ab2a 18015+
0b1ff5c3
JR
18016+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
18017+ ia->ia_valid &= ~ATTR_MODE;
5afbbe0d 18018+
0b1ff5c3
JR
18019+ file = NULL;
18020+ sb = dentry->d_sb;
18021+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
18022+ if (unlikely(err))
18023+ goto out_kfree;
5afbbe0d 18024+
0b1ff5c3
JR
18025+ if (ia->ia_valid & ATTR_FILE) {
18026+ /* currently ftruncate(2) only */
18027+ AuDebugOn(!d_is_reg(dentry));
18028+ file = ia->ia_file;
18029+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1,
18030+ /*fi_lsc*/0);
18031+ if (unlikely(err))
18032+ goto out_si;
18033+ ia->ia_file = au_hf_top(file);
18034+ a->udba = AuOpt_UDBA_NONE;
18035+ } else {
18036+ /* fchmod() doesn't pass ia_file */
18037+ a->udba = au_opt_udba(sb);
18038+ di_write_lock_child(dentry);
18039+ /* no d_unlinked(), to set UDBA_NONE for root */
18040+ if (d_unhashed(dentry))
18041+ a->udba = AuOpt_UDBA_NONE;
18042+ if (a->udba != AuOpt_UDBA_NONE) {
18043+ AuDebugOn(IS_ROOT(dentry));
18044+ err = au_reval_for_attr(dentry, au_sigen(sb));
18045+ if (unlikely(err))
18046+ goto out_dentry;
18047+ }
18048+ }
1308ab2a 18049+
0b1ff5c3
JR
18050+ err = au_pin_and_icpup(dentry, ia, a);
18051+ if (unlikely(err < 0))
18052+ goto out_dentry;
18053+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
18054+ ia->ia_file = NULL;
18055+ ia->ia_valid &= ~ATTR_FILE;
18056+ }
1308ab2a 18057+
0b1ff5c3
JR
18058+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
18059+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
18060+ == (ATTR_MODE | ATTR_CTIME)) {
18061+ err = security_path_chmod(&a->h_path, ia->ia_mode);
18062+ if (unlikely(err))
18063+ goto out_unlock;
18064+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
18065+ && (ia->ia_valid & ATTR_CTIME)) {
18066+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
18067+ if (unlikely(err))
18068+ goto out_unlock;
18069+ }
1308ab2a 18070+
0b1ff5c3
JR
18071+ if (ia->ia_valid & ATTR_SIZE) {
18072+ struct file *f;
1308ab2a 18073+
0b1ff5c3
JR
18074+ if (ia->ia_size < i_size_read(inode))
18075+ /* unmap only */
18076+ truncate_setsize(inode, ia->ia_size);
1308ab2a 18077+
0b1ff5c3
JR
18078+ f = NULL;
18079+ if (ia->ia_valid & ATTR_FILE)
18080+ f = ia->ia_file;
18081+ inode_unlock(a->h_inode);
18082+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
18083+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD);
18084+ } else {
18085+ delegated = NULL;
18086+ while (1) {
18087+ err = vfsub_notify_change(&a->h_path, ia, &delegated);
18088+ if (delegated) {
18089+ err = break_deleg_wait(&delegated);
18090+ if (!err)
18091+ continue;
18092+ }
18093+ break;
18094+ }
18095+ }
18096+ /*
18097+ * regardless aufs 'acl' option setting.
18098+ * why don't all acl-aware fs call this func from their ->setattr()?
18099+ */
18100+ if (!err && (ia->ia_valid & ATTR_MODE))
18101+ err = vfsub_acl_chmod(a->h_inode, ia->ia_mode);
18102+ if (!err)
18103+ au_cpup_attr_changeable(inode);
1308ab2a 18104+
0b1ff5c3
JR
18105+out_unlock:
18106+ inode_unlock(a->h_inode);
18107+ au_unpin(&a->pin);
18108+ if (unlikely(err))
18109+ au_update_dbtop(dentry);
18110+out_dentry:
18111+ di_write_unlock(dentry);
18112+ if (file) {
18113+ fi_write_unlock(file);
18114+ ia->ia_file = file;
18115+ ia->ia_valid |= ATTR_FILE;
18116+ }
18117+out_si:
18118+ si_read_unlock(sb);
18119+out_kfree:
18120+ kfree(a);
18121+out:
18122+ AuTraceErr(err);
18123+ return err;
1308ab2a 18124+}
18125+
0b1ff5c3
JR
18126+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
18127+static int au_h_path_to_set_attr(struct dentry *dentry,
18128+ struct au_icpup_args *a, struct path *h_path)
4a4d8108 18129+{
0b1ff5c3
JR
18130+ int err;
18131+ struct super_block *sb;
1facf9fc 18132+
0b1ff5c3
JR
18133+ sb = dentry->d_sb;
18134+ a->udba = au_opt_udba(sb);
18135+ /* no d_unlinked(), to set UDBA_NONE for root */
18136+ if (d_unhashed(dentry))
18137+ a->udba = AuOpt_UDBA_NONE;
18138+ if (a->udba != AuOpt_UDBA_NONE) {
18139+ AuDebugOn(IS_ROOT(dentry));
18140+ err = au_reval_for_attr(dentry, au_sigen(sb));
18141+ if (unlikely(err))
18142+ goto out;
18143+ }
18144+ err = au_pin_and_icpup(dentry, /*ia*/NULL, a);
18145+ if (unlikely(err < 0))
18146+ goto out;
dece6358 18147+
0b1ff5c3
JR
18148+ h_path->dentry = a->h_path.dentry;
18149+ h_path->mnt = au_sbr_mnt(sb, a->btgt);
1facf9fc 18150+
0b1ff5c3
JR
18151+out:
18152+ return err;
1facf9fc 18153+}
18154+
0b1ff5c3
JR
18155+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode,
18156+ struct au_sxattr *arg)
1facf9fc 18157+{
0b1ff5c3
JR
18158+ int err;
18159+ struct path h_path;
18160+ struct super_block *sb;
18161+ struct au_icpup_args *a;
18162+ struct inode *h_inode;
1facf9fc 18163+
0b1ff5c3 18164+ IMustLock(inode);
1facf9fc 18165+
0b1ff5c3
JR
18166+ err = -ENOMEM;
18167+ a = kzalloc(sizeof(*a), GFP_NOFS);
18168+ if (unlikely(!a))
18169+ goto out;
1308ab2a 18170+
0b1ff5c3
JR
18171+ sb = dentry->d_sb;
18172+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
18173+ if (unlikely(err))
18174+ goto out_kfree;
4a4d8108 18175+
0b1ff5c3
JR
18176+ h_path.dentry = NULL; /* silence gcc */
18177+ di_write_lock_child(dentry);
18178+ err = au_h_path_to_set_attr(dentry, a, &h_path);
18179+ if (unlikely(err))
18180+ goto out_di;
18181+
18182+ inode_unlock(a->h_inode);
18183+ switch (arg->type) {
18184+ case AU_XATTR_SET:
18185+ AuDebugOn(d_is_negative(h_path.dentry));
18186+ err = vfsub_setxattr(h_path.dentry,
18187+ arg->u.set.name, arg->u.set.value,
18188+ arg->u.set.size, arg->u.set.flags);
18189+ break;
18190+ case AU_ACL_SET:
18191+ err = -EOPNOTSUPP;
18192+ h_inode = d_inode(h_path.dentry);
18193+ if (h_inode->i_op->set_acl)
18194+ /* this will call posix_acl_update_mode */
18195+ err = h_inode->i_op->set_acl(h_inode,
18196+ arg->u.acl_set.acl,
18197+ arg->u.acl_set.type);
18198+ break;
1facf9fc 18199+ }
0b1ff5c3
JR
18200+ if (!err)
18201+ au_cpup_attr_timesizes(inode);
18202+
18203+ au_unpin(&a->pin);
18204+ if (unlikely(err))
18205+ au_update_dbtop(dentry);
18206+
18207+out_di:
18208+ di_write_unlock(dentry);
18209+ si_read_unlock(sb);
18210+out_kfree:
18211+ kfree(a);
18212+out:
18213+ AuTraceErr(err);
18214+ return err;
4a4d8108 18215+}
7e9cd9fe 18216+#endif
1facf9fc 18217+
0b1ff5c3
JR
18218+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
18219+ unsigned int nlink)
18220+{
18221+ unsigned int n;
4a4d8108 18222+
0b1ff5c3
JR
18223+ inode->i_mode = st->mode;
18224+ /* don't i_[ug]id_write() here */
18225+ inode->i_uid = st->uid;
18226+ inode->i_gid = st->gid;
18227+ inode->i_atime = st->atime;
18228+ inode->i_mtime = st->mtime;
18229+ inode->i_ctime = st->ctime;
7eafdf33 18230+
0b1ff5c3
JR
18231+ au_cpup_attr_nlink(inode, /*force*/0);
18232+ if (S_ISDIR(inode->i_mode)) {
18233+ n = inode->i_nlink;
18234+ n -= nlink;
18235+ n += st->nlink;
18236+ smp_mb(); /* for i_nlink */
18237+ /* 0 can happen */
18238+ set_nlink(inode, n);
18239+ }
4a4d8108 18240+
0b1ff5c3
JR
18241+ spin_lock(&inode->i_lock);
18242+ inode->i_blocks = st->blocks;
18243+ i_size_write(inode, st->size);
18244+ spin_unlock(&inode->i_lock);
18245+}
027c5e7a 18246+
0b1ff5c3
JR
18247+/*
18248+ * common routine for aufs_getattr() and au_getxattr().
18249+ * returns zero or negative (an error).
18250+ * @dentry will be read-locked in success.
18251+ */
18252+int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path,
18253+ int locked)
18254+{
18255+ int err;
18256+ unsigned int mnt_flags, sigen;
18257+ unsigned char udba_none;
18258+ aufs_bindex_t bindex;
18259+ struct super_block *sb, *h_sb;
18260+ struct inode *inode;
4a4d8108 18261+
0b1ff5c3
JR
18262+ h_path->mnt = NULL;
18263+ h_path->dentry = NULL;
4a4d8108 18264+
0b1ff5c3
JR
18265+ err = 0;
18266+ sb = dentry->d_sb;
18267+ mnt_flags = au_mntflags(sb);
18268+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
4a4d8108 18269+
0b1ff5c3
JR
18270+ if (unlikely(locked))
18271+ goto body; /* skip locking dinfo */
1308ab2a 18272+
0b1ff5c3
JR
18273+ /* support fstat(2) */
18274+ if (!d_unlinked(dentry) && !udba_none) {
18275+ sigen = au_sigen(sb);
18276+ err = au_digen_test(dentry, sigen);
18277+ if (!err) {
18278+ di_read_lock_child(dentry, AuLock_IR);
18279+ err = au_dbrange_test(dentry);
18280+ if (unlikely(err)) {
18281+ di_read_unlock(dentry, AuLock_IR);
18282+ goto out;
18283+ }
18284+ } else {
18285+ AuDebugOn(IS_ROOT(dentry));
18286+ di_write_lock_child(dentry);
18287+ err = au_dbrange_test(dentry);
18288+ if (!err)
18289+ err = au_reval_for_attr(dentry, sigen);
18290+ if (!err)
18291+ di_downgrade_lock(dentry, AuLock_IR);
18292+ else {
18293+ di_write_unlock(dentry);
18294+ goto out;
18295+ }
18296+ }
18297+ } else
18298+ di_read_lock_child(dentry, AuLock_IR);
53392da6 18299+
0b1ff5c3
JR
18300+body:
18301+ inode = d_inode(dentry);
18302+ bindex = au_ibtop(inode);
18303+ h_path->mnt = au_sbr_mnt(sb, bindex);
18304+ h_sb = h_path->mnt->mnt_sb;
18305+ if (!force
18306+ && !au_test_fs_bad_iattr(h_sb)
18307+ && udba_none)
18308+ goto out; /* success */
4a4d8108 18309+
0b1ff5c3
JR
18310+ if (au_dbtop(dentry) == bindex)
18311+ h_path->dentry = au_h_dptr(dentry, bindex);
18312+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
18313+ h_path->dentry = au_plink_lkup(inode, bindex);
18314+ if (IS_ERR(h_path->dentry))
18315+ /* pretending success */
18316+ h_path->dentry = NULL;
18317+ else
18318+ dput(h_path->dentry);
18319+ }
1308ab2a 18320+
0b1ff5c3
JR
18321+out:
18322+ return err;
4a4d8108 18323+}
1308ab2a 18324+
0b1ff5c3
JR
18325+static int aufs_getattr(const struct path *path, struct kstat *st,
18326+ u32 request, unsigned int query)
4a4d8108 18327+{
0b1ff5c3
JR
18328+ int err;
18329+ unsigned char positive;
18330+ struct path h_path;
18331+ struct dentry *dentry;
18332+ struct inode *inode;
18333+ struct super_block *sb;
dece6358 18334+
0b1ff5c3
JR
18335+ dentry = path->dentry;
18336+ inode = d_inode(dentry);
18337+ sb = dentry->d_sb;
18338+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
18339+ if (unlikely(err))
18340+ goto out;
18341+ err = au_h_path_getattr(dentry, /*force*/0, &h_path, /*locked*/0);
18342+ if (unlikely(err))
18343+ goto out_si;
18344+ if (unlikely(!h_path.dentry))
18345+ /* illegally overlapped or something */
18346+ goto out_fill; /* pretending success */
1facf9fc 18347+
0b1ff5c3
JR
18348+ positive = d_is_positive(h_path.dentry);
18349+ if (positive)
18350+ /* no vfsub version */
18351+ err = vfs_getattr(&h_path, st, request, query);
18352+ if (!err) {
18353+ if (positive)
18354+ au_refresh_iattr(inode, st,
18355+ d_inode(h_path.dentry)->i_nlink);
18356+ goto out_fill; /* success */
18357+ }
18358+ AuTraceErr(err);
18359+ goto out_di;
3c1bdaff 18360+
0b1ff5c3
JR
18361+out_fill:
18362+ generic_fillattr(inode, st);
18363+out_di:
18364+ di_read_unlock(dentry, AuLock_IR);
18365+out_si:
18366+ si_read_unlock(sb);
18367+out:
18368+ AuTraceErr(err);
18369+ return err;
4a4d8108
AM
18370+}
18371+
0b1ff5c3 18372+/* ---------------------------------------------------------------------- */
4a4d8108 18373+
0b1ff5c3
JR
18374+static const char *aufs_get_link(struct dentry *dentry, struct inode *inode,
18375+ struct delayed_call *done)
4a4d8108 18376+{
0b1ff5c3
JR
18377+ const char *ret;
18378+ struct dentry *h_dentry;
18379+ struct inode *h_inode;
18380+ int err;
18381+ aufs_bindex_t bindex;
4a4d8108 18382+
0b1ff5c3
JR
18383+ ret = NULL; /* suppress a warning */
18384+ err = -ECHILD;
18385+ if (!dentry)
18386+ goto out;
1e00d052 18387+
0b1ff5c3
JR
18388+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
18389+ if (unlikely(err))
18390+ goto out;
1e00d052 18391+
0b1ff5c3
JR
18392+ err = au_d_hashed_positive(dentry);
18393+ if (unlikely(err))
18394+ goto out_unlock;
1e00d052 18395+
0b1ff5c3
JR
18396+ err = -EINVAL;
18397+ inode = d_inode(dentry);
18398+ bindex = au_ibtop(inode);
18399+ h_inode = au_h_iptr(inode, bindex);
18400+ if (unlikely(!h_inode->i_op->get_link))
18401+ goto out_unlock;
4a4d8108 18402+
0b1ff5c3
JR
18403+ err = -EBUSY;
18404+ h_dentry = NULL;
18405+ if (au_dbtop(dentry) <= bindex) {
18406+ h_dentry = au_h_dptr(dentry, bindex);
18407+ if (h_dentry)
18408+ dget(h_dentry);
1e00d052 18409+ }
0b1ff5c3
JR
18410+ if (!h_dentry) {
18411+ h_dentry = d_find_any_alias(h_inode);
18412+ if (IS_ERR(h_dentry)) {
18413+ err = PTR_ERR(h_dentry);
1e00d052 18414+ goto out_unlock;
4a4d8108 18415+ }
4a4d8108 18416+ }
0b1ff5c3
JR
18417+ if (unlikely(!h_dentry))
18418+ goto out_unlock;
4a4d8108 18419+
0b1ff5c3
JR
18420+ err = 0;
18421+ AuDbg("%pf\n", h_inode->i_op->get_link);
18422+ AuDbgDentry(h_dentry);
18423+ ret = vfs_get_link(h_dentry, done);
18424+ dput(h_dentry);
18425+ if (IS_ERR(ret))
18426+ err = PTR_ERR(ret);
4a4d8108 18427+
0b1ff5c3
JR
18428+out_unlock:
18429+ aufs_read_unlock(dentry, AuLock_IR);
4f0767ce 18430+out:
0b1ff5c3
JR
18431+ if (unlikely(err))
18432+ ret = ERR_PTR(err);
18433+ AuTraceErrPtr(ret);
18434+ return ret;
4a4d8108
AM
18435+}
18436+
18437+/* ---------------------------------------------------------------------- */
18438+
0b1ff5c3 18439+static int au_is_special(struct inode *inode)
4a4d8108 18440+{
0b1ff5c3
JR
18441+ return (inode->i_mode & (S_IFBLK | S_IFCHR | S_IFIFO | S_IFSOCK));
18442+}
4a4d8108 18443+
0b1ff5c3
JR
18444+static int aufs_update_time(struct inode *inode, struct timespec *ts, int flags)
18445+{
18446+ int err;
18447+ aufs_bindex_t bindex;
18448+ struct super_block *sb;
18449+ struct inode *h_inode;
18450+ struct vfsmount *h_mnt;
4a4d8108 18451+
0b1ff5c3
JR
18452+ sb = inode->i_sb;
18453+ WARN_ONCE((flags & S_ATIME) && !IS_NOATIME(inode),
18454+ "unexpected s_flags 0x%lx", sb->s_flags);
4a4d8108 18455+
0b1ff5c3
JR
18456+ /* mmap_sem might be acquired already, cf. aufs_mmap() */
18457+ lockdep_off();
18458+ si_read_lock(sb, AuLock_FLUSH);
18459+ ii_write_lock_child(inode);
027c5e7a 18460+
0b1ff5c3
JR
18461+ err = 0;
18462+ bindex = au_ibtop(inode);
18463+ h_inode = au_h_iptr(inode, bindex);
18464+ if (!au_test_ro(sb, bindex, inode)) {
18465+ h_mnt = au_sbr_mnt(sb, bindex);
18466+ err = vfsub_mnt_want_write(h_mnt);
18467+ if (!err) {
18468+ err = vfsub_update_time(h_inode, ts, flags);
18469+ vfsub_mnt_drop_write(h_mnt);
18470+ }
18471+ } else if (au_is_special(h_inode)) {
18472+ /*
18473+ * Never copy-up here.
18474+ * These special files may already be opened and used for
18475+ * communicating. If we copied it up, then the communication
18476+ * would be corrupted.
18477+ */
18478+ AuWarn1("timestamps for i%lu are ignored "
18479+ "since it is on readonly branch (hi%lu).\n",
18480+ inode->i_ino, h_inode->i_ino);
18481+ } else if (flags & ~S_ATIME) {
18482+ err = -EIO;
18483+ AuIOErr1("unexpected flags 0x%x\n", flags);
18484+ AuDebugOn(1);
18485+ }
076b876e 18486+
0b1ff5c3
JR
18487+ if (!err)
18488+ au_cpup_attr_timesizes(inode);
18489+ ii_write_unlock(inode);
18490+ si_read_unlock(sb);
18491+ lockdep_on();
076b876e 18492+
0b1ff5c3
JR
18493+ if (!err && (flags & S_VERSION))
18494+ inode_inc_iversion(inode);
4a4d8108 18495+
4a4d8108
AM
18496+ return err;
18497+}
18498+
0b1ff5c3 18499+/* ---------------------------------------------------------------------- */
4a4d8108 18500+
0b1ff5c3
JR
18501+/* no getattr version will be set by module.c:aufs_init() */
18502+struct inode_operations aufs_iop_nogetattr[AuIop_Last],
18503+ aufs_iop[] = {
18504+ [AuIop_SYMLINK] = {
18505+ .permission = aufs_permission,
18506+#ifdef CONFIG_FS_POSIX_ACL
18507+ .get_acl = aufs_get_acl,
18508+ .set_acl = aufs_set_acl, /* unsupport for symlink? */
18509+#endif
c2b27bf2 18510+
0b1ff5c3
JR
18511+ .setattr = aufs_setattr,
18512+ .getattr = aufs_getattr,
4a4d8108 18513+
0b1ff5c3
JR
18514+#ifdef CONFIG_AUFS_XATTR
18515+ .listxattr = aufs_listxattr,
18516+#endif
4a4d8108 18517+
0b1ff5c3 18518+ .get_link = aufs_get_link,
b752ccd1 18519+
0b1ff5c3
JR
18520+ /* .update_time = aufs_update_time */
18521+ },
18522+ [AuIop_DIR] = {
18523+ .create = aufs_create,
18524+ .lookup = aufs_lookup,
18525+ .link = aufs_link,
18526+ .unlink = aufs_unlink,
18527+ .symlink = aufs_symlink,
18528+ .mkdir = aufs_mkdir,
18529+ .rmdir = aufs_rmdir,
18530+ .mknod = aufs_mknod,
18531+ .rename = aufs_rename,
b752ccd1 18532+
0b1ff5c3
JR
18533+ .permission = aufs_permission,
18534+#ifdef CONFIG_FS_POSIX_ACL
18535+ .get_acl = aufs_get_acl,
18536+ .set_acl = aufs_set_acl,
18537+#endif
b752ccd1 18538+
0b1ff5c3
JR
18539+ .setattr = aufs_setattr,
18540+ .getattr = aufs_getattr,
027c5e7a 18541+
0b1ff5c3
JR
18542+#ifdef CONFIG_AUFS_XATTR
18543+ .listxattr = aufs_listxattr,
18544+#endif
076b876e 18545+
0b1ff5c3
JR
18546+ .update_time = aufs_update_time,
18547+ .atomic_open = aufs_atomic_open,
18548+ .tmpfile = aufs_tmpfile
18549+ },
18550+ [AuIop_OTHER] = {
18551+ .permission = aufs_permission,
18552+#ifdef CONFIG_FS_POSIX_ACL
18553+ .get_acl = aufs_get_acl,
18554+ .set_acl = aufs_set_acl,
18555+#endif
b752ccd1 18556+
0b1ff5c3
JR
18557+ .setattr = aufs_setattr,
18558+ .getattr = aufs_getattr,
b752ccd1 18559+
0b1ff5c3
JR
18560+#ifdef CONFIG_AUFS_XATTR
18561+ .listxattr = aufs_listxattr,
b752ccd1 18562+#endif
0b1ff5c3
JR
18563+
18564+ .update_time = aufs_update_time
18565+ }
18566+};
18567diff -urNp -x '*.orig' linux-4.14/fs/aufs/i_op_add.c linux-4.14/fs/aufs/i_op_add.c
18568--- linux-4.14/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
18569+++ linux-4.14/fs/aufs/i_op_add.c 2021-02-24 21:42:43.444448075 +0100
521ced18 18570@@ -0,0 +1,920 @@
4a4d8108 18571+/*
a2654f78 18572+ * Copyright (C) 2005-2017 Junjiro R. Okajima
4a4d8108
AM
18573+ *
18574+ * This program, aufs is free software; you can redistribute it and/or modify
18575+ * it under the terms of the GNU General Public License as published by
18576+ * the Free Software Foundation; either version 2 of the License, or
18577+ * (at your option) any later version.
18578+ *
18579+ * This program is distributed in the hope that it will be useful,
18580+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18581+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18582+ * GNU General Public License for more details.
18583+ *
18584+ * You should have received a copy of the GNU General Public License
523b37e3 18585+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
18586+ */
18587+
18588+/*
18589+ * inode operations (add entry)
18590+ */
18591+
18592+#include "aufs.h"
18593+
18594+/*
18595+ * final procedure of adding a new entry, except link(2).
18596+ * remove whiteout, instantiate, copyup the parent dir's times and size
18597+ * and update version.
18598+ * if it failed, re-create the removed whiteout.
18599+ */
18600+static int epilog(struct inode *dir, aufs_bindex_t bindex,
18601+ struct dentry *wh_dentry, struct dentry *dentry)
18602+{
18603+ int err, rerr;
18604+ aufs_bindex_t bwh;
18605+ struct path h_path;
076b876e 18606+ struct super_block *sb;
4a4d8108
AM
18607+ struct inode *inode, *h_dir;
18608+ struct dentry *wh;
18609+
18610+ bwh = -1;
076b876e 18611+ sb = dir->i_sb;
4a4d8108 18612+ if (wh_dentry) {
5527c038 18613+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */
4a4d8108
AM
18614+ IMustLock(h_dir);
18615+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
18616+ bwh = au_dbwh(dentry);
18617+ h_path.dentry = wh_dentry;
076b876e 18618+ h_path.mnt = au_sbr_mnt(sb, bindex);
4a4d8108
AM
18619+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
18620+ dentry);
18621+ if (unlikely(err))
18622+ goto out;
18623+ }
18624+
18625+ inode = au_new_inode(dentry, /*must_new*/1);
18626+ if (!IS_ERR(inode)) {
18627+ d_instantiate(dentry, inode);
5527c038 18628+ dir = d_inode(dentry->d_parent); /* dir inode is locked */
4a4d8108 18629+ IMustLock(dir);
b912730e 18630+ au_dir_ts(dir, bindex);
4a4d8108 18631+ dir->i_version++;
076b876e 18632+ au_fhsm_wrote(sb, bindex, /*force*/0);
4a4d8108
AM
18633+ return 0; /* success */
18634+ }
18635+
18636+ err = PTR_ERR(inode);
18637+ if (!wh_dentry)
18638+ goto out;
18639+
18640+ /* revert */
18641+ /* dir inode is locked */
18642+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
18643+ rerr = PTR_ERR(wh);
18644+ if (IS_ERR(wh)) {
523b37e3
AM
18645+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n",
18646+ dentry, err, rerr);
4a4d8108
AM
18647+ err = -EIO;
18648+ } else
18649+ dput(wh);
18650+
4f0767ce 18651+out:
4a4d8108
AM
18652+ return err;
18653+}
18654+
027c5e7a
AM
18655+static int au_d_may_add(struct dentry *dentry)
18656+{
18657+ int err;
18658+
18659+ err = 0;
18660+ if (unlikely(d_unhashed(dentry)))
18661+ err = -ENOENT;
5527c038 18662+ if (unlikely(d_really_is_positive(dentry)))
027c5e7a
AM
18663+ err = -EEXIST;
18664+ return err;
18665+}
18666+
4a4d8108
AM
18667+/*
18668+ * simple tests for the adding inode operations.
18669+ * following the checks in vfs, plus the parent-child relationship.
18670+ */
18671+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
18672+ struct dentry *h_parent, int isdir)
18673+{
18674+ int err;
18675+ umode_t h_mode;
18676+ struct dentry *h_dentry;
18677+ struct inode *h_inode;
18678+
18679+ err = -ENAMETOOLONG;
18680+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
18681+ goto out;
18682+
18683+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 18684+ if (d_really_is_negative(dentry)) {
4a4d8108 18685+ err = -EEXIST;
5527c038 18686+ if (unlikely(d_is_positive(h_dentry)))
4a4d8108
AM
18687+ goto out;
18688+ } else {
18689+ /* rename(2) case */
18690+ err = -EIO;
5527c038
JR
18691+ if (unlikely(d_is_negative(h_dentry)))
18692+ goto out;
18693+ h_inode = d_inode(h_dentry);
18694+ if (unlikely(!h_inode->i_nlink))
4a4d8108
AM
18695+ goto out;
18696+
18697+ h_mode = h_inode->i_mode;
18698+ if (!isdir) {
18699+ err = -EISDIR;
18700+ if (unlikely(S_ISDIR(h_mode)))
18701+ goto out;
18702+ } else if (unlikely(!S_ISDIR(h_mode))) {
18703+ err = -ENOTDIR;
18704+ goto out;
18705+ }
18706+ }
18707+
18708+ err = 0;
18709+ /* expected parent dir is locked */
18710+ if (unlikely(h_parent != h_dentry->d_parent))
18711+ err = -EIO;
18712+
4f0767ce 18713+out:
4a4d8108
AM
18714+ AuTraceErr(err);
18715+ return err;
18716+}
18717+
18718+/*
18719+ * initial procedure of adding a new entry.
18720+ * prepare writable branch and the parent dir, lock it,
18721+ * and lookup whiteout for the new entry.
18722+ */
18723+static struct dentry*
18724+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
18725+ struct dentry *src_dentry, struct au_pin *pin,
18726+ struct au_wr_dir_args *wr_dir_args)
18727+{
18728+ struct dentry *wh_dentry, *h_parent;
18729+ struct super_block *sb;
18730+ struct au_branch *br;
18731+ int err;
18732+ unsigned int udba;
18733+ aufs_bindex_t bcpup;
18734+
523b37e3 18735+ AuDbg("%pd\n", dentry);
4a4d8108
AM
18736+
18737+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
18738+ bcpup = err;
18739+ wh_dentry = ERR_PTR(err);
18740+ if (unlikely(err < 0))
18741+ goto out;
18742+
18743+ sb = dentry->d_sb;
18744+ udba = au_opt_udba(sb);
18745+ err = au_pin(pin, dentry, bcpup, udba,
18746+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
18747+ wh_dentry = ERR_PTR(err);
18748+ if (unlikely(err))
18749+ goto out;
18750+
18751+ h_parent = au_pinned_h_parent(pin);
18752+ if (udba != AuOpt_UDBA_NONE
5afbbe0d 18753+ && au_dbtop(dentry) == bcpup)
4a4d8108
AM
18754+ err = au_may_add(dentry, bcpup, h_parent,
18755+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
18756+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
18757+ err = -ENAMETOOLONG;
18758+ wh_dentry = ERR_PTR(err);
18759+ if (unlikely(err))
18760+ goto out_unpin;
18761+
18762+ br = au_sbr(sb, bcpup);
18763+ if (dt) {
18764+ struct path tmp = {
18765+ .dentry = h_parent,
86dc4139 18766+ .mnt = au_br_mnt(br)
4a4d8108
AM
18767+ };
18768+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
18769+ }
18770+
18771+ wh_dentry = NULL;
18772+ if (bcpup != au_dbwh(dentry))
18773+ goto out; /* success */
18774+
2000de60
JR
18775+ /*
18776+ * ENAMETOOLONG here means that if we allowed create such name, then it
18777+ * would not be able to removed in the future. So we don't allow such
18778+ * name here and we don't handle ENAMETOOLONG differently here.
18779+ */
4a4d8108
AM
18780+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
18781+
4f0767ce 18782+out_unpin:
4a4d8108
AM
18783+ if (IS_ERR(wh_dentry))
18784+ au_unpin(pin);
4f0767ce 18785+out:
4a4d8108
AM
18786+ return wh_dentry;
18787+}
18788+
18789+/* ---------------------------------------------------------------------- */
18790+
18791+enum { Mknod, Symlink, Creat };
18792+struct simple_arg {
18793+ int type;
18794+ union {
18795+ struct {
b912730e
AM
18796+ umode_t mode;
18797+ bool want_excl;
18798+ bool try_aopen;
18799+ struct vfsub_aopen_args *aopen;
4a4d8108
AM
18800+ } c;
18801+ struct {
18802+ const char *symname;
18803+ } s;
18804+ struct {
7eafdf33 18805+ umode_t mode;
4a4d8108
AM
18806+ dev_t dev;
18807+ } m;
18808+ } u;
18809+};
18810+
18811+static int add_simple(struct inode *dir, struct dentry *dentry,
18812+ struct simple_arg *arg)
18813+{
076b876e 18814+ int err, rerr;
5afbbe0d 18815+ aufs_bindex_t btop;
4a4d8108 18816+ unsigned char created;
b912730e
AM
18817+ const unsigned char try_aopen
18818+ = (arg->type == Creat && arg->u.c.try_aopen);
4a4d8108
AM
18819+ struct dentry *wh_dentry, *parent;
18820+ struct inode *h_dir;
b912730e
AM
18821+ struct super_block *sb;
18822+ struct au_branch *br;
c2b27bf2
AM
18823+ /* to reuduce stack size */
18824+ struct {
18825+ struct au_dtime dt;
18826+ struct au_pin pin;
18827+ struct path h_path;
18828+ struct au_wr_dir_args wr_dir_args;
18829+ } *a;
4a4d8108 18830+
523b37e3 18831+ AuDbg("%pd\n", dentry);
4a4d8108
AM
18832+ IMustLock(dir);
18833+
c2b27bf2
AM
18834+ err = -ENOMEM;
18835+ a = kmalloc(sizeof(*a), GFP_NOFS);
18836+ if (unlikely(!a))
18837+ goto out;
18838+ a->wr_dir_args.force_btgt = -1;
18839+ a->wr_dir_args.flags = AuWrDir_ADD_ENTRY;
18840+
4a4d8108 18841+ parent = dentry->d_parent; /* dir inode is locked */
b912730e
AM
18842+ if (!try_aopen) {
18843+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
18844+ if (unlikely(err))
18845+ goto out_free;
18846+ }
027c5e7a
AM
18847+ err = au_d_may_add(dentry);
18848+ if (unlikely(err))
18849+ goto out_unlock;
b912730e
AM
18850+ if (!try_aopen)
18851+ di_write_lock_parent(parent);
c2b27bf2
AM
18852+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
18853+ &a->pin, &a->wr_dir_args);
4a4d8108
AM
18854+ err = PTR_ERR(wh_dentry);
18855+ if (IS_ERR(wh_dentry))
027c5e7a 18856+ goto out_parent;
4a4d8108 18857+
5afbbe0d 18858+ btop = au_dbtop(dentry);
b912730e 18859+ sb = dentry->d_sb;
5afbbe0d
AM
18860+ br = au_sbr(sb, btop);
18861+ a->h_path.dentry = au_h_dptr(dentry, btop);
b912730e 18862+ a->h_path.mnt = au_br_mnt(br);
c2b27bf2 18863+ h_dir = au_pinned_h_dir(&a->pin);
4a4d8108
AM
18864+ switch (arg->type) {
18865+ case Creat:
b912730e
AM
18866+ err = 0;
18867+ if (!try_aopen || !h_dir->i_op->atomic_open)
18868+ err = vfsub_create(h_dir, &a->h_path, arg->u.c.mode,
18869+ arg->u.c.want_excl);
18870+ else
18871+ err = vfsub_atomic_open(h_dir, a->h_path.dentry,
18872+ arg->u.c.aopen, br);
4a4d8108
AM
18873+ break;
18874+ case Symlink:
c2b27bf2 18875+ err = vfsub_symlink(h_dir, &a->h_path, arg->u.s.symname);
4a4d8108
AM
18876+ break;
18877+ case Mknod:
c2b27bf2
AM
18878+ err = vfsub_mknod(h_dir, &a->h_path, arg->u.m.mode,
18879+ arg->u.m.dev);
4a4d8108
AM
18880+ break;
18881+ default:
18882+ BUG();
18883+ }
18884+ created = !err;
18885+ if (!err)
5afbbe0d 18886+ err = epilog(dir, btop, wh_dentry, dentry);
4a4d8108
AM
18887+
18888+ /* revert */
5527c038 18889+ if (unlikely(created && err && d_is_positive(a->h_path.dentry))) {
523b37e3
AM
18890+ /* no delegation since it is just created */
18891+ rerr = vfsub_unlink(h_dir, &a->h_path, /*delegated*/NULL,
18892+ /*force*/0);
4a4d8108 18893+ if (rerr) {
523b37e3
AM
18894+ AuIOErr("%pd revert failure(%d, %d)\n",
18895+ dentry, err, rerr);
4a4d8108
AM
18896+ err = -EIO;
18897+ }
c2b27bf2 18898+ au_dtime_revert(&a->dt);
4a4d8108
AM
18899+ }
18900+
b912730e
AM
18901+ if (!err && try_aopen && !h_dir->i_op->atomic_open)
18902+ *arg->u.c.aopen->opened |= FILE_CREATED;
18903+
c2b27bf2 18904+ au_unpin(&a->pin);
4a4d8108
AM
18905+ dput(wh_dentry);
18906+
027c5e7a 18907+out_parent:
b912730e
AM
18908+ if (!try_aopen)
18909+ di_write_unlock(parent);
027c5e7a 18910+out_unlock:
4a4d8108 18911+ if (unlikely(err)) {
5afbbe0d 18912+ au_update_dbtop(dentry);
4a4d8108
AM
18913+ d_drop(dentry);
18914+ }
b912730e
AM
18915+ if (!try_aopen)
18916+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 18917+out_free:
1c60b727 18918+ kfree(a);
027c5e7a 18919+out:
4a4d8108
AM
18920+ return err;
18921+}
18922+
7eafdf33
AM
18923+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
18924+ dev_t dev)
4a4d8108
AM
18925+{
18926+ struct simple_arg arg = {
18927+ .type = Mknod,
18928+ .u.m = {
18929+ .mode = mode,
18930+ .dev = dev
18931+ }
18932+ };
18933+ return add_simple(dir, dentry, &arg);
18934+}
18935+
18936+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
18937+{
18938+ struct simple_arg arg = {
18939+ .type = Symlink,
18940+ .u.s.symname = symname
18941+ };
18942+ return add_simple(dir, dentry, &arg);
18943+}
18944+
7eafdf33 18945+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
b4510431 18946+ bool want_excl)
4a4d8108
AM
18947+{
18948+ struct simple_arg arg = {
18949+ .type = Creat,
18950+ .u.c = {
b4510431
AM
18951+ .mode = mode,
18952+ .want_excl = want_excl
4a4d8108
AM
18953+ }
18954+ };
18955+ return add_simple(dir, dentry, &arg);
18956+}
18957+
b912730e
AM
18958+int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
18959+ struct vfsub_aopen_args *aopen_args)
18960+{
18961+ struct simple_arg arg = {
18962+ .type = Creat,
18963+ .u.c = {
18964+ .mode = aopen_args->create_mode,
18965+ .want_excl = aopen_args->open_flag & O_EXCL,
18966+ .try_aopen = true,
18967+ .aopen = aopen_args
18968+ }
18969+ };
18970+ return add_simple(dir, dentry, &arg);
18971+}
18972+
38d290e6
JR
18973+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
18974+{
18975+ int err;
18976+ aufs_bindex_t bindex;
18977+ struct super_block *sb;
18978+ struct dentry *parent, *h_parent, *h_dentry;
18979+ struct inode *h_dir, *inode;
18980+ struct vfsmount *h_mnt;
18981+ struct au_wr_dir_args wr_dir_args = {
18982+ .force_btgt = -1,
18983+ .flags = AuWrDir_TMPFILE
18984+ };
18985+
18986+ /* copy-up may happen */
febd17d6 18987+ inode_lock(dir);
38d290e6
JR
18988+
18989+ sb = dir->i_sb;
18990+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
18991+ if (unlikely(err))
18992+ goto out;
18993+
18994+ err = au_di_init(dentry);
18995+ if (unlikely(err))
18996+ goto out_si;
18997+
18998+ err = -EBUSY;
18999+ parent = d_find_any_alias(dir);
19000+ AuDebugOn(!parent);
19001+ di_write_lock_parent(parent);
5527c038 19002+ if (unlikely(d_inode(parent) != dir))
38d290e6
JR
19003+ goto out_parent;
19004+
19005+ err = au_digen_test(parent, au_sigen(sb));
19006+ if (unlikely(err))
19007+ goto out_parent;
19008+
5afbbe0d
AM
19009+ bindex = au_dbtop(parent);
19010+ au_set_dbtop(dentry, bindex);
19011+ au_set_dbbot(dentry, bindex);
38d290e6
JR
19012+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
19013+ bindex = err;
19014+ if (unlikely(err < 0))
19015+ goto out_parent;
19016+
19017+ err = -EOPNOTSUPP;
19018+ h_dir = au_h_iptr(dir, bindex);
19019+ if (unlikely(!h_dir->i_op->tmpfile))
19020+ goto out_parent;
19021+
19022+ h_mnt = au_sbr_mnt(sb, bindex);
19023+ err = vfsub_mnt_want_write(h_mnt);
19024+ if (unlikely(err))
19025+ goto out_parent;
19026+
19027+ h_parent = au_h_dptr(parent, bindex);
521ced18
JR
19028+ h_dentry = vfs_tmpfile(h_parent, mode, /*open_flag*/0);
19029+ if (IS_ERR(h_dentry)) {
19030+ err = PTR_ERR(h_dentry);
38d290e6 19031+ goto out_mnt;
521ced18 19032+ }
38d290e6 19033+
5afbbe0d
AM
19034+ au_set_dbtop(dentry, bindex);
19035+ au_set_dbbot(dentry, bindex);
38d290e6
JR
19036+ au_set_h_dptr(dentry, bindex, dget(h_dentry));
19037+ inode = au_new_inode(dentry, /*must_new*/1);
19038+ if (IS_ERR(inode)) {
19039+ err = PTR_ERR(inode);
19040+ au_set_h_dptr(dentry, bindex, NULL);
5afbbe0d
AM
19041+ au_set_dbtop(dentry, -1);
19042+ au_set_dbbot(dentry, -1);
38d290e6
JR
19043+ } else {
19044+ if (!inode->i_nlink)
19045+ set_nlink(inode, 1);
19046+ d_tmpfile(dentry, inode);
19047+ au_di(dentry)->di_tmpfile = 1;
19048+
19049+ /* update without i_mutex */
5afbbe0d 19050+ if (au_ibtop(dir) == au_dbtop(dentry))
38d290e6
JR
19051+ au_cpup_attr_timesizes(dir);
19052+ }
38d290e6 19053+ dput(h_dentry);
521ced18 19054+
38d290e6
JR
19055+out_mnt:
19056+ vfsub_mnt_drop_write(h_mnt);
19057+out_parent:
19058+ di_write_unlock(parent);
19059+ dput(parent);
19060+ di_write_unlock(dentry);
5afbbe0d 19061+ if (unlikely(err)) {
38d290e6
JR
19062+ au_di_fin(dentry);
19063+ dentry->d_fsdata = NULL;
19064+ }
19065+out_si:
19066+ si_read_unlock(sb);
19067+out:
febd17d6 19068+ inode_unlock(dir);
38d290e6
JR
19069+ return err;
19070+}
19071+
4a4d8108
AM
19072+/* ---------------------------------------------------------------------- */
19073+
19074+struct au_link_args {
19075+ aufs_bindex_t bdst, bsrc;
19076+ struct au_pin pin;
19077+ struct path h_path;
19078+ struct dentry *src_parent, *parent;
19079+};
19080+
19081+static int au_cpup_before_link(struct dentry *src_dentry,
19082+ struct au_link_args *a)
19083+{
19084+ int err;
19085+ struct dentry *h_src_dentry;
c2b27bf2
AM
19086+ struct au_cp_generic cpg = {
19087+ .dentry = src_dentry,
19088+ .bdst = a->bdst,
19089+ .bsrc = a->bsrc,
19090+ .len = -1,
19091+ .pin = &a->pin,
19092+ .flags = AuCpup_DTIME | AuCpup_HOPEN /* | AuCpup_KEEPLINO */
19093+ };
4a4d8108
AM
19094+
19095+ di_read_lock_parent(a->src_parent, AuLock_IR);
19096+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
19097+ if (unlikely(err))
19098+ goto out;
19099+
19100+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
4a4d8108
AM
19101+ err = au_pin(&a->pin, src_dentry, a->bdst,
19102+ au_opt_udba(src_dentry->d_sb),
19103+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
19104+ if (unlikely(err))
19105+ goto out;
367653fa 19106+
c2b27bf2 19107+ err = au_sio_cpup_simple(&cpg);
4a4d8108
AM
19108+ au_unpin(&a->pin);
19109+
4f0767ce 19110+out:
4a4d8108
AM
19111+ di_read_unlock(a->src_parent, AuLock_IR);
19112+ return err;
19113+}
19114+
86dc4139
AM
19115+static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry,
19116+ struct au_link_args *a)
4a4d8108
AM
19117+{
19118+ int err;
19119+ unsigned char plink;
5afbbe0d 19120+ aufs_bindex_t bbot;
4a4d8108 19121+ struct dentry *h_src_dentry;
523b37e3 19122+ struct inode *h_inode, *inode, *delegated;
4a4d8108
AM
19123+ struct super_block *sb;
19124+ struct file *h_file;
19125+
19126+ plink = 0;
19127+ h_inode = NULL;
19128+ sb = src_dentry->d_sb;
5527c038 19129+ inode = d_inode(src_dentry);
5afbbe0d 19130+ if (au_ibtop(inode) <= a->bdst)
4a4d8108
AM
19131+ h_inode = au_h_iptr(inode, a->bdst);
19132+ if (!h_inode || !h_inode->i_nlink) {
19133+ /* copyup src_dentry as the name of dentry. */
5afbbe0d
AM
19134+ bbot = au_dbbot(dentry);
19135+ if (bbot < a->bsrc)
19136+ au_set_dbbot(dentry, a->bsrc);
86dc4139
AM
19137+ au_set_h_dptr(dentry, a->bsrc,
19138+ dget(au_h_dptr(src_dentry, a->bsrc)));
19139+ dget(a->h_path.dentry);
19140+ au_set_h_dptr(dentry, a->bdst, NULL);
c1595e42
JR
19141+ AuDbg("temporary d_inode...\n");
19142+ spin_lock(&dentry->d_lock);
5527c038 19143+ dentry->d_inode = d_inode(src_dentry); /* tmp */
c1595e42 19144+ spin_unlock(&dentry->d_lock);
392086de 19145+ h_file = au_h_open_pre(dentry, a->bsrc, /*force_wr*/0);
86dc4139 19146+ if (IS_ERR(h_file))
4a4d8108 19147+ err = PTR_ERR(h_file);
86dc4139 19148+ else {
c2b27bf2
AM
19149+ struct au_cp_generic cpg = {
19150+ .dentry = dentry,
19151+ .bdst = a->bdst,
19152+ .bsrc = -1,
19153+ .len = -1,
19154+ .pin = &a->pin,
19155+ .flags = AuCpup_KEEPLINO
19156+ };
19157+ err = au_sio_cpup_simple(&cpg);
86dc4139
AM
19158+ au_h_open_post(dentry, a->bsrc, h_file);
19159+ if (!err) {
19160+ dput(a->h_path.dentry);
19161+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
19162+ } else
19163+ au_set_h_dptr(dentry, a->bdst,
19164+ a->h_path.dentry);
19165+ }
c1595e42 19166+ spin_lock(&dentry->d_lock);
86dc4139 19167+ dentry->d_inode = NULL; /* restore */
c1595e42
JR
19168+ spin_unlock(&dentry->d_lock);
19169+ AuDbg("temporary d_inode...done\n");
86dc4139 19170+ au_set_h_dptr(dentry, a->bsrc, NULL);
5afbbe0d 19171+ au_set_dbbot(dentry, bbot);
4a4d8108
AM
19172+ } else {
19173+ /* the inode of src_dentry already exists on a.bdst branch */
19174+ h_src_dentry = d_find_alias(h_inode);
19175+ if (!h_src_dentry && au_plink_test(inode)) {
19176+ plink = 1;
19177+ h_src_dentry = au_plink_lkup(inode, a->bdst);
19178+ err = PTR_ERR(h_src_dentry);
19179+ if (IS_ERR(h_src_dentry))
19180+ goto out;
19181+
5527c038 19182+ if (unlikely(d_is_negative(h_src_dentry))) {
4a4d8108
AM
19183+ dput(h_src_dentry);
19184+ h_src_dentry = NULL;
19185+ }
19186+
19187+ }
19188+ if (h_src_dentry) {
523b37e3 19189+ delegated = NULL;
4a4d8108 19190+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
523b37e3
AM
19191+ &a->h_path, &delegated);
19192+ if (unlikely(err == -EWOULDBLOCK)) {
19193+ pr_warn("cannot retry for NFSv4 delegation"
19194+ " for an internal link\n");
19195+ iput(delegated);
19196+ }
4a4d8108
AM
19197+ dput(h_src_dentry);
19198+ } else {
19199+ AuIOErr("no dentry found for hi%lu on b%d\n",
19200+ h_inode->i_ino, a->bdst);
19201+ err = -EIO;
19202+ }
19203+ }
19204+
19205+ if (!err && !plink)
19206+ au_plink_append(inode, a->bdst, a->h_path.dentry);
19207+
19208+out:
2cbb1c4b 19209+ AuTraceErr(err);
4a4d8108
AM
19210+ return err;
19211+}
19212+
19213+int aufs_link(struct dentry *src_dentry, struct inode *dir,
19214+ struct dentry *dentry)
19215+{
19216+ int err, rerr;
19217+ struct au_dtime dt;
19218+ struct au_link_args *a;
19219+ struct dentry *wh_dentry, *h_src_dentry;
523b37e3 19220+ struct inode *inode, *delegated;
4a4d8108
AM
19221+ struct super_block *sb;
19222+ struct au_wr_dir_args wr_dir_args = {
19223+ /* .force_btgt = -1, */
19224+ .flags = AuWrDir_ADD_ENTRY
19225+ };
19226+
19227+ IMustLock(dir);
5527c038 19228+ inode = d_inode(src_dentry);
4a4d8108
AM
19229+ IMustLock(inode);
19230+
4a4d8108
AM
19231+ err = -ENOMEM;
19232+ a = kzalloc(sizeof(*a), GFP_NOFS);
19233+ if (unlikely(!a))
19234+ goto out;
19235+
19236+ a->parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
19237+ err = aufs_read_and_write_lock2(dentry, src_dentry,
19238+ AuLock_NOPLM | AuLock_GEN);
e49829fe
JR
19239+ if (unlikely(err))
19240+ goto out_kfree;
38d290e6 19241+ err = au_d_linkable(src_dentry);
027c5e7a
AM
19242+ if (unlikely(err))
19243+ goto out_unlock;
19244+ err = au_d_may_add(dentry);
19245+ if (unlikely(err))
19246+ goto out_unlock;
e49829fe 19247+
4a4d8108 19248+ a->src_parent = dget_parent(src_dentry);
5afbbe0d 19249+ wr_dir_args.force_btgt = au_ibtop(inode);
4a4d8108
AM
19250+
19251+ di_write_lock_parent(a->parent);
19252+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
19253+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
19254+ &wr_dir_args);
19255+ err = PTR_ERR(wh_dentry);
19256+ if (IS_ERR(wh_dentry))
027c5e7a 19257+ goto out_parent;
4a4d8108
AM
19258+
19259+ err = 0;
19260+ sb = dentry->d_sb;
5afbbe0d 19261+ a->bdst = au_dbtop(dentry);
4a4d8108
AM
19262+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
19263+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
5afbbe0d 19264+ a->bsrc = au_ibtop(inode);
2cbb1c4b 19265+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
38d290e6
JR
19266+ if (!h_src_dentry && au_di(src_dentry)->di_tmpfile)
19267+ h_src_dentry = dget(au_hi_wh(inode, a->bsrc));
2cbb1c4b 19268+ if (!h_src_dentry) {
5afbbe0d 19269+ a->bsrc = au_dbtop(src_dentry);
2cbb1c4b
JR
19270+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
19271+ AuDebugOn(!h_src_dentry);
38d290e6
JR
19272+ } else if (IS_ERR(h_src_dentry)) {
19273+ err = PTR_ERR(h_src_dentry);
2cbb1c4b 19274+ goto out_parent;
38d290e6 19275+ }
2cbb1c4b 19276+
f2c43d5f
AM
19277+ /*
19278+ * aufs doesn't touch the credential so
19279+ * security_dentry_create_files_as() is unnecrssary.
19280+ */
4a4d8108
AM
19281+ if (au_opt_test(au_mntflags(sb), PLINK)) {
19282+ if (a->bdst < a->bsrc
19283+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
86dc4139 19284+ err = au_cpup_or_link(src_dentry, dentry, a);
523b37e3
AM
19285+ else {
19286+ delegated = NULL;
4a4d8108 19287+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
523b37e3
AM
19288+ &a->h_path, &delegated);
19289+ if (unlikely(err == -EWOULDBLOCK)) {
19290+ pr_warn("cannot retry for NFSv4 delegation"
19291+ " for an internal link\n");
19292+ iput(delegated);
19293+ }
19294+ }
2cbb1c4b 19295+ dput(h_src_dentry);
4a4d8108
AM
19296+ } else {
19297+ /*
19298+ * copyup src_dentry to the branch we process,
19299+ * and then link(2) to it.
19300+ */
2cbb1c4b 19301+ dput(h_src_dentry);
4a4d8108
AM
19302+ if (a->bdst < a->bsrc
19303+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
19304+ au_unpin(&a->pin);
19305+ di_write_unlock(a->parent);
19306+ err = au_cpup_before_link(src_dentry, a);
19307+ di_write_lock_parent(a->parent);
19308+ if (!err)
19309+ err = au_pin(&a->pin, dentry, a->bdst,
19310+ au_opt_udba(sb),
19311+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
19312+ if (unlikely(err))
19313+ goto out_wh;
19314+ }
19315+ if (!err) {
19316+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
19317+ err = -ENOENT;
5527c038 19318+ if (h_src_dentry && d_is_positive(h_src_dentry)) {
523b37e3 19319+ delegated = NULL;
4a4d8108
AM
19320+ err = vfsub_link(h_src_dentry,
19321+ au_pinned_h_dir(&a->pin),
523b37e3
AM
19322+ &a->h_path, &delegated);
19323+ if (unlikely(err == -EWOULDBLOCK)) {
19324+ pr_warn("cannot retry"
19325+ " for NFSv4 delegation"
19326+ " for an internal link\n");
19327+ iput(delegated);
19328+ }
19329+ }
4a4d8108
AM
19330+ }
19331+ }
19332+ if (unlikely(err))
19333+ goto out_unpin;
19334+
19335+ if (wh_dentry) {
19336+ a->h_path.dentry = wh_dentry;
19337+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
19338+ dentry);
19339+ if (unlikely(err))
19340+ goto out_revert;
19341+ }
19342+
b912730e 19343+ au_dir_ts(dir, a->bdst);
4a4d8108 19344+ dir->i_version++;
4a4d8108
AM
19345+ inc_nlink(inode);
19346+ inode->i_ctime = dir->i_ctime;
027c5e7a
AM
19347+ d_instantiate(dentry, au_igrab(inode));
19348+ if (d_unhashed(a->h_path.dentry))
4a4d8108
AM
19349+ /* some filesystem calls d_drop() */
19350+ d_drop(dentry);
076b876e
AM
19351+ /* some filesystems consume an inode even hardlink */
19352+ au_fhsm_wrote(sb, a->bdst, /*force*/0);
4a4d8108
AM
19353+ goto out_unpin; /* success */
19354+
4f0767ce 19355+out_revert:
523b37e3
AM
19356+ /* no delegation since it is just created */
19357+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path,
19358+ /*delegated*/NULL, /*force*/0);
027c5e7a 19359+ if (unlikely(rerr)) {
523b37e3 19360+ AuIOErr("%pd reverting failed(%d, %d)\n", dentry, err, rerr);
027c5e7a
AM
19361+ err = -EIO;
19362+ }
4a4d8108 19363+ au_dtime_revert(&dt);
4f0767ce 19364+out_unpin:
4a4d8108 19365+ au_unpin(&a->pin);
4f0767ce 19366+out_wh:
4a4d8108 19367+ dput(wh_dentry);
027c5e7a
AM
19368+out_parent:
19369+ di_write_unlock(a->parent);
19370+ dput(a->src_parent);
4f0767ce 19371+out_unlock:
4a4d8108 19372+ if (unlikely(err)) {
5afbbe0d 19373+ au_update_dbtop(dentry);
4a4d8108
AM
19374+ d_drop(dentry);
19375+ }
4a4d8108 19376+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 19377+out_kfree:
1c60b727 19378+ kfree(a);
4f0767ce 19379+out:
86dc4139 19380+ AuTraceErr(err);
4a4d8108
AM
19381+ return err;
19382+}
19383+
7eafdf33 19384+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
4a4d8108
AM
19385+{
19386+ int err, rerr;
19387+ aufs_bindex_t bindex;
19388+ unsigned char diropq;
19389+ struct path h_path;
19390+ struct dentry *wh_dentry, *parent, *opq_dentry;
febd17d6 19391+ struct inode *h_inode;
4a4d8108
AM
19392+ struct super_block *sb;
19393+ struct {
19394+ struct au_pin pin;
19395+ struct au_dtime dt;
19396+ } *a; /* reduce the stack usage */
19397+ struct au_wr_dir_args wr_dir_args = {
19398+ .force_btgt = -1,
19399+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
19400+ };
19401+
19402+ IMustLock(dir);
19403+
19404+ err = -ENOMEM;
19405+ a = kmalloc(sizeof(*a), GFP_NOFS);
19406+ if (unlikely(!a))
19407+ goto out;
19408+
027c5e7a
AM
19409+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
19410+ if (unlikely(err))
19411+ goto out_free;
19412+ err = au_d_may_add(dentry);
19413+ if (unlikely(err))
19414+ goto out_unlock;
19415+
4a4d8108
AM
19416+ parent = dentry->d_parent; /* dir inode is locked */
19417+ di_write_lock_parent(parent);
19418+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
19419+ &a->pin, &wr_dir_args);
19420+ err = PTR_ERR(wh_dentry);
19421+ if (IS_ERR(wh_dentry))
027c5e7a 19422+ goto out_parent;
4a4d8108
AM
19423+
19424+ sb = dentry->d_sb;
5afbbe0d 19425+ bindex = au_dbtop(dentry);
4a4d8108
AM
19426+ h_path.dentry = au_h_dptr(dentry, bindex);
19427+ h_path.mnt = au_sbr_mnt(sb, bindex);
19428+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
19429+ if (unlikely(err))
027c5e7a 19430+ goto out_unpin;
4a4d8108
AM
19431+
19432+ /* make the dir opaque */
19433+ diropq = 0;
febd17d6 19434+ h_inode = d_inode(h_path.dentry);
4a4d8108
AM
19435+ if (wh_dentry
19436+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
febd17d6 19437+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 19438+ opq_dentry = au_diropq_create(dentry, bindex);
febd17d6 19439+ inode_unlock(h_inode);
4a4d8108
AM
19440+ err = PTR_ERR(opq_dentry);
19441+ if (IS_ERR(opq_dentry))
19442+ goto out_dir;
19443+ dput(opq_dentry);
19444+ diropq = 1;
19445+ }
19446+
19447+ err = epilog(dir, bindex, wh_dentry, dentry);
19448+ if (!err) {
19449+ inc_nlink(dir);
027c5e7a 19450+ goto out_unpin; /* success */
4a4d8108
AM
19451+ }
19452+
19453+ /* revert */
19454+ if (diropq) {
19455+ AuLabel(revert opq);
febd17d6 19456+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 19457+ rerr = au_diropq_remove(dentry, bindex);
febd17d6 19458+ inode_unlock(h_inode);
4a4d8108 19459+ if (rerr) {
523b37e3
AM
19460+ AuIOErr("%pd reverting diropq failed(%d, %d)\n",
19461+ dentry, err, rerr);
4a4d8108
AM
19462+ err = -EIO;
19463+ }
19464+ }
19465+
4f0767ce 19466+out_dir:
4a4d8108
AM
19467+ AuLabel(revert dir);
19468+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
19469+ if (rerr) {
523b37e3
AM
19470+ AuIOErr("%pd reverting dir failed(%d, %d)\n",
19471+ dentry, err, rerr);
4a4d8108
AM
19472+ err = -EIO;
19473+ }
4a4d8108 19474+ au_dtime_revert(&a->dt);
027c5e7a 19475+out_unpin:
4a4d8108
AM
19476+ au_unpin(&a->pin);
19477+ dput(wh_dentry);
027c5e7a
AM
19478+out_parent:
19479+ di_write_unlock(parent);
19480+out_unlock:
4a4d8108 19481+ if (unlikely(err)) {
5afbbe0d 19482+ au_update_dbtop(dentry);
4a4d8108
AM
19483+ d_drop(dentry);
19484+ }
4a4d8108 19485+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 19486+out_free:
1c60b727 19487+ kfree(a);
4f0767ce 19488+out:
4a4d8108
AM
19489+ return err;
19490+}
0b1ff5c3
JR
19491diff -urNp -x '*.orig' linux-4.14/fs/aufs/i_op_del.c linux-4.14/fs/aufs/i_op_del.c
19492--- linux-4.14/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
19493+++ linux-4.14/fs/aufs/i_op_del.c 2021-02-24 21:42:43.444448075 +0100
19494@@ -0,0 +1,511 @@
4a4d8108 19495+/*
a2654f78 19496+ * Copyright (C) 2005-2017 Junjiro R. Okajima
4a4d8108
AM
19497+ *
19498+ * This program, aufs is free software; you can redistribute it and/or modify
19499+ * it under the terms of the GNU General Public License as published by
19500+ * the Free Software Foundation; either version 2 of the License, or
19501+ * (at your option) any later version.
19502+ *
19503+ * This program is distributed in the hope that it will be useful,
19504+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19505+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19506+ * GNU General Public License for more details.
19507+ *
19508+ * You should have received a copy of the GNU General Public License
523b37e3 19509+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 19510+ */
1facf9fc 19511+
1308ab2a 19512+/*
0b1ff5c3 19513+ * inode operations (del entry)
1308ab2a 19514+ */
4a4d8108 19515+
4a4d8108
AM
19516+#include "aufs.h"
19517+
0b1ff5c3
JR
19518+/*
19519+ * decide if a new whiteout for @dentry is necessary or not.
19520+ * when it is necessary, prepare the parent dir for the upper branch whose
19521+ * branch index is @bcpup for creation. the actual creation of the whiteout will
19522+ * be done by caller.
19523+ * return value:
19524+ * 0: wh is unnecessary
19525+ * plus: wh is necessary
19526+ * minus: error
19527+ */
19528+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1facf9fc 19529+{
0b1ff5c3
JR
19530+ int need_wh, err;
19531+ aufs_bindex_t btop;
19532+ struct super_block *sb;
e2f27e51 19533+
0b1ff5c3
JR
19534+ sb = dentry->d_sb;
19535+ btop = au_dbtop(dentry);
19536+ if (*bcpup < 0) {
19537+ *bcpup = btop;
19538+ if (au_test_ro(sb, btop, d_inode(dentry))) {
19539+ err = AuWbrCopyup(au_sbi(sb), dentry);
19540+ *bcpup = err;
19541+ if (unlikely(err < 0))
19542+ goto out;
19543+ }
19544+ } else
19545+ AuDebugOn(btop < *bcpup
19546+ || au_test_ro(sb, *bcpup, d_inode(dentry)));
19547+ AuDbg("bcpup %d, btop %d\n", *bcpup, btop);
4a4d8108 19548+
0b1ff5c3
JR
19549+ if (*bcpup != btop) {
19550+ err = au_cpup_dirs(dentry, *bcpup);
19551+ if (unlikely(err))
19552+ goto out;
19553+ need_wh = 1;
1308ab2a 19554+ } else {
0b1ff5c3
JR
19555+ struct au_dinfo *dinfo, *tmp;
19556+
19557+ need_wh = -ENOMEM;
19558+ dinfo = au_di(dentry);
19559+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
19560+ if (tmp) {
19561+ au_di_cp(tmp, dinfo);
19562+ au_di_swap(tmp, dinfo);
19563+ /* returns the number of positive dentries */
19564+ need_wh = au_lkup_dentry(dentry, btop + 1,
19565+ /* AuLkup_IGNORE_PERM */ 0);
19566+ au_di_swap(tmp, dinfo);
19567+ au_rw_write_unlock(&tmp->di_rwsem);
19568+ au_di_free(tmp);
19569+ }
4a4d8108 19570+ }
0b1ff5c3
JR
19571+ AuDbg("need_wh %d\n", need_wh);
19572+ err = need_wh;
1facf9fc 19573+
0b1ff5c3
JR
19574+out:
19575+ return err;
19576+}
4a4d8108 19577+
0b1ff5c3
JR
19578+/*
19579+ * simple tests for the del-entry operations.
19580+ * following the checks in vfs, plus the parent-child relationship.
19581+ */
19582+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
19583+ struct dentry *h_parent, int isdir)
19584+{
19585+ int err;
19586+ umode_t h_mode;
19587+ struct dentry *h_dentry, *h_latest;
19588+ struct inode *h_inode;
19589+
19590+ h_dentry = au_h_dptr(dentry, bindex);
19591+ if (d_really_is_positive(dentry)) {
19592+ err = -ENOENT;
19593+ if (unlikely(d_is_negative(h_dentry)))
19594+ goto out;
19595+ h_inode = d_inode(h_dentry);
19596+ if (unlikely(!h_inode->i_nlink))
19597+ goto out;
19598+
19599+ h_mode = h_inode->i_mode;
19600+ if (!isdir) {
19601+ err = -EISDIR;
19602+ if (unlikely(S_ISDIR(h_mode)))
19603+ goto out;
19604+ } else if (unlikely(!S_ISDIR(h_mode))) {
19605+ err = -ENOTDIR;
19606+ goto out;
19607+ }
19608+ } else {
19609+ /* rename(2) case */
19610+ err = -EIO;
19611+ if (unlikely(d_is_positive(h_dentry)))
19612+ goto out;
1308ab2a 19613+ }
0b1ff5c3
JR
19614+
19615+ err = -ENOENT;
19616+ /* expected parent dir is locked */
19617+ if (unlikely(h_parent != h_dentry->d_parent))
19618+ goto out;
19619+ err = 0;
19620+
19621+ /*
19622+ * rmdir a dir may break the consistency on some filesystem.
19623+ * let's try heavy test.
19624+ */
19625+ err = -EACCES;
19626+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1)
19627+ && au_test_h_perm(d_inode(h_parent),
19628+ MAY_EXEC | MAY_WRITE)))
19629+ goto out;
19630+
19631+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent);
19632+ err = -EIO;
19633+ if (IS_ERR(h_latest))
19634+ goto out;
19635+ if (h_latest == h_dentry)
19636+ err = 0;
19637+ dput(h_latest);
dece6358 19638+
4f0767ce 19639+out:
1308ab2a 19640+ return err;
19641+}
dece6358 19642+
0b1ff5c3
JR
19643+/*
19644+ * decide the branch where we operate for @dentry. the branch index will be set
19645+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
19646+ * dir for reverting.
19647+ * when a new whiteout is necessary, create it.
19648+ */
19649+static struct dentry*
19650+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
19651+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 19652+{
0b1ff5c3 19653+ struct dentry *wh_dentry;
4a4d8108 19654+ struct super_block *sb;
0b1ff5c3
JR
19655+ struct path h_path;
19656+ int err, need_wh;
19657+ unsigned int udba;
19658+ aufs_bindex_t bcpup;
1facf9fc 19659+
0b1ff5c3
JR
19660+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
19661+ wh_dentry = ERR_PTR(need_wh);
19662+ if (unlikely(need_wh < 0))
19663+ goto out;
027c5e7a 19664+
0b1ff5c3
JR
19665+ sb = dentry->d_sb;
19666+ udba = au_opt_udba(sb);
19667+ bcpup = *rbcpup;
19668+ err = au_pin(pin, dentry, bcpup, udba,
19669+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
19670+ wh_dentry = ERR_PTR(err);
027c5e7a
AM
19671+ if (unlikely(err))
19672+ goto out;
1facf9fc 19673+
0b1ff5c3
JR
19674+ h_path.dentry = au_pinned_h_parent(pin);
19675+ if (udba != AuOpt_UDBA_NONE
19676+ && au_dbtop(dentry) == bcpup) {
19677+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
19678+ wh_dentry = ERR_PTR(err);
19679+ if (unlikely(err))
19680+ goto out_unpin;
4a4d8108 19681+ }
dece6358 19682+
0b1ff5c3
JR
19683+ h_path.mnt = au_sbr_mnt(sb, bcpup);
19684+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
19685+ wh_dentry = NULL;
19686+ if (!need_wh)
19687+ goto out; /* success, no need to create whiteout */
4a4d8108 19688+
0b1ff5c3
JR
19689+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
19690+ if (IS_ERR(wh_dentry))
19691+ goto out_unpin;
19692+
19693+ /* returns with the parent is locked and wh_dentry is dget-ed */
19694+ goto out; /* success */
1308ab2a 19695+
0b1ff5c3
JR
19696+out_unpin:
19697+ au_unpin(pin);
4f0767ce 19698+out:
0b1ff5c3 19699+ return wh_dentry;
1308ab2a 19700+}
19701+
0b1ff5c3
JR
19702+/*
19703+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
19704+ * in order to be revertible and save time for removing many child whiteouts
19705+ * under the dir.
19706+ * returns 1 when there are too many child whiteout and caller should remove
19707+ * them asynchronously. returns 0 when the number of children is enough small to
19708+ * remove now or the branch fs is a remote fs.
19709+ * otherwise return an error.
19710+ */
19711+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
19712+ struct au_nhash *whlist, struct inode *dir)
4a4d8108 19713+{
0b1ff5c3
JR
19714+ int rmdir_later, err, dirwh;
19715+ struct dentry *h_dentry;
4a4d8108 19716+ struct super_block *sb;
0b1ff5c3 19717+ struct inode *inode;
537831f9 19718+
0b1ff5c3
JR
19719+ sb = dentry->d_sb;
19720+ SiMustAnyLock(sb);
19721+ h_dentry = au_h_dptr(dentry, bindex);
19722+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
7f207e10
AM
19723+ if (unlikely(err))
19724+ goto out;
19725+
0b1ff5c3
JR
19726+ /* stop monitoring */
19727+ inode = d_inode(dentry);
19728+ au_hn_free(au_hi(inode, bindex));
1308ab2a 19729+
0b1ff5c3
JR
19730+ if (!au_test_fs_remote(h_dentry->d_sb)) {
19731+ dirwh = au_sbi(sb)->si_dirwh;
19732+ rmdir_later = (dirwh <= 1);
19733+ if (!rmdir_later)
19734+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
19735+ dirwh);
19736+ if (rmdir_later)
19737+ return rmdir_later;
9dbd164d 19738+ }
4a4d8108 19739+
0b1ff5c3
JR
19740+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
19741+ if (unlikely(err)) {
19742+ AuIOErr("rmdir %pd, b%d failed, %d. ignored\n",
19743+ h_dentry, bindex, err);
19744+ err = 0;
7f207e10 19745+ }
1facf9fc 19746+
7f207e10 19747+out:
0b1ff5c3
JR
19748+ AuTraceErr(err);
19749+ return err;
4a4d8108 19750+}
1facf9fc 19751+
0b1ff5c3
JR
19752+/*
19753+ * final procedure for deleting a entry.
19754+ * maintain dentry and iattr.
19755+ */
19756+static void epilog(struct inode *dir, struct dentry *dentry,
19757+ aufs_bindex_t bindex)
19758+{
19759+ struct inode *inode;
1facf9fc 19760+
0b1ff5c3
JR
19761+ inode = d_inode(dentry);
19762+ d_drop(dentry);
19763+ inode->i_ctime = dir->i_ctime;
b912730e 19764+
0b1ff5c3
JR
19765+ au_dir_ts(dir, bindex);
19766+ dir->i_version++;
19767+}
19768+
19769+/*
19770+ * when an error happened, remove the created whiteout and revert everything.
19771+ */
19772+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
19773+ aufs_bindex_t bwh, struct dentry *wh_dentry,
19774+ struct dentry *dentry, struct au_dtime *dt)
b912730e 19775+{
0b1ff5c3
JR
19776+ int rerr;
19777+ struct path h_path = {
19778+ .dentry = wh_dentry,
19779+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
b912730e
AM
19780+ };
19781+
0b1ff5c3
JR
19782+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
19783+ if (!rerr) {
19784+ au_set_dbwh(dentry, bwh);
19785+ au_dtime_revert(dt);
19786+ return 0;
19787+ }
b912730e 19788+
0b1ff5c3
JR
19789+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", dentry, err, rerr);
19790+ return -EIO;
b912730e
AM
19791+}
19792+
0b1ff5c3
JR
19793+/* ---------------------------------------------------------------------- */
19794+
19795+int aufs_unlink(struct inode *dir, struct dentry *dentry)
b912730e 19796+{
0b1ff5c3
JR
19797+ int err;
19798+ aufs_bindex_t bwh, bindex, btop;
19799+ struct inode *inode, *h_dir, *delegated;
19800+ struct dentry *parent, *wh_dentry;
19801+ /* to reuduce stack size */
19802+ struct {
19803+ struct au_dtime dt;
19804+ struct au_pin pin;
19805+ struct path h_path;
19806+ } *a;
b912730e
AM
19807+
19808+ IMustLock(dir);
b912730e 19809+
0b1ff5c3
JR
19810+ err = -ENOMEM;
19811+ a = kmalloc(sizeof(*a), GFP_NOFS);
19812+ if (unlikely(!a))
b912730e
AM
19813+ goto out;
19814+
0b1ff5c3
JR
19815+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
19816+ if (unlikely(err))
19817+ goto out_free;
19818+ err = au_d_hashed_positive(dentry);
b912730e
AM
19819+ if (unlikely(err))
19820+ goto out_unlock;
0b1ff5c3
JR
19821+ inode = d_inode(dentry);
19822+ IMustLock(inode);
19823+ err = -EISDIR;
19824+ if (unlikely(d_is_dir(dentry)))
19825+ goto out_unlock; /* possible? */
b912730e 19826+
0b1ff5c3
JR
19827+ btop = au_dbtop(dentry);
19828+ bwh = au_dbwh(dentry);
19829+ bindex = -1;
19830+ parent = dentry->d_parent; /* dir inode is locked */
19831+ di_write_lock_parent(parent);
19832+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &a->dt,
19833+ &a->pin);
19834+ err = PTR_ERR(wh_dentry);
19835+ if (IS_ERR(wh_dentry))
19836+ goto out_parent;
b912730e 19837+
0b1ff5c3
JR
19838+ a->h_path.mnt = au_sbr_mnt(dentry->d_sb, btop);
19839+ a->h_path.dentry = au_h_dptr(dentry, btop);
19840+ dget(a->h_path.dentry);
19841+ if (bindex == btop) {
19842+ h_dir = au_pinned_h_dir(&a->pin);
19843+ delegated = NULL;
19844+ err = vfsub_unlink(h_dir, &a->h_path, &delegated, /*force*/0);
19845+ if (unlikely(err == -EWOULDBLOCK)) {
19846+ pr_warn("cannot retry for NFSv4 delegation"
19847+ " for an internal unlink\n");
19848+ iput(delegated);
19849+ }
19850+ } else {
19851+ /* dir inode is locked */
19852+ h_dir = d_inode(wh_dentry->d_parent);
19853+ IMustLock(h_dir);
19854+ err = 0;
b912730e
AM
19855+ }
19856+
0b1ff5c3
JR
19857+ if (!err) {
19858+ vfsub_drop_nlink(inode);
19859+ epilog(dir, dentry, bindex);
b912730e 19860+
0b1ff5c3
JR
19861+ /* update target timestamps */
19862+ if (bindex == btop) {
19863+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL);
19864+ /*ignore*/
19865+ inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
19866+ } else
19867+ /* todo: this timestamp may be reverted later */
19868+ inode->i_ctime = h_dir->i_ctime;
19869+ goto out_unpin; /* success */
b912730e 19870+ }
4a4d8108 19871+
0b1ff5c3
JR
19872+ /* revert */
19873+ if (wh_dentry) {
19874+ int rerr;
027c5e7a 19875+
0b1ff5c3
JR
19876+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
19877+ &a->dt);
19878+ if (rerr)
19879+ err = rerr;
1308ab2a 19880+ }
1facf9fc 19881+
0b1ff5c3
JR
19882+out_unpin:
19883+ au_unpin(&a->pin);
19884+ dput(wh_dentry);
19885+ dput(a->h_path.dentry);
19886+out_parent:
19887+ di_write_unlock(parent);
19888+out_unlock:
19889+ aufs_read_unlock(dentry, AuLock_DW);
19890+out_free:
19891+ kfree(a);
19892+out:
4a4d8108
AM
19893+ return err;
19894+}
1facf9fc 19895+
0b1ff5c3 19896+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
4a4d8108 19897+{
0b1ff5c3
JR
19898+ int err, rmdir_later;
19899+ aufs_bindex_t bwh, bindex, btop;
19900+ struct inode *inode;
19901+ struct dentry *parent, *wh_dentry, *h_dentry;
19902+ struct au_whtmp_rmdir *args;
19903+ /* to reuduce stack size */
19904+ struct {
19905+ struct au_dtime dt;
19906+ struct au_pin pin;
19907+ } *a;
19908+
19909+ IMustLock(dir);
19910+
19911+ err = -ENOMEM;
19912+ a = kmalloc(sizeof(*a), GFP_NOFS);
19913+ if (unlikely(!a))
19914+ goto out;
19915+
19916+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
19917+ if (unlikely(err))
19918+ goto out_free;
19919+ err = au_alive_dir(dentry);
19920+ if (unlikely(err))
19921+ goto out_unlock;
19922+ inode = d_inode(dentry);
19923+ IMustLock(inode);
19924+ err = -ENOTDIR;
19925+ if (unlikely(!d_is_dir(dentry)))
19926+ goto out_unlock; /* possible? */
19927+
19928+ err = -ENOMEM;
19929+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
19930+ if (unlikely(!args))
19931+ goto out_unlock;
19932+
19933+ parent = dentry->d_parent; /* dir inode is locked */
19934+ di_write_lock_parent(parent);
19935+ err = au_test_empty(dentry, &args->whlist);
19936+ if (unlikely(err))
19937+ goto out_parent;
1facf9fc 19938+
5afbbe0d 19939+ btop = au_dbtop(dentry);
0b1ff5c3
JR
19940+ bwh = au_dbwh(dentry);
19941+ bindex = -1;
19942+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &a->dt,
19943+ &a->pin);
19944+ err = PTR_ERR(wh_dentry);
19945+ if (IS_ERR(wh_dentry))
19946+ goto out_parent;
1facf9fc 19947+
0b1ff5c3
JR
19948+ h_dentry = au_h_dptr(dentry, btop);
19949+ dget(h_dentry);
19950+ rmdir_later = 0;
19951+ if (bindex == btop) {
19952+ err = renwh_and_rmdir(dentry, btop, &args->whlist, dir);
19953+ if (err > 0) {
19954+ rmdir_later = err;
19955+ err = 0;
4a4d8108
AM
19956+ }
19957+ } else {
0b1ff5c3
JR
19958+ /* stop monitoring */
19959+ au_hn_free(au_hi(inode, btop));
19960+
19961+ /* dir inode is locked */
19962+ IMustLock(d_inode(wh_dentry->d_parent));
19963+ err = 0;
1308ab2a 19964+ }
027c5e7a 19965+
0b1ff5c3
JR
19966+ if (!err) {
19967+ vfsub_dead_dir(inode);
19968+ au_set_dbdiropq(dentry, -1);
19969+ epilog(dir, dentry, bindex);
4a4d8108 19970+
0b1ff5c3
JR
19971+ if (rmdir_later) {
19972+ au_whtmp_kick_rmdir(dir, btop, h_dentry, args);
19973+ args = NULL;
027c5e7a 19974+ }
0b1ff5c3
JR
19975+
19976+ goto out_unpin; /* success */
19977+ }
19978+
19979+ /* revert */
19980+ AuLabel(revert);
19981+ if (wh_dentry) {
19982+ int rerr;
19983+
19984+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
19985+ &a->dt);
19986+ if (rerr)
19987+ err = rerr;
027c5e7a 19988+ }
86dc4139 19989+
0b1ff5c3
JR
19990+out_unpin:
19991+ au_unpin(&a->pin);
19992+ dput(wh_dentry);
19993+ dput(h_dentry);
19994+out_parent:
19995+ di_write_unlock(parent);
19996+ if (args)
19997+ au_whtmp_rmdir_free(args);
19998+out_unlock:
19999+ aufs_read_unlock(dentry, AuLock_DW);
20000+out_free:
20001+ kfree(a);
86dc4139 20002+out:
0b1ff5c3 20003+ AuTraceErr(err);
86dc4139
AM
20004+ return err;
20005+}
0b1ff5c3
JR
20006diff -urNp -x '*.orig' linux-4.14/fs/aufs/i_op_ren.c linux-4.14/fs/aufs/i_op_ren.c
20007--- linux-4.14/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
20008+++ linux-4.14/fs/aufs/i_op_ren.c 2021-02-24 21:42:43.444448075 +0100
20009@@ -0,0 +1,1246 @@
20010+/*
20011+ * Copyright (C) 2005-2017 Junjiro R. Okajima
20012+ *
20013+ * This program, aufs is free software; you can redistribute it and/or modify
20014+ * it under the terms of the GNU General Public License as published by
20015+ * the Free Software Foundation; either version 2 of the License, or
20016+ * (at your option) any later version.
20017+ *
20018+ * This program is distributed in the hope that it will be useful,
20019+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20020+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20021+ * GNU General Public License for more details.
20022+ *
20023+ * You should have received a copy of the GNU General Public License
20024+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
20025+ */
86dc4139 20026+
0b1ff5c3
JR
20027+/*
20028+ * inode operation (rename entry)
20029+ * todo: this is crazy monster
20030+ */
86dc4139 20031+
0b1ff5c3 20032+#include "aufs.h"
86dc4139 20033+
0b1ff5c3
JR
20034+enum { AuSRC, AuDST, AuSrcDst };
20035+enum { AuPARENT, AuCHILD, AuParentChild };
86dc4139 20036+
0b1ff5c3
JR
20037+#define AuRen_ISDIR_SRC 1
20038+#define AuRen_ISDIR_DST (1 << 1)
20039+#define AuRen_ISSAMEDIR (1 << 2)
20040+#define AuRen_WHSRC (1 << 3)
20041+#define AuRen_WHDST (1 << 4)
20042+#define AuRen_MNT_WRITE (1 << 5)
20043+#define AuRen_DT_DSTDIR (1 << 6)
20044+#define AuRen_DIROPQ_SRC (1 << 7)
20045+#define AuRen_DIROPQ_DST (1 << 8)
20046+#define AuRen_DIRREN (1 << 9)
20047+#define AuRen_DROPPED_SRC (1 << 10)
20048+#define AuRen_DROPPED_DST (1 << 11)
20049+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
20050+#define au_fset_ren(flags, name) \
20051+ do { (flags) |= AuRen_##name; } while (0)
20052+#define au_fclr_ren(flags, name) \
20053+ do { (flags) &= ~AuRen_##name; } while (0)
86dc4139 20054+
0b1ff5c3
JR
20055+#ifndef CONFIG_AUFS_DIRREN
20056+#undef AuRen_DIRREN
20057+#define AuRen_DIRREN 0
20058+#endif
86dc4139 20059+
0b1ff5c3
JR
20060+struct au_ren_args {
20061+ struct {
20062+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
20063+ *wh_dentry;
20064+ struct inode *dir, *inode;
20065+ struct au_hinode *hdir, *hinode;
20066+ struct au_dtime dt[AuParentChild];
20067+ aufs_bindex_t btop, bdiropq;
20068+ } sd[AuSrcDst];
86dc4139 20069+
0b1ff5c3
JR
20070+#define src_dentry sd[AuSRC].dentry
20071+#define src_dir sd[AuSRC].dir
20072+#define src_inode sd[AuSRC].inode
20073+#define src_h_dentry sd[AuSRC].h_dentry
20074+#define src_parent sd[AuSRC].parent
20075+#define src_h_parent sd[AuSRC].h_parent
20076+#define src_wh_dentry sd[AuSRC].wh_dentry
20077+#define src_hdir sd[AuSRC].hdir
20078+#define src_hinode sd[AuSRC].hinode
20079+#define src_h_dir sd[AuSRC].hdir->hi_inode
20080+#define src_dt sd[AuSRC].dt
20081+#define src_btop sd[AuSRC].btop
20082+#define src_bdiropq sd[AuSRC].bdiropq
86dc4139 20083+
0b1ff5c3
JR
20084+#define dst_dentry sd[AuDST].dentry
20085+#define dst_dir sd[AuDST].dir
20086+#define dst_inode sd[AuDST].inode
20087+#define dst_h_dentry sd[AuDST].h_dentry
20088+#define dst_parent sd[AuDST].parent
20089+#define dst_h_parent sd[AuDST].h_parent
20090+#define dst_wh_dentry sd[AuDST].wh_dentry
20091+#define dst_hdir sd[AuDST].hdir
20092+#define dst_hinode sd[AuDST].hinode
20093+#define dst_h_dir sd[AuDST].hdir->hi_inode
20094+#define dst_dt sd[AuDST].dt
20095+#define dst_btop sd[AuDST].btop
20096+#define dst_bdiropq sd[AuDST].bdiropq
86dc4139 20097+
0b1ff5c3
JR
20098+ struct dentry *h_trap;
20099+ struct au_branch *br;
20100+ struct path h_path;
20101+ struct au_nhash whlist;
20102+ aufs_bindex_t btgt, src_bwh;
86dc4139 20103+
0b1ff5c3
JR
20104+ struct {
20105+ unsigned short auren_flags;
20106+ unsigned char flags; /* syscall parameter */
20107+ unsigned char exchange;
20108+ } __packed;
86dc4139 20109+
0b1ff5c3
JR
20110+ struct au_whtmp_rmdir *thargs;
20111+ struct dentry *h_dst;
20112+ struct au_hinode *h_root;
20113+};
86dc4139 20114+
0b1ff5c3 20115+/* ---------------------------------------------------------------------- */
86dc4139 20116+
0b1ff5c3
JR
20117+/*
20118+ * functions for reverting.
20119+ * when an error happened in a single rename systemcall, we should revert
20120+ * everything as if nothing happened.
20121+ * we don't need to revert the copied-up/down the parent dir since they are
20122+ * harmless.
20123+ */
86dc4139 20124+
0b1ff5c3
JR
20125+#define RevertFailure(fmt, ...) do { \
20126+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
20127+ ##__VA_ARGS__, err, rerr); \
20128+ err = -EIO; \
20129+} while (0)
1facf9fc 20130+
0b1ff5c3 20131+static void au_ren_do_rev_diropq(int err, struct au_ren_args *a, int idx)
86dc4139 20132+{
0b1ff5c3
JR
20133+ int rerr;
20134+ struct dentry *d;
20135+#define src_or_dst(member) a->sd[idx].member
1308ab2a 20136+
0b1ff5c3
JR
20137+ d = src_or_dst(dentry); /* {src,dst}_dentry */
20138+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD);
20139+ rerr = au_diropq_remove(d, a->btgt);
20140+ au_hn_inode_unlock(src_or_dst(hinode));
20141+ au_set_dbdiropq(d, src_or_dst(bdiropq));
20142+ if (rerr)
20143+ RevertFailure("remove diropq %pd", d);
20144+
20145+#undef src_or_dst_
dece6358 20146+}
1facf9fc 20147+
0b1ff5c3 20148+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
dece6358 20149+{
0b1ff5c3
JR
20150+ if (au_ftest_ren(a->auren_flags, DIROPQ_SRC))
20151+ au_ren_do_rev_diropq(err, a, AuSRC);
20152+ if (au_ftest_ren(a->auren_flags, DIROPQ_DST))
20153+ au_ren_do_rev_diropq(err, a, AuDST);
4a4d8108 20154+}
1308ab2a 20155+
0b1ff5c3 20156+static void au_ren_rev_rename(int err, struct au_ren_args *a)
4a4d8108 20157+{
0b1ff5c3
JR
20158+ int rerr;
20159+ struct inode *delegated;
dece6358 20160+
0b1ff5c3
JR
20161+ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name,
20162+ a->src_h_parent);
20163+ rerr = PTR_ERR(a->h_path.dentry);
20164+ if (IS_ERR(a->h_path.dentry)) {
20165+ RevertFailure("lkup one %pd", a->src_dentry);
20166+ return;
4a4d8108 20167+ }
1308ab2a 20168+
0b1ff5c3
JR
20169+ delegated = NULL;
20170+ rerr = vfsub_rename(a->dst_h_dir,
20171+ au_h_dptr(a->src_dentry, a->btgt),
20172+ a->src_h_dir, &a->h_path, &delegated, a->flags);
20173+ if (unlikely(rerr == -EWOULDBLOCK)) {
20174+ pr_warn("cannot retry for NFSv4 delegation"
20175+ " for an internal rename\n");
20176+ iput(delegated);
dece6358 20177+ }
0b1ff5c3
JR
20178+ d_drop(a->h_path.dentry);
20179+ dput(a->h_path.dentry);
20180+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
20181+ if (rerr)
20182+ RevertFailure("rename %pd", a->src_dentry);
1facf9fc 20183+}
20184+
0b1ff5c3 20185+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
4a4d8108 20186+{
0b1ff5c3
JR
20187+ int rerr;
20188+ struct inode *delegated;
4a4d8108 20189+
0b1ff5c3
JR
20190+ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name,
20191+ a->dst_h_parent);
20192+ rerr = PTR_ERR(a->h_path.dentry);
20193+ if (IS_ERR(a->h_path.dentry)) {
20194+ RevertFailure("lkup one %pd", a->dst_dentry);
20195+ return;
20196+ }
20197+ if (d_is_positive(a->h_path.dentry)) {
20198+ d_drop(a->h_path.dentry);
20199+ dput(a->h_path.dentry);
20200+ return;
20201+ }
86dc4139 20202+
0b1ff5c3
JR
20203+ delegated = NULL;
20204+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path,
20205+ &delegated, a->flags);
20206+ if (unlikely(rerr == -EWOULDBLOCK)) {
20207+ pr_warn("cannot retry for NFSv4 delegation"
20208+ " for an internal rename\n");
20209+ iput(delegated);
20210+ }
20211+ d_drop(a->h_path.dentry);
20212+ dput(a->h_path.dentry);
20213+ if (!rerr)
20214+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
20215+ else
20216+ RevertFailure("rename %pd", a->h_dst);
4a4d8108
AM
20217+}
20218+
0b1ff5c3 20219+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
4a4d8108 20220+{
0b1ff5c3
JR
20221+ int rerr;
20222+
20223+ a->h_path.dentry = a->src_wh_dentry;
20224+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
20225+ au_set_dbwh(a->src_dentry, a->src_bwh);
20226+ if (rerr)
20227+ RevertFailure("unlink %pd", a->src_wh_dentry);
4a4d8108 20228+}
0b1ff5c3 20229+#undef RevertFailure
4a4d8108 20230+
dece6358
AM
20231+/* ---------------------------------------------------------------------- */
20232+
1308ab2a 20233+/*
0b1ff5c3
JR
20234+ * when we have to copyup the renaming entry, do it with the rename-target name
20235+ * in order to minimize the cost (the later actual rename is unnecessary).
20236+ * otherwise rename it on the target branch.
1308ab2a 20237+ */
0b1ff5c3 20238+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 20239+{
4a4d8108 20240+ int err;
0b1ff5c3
JR
20241+ struct dentry *d;
20242+ struct inode *delegated;
1facf9fc 20243+
0b1ff5c3
JR
20244+ d = a->src_dentry;
20245+ if (au_dbtop(d) == a->btgt) {
20246+ a->h_path.dentry = a->dst_h_dentry;
20247+ AuDebugOn(au_dbtop(d) != a->btgt);
20248+ delegated = NULL;
20249+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
20250+ a->dst_h_dir, &a->h_path, &delegated,
20251+ a->flags);
20252+ if (unlikely(err == -EWOULDBLOCK)) {
20253+ pr_warn("cannot retry for NFSv4 delegation"
20254+ " for an internal rename\n");
20255+ iput(delegated);
20256+ }
20257+ } else
20258+ BUG();
20259+
20260+ if (!err && a->h_dst)
20261+ /* it will be set to dinfo later */
20262+ dget(a->h_dst);
1facf9fc 20263+
1308ab2a 20264+ return err;
20265+}
dece6358 20266+
0b1ff5c3
JR
20267+/* cf. aufs_rmdir() */
20268+static int au_ren_del_whtmp(struct au_ren_args *a)
1308ab2a 20269+{
20270+ int err;
0b1ff5c3 20271+ struct inode *dir;
4a4d8108 20272+
0b1ff5c3
JR
20273+ dir = a->dst_dir;
20274+ SiMustAnyLock(dir->i_sb);
20275+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
20276+ au_sbi(dir->i_sb)->si_dirwh)
20277+ || au_test_fs_remote(a->h_dst->d_sb)) {
20278+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
20279+ if (unlikely(err))
20280+ pr_warn("failed removing whtmp dir %pd (%d), "
20281+ "ignored.\n", a->h_dst, err);
20282+ } else {
20283+ au_nhash_wh_free(&a->thargs->whlist);
20284+ a->thargs->whlist = a->whlist;
20285+ a->whlist.nh_num = 0;
20286+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
20287+ dput(a->h_dst);
20288+ a->thargs = NULL;
4a4d8108
AM
20289+ }
20290+
0b1ff5c3
JR
20291+ return 0;
20292+}
4a4d8108 20293+
0b1ff5c3
JR
20294+/* make it 'opaque' dir. */
20295+static int au_ren_do_diropq(struct au_ren_args *a, int idx)
20296+{
20297+ int err;
20298+ struct dentry *d, *diropq;
20299+#define src_or_dst(member) a->sd[idx].member
4a4d8108 20300+
0b1ff5c3
JR
20301+ err = 0;
20302+ d = src_or_dst(dentry); /* {src,dst}_dentry */
20303+ src_or_dst(bdiropq) = au_dbdiropq(d);
20304+ src_or_dst(hinode) = au_hi(src_or_dst(inode), a->btgt);
20305+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD);
20306+ diropq = au_diropq_create(d, a->btgt);
20307+ au_hn_inode_unlock(src_or_dst(hinode));
20308+ if (IS_ERR(diropq))
20309+ err = PTR_ERR(diropq);
20310+ else
20311+ dput(diropq);
4a4d8108 20312+
0b1ff5c3
JR
20313+#undef src_or_dst_
20314+ return err;
20315+}
4a4d8108 20316+
0b1ff5c3
JR
20317+static int au_ren_diropq(struct au_ren_args *a)
20318+{
20319+ int err;
20320+ unsigned char always;
20321+ struct dentry *d;
1308ab2a 20322+
0b1ff5c3
JR
20323+ err = 0;
20324+ d = a->dst_dentry; /* already renamed on the branch */
20325+ always = !!au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ);
20326+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)
20327+ && !au_ftest_ren(a->auren_flags, DIRREN)
20328+ && a->btgt != au_dbdiropq(a->src_dentry)
20329+ && (a->dst_wh_dentry
20330+ || a->btgt <= au_dbdiropq(d)
20331+ /* hide the lower to keep xino */
20332+ /* the lowers may not be a dir, but we hide them anyway */
20333+ || a->btgt < au_dbbot(d)
20334+ || always)) {
20335+ AuDbg("here\n");
20336+ err = au_ren_do_diropq(a, AuSRC);
20337+ if (unlikely(err))
20338+ goto out;
20339+ au_fset_ren(a->auren_flags, DIROPQ_SRC);
20340+ }
20341+ if (!a->exchange)
dece6358 20342+ goto out; /* success */
0b1ff5c3
JR
20343+
20344+ d = a->src_dentry; /* already renamed on the branch */
20345+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)
20346+ && a->btgt != au_dbdiropq(a->dst_dentry)
20347+ && (a->btgt < au_dbdiropq(d)
20348+ || a->btgt < au_dbbot(d)
20349+ || always)) {
20350+ AuDbgDentry(a->src_dentry);
20351+ AuDbgDentry(a->dst_dentry);
20352+ err = au_ren_do_diropq(a, AuDST);
20353+ if (unlikely(err))
20354+ goto out_rev_src;
20355+ au_fset_ren(a->auren_flags, DIROPQ_DST);
4a4d8108 20356+ }
0b1ff5c3
JR
20357+ goto out; /* success */
20358+
20359+out_rev_src:
20360+ AuDbg("err %d, reverting src\n", err);
20361+ au_ren_rev_diropq(err, a);
4f0767ce 20362+out:
1facf9fc 20363+ return err;
20364+}
20365+
0b1ff5c3 20366+static int do_rename(struct au_ren_args *a)
1facf9fc 20367+{
4a4d8108 20368+ int err;
0b1ff5c3 20369+ struct dentry *d, *h_d;
dece6358 20370+
0b1ff5c3
JR
20371+ if (!a->exchange) {
20372+ /* prepare workqueue args for asynchronous rmdir */
20373+ h_d = a->dst_h_dentry;
20374+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)
20375+ /* && !au_ftest_ren(a->auren_flags, DIRREN) */
20376+ && d_is_positive(h_d)) {
20377+ err = -ENOMEM;
20378+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb,
20379+ GFP_NOFS);
20380+ if (unlikely(!a->thargs))
20381+ goto out;
20382+ a->h_dst = dget(h_d);
20383+ }
f2c43d5f 20384+
0b1ff5c3
JR
20385+ /* create whiteout for src_dentry */
20386+ if (au_ftest_ren(a->auren_flags, WHSRC)) {
20387+ a->src_bwh = au_dbwh(a->src_dentry);
20388+ AuDebugOn(a->src_bwh >= 0);
20389+ a->src_wh_dentry = au_wh_create(a->src_dentry, a->btgt,
20390+ a->src_h_parent);
20391+ err = PTR_ERR(a->src_wh_dentry);
20392+ if (IS_ERR(a->src_wh_dentry))
20393+ goto out_thargs;
20394+ }
1facf9fc 20395+
0b1ff5c3
JR
20396+ /* lookup whiteout for dentry */
20397+ if (au_ftest_ren(a->auren_flags, WHDST)) {
20398+ h_d = au_wh_lkup(a->dst_h_parent,
20399+ &a->dst_dentry->d_name, a->br);
20400+ err = PTR_ERR(h_d);
20401+ if (IS_ERR(h_d))
20402+ goto out_whsrc;
20403+ if (d_is_negative(h_d))
20404+ dput(h_d);
20405+ else
20406+ a->dst_wh_dentry = h_d;
20407+ }
dece6358 20408+
0b1ff5c3
JR
20409+ /* rename dentry to tmpwh */
20410+ if (a->thargs) {
20411+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
20412+ if (unlikely(err))
20413+ goto out_whdst;
e49829fe 20414+
0b1ff5c3
JR
20415+ d = a->dst_dentry;
20416+ au_set_h_dptr(d, a->btgt, NULL);
20417+ err = au_lkup_neg(d, a->btgt, /*wh*/0);
4a4d8108 20418+ if (unlikely(err))
0b1ff5c3
JR
20419+ goto out_whtmp;
20420+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
4a4d8108 20421+ }
dece6358 20422+ }
dece6358 20423+
0b1ff5c3
JR
20424+ BUG_ON(d_is_positive(a->dst_h_dentry) && a->src_btop != a->btgt);
20425+#if 0
20426+ BUG_ON(!au_ftest_ren(a->auren_flags, DIRREN)
20427+ && d_is_positive(a->dst_h_dentry)
20428+ && a->src_btop != a->btgt);
20429+#endif
dece6358 20430+
0b1ff5c3
JR
20431+ /* rename by vfs_rename or cpup */
20432+ err = au_ren_or_cpup(a);
20433+ if (unlikely(err))
20434+ /* leave the copied-up one */
20435+ goto out_whtmp;
dece6358 20436+
0b1ff5c3
JR
20437+ /* make dir opaque */
20438+ err = au_ren_diropq(a);
20439+ if (unlikely(err))
20440+ goto out_rename;
1308ab2a 20441+
0b1ff5c3
JR
20442+ /* update target timestamps */
20443+ if (a->exchange) {
20444+ AuDebugOn(au_dbtop(a->dst_dentry) != a->btgt);
20445+ a->h_path.dentry = au_h_dptr(a->dst_dentry, a->btgt);
20446+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
20447+ a->dst_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
20448+ }
20449+ AuDebugOn(au_dbtop(a->src_dentry) != a->btgt);
20450+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
20451+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
20452+ a->src_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
1308ab2a 20453+
0b1ff5c3
JR
20454+ if (!a->exchange) {
20455+ /* remove whiteout for dentry */
20456+ if (a->dst_wh_dentry) {
20457+ a->h_path.dentry = a->dst_wh_dentry;
20458+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
20459+ a->dst_dentry);
20460+ if (unlikely(err))
20461+ goto out_diropq;
523b37e3 20462+ }
0b1ff5c3
JR
20463+
20464+ /* remove whtmp */
20465+ if (a->thargs)
20466+ au_ren_del_whtmp(a); /* ignore this error */
20467+
20468+ au_fhsm_wrote(a->src_dentry->d_sb, a->btgt, /*force*/0);
523b37e3 20469+ }
0b1ff5c3
JR
20470+ err = 0;
20471+ goto out_success;
1308ab2a 20472+
0b1ff5c3
JR
20473+out_diropq:
20474+ au_ren_rev_diropq(err, a);
20475+out_rename:
20476+ au_ren_rev_rename(err, a);
20477+ dput(a->h_dst);
20478+out_whtmp:
20479+ if (a->thargs)
20480+ au_ren_rev_whtmp(err, a);
20481+out_whdst:
20482+ dput(a->dst_wh_dentry);
20483+ a->dst_wh_dentry = NULL;
20484+out_whsrc:
20485+ if (a->src_wh_dentry)
20486+ au_ren_rev_whsrc(err, a);
20487+out_success:
20488+ dput(a->src_wh_dentry);
20489+ dput(a->dst_wh_dentry);
20490+out_thargs:
20491+ if (a->thargs) {
20492+ dput(a->h_dst);
20493+ au_whtmp_rmdir_free(a->thargs);
20494+ a->thargs = NULL;
4a4d8108 20495+ }
4f0767ce 20496+out:
4a4d8108 20497+ return err;
1facf9fc 20498+}
20499+
0b1ff5c3 20500+/* ---------------------------------------------------------------------- */
c1595e42 20501+
0b1ff5c3
JR
20502+/*
20503+ * test if @dentry dir can be rename destination or not.
20504+ * success means, it is a logically empty dir.
20505+ */
20506+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
20507+{
20508+ return au_test_empty(dentry, whlist);
c1595e42
JR
20509+}
20510+
0b1ff5c3
JR
20511+/*
20512+ * test if @a->src_dentry dir can be rename source or not.
20513+ * if it can, return 0.
20514+ * success means,
20515+ * - it is a logically empty dir.
20516+ * - or, it exists on writable branch and has no children including whiteouts
20517+ * on the lower branch unless DIRREN is on.
20518+ */
20519+static int may_rename_srcdir(struct au_ren_args *a)
c1595e42
JR
20520+{
20521+ int err;
0b1ff5c3
JR
20522+ unsigned int rdhash;
20523+ aufs_bindex_t btop, btgt;
20524+ struct dentry *dentry;
c1595e42 20525+ struct super_block *sb;
0b1ff5c3 20526+ struct au_sbinfo *sbinfo;
c1595e42 20527+
0b1ff5c3 20528+ dentry = a->src_dentry;
c1595e42 20529+ sb = dentry->d_sb;
0b1ff5c3
JR
20530+ sbinfo = au_sbi(sb);
20531+ if (au_opt_test(sbinfo->si_mntflags, DIRREN))
20532+ au_fset_ren(a->auren_flags, DIRREN);
c1595e42 20533+
0b1ff5c3
JR
20534+ btgt = a->btgt;
20535+ btop = au_dbtop(dentry);
20536+ if (btop != btgt) {
20537+ struct au_nhash whlist;
c1595e42 20538+
0b1ff5c3
JR
20539+ SiMustAnyLock(sb);
20540+ rdhash = sbinfo->si_rdhash;
20541+ if (!rdhash)
20542+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
20543+ dentry));
20544+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
20545+ if (unlikely(err))
20546+ goto out;
20547+ err = au_test_empty(dentry, &whlist);
20548+ au_nhash_wh_free(&whlist);
20549+ goto out;
c1595e42 20550+ }
c1595e42 20551+
0b1ff5c3
JR
20552+ if (btop == au_dbtaildir(dentry))
20553+ return 0; /* success */
9dbd164d 20554+
0b1ff5c3 20555+ err = au_test_empty_lower(dentry);
1facf9fc 20556+
0b1ff5c3
JR
20557+out:
20558+ if (err == -ENOTEMPTY) {
20559+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
20560+ err = 0;
20561+ } else {
20562+ AuWarn1("renaming dir who has child(ren) on multiple "
20563+ "branches, is not supported\n");
20564+ err = -EXDEV;
20565+ }
4a4d8108 20566+ }
0b1ff5c3 20567+ return err;
1facf9fc 20568+}
20569+
0b1ff5c3
JR
20570+/* side effect: sets whlist and h_dentry */
20571+static int au_ren_may_dir(struct au_ren_args *a)
1facf9fc 20572+{
4a4d8108 20573+ int err;
0b1ff5c3
JR
20574+ unsigned int rdhash;
20575+ struct dentry *d;
1facf9fc 20576+
0b1ff5c3
JR
20577+ d = a->dst_dentry;
20578+ SiMustAnyLock(d->d_sb);
c1595e42
JR
20579+
20580+ err = 0;
0b1ff5c3
JR
20581+ if (au_ftest_ren(a->auren_flags, ISDIR_DST) && a->dst_inode) {
20582+ rdhash = au_sbi(d->d_sb)->si_rdhash;
20583+ if (!rdhash)
20584+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
20585+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
20586+ if (unlikely(err))
20587+ goto out;
1facf9fc 20588+
0b1ff5c3
JR
20589+ if (!a->exchange) {
20590+ au_set_dbtop(d, a->dst_btop);
20591+ err = may_rename_dstdir(d, &a->whlist);
20592+ au_set_dbtop(d, a->btgt);
20593+ } else
20594+ err = may_rename_srcdir(a);
20595+ }
20596+ a->dst_h_dentry = au_h_dptr(d, au_dbtop(d));
20597+ if (unlikely(err))
20598+ goto out;
a2654f78 20599+
0b1ff5c3
JR
20600+ d = a->src_dentry;
20601+ a->src_h_dentry = au_h_dptr(d, au_dbtop(d));
20602+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) {
20603+ err = may_rename_srcdir(a);
20604+ if (unlikely(err)) {
20605+ au_nhash_wh_free(&a->whlist);
20606+ a->whlist.nh_num = 0;
4a4d8108 20607+ }
4a4d8108 20608+ }
c1595e42
JR
20609+out:
20610+ return err;
20611+}
20612+
0b1ff5c3
JR
20613+/* ---------------------------------------------------------------------- */
20614+
20615+/*
20616+ * simple tests for rename.
20617+ * following the checks in vfs, plus the parent-child relationship.
20618+ */
20619+static int au_may_ren(struct au_ren_args *a)
c1595e42 20620+{
0b1ff5c3
JR
20621+ int err, isdir;
20622+ struct inode *h_inode;
c1595e42 20623+
0b1ff5c3
JR
20624+ if (a->src_btop == a->btgt) {
20625+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
20626+ au_ftest_ren(a->auren_flags, ISDIR_SRC));
20627+ if (unlikely(err))
20628+ goto out;
20629+ err = -EINVAL;
20630+ if (unlikely(a->src_h_dentry == a->h_trap))
20631+ goto out;
20632+ }
20633+
20634+ err = 0;
20635+ if (a->dst_btop != a->btgt)
c1595e42 20636+ goto out;
4a4d8108 20637+
0b1ff5c3
JR
20638+ err = -ENOTEMPTY;
20639+ if (unlikely(a->dst_h_dentry == a->h_trap))
20640+ goto out;
20641+
20642+ err = -EIO;
20643+ isdir = !!au_ftest_ren(a->auren_flags, ISDIR_DST);
20644+ if (d_really_is_negative(a->dst_dentry)) {
20645+ if (d_is_negative(a->dst_h_dentry))
20646+ err = au_may_add(a->dst_dentry, a->btgt,
20647+ a->dst_h_parent, isdir);
20648+ } else {
20649+ if (unlikely(d_is_negative(a->dst_h_dentry)))
20650+ goto out;
20651+ h_inode = d_inode(a->dst_h_dentry);
20652+ if (h_inode->i_nlink)
20653+ err = au_may_del(a->dst_dentry, a->btgt,
20654+ a->dst_h_parent, isdir);
1facf9fc 20655+ }
4a4d8108 20656+
7f207e10 20657+out:
0b1ff5c3
JR
20658+ if (unlikely(err == -ENOENT || err == -EEXIST))
20659+ err = -EIO;
7f207e10 20660+ AuTraceErr(err);
4a4d8108 20661+ return err;
1facf9fc 20662+}
20663+
20664+/* ---------------------------------------------------------------------- */
20665+
0b1ff5c3
JR
20666+/*
20667+ * locking order
20668+ * (VFS)
20669+ * - src_dir and dir by lock_rename()
20670+ * - inode if exitsts
20671+ * (aufs)
20672+ * - lock all
20673+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
20674+ * + si_read_lock
20675+ * + di_write_lock2_child()
20676+ * + di_write_lock_child()
20677+ * + ii_write_lock_child()
20678+ * + di_write_lock_child2()
20679+ * + ii_write_lock_child2()
20680+ * + src_parent and parent
20681+ * + di_write_lock_parent()
20682+ * + ii_write_lock_parent()
20683+ * + di_write_lock_parent2()
20684+ * + ii_write_lock_parent2()
20685+ * + lower src_dir and dir by vfsub_lock_rename()
20686+ * + verify the every relationships between child and parent. if any
20687+ * of them failed, unlock all and return -EBUSY.
20688+ */
20689+static void au_ren_unlock(struct au_ren_args *a)
20690+{
20691+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
20692+ a->dst_h_parent, a->dst_hdir);
20693+ if (au_ftest_ren(a->auren_flags, DIRREN)
20694+ && a->h_root)
20695+ au_hn_inode_unlock(a->h_root);
20696+ if (au_ftest_ren(a->auren_flags, MNT_WRITE))
20697+ vfsub_mnt_drop_write(au_br_mnt(a->br));
20698+}
20699+
20700+static int au_ren_lock(struct au_ren_args *a)
4a4d8108
AM
20701+{
20702+ int err;
0b1ff5c3 20703+ unsigned int udba;
1facf9fc 20704+
0b1ff5c3
JR
20705+ err = 0;
20706+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
20707+ a->src_hdir = au_hi(a->src_dir, a->btgt);
20708+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
20709+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
febd17d6 20710+
0b1ff5c3 20711+ err = vfsub_mnt_want_write(au_br_mnt(a->br));
027c5e7a 20712+ if (unlikely(err))
c2c0f25c 20713+ goto out;
0b1ff5c3
JR
20714+ au_fset_ren(a->auren_flags, MNT_WRITE);
20715+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
20716+ struct dentry *root;
20717+ struct inode *dir;
027c5e7a 20718+
0b1ff5c3
JR
20719+ /*
20720+ * sbinfo is already locked, so this ii_read_lock is
20721+ * unnecessary. but our debugging feature checks it.
20722+ */
20723+ root = a->src_inode->i_sb->s_root;
20724+ if (root != a->src_parent && root != a->dst_parent) {
20725+ dir = d_inode(root);
20726+ ii_read_lock_parent3(dir);
20727+ a->h_root = au_hi(dir, a->btgt);
20728+ ii_read_unlock(dir);
20729+ au_hn_inode_lock_nested(a->h_root, AuLsc_I_PARENT3);
c2c0f25c
AM
20730+ }
20731+ }
0b1ff5c3
JR
20732+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
20733+ a->dst_h_parent, a->dst_hdir);
20734+ udba = au_opt_udba(a->src_dentry->d_sb);
20735+ if (unlikely(a->src_hdir->hi_inode != d_inode(a->src_h_parent)
20736+ || a->dst_hdir->hi_inode != d_inode(a->dst_h_parent)))
20737+ err = au_busy_or_stale();
20738+ if (!err && au_dbtop(a->src_dentry) == a->btgt)
20739+ err = au_h_verify(a->src_h_dentry, udba,
20740+ d_inode(a->src_h_parent), a->src_h_parent,
20741+ a->br);
20742+ if (!err && au_dbtop(a->dst_dentry) == a->btgt)
20743+ err = au_h_verify(a->dst_h_dentry, udba,
20744+ d_inode(a->dst_h_parent), a->dst_h_parent,
20745+ a->br);
20746+ if (!err)
20747+ goto out; /* success */
1facf9fc 20748+
0b1ff5c3
JR
20749+ err = au_busy_or_stale();
20750+ au_ren_unlock(a);
c2c0f25c 20751+
4f0767ce 20752+out:
0b1ff5c3 20753+ return err;
4a4d8108 20754+}
1facf9fc 20755+
4a4d8108 20756+/* ---------------------------------------------------------------------- */
1facf9fc 20757+
0b1ff5c3 20758+static void au_ren_refresh_dir(struct au_ren_args *a)
e2f27e51 20759+{
0b1ff5c3
JR
20760+ struct inode *dir;
20761+
20762+ dir = a->dst_dir;
20763+ dir->i_version++;
20764+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) {
20765+ /* is this updating defined in POSIX? */
20766+ au_cpup_attr_timesizes(a->src_inode);
20767+ au_cpup_attr_nlink(dir, /*force*/1);
20768+ }
20769+ au_dir_ts(dir, a->btgt);
20770+
20771+ if (a->exchange) {
20772+ dir = a->src_dir;
20773+ dir->i_version++;
20774+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)) {
20775+ /* is this updating defined in POSIX? */
20776+ au_cpup_attr_timesizes(a->dst_inode);
20777+ au_cpup_attr_nlink(dir, /*force*/1);
20778+ }
20779+ au_dir_ts(dir, a->btgt);
20780+ }
20781+
20782+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR))
20783+ return;
20784+
20785+ dir = a->src_dir;
20786+ dir->i_version++;
20787+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC))
20788+ au_cpup_attr_nlink(dir, /*force*/1);
20789+ au_dir_ts(dir, a->btgt);
e2f27e51
AM
20790+}
20791+
0b1ff5c3 20792+static void au_ren_refresh(struct au_ren_args *a)
4a4d8108 20793+{
0b1ff5c3
JR
20794+ aufs_bindex_t bbot, bindex;
20795+ struct dentry *d, *h_d;
20796+ struct inode *i, *h_i;
0c3ec466 20797+ struct super_block *sb;
0c3ec466 20798+
0b1ff5c3
JR
20799+ d = a->dst_dentry;
20800+ d_drop(d);
20801+ if (a->h_dst)
20802+ /* already dget-ed by au_ren_or_cpup() */
20803+ au_set_h_dptr(d, a->btgt, a->h_dst);
e2f27e51 20804+
0b1ff5c3
JR
20805+ i = a->dst_inode;
20806+ if (i) {
20807+ if (!a->exchange) {
20808+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST))
20809+ vfsub_drop_nlink(i);
20810+ else {
20811+ vfsub_dead_dir(i);
20812+ au_cpup_attr_timesizes(i);
20813+ }
20814+ au_update_dbrange(d, /*do_put_zero*/1);
20815+ } else
20816+ au_cpup_attr_nlink(i, /*force*/1);
20817+ } else {
20818+ bbot = a->btgt;
20819+ for (bindex = au_dbtop(d); bindex < bbot; bindex++)
20820+ au_set_h_dptr(d, bindex, NULL);
20821+ bbot = au_dbbot(d);
20822+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++)
20823+ au_set_h_dptr(d, bindex, NULL);
20824+ au_update_dbrange(d, /*do_put_zero*/0);
20825+ }
e2f27e51 20826+
0b1ff5c3
JR
20827+ if (a->exchange
20828+ || au_ftest_ren(a->auren_flags, DIRREN)) {
20829+ d_drop(a->src_dentry);
20830+ if (au_ftest_ren(a->auren_flags, DIRREN))
20831+ au_set_dbwh(a->src_dentry, -1);
20832+ return;
e2f27e51
AM
20833+ }
20834+
0b1ff5c3
JR
20835+ d = a->src_dentry;
20836+ au_set_dbwh(d, -1);
20837+ bbot = au_dbbot(d);
20838+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) {
20839+ h_d = au_h_dptr(d, bindex);
20840+ if (h_d)
20841+ au_set_h_dptr(d, bindex, NULL);
20842+ }
20843+ au_set_dbbot(d, a->btgt);
38d290e6 20844+
0b1ff5c3
JR
20845+ sb = d->d_sb;
20846+ i = a->src_inode;
20847+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
20848+ return; /* success */
38d290e6 20849+
0b1ff5c3
JR
20850+ bbot = au_ibbot(i);
20851+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) {
20852+ h_i = au_h_iptr(i, bindex);
20853+ if (h_i) {
20854+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
20855+ /* ignore this error */
20856+ au_set_h_iptr(i, bindex, NULL, 0);
20857+ }
20858+ }
20859+ au_set_ibbot(i, a->btgt);
4a4d8108 20860+}
1facf9fc 20861+
4a4d8108 20862+/* ---------------------------------------------------------------------- */
1308ab2a 20863+
0b1ff5c3
JR
20864+/* mainly for link(2) and rename(2) */
20865+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
20866+{
20867+ aufs_bindex_t bdiropq, bwh;
20868+ struct dentry *parent;
20869+ struct au_branch *br;
b95c5147 20870+
0b1ff5c3
JR
20871+ parent = dentry->d_parent;
20872+ IMustLock(d_inode(parent)); /* dir is locked */
c1595e42 20873+
0b1ff5c3
JR
20874+ bdiropq = au_dbdiropq(parent);
20875+ bwh = au_dbwh(dentry);
20876+ br = au_sbr(dentry->d_sb, btgt);
20877+ if (au_br_rdonly(br)
20878+ || (0 <= bdiropq && bdiropq < btgt)
20879+ || (0 <= bwh && bwh < btgt))
20880+ btgt = -1;
0c3ec466 20881+
0b1ff5c3
JR
20882+ AuDbg("btgt %d\n", btgt);
20883+ return btgt;
20884+}
c1595e42 20885+
0b1ff5c3
JR
20886+/* sets src_btop, dst_btop and btgt */
20887+static int au_ren_wbr(struct au_ren_args *a)
20888+{
20889+ int err;
20890+ struct au_wr_dir_args wr_dir_args = {
20891+ /* .force_btgt = -1, */
20892+ .flags = AuWrDir_ADD_ENTRY
20893+ };
c1595e42 20894+
0b1ff5c3
JR
20895+ a->src_btop = au_dbtop(a->src_dentry);
20896+ a->dst_btop = au_dbtop(a->dst_dentry);
20897+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)
20898+ || au_ftest_ren(a->auren_flags, ISDIR_DST))
20899+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
20900+ wr_dir_args.force_btgt = a->src_btop;
20901+ if (a->dst_inode && a->dst_btop < a->src_btop)
20902+ wr_dir_args.force_btgt = a->dst_btop;
20903+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
20904+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
20905+ a->btgt = err;
20906+ if (a->exchange)
20907+ au_update_dbtop(a->dst_dentry);
0c3ec466 20908+
0b1ff5c3
JR
20909+ return err;
20910+}
c1595e42 20911+
0b1ff5c3
JR
20912+static void au_ren_dt(struct au_ren_args *a)
20913+{
20914+ a->h_path.dentry = a->src_h_parent;
20915+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
20916+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) {
20917+ a->h_path.dentry = a->dst_h_parent;
20918+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
b95c5147 20919+ }
1facf9fc 20920+
0b1ff5c3
JR
20921+ au_fclr_ren(a->auren_flags, DT_DSTDIR);
20922+ if (!au_ftest_ren(a->auren_flags, ISDIR_SRC)
20923+ && !a->exchange)
20924+ return;
dece6358 20925+
0b1ff5c3
JR
20926+ a->h_path.dentry = a->src_h_dentry;
20927+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
20928+ if (d_is_positive(a->dst_h_dentry)) {
20929+ au_fset_ren(a->auren_flags, DT_DSTDIR);
20930+ a->h_path.dentry = a->dst_h_dentry;
20931+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
20932+ }
20933+}
dece6358 20934+
0b1ff5c3 20935+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 20936+{
0b1ff5c3
JR
20937+ struct dentry *h_d;
20938+ struct inode *h_inode;
dece6358 20939+
0b1ff5c3
JR
20940+ au_dtime_revert(a->src_dt + AuPARENT);
20941+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR))
20942+ au_dtime_revert(a->dst_dt + AuPARENT);
1308ab2a 20943+
0b1ff5c3
JR
20944+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) && err != -EIO) {
20945+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
20946+ h_inode = d_inode(h_d);
20947+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
20948+ au_dtime_revert(a->src_dt + AuCHILD);
20949+ inode_unlock(h_inode);
4a4d8108 20950+
0b1ff5c3
JR
20951+ if (au_ftest_ren(a->auren_flags, DT_DSTDIR)) {
20952+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
20953+ h_inode = d_inode(h_d);
20954+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
20955+ au_dtime_revert(a->dst_dt + AuCHILD);
20956+ inode_unlock(h_inode);
4a4d8108
AM
20957+ }
20958+ }
1facf9fc 20959+}
20960+
0b1ff5c3
JR
20961+/* ---------------------------------------------------------------------- */
20962+
20963+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
20964+ struct inode *_dst_dir, struct dentry *_dst_dentry,
20965+ unsigned int _flags)
1facf9fc 20966+{
0b1ff5c3
JR
20967+ int err, lock_flags;
20968+ void *rev;
20969+ /* reduce stack space */
20970+ struct au_ren_args *a;
20971+ struct au_pin pin;
1facf9fc 20972+
0b1ff5c3
JR
20973+ AuDbg("%pd, %pd, 0x%x\n", _src_dentry, _dst_dentry, _flags);
20974+ IMustLock(_src_dir);
20975+ IMustLock(_dst_dir);
1facf9fc 20976+
0b1ff5c3
JR
20977+ err = -EINVAL;
20978+ if (unlikely(_flags & RENAME_WHITEOUT))
20979+ goto out;
20980+
20981+ err = -ENOMEM;
20982+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
20983+ a = kzalloc(sizeof(*a), GFP_NOFS);
20984+ if (unlikely(!a))
20985+ goto out;
20986+
20987+ a->flags = _flags;
20988+ a->exchange = _flags & RENAME_EXCHANGE;
20989+ a->src_dir = _src_dir;
20990+ a->src_dentry = _src_dentry;
20991+ a->src_inode = NULL;
20992+ if (d_really_is_positive(a->src_dentry))
20993+ a->src_inode = d_inode(a->src_dentry);
20994+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
20995+ a->dst_dir = _dst_dir;
20996+ a->dst_dentry = _dst_dentry;
20997+ a->dst_inode = NULL;
20998+ if (d_really_is_positive(a->dst_dentry))
20999+ a->dst_inode = d_inode(a->dst_dentry);
21000+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
21001+ if (a->dst_inode) {
21002+ /*
21003+ * if EXCHANGE && src is non-dir && dst is dir,
21004+ * dst is not locked.
21005+ */
21006+ /* IMustLock(a->dst_inode); */
21007+ au_igrab(a->dst_inode);
21008+ }
21009+
21010+ err = -ENOTDIR;
21011+ lock_flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN;
21012+ if (d_is_dir(a->src_dentry)) {
21013+ au_fset_ren(a->auren_flags, ISDIR_SRC);
21014+ if (unlikely(!a->exchange
21015+ && d_really_is_positive(a->dst_dentry)
21016+ && !d_is_dir(a->dst_dentry)))
21017+ goto out_free;
21018+ lock_flags |= AuLock_DIRS;
21019+ }
21020+ if (a->dst_inode && d_is_dir(a->dst_dentry)) {
21021+ au_fset_ren(a->auren_flags, ISDIR_DST);
21022+ if (unlikely(!a->exchange
21023+ && d_really_is_positive(a->src_dentry)
21024+ && !d_is_dir(a->src_dentry)))
21025+ goto out_free;
21026+ lock_flags |= AuLock_DIRS;
4a4d8108 21027+ }
0b1ff5c3
JR
21028+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
21029+ lock_flags);
21030+ if (unlikely(err))
21031+ goto out_free;
1facf9fc 21032+
0b1ff5c3
JR
21033+ err = au_d_hashed_positive(a->src_dentry);
21034+ if (unlikely(err))
21035+ goto out_unlock;
4a4d8108 21036+ err = -ENOENT;
0b1ff5c3
JR
21037+ if (a->dst_inode) {
21038+ /*
21039+ * If it is a dir, VFS unhash it before this
21040+ * function. It means we cannot rely upon d_unhashed().
21041+ */
21042+ if (unlikely(!a->dst_inode->i_nlink))
21043+ goto out_unlock;
21044+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) {
21045+ err = au_d_hashed_positive(a->dst_dentry);
21046+ if (unlikely(err && !a->exchange))
21047+ goto out_unlock;
21048+ } else if (unlikely(IS_DEADDIR(a->dst_inode)))
21049+ goto out_unlock;
21050+ } else if (unlikely(d_unhashed(a->dst_dentry)))
21051+ goto out_unlock;
4a4d8108
AM
21052+
21053+ /*
0b1ff5c3
JR
21054+ * is it possible?
21055+ * yes, it happened (in linux-3.3-rcN) but I don't know why.
21056+ * there may exist a problem somewhere else.
4a4d8108 21057+ */
0b1ff5c3
JR
21058+ err = -EINVAL;
21059+ if (unlikely(d_inode(a->dst_parent) == d_inode(a->src_dentry)))
21060+ goto out_unlock;
4a4d8108 21061+
0b1ff5c3
JR
21062+ au_fset_ren(a->auren_flags, ISSAMEDIR); /* temporary */
21063+ di_write_lock_parent(a->dst_parent);
4a4d8108 21064+
0b1ff5c3
JR
21065+ /* which branch we process */
21066+ err = au_ren_wbr(a);
21067+ if (unlikely(err < 0))
21068+ goto out_parent;
21069+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
21070+ a->h_path.mnt = au_br_mnt(a->br);
1facf9fc 21071+
0b1ff5c3
JR
21072+ /* are they available to be renamed */
21073+ err = au_ren_may_dir(a);
21074+ if (unlikely(err))
21075+ goto out_children;
dece6358 21076+
0b1ff5c3
JR
21077+ /* prepare the writable parent dir on the same branch */
21078+ if (a->dst_btop == a->btgt) {
21079+ au_fset_ren(a->auren_flags, WHDST);
21080+ } else {
21081+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
21082+ if (unlikely(err))
21083+ goto out_children;
21084+ }
4a4d8108 21085+
0b1ff5c3
JR
21086+ err = 0;
21087+ if (!a->exchange) {
21088+ if (a->src_dir != a->dst_dir) {
21089+ /*
21090+ * this temporary unlock is safe,
21091+ * because both dir->i_mutex are locked.
21092+ */
21093+ di_write_unlock(a->dst_parent);
21094+ di_write_lock_parent(a->src_parent);
21095+ err = au_wr_dir_need_wh(a->src_dentry,
21096+ au_ftest_ren(a->auren_flags,
21097+ ISDIR_SRC),
21098+ &a->btgt);
21099+ di_write_unlock(a->src_parent);
21100+ di_write_lock2_parent(a->src_parent, a->dst_parent,
21101+ /*isdir*/1);
21102+ au_fclr_ren(a->auren_flags, ISSAMEDIR);
21103+ } else
21104+ err = au_wr_dir_need_wh(a->src_dentry,
21105+ au_ftest_ren(a->auren_flags,
21106+ ISDIR_SRC),
21107+ &a->btgt);
21108+ }
21109+ if (unlikely(err < 0))
21110+ goto out_children;
21111+ if (err)
21112+ au_fset_ren(a->auren_flags, WHSRC);
21113+
21114+ /* cpup src */
21115+ if (a->src_btop != a->btgt) {
21116+ err = au_pin(&pin, a->src_dentry, a->btgt,
21117+ au_opt_udba(a->src_dentry->d_sb),
21118+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
21119+ if (!err) {
21120+ struct au_cp_generic cpg = {
21121+ .dentry = a->src_dentry,
21122+ .bdst = a->btgt,
21123+ .bsrc = a->src_btop,
21124+ .len = -1,
21125+ .pin = &pin,
21126+ .flags = AuCpup_DTIME | AuCpup_HOPEN
21127+ };
21128+ AuDebugOn(au_dbtop(a->src_dentry) != a->src_btop);
21129+ err = au_sio_cpup_simple(&cpg);
21130+ au_unpin(&pin);
21131+ }
21132+ if (unlikely(err))
21133+ goto out_children;
21134+ a->src_btop = a->btgt;
21135+ a->src_h_dentry = au_h_dptr(a->src_dentry, a->btgt);
21136+ if (!a->exchange)
21137+ au_fset_ren(a->auren_flags, WHSRC);
21138+ }
21139+
21140+ /* cpup dst */
21141+ if (a->exchange && a->dst_inode
21142+ && a->dst_btop != a->btgt) {
21143+ err = au_pin(&pin, a->dst_dentry, a->btgt,
21144+ au_opt_udba(a->dst_dentry->d_sb),
21145+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
21146+ if (!err) {
21147+ struct au_cp_generic cpg = {
21148+ .dentry = a->dst_dentry,
21149+ .bdst = a->btgt,
21150+ .bsrc = a->dst_btop,
21151+ .len = -1,
21152+ .pin = &pin,
21153+ .flags = AuCpup_DTIME | AuCpup_HOPEN
21154+ };
21155+ err = au_sio_cpup_simple(&cpg);
21156+ au_unpin(&pin);
21157+ }
21158+ if (unlikely(err))
21159+ goto out_children;
21160+ a->dst_btop = a->btgt;
21161+ a->dst_h_dentry = au_h_dptr(a->dst_dentry, a->btgt);
21162+ }
21163+
21164+ /* lock them all */
21165+ err = au_ren_lock(a);
4a4d8108 21166+ if (unlikely(err))
0b1ff5c3
JR
21167+ /* leave the copied-up one */
21168+ goto out_children;
4a4d8108 21169+
0b1ff5c3
JR
21170+ if (!a->exchange) {
21171+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
21172+ err = au_may_ren(a);
21173+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
21174+ err = -ENAMETOOLONG;
4a4d8108 21175+ if (unlikely(err))
0b1ff5c3 21176+ goto out_hdir;
4a4d8108
AM
21177+ }
21178+
0b1ff5c3
JR
21179+ /* store timestamps to be revertible */
21180+ au_ren_dt(a);
4a4d8108 21181+
0b1ff5c3
JR
21182+ /* store dirren info */
21183+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
21184+ err = au_dr_rename(a->src_dentry, a->btgt,
21185+ &a->dst_dentry->d_name, &rev);
21186+ AuTraceErr(err);
21187+ if (unlikely(err))
21188+ goto out_dt;
21189+ }
4a4d8108 21190+
0b1ff5c3
JR
21191+ /* here we go */
21192+ err = do_rename(a);
21193+ if (unlikely(err))
21194+ goto out_dirren;
4a4d8108 21195+
0b1ff5c3
JR
21196+ if (au_ftest_ren(a->auren_flags, DIRREN))
21197+ au_dr_rename_fin(a->src_dentry, a->btgt, rev);
1facf9fc 21198+
0b1ff5c3
JR
21199+ /* update dir attributes */
21200+ au_ren_refresh_dir(a);
4a4d8108 21201+
0b1ff5c3
JR
21202+ /* dput/iput all lower dentries */
21203+ au_ren_refresh(a);
4a4d8108 21204+
0b1ff5c3 21205+ goto out_hdir; /* success */
4a4d8108 21206+
0b1ff5c3
JR
21207+out_dirren:
21208+ if (au_ftest_ren(a->auren_flags, DIRREN))
21209+ au_dr_rename_rev(a->src_dentry, a->btgt, rev);
21210+out_dt:
21211+ au_ren_rev_dt(err, a);
21212+out_hdir:
21213+ au_ren_unlock(a);
21214+out_children:
21215+ au_nhash_wh_free(&a->whlist);
21216+ if (err && a->dst_inode && a->dst_btop != a->btgt) {
21217+ AuDbg("btop %d, btgt %d\n", a->dst_btop, a->btgt);
21218+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
21219+ au_set_dbtop(a->dst_dentry, a->dst_btop);
4a4d8108 21220+ }
0b1ff5c3
JR
21221+out_parent:
21222+ if (!err) {
21223+ if (d_unhashed(a->src_dentry))
21224+ au_fset_ren(a->auren_flags, DROPPED_SRC);
21225+ if (d_unhashed(a->dst_dentry))
21226+ au_fset_ren(a->auren_flags, DROPPED_DST);
21227+ if (!a->exchange)
21228+ d_move(a->src_dentry, a->dst_dentry);
21229+ else {
21230+ d_exchange(a->src_dentry, a->dst_dentry);
21231+ if (au_ftest_ren(a->auren_flags, DROPPED_DST))
21232+ d_drop(a->dst_dentry);
21233+ }
21234+ if (au_ftest_ren(a->auren_flags, DROPPED_SRC))
21235+ d_drop(a->src_dentry);
21236+ } else {
21237+ au_update_dbtop(a->dst_dentry);
21238+ if (!a->dst_inode)
21239+ d_drop(a->dst_dentry);
4a4d8108 21240+ }
0b1ff5c3
JR
21241+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR))
21242+ di_write_unlock(a->dst_parent);
21243+ else
21244+ di_write_unlock2(a->src_parent, a->dst_parent);
21245+out_unlock:
21246+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
21247+out_free:
21248+ iput(a->dst_inode);
21249+ if (a->thargs)
21250+ au_whtmp_rmdir_free(a->thargs);
21251+ kfree(a);
4f0767ce 21252+out:
4a4d8108
AM
21253+ AuTraceErr(err);
21254+ return err;
21255+}
0b1ff5c3
JR
21256diff -urNp -x '*.orig' linux-4.14/fs/aufs/iinfo.c linux-4.14/fs/aufs/iinfo.c
21257--- linux-4.14/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
21258+++ linux-4.14/fs/aufs/iinfo.c 2021-02-24 21:42:43.444448075 +0100
21259@@ -0,0 +1,285 @@
21260+/*
21261+ * Copyright (C) 2005-2017 Junjiro R. Okajima
21262+ *
21263+ * This program, aufs is free software; you can redistribute it and/or modify
21264+ * it under the terms of the GNU General Public License as published by
21265+ * the Free Software Foundation; either version 2 of the License, or
21266+ * (at your option) any later version.
21267+ *
21268+ * This program is distributed in the hope that it will be useful,
21269+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21270+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21271+ * GNU General Public License for more details.
21272+ *
21273+ * You should have received a copy of the GNU General Public License
21274+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
21275+ */
1308ab2a 21276+
4a4d8108 21277+/*
0b1ff5c3 21278+ * inode private data
4a4d8108 21279+ */
0b1ff5c3
JR
21280+
21281+#include "aufs.h"
21282+
21283+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
4a4d8108 21284+{
0b1ff5c3
JR
21285+ struct inode *h_inode;
21286+ struct au_hinode *hinode;
1308ab2a 21287+
0b1ff5c3 21288+ IiMustAnyLock(inode);
1308ab2a 21289+
0b1ff5c3
JR
21290+ hinode = au_hinode(au_ii(inode), bindex);
21291+ h_inode = hinode->hi_inode;
21292+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
21293+ return h_inode;
1facf9fc 21294+}
21295+
0b1ff5c3
JR
21296+/* todo: hard/soft set? */
21297+void au_hiput(struct au_hinode *hinode)
1facf9fc 21298+{
0b1ff5c3
JR
21299+ au_hn_free(hinode);
21300+ dput(hinode->hi_whdentry);
21301+ iput(hinode->hi_inode);
21302+}
dece6358 21303+
0b1ff5c3
JR
21304+unsigned int au_hi_flags(struct inode *inode, int isdir)
21305+{
21306+ unsigned int flags;
21307+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
dece6358 21308+
0b1ff5c3
JR
21309+ flags = 0;
21310+ if (au_opt_test(mnt_flags, XINO))
21311+ au_fset_hi(flags, XINO);
21312+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
21313+ au_fset_hi(flags, HNOTIFY);
21314+ return flags;
1facf9fc 21315+}
21316+
0b1ff5c3
JR
21317+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
21318+ struct inode *h_inode, unsigned int flags)
1308ab2a 21319+{
0b1ff5c3
JR
21320+ struct au_hinode *hinode;
21321+ struct inode *hi;
21322+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 21323+
0b1ff5c3 21324+ IiMustWriteLock(inode);
027c5e7a 21325+
0b1ff5c3
JR
21326+ hinode = au_hinode(iinfo, bindex);
21327+ hi = hinode->hi_inode;
21328+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
c2b27bf2 21329+
0b1ff5c3
JR
21330+ if (hi)
21331+ au_hiput(hinode);
21332+ hinode->hi_inode = h_inode;
21333+ if (h_inode) {
21334+ int err;
21335+ struct super_block *sb = inode->i_sb;
21336+ struct au_branch *br;
1facf9fc 21337+
0b1ff5c3
JR
21338+ AuDebugOn(inode->i_mode
21339+ && (h_inode->i_mode & S_IFMT)
21340+ != (inode->i_mode & S_IFMT));
21341+ if (bindex == iinfo->ii_btop)
21342+ au_cpup_igen(inode, h_inode);
21343+ br = au_sbr(sb, bindex);
21344+ hinode->hi_id = br->br_id;
21345+ if (au_ftest_hi(flags, XINO)) {
21346+ err = au_xino_write(sb, bindex, h_inode->i_ino,
21347+ inode->i_ino);
21348+ if (unlikely(err))
21349+ AuIOErr1("failed au_xino_write() %d\n", err);
21350+ }
1facf9fc 21351+
0b1ff5c3
JR
21352+ if (au_ftest_hi(flags, HNOTIFY)
21353+ && au_br_hnotifyable(br->br_perm)) {
21354+ err = au_hn_alloc(hinode, inode);
21355+ if (unlikely(err))
21356+ AuIOErr1("au_hn_alloc() %d\n", err);
523b37e3 21357+ }
4a4d8108 21358+ }
0b1ff5c3 21359+}
dece6358 21360+
0b1ff5c3
JR
21361+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
21362+ struct dentry *h_wh)
21363+{
21364+ struct au_hinode *hinode;
4a4d8108 21365+
0b1ff5c3 21366+ IiMustWriteLock(inode);
1facf9fc 21367+
0b1ff5c3
JR
21368+ hinode = au_hinode(au_ii(inode), bindex);
21369+ AuDebugOn(hinode->hi_whdentry);
21370+ hinode->hi_whdentry = h_wh;
21371+}
4a4d8108 21372+
0b1ff5c3
JR
21373+void au_update_iigen(struct inode *inode, int half)
21374+{
21375+ struct au_iinfo *iinfo;
21376+ struct au_iigen *iigen;
21377+ unsigned int sigen;
21378+
21379+ sigen = au_sigen(inode->i_sb);
21380+ iinfo = au_ii(inode);
21381+ iigen = &iinfo->ii_generation;
21382+ spin_lock(&iigen->ig_spin);
21383+ iigen->ig_generation = sigen;
21384+ if (half)
21385+ au_ig_fset(iigen->ig_flags, HALF_REFRESHED);
21386+ else
21387+ au_ig_fclr(iigen->ig_flags, HALF_REFRESHED);
21388+ spin_unlock(&iigen->ig_spin);
21389+}
21390+
21391+/* it may be called at remount time, too */
21392+void au_update_ibrange(struct inode *inode, int do_put_zero)
21393+{
21394+ struct au_iinfo *iinfo;
21395+ aufs_bindex_t bindex, bbot;
21396+
21397+ AuDebugOn(au_is_bad_inode(inode));
21398+ IiMustWriteLock(inode);
21399+
21400+ iinfo = au_ii(inode);
21401+ if (do_put_zero && iinfo->ii_btop >= 0) {
21402+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot;
21403+ bindex++) {
21404+ struct inode *h_i;
21405+
21406+ h_i = au_hinode(iinfo, bindex)->hi_inode;
21407+ if (h_i
21408+ && !h_i->i_nlink
21409+ && !(h_i->i_state & I_LINKABLE))
21410+ au_set_h_iptr(inode, bindex, NULL, 0);
21411+ }
dece6358 21412+ }
1facf9fc 21413+
0b1ff5c3
JR
21414+ iinfo->ii_btop = -1;
21415+ iinfo->ii_bbot = -1;
21416+ bbot = au_sbbot(inode->i_sb);
21417+ for (bindex = 0; bindex <= bbot; bindex++)
21418+ if (au_hinode(iinfo, bindex)->hi_inode) {
21419+ iinfo->ii_btop = bindex;
21420+ break;
21421+ }
21422+ if (iinfo->ii_btop >= 0)
21423+ for (bindex = bbot; bindex >= iinfo->ii_btop; bindex--)
21424+ if (au_hinode(iinfo, bindex)->hi_inode) {
21425+ iinfo->ii_bbot = bindex;
21426+ break;
21427+ }
21428+ AuDebugOn(iinfo->ii_btop > iinfo->ii_bbot);
dece6358
AM
21429+}
21430+
0b1ff5c3
JR
21431+/* ---------------------------------------------------------------------- */
21432+
21433+void au_icntnr_init_once(void *_c)
1308ab2a 21434+{
0b1ff5c3
JR
21435+ struct au_icntnr *c = _c;
21436+ struct au_iinfo *iinfo = &c->iinfo;
1facf9fc 21437+
0b1ff5c3
JR
21438+ spin_lock_init(&iinfo->ii_generation.ig_spin);
21439+ au_rw_init(&iinfo->ii_rwsem);
21440+ inode_init_once(&c->vfs_inode);
21441+}
027c5e7a 21442+
0b1ff5c3
JR
21443+void au_hinode_init(struct au_hinode *hinode)
21444+{
21445+ hinode->hi_inode = NULL;
21446+ hinode->hi_id = -1;
21447+ au_hn_init(hinode);
21448+ hinode->hi_whdentry = NULL;
21449+}
c2b27bf2 21450+
0b1ff5c3
JR
21451+int au_iinfo_init(struct inode *inode)
21452+{
21453+ struct au_iinfo *iinfo;
21454+ struct super_block *sb;
21455+ struct au_hinode *hi;
21456+ int nbr, i;
dece6358 21457+
0b1ff5c3
JR
21458+ sb = inode->i_sb;
21459+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
21460+ nbr = au_sbbot(sb) + 1;
21461+ if (unlikely(nbr <= 0))
21462+ nbr = 1;
21463+ hi = kmalloc_array(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
21464+ if (hi) {
21465+ au_ninodes_inc(sb);
dece6358 21466+
0b1ff5c3
JR
21467+ iinfo->ii_hinode = hi;
21468+ for (i = 0; i < nbr; i++, hi++)
21469+ au_hinode_init(hi);
1facf9fc 21470+
0b1ff5c3
JR
21471+ iinfo->ii_generation.ig_generation = au_sigen(sb);
21472+ iinfo->ii_btop = -1;
21473+ iinfo->ii_bbot = -1;
21474+ iinfo->ii_vdir = NULL;
21475+ return 0;
21476+ }
21477+ return -ENOMEM;
21478+}
1facf9fc 21479+
0b1ff5c3
JR
21480+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink)
21481+{
21482+ int err, i;
21483+ struct au_hinode *hip;
4a4d8108 21484+
0b1ff5c3
JR
21485+ AuRwMustWriteLock(&iinfo->ii_rwsem);
21486+
21487+ err = -ENOMEM;
21488+ hip = au_krealloc(iinfo->ii_hinode, sizeof(*hip) * nbr, GFP_NOFS,
21489+ may_shrink);
21490+ if (hip) {
21491+ iinfo->ii_hinode = hip;
21492+ i = iinfo->ii_bbot + 1;
21493+ hip += i;
21494+ for (; i < nbr; i++, hip++)
21495+ au_hinode_init(hip);
1facf9fc 21496+ err = 0;
21497+ }
21498+
0b1ff5c3
JR
21499+ return err;
21500+}
1308ab2a 21501+
0b1ff5c3
JR
21502+void au_iinfo_fin(struct inode *inode)
21503+{
21504+ struct au_iinfo *iinfo;
21505+ struct au_hinode *hi;
21506+ struct super_block *sb;
21507+ aufs_bindex_t bindex, bbot;
21508+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 21509+
0b1ff5c3
JR
21510+ AuDebugOn(au_is_bad_inode(inode));
21511+
21512+ sb = inode->i_sb;
21513+ au_ninodes_dec(sb);
21514+ if (si_pid_test(sb))
21515+ au_xino_delete_inode(inode, unlinked);
21516+ else {
21517+ /*
21518+ * it is safe to hide the dependency between sbinfo and
21519+ * sb->s_umount.
21520+ */
21521+ lockdep_off();
21522+ si_noflush_read_lock(sb);
21523+ au_xino_delete_inode(inode, unlinked);
21524+ si_read_unlock(sb);
21525+ lockdep_on();
1facf9fc 21526+ }
21527+
0b1ff5c3
JR
21528+ iinfo = au_ii(inode);
21529+ if (iinfo->ii_vdir)
21530+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 21531+
0b1ff5c3
JR
21532+ bindex = iinfo->ii_btop;
21533+ if (bindex >= 0) {
21534+ hi = au_hinode(iinfo, bindex);
21535+ bbot = iinfo->ii_bbot;
21536+ while (bindex++ <= bbot) {
21537+ if (hi->hi_inode)
21538+ au_hiput(hi);
21539+ hi++;
21540+ }
1facf9fc 21541+ }
0b1ff5c3
JR
21542+ kfree(iinfo->ii_hinode);
21543+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 21544+}
0b1ff5c3
JR
21545diff -urNp -x '*.orig' linux-4.14/fs/aufs/inode.c linux-4.14/fs/aufs/inode.c
21546--- linux-4.14/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
21547+++ linux-4.14/fs/aufs/inode.c 2021-02-24 21:42:43.444448075 +0100
21548@@ -0,0 +1,527 @@
1facf9fc 21549+/*
a2654f78 21550+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 21551+ *
21552+ * This program, aufs is free software; you can redistribute it and/or modify
21553+ * it under the terms of the GNU General Public License as published by
21554+ * the Free Software Foundation; either version 2 of the License, or
21555+ * (at your option) any later version.
dece6358
AM
21556+ *
21557+ * This program is distributed in the hope that it will be useful,
21558+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21559+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21560+ * GNU General Public License for more details.
21561+ *
21562+ * You should have received a copy of the GNU General Public License
523b37e3 21563+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 21564+ */
21565+
21566+/*
0b1ff5c3 21567+ * inode functions
1facf9fc 21568+ */
21569+
21570+#include "aufs.h"
21571+
0b1ff5c3
JR
21572+struct inode *au_igrab(struct inode *inode)
21573+{
21574+ if (inode) {
21575+ AuDebugOn(!atomic_read(&inode->i_count));
21576+ ihold(inode);
21577+ }
21578+ return inode;
21579+}
1facf9fc 21580+
0b1ff5c3
JR
21581+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
21582+{
21583+ au_cpup_attr_all(inode, /*force*/0);
21584+ au_update_iigen(inode, /*half*/1);
21585+ if (do_version)
21586+ inode->i_version++;
21587+}
1facf9fc 21588+
0b1ff5c3
JR
21589+static int au_ii_refresh(struct inode *inode, int *update)
21590+{
21591+ int err, e, nbr;
21592+ umode_t type;
21593+ aufs_bindex_t bindex, new_bindex;
21594+ struct super_block *sb;
21595+ struct au_iinfo *iinfo;
21596+ struct au_hinode *p, *q, tmp;
1308ab2a 21597+
0b1ff5c3
JR
21598+ AuDebugOn(au_is_bad_inode(inode));
21599+ IiMustWriteLock(inode);
1308ab2a 21600+
0b1ff5c3
JR
21601+ *update = 0;
21602+ sb = inode->i_sb;
21603+ nbr = au_sbbot(sb) + 1;
21604+ type = inode->i_mode & S_IFMT;
21605+ iinfo = au_ii(inode);
21606+ err = au_hinode_realloc(iinfo, nbr, /*may_shrink*/0);
21607+ if (unlikely(err))
21608+ goto out;
1facf9fc 21609+
0b1ff5c3
JR
21610+ AuDebugOn(iinfo->ii_btop < 0);
21611+ p = au_hinode(iinfo, iinfo->ii_btop);
21612+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot;
21613+ bindex++, p++) {
21614+ if (!p->hi_inode)
21615+ continue;
1facf9fc 21616+
0b1ff5c3
JR
21617+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT));
21618+ new_bindex = au_br_index(sb, p->hi_id);
21619+ if (new_bindex == bindex)
21620+ continue;
1facf9fc 21621+
0b1ff5c3
JR
21622+ if (new_bindex < 0) {
21623+ *update = 1;
21624+ au_hiput(p);
21625+ p->hi_inode = NULL;
21626+ continue;
21627+ }
f2c43d5f 21628+
0b1ff5c3
JR
21629+ if (new_bindex < iinfo->ii_btop)
21630+ iinfo->ii_btop = new_bindex;
21631+ if (iinfo->ii_bbot < new_bindex)
21632+ iinfo->ii_bbot = new_bindex;
21633+ /* swap two lower inode, and loop again */
21634+ q = au_hinode(iinfo, new_bindex);
21635+ tmp = *q;
21636+ *q = *p;
21637+ *p = tmp;
21638+ if (tmp.hi_inode) {
21639+ bindex--;
21640+ p--;
21641+ }
21642+ }
21643+ au_update_ibrange(inode, /*do_put_zero*/0);
21644+ au_hinode_realloc(iinfo, nbr, /*may_shrink*/1); /* harmless if err */
21645+ e = au_dy_irefresh(inode);
21646+ if (unlikely(e && !err))
21647+ err = e;
f2c43d5f 21648+
0b1ff5c3
JR
21649+out:
21650+ AuTraceErr(err);
21651+ return err;
4a4d8108 21652+}
1facf9fc 21653+
0b1ff5c3 21654+void au_refresh_iop(struct inode *inode, int force_getattr)
4a4d8108 21655+{
0b1ff5c3
JR
21656+ int type;
21657+ struct au_sbinfo *sbi = au_sbi(inode->i_sb);
21658+ const struct inode_operations *iop
21659+ = force_getattr ? aufs_iop : sbi->si_iop_array;
1facf9fc 21660+
0b1ff5c3 21661+ if (inode->i_op == iop)
4a4d8108 21662+ return;
1facf9fc 21663+
0b1ff5c3
JR
21664+ switch (inode->i_mode & S_IFMT) {
21665+ case S_IFDIR:
21666+ type = AuIop_DIR;
21667+ break;
21668+ case S_IFLNK:
21669+ type = AuIop_SYMLINK;
21670+ break;
21671+ default:
21672+ type = AuIop_OTHER;
21673+ break;
523b37e3 21674+ }
0b1ff5c3
JR
21675+
21676+ inode->i_op = iop + type;
21677+ /* unnecessary smp_wmb() */
1facf9fc 21678+}
21679+
0b1ff5c3 21680+int au_refresh_hinode_self(struct inode *inode)
1facf9fc 21681+{
0b1ff5c3 21682+ int err, update;
dece6358 21683+
0b1ff5c3
JR
21684+ err = au_ii_refresh(inode, &update);
21685+ if (!err)
21686+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
dece6358 21687+
0b1ff5c3
JR
21688+ AuTraceErr(err);
21689+ return err;
4a4d8108 21690+}
1308ab2a 21691+
0b1ff5c3 21692+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
4a4d8108 21693+{
0b1ff5c3
JR
21694+ int err, e, update;
21695+ unsigned int flags;
21696+ umode_t mode;
21697+ aufs_bindex_t bindex, bbot;
21698+ unsigned char isdir;
21699+ struct au_hinode *p;
21700+ struct au_iinfo *iinfo;
1308ab2a 21701+
0b1ff5c3
JR
21702+ err = au_ii_refresh(inode, &update);
21703+ if (unlikely(err))
21704+ goto out;
1facf9fc 21705+
0b1ff5c3
JR
21706+ update = 0;
21707+ iinfo = au_ii(inode);
21708+ p = au_hinode(iinfo, iinfo->ii_btop);
21709+ mode = (inode->i_mode & S_IFMT);
21710+ isdir = S_ISDIR(mode);
21711+ flags = au_hi_flags(inode, isdir);
21712+ bbot = au_dbbot(dentry);
21713+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) {
21714+ struct inode *h_i, *h_inode;
21715+ struct dentry *h_d;
1308ab2a 21716+
0b1ff5c3
JR
21717+ h_d = au_h_dptr(dentry, bindex);
21718+ if (!h_d || d_is_negative(h_d))
21719+ continue;
1facf9fc 21720+
0b1ff5c3
JR
21721+ h_inode = d_inode(h_d);
21722+ AuDebugOn(mode != (h_inode->i_mode & S_IFMT));
21723+ if (iinfo->ii_btop <= bindex && bindex <= iinfo->ii_bbot) {
21724+ h_i = au_h_iptr(inode, bindex);
21725+ if (h_i) {
21726+ if (h_i == h_inode)
21727+ continue;
21728+ err = -EIO;
21729+ break;
21730+ }
523b37e3 21731+ }
0b1ff5c3
JR
21732+ if (bindex < iinfo->ii_btop)
21733+ iinfo->ii_btop = bindex;
21734+ if (iinfo->ii_bbot < bindex)
21735+ iinfo->ii_bbot = bindex;
21736+ au_set_h_iptr(inode, bindex, au_igrab(h_inode), flags);
21737+ update = 1;
21738+ }
21739+ au_update_ibrange(inode, /*do_put_zero*/0);
21740+ e = au_dy_irefresh(inode);
21741+ if (unlikely(e && !err))
21742+ err = e;
21743+ if (!err)
21744+ au_refresh_hinode_attr(inode, update && isdir);
1facf9fc 21745+
0b1ff5c3
JR
21746+out:
21747+ AuTraceErr(err);
dece6358
AM
21748+ return err;
21749+}
1facf9fc 21750+
0b1ff5c3 21751+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 21752+{
4a4d8108 21753+ int err;
0b1ff5c3
JR
21754+ unsigned int flags;
21755+ umode_t mode;
21756+ aufs_bindex_t bindex, btop, btail;
21757+ unsigned char isdir;
21758+ struct dentry *h_dentry;
21759+ struct inode *h_inode;
21760+ struct au_iinfo *iinfo;
21761+ struct inode_operations *iop;
1facf9fc 21762+
0b1ff5c3
JR
21763+ IiMustWriteLock(inode);
21764+
21765+ err = 0;
21766+ isdir = 0;
21767+ iop = au_sbi(inode->i_sb)->si_iop_array;
21768+ btop = au_dbtop(dentry);
21769+ h_dentry = au_h_dptr(dentry, btop);
21770+ h_inode = d_inode(h_dentry);
21771+ mode = h_inode->i_mode;
21772+ switch (mode & S_IFMT) {
21773+ case S_IFREG:
21774+ btail = au_dbtail(dentry);
21775+ inode->i_op = iop + AuIop_OTHER;
21776+ inode->i_fop = &aufs_file_fop;
21777+ err = au_dy_iaop(inode, btop, h_inode);
4a4d8108 21778+ if (unlikely(err))
0b1ff5c3
JR
21779+ goto out;
21780+ break;
21781+ case S_IFDIR:
21782+ isdir = 1;
21783+ btail = au_dbtaildir(dentry);
21784+ inode->i_op = iop + AuIop_DIR;
21785+ inode->i_fop = &aufs_dir_fop;
21786+ break;
21787+ case S_IFLNK:
21788+ btail = au_dbtail(dentry);
21789+ inode->i_op = iop + AuIop_SYMLINK;
21790+ break;
21791+ case S_IFBLK:
21792+ case S_IFCHR:
21793+ case S_IFIFO:
21794+ case S_IFSOCK:
21795+ btail = au_dbtail(dentry);
21796+ inode->i_op = iop + AuIop_OTHER;
21797+ init_special_inode(inode, mode, h_inode->i_rdev);
21798+ break;
21799+ default:
21800+ AuIOErr("Unknown file type 0%o\n", mode);
21801+ err = -EIO;
21802+ goto out;
4a4d8108
AM
21803+ }
21804+
0b1ff5c3
JR
21805+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
21806+ flags = au_hi_flags(inode, isdir);
21807+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
21808+ && au_ftest_hi(flags, HNOTIFY)
21809+ && dentry->d_name.len > AUFS_WH_PFX_LEN
21810+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
21811+ au_fclr_hi(flags, HNOTIFY);
21812+ iinfo = au_ii(inode);
21813+ iinfo->ii_btop = btop;
21814+ iinfo->ii_bbot = btail;
21815+ for (bindex = btop; bindex <= btail; bindex++) {
21816+ h_dentry = au_h_dptr(dentry, bindex);
21817+ if (h_dentry)
21818+ au_set_h_iptr(inode, bindex,
21819+ au_igrab(d_inode(h_dentry)), flags);
21820+ }
21821+ au_cpup_attr_all(inode, /*force*/1);
21822+ /*
21823+ * to force calling aufs_get_acl() every time,
21824+ * do not call cache_no_acl() for aufs inode.
21825+ */
21826+
21827+out:
21828+ return err;
1308ab2a 21829+}
1facf9fc 21830+
0b1ff5c3
JR
21831+/*
21832+ * successful returns with iinfo write_locked
21833+ * minus: errno
21834+ * zero: success, matched
21835+ * plus: no error, but unmatched
21836+ */
21837+static int reval_inode(struct inode *inode, struct dentry *dentry)
4a4d8108
AM
21838+{
21839+ int err;
0b1ff5c3
JR
21840+ unsigned int gen, igflags;
21841+ aufs_bindex_t bindex, bbot;
21842+ struct inode *h_inode, *h_dinode;
21843+ struct dentry *h_dentry;
1facf9fc 21844+
0b1ff5c3
JR
21845+ /*
21846+ * before this function, if aufs got any iinfo lock, it must be only
21847+ * one, the parent dir.
21848+ * it can happen by UDBA and the obsoleted inode number.
21849+ */
21850+ err = -EIO;
21851+ if (unlikely(inode->i_ino == parent_ino(dentry)))
21852+ goto out;
1facf9fc 21853+
0b1ff5c3
JR
21854+ err = 1;
21855+ ii_write_lock_new_child(inode);
21856+ h_dentry = au_h_dptr(dentry, au_dbtop(dentry));
21857+ h_dinode = d_inode(h_dentry);
21858+ bbot = au_ibbot(inode);
21859+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) {
21860+ h_inode = au_h_iptr(inode, bindex);
21861+ if (!h_inode || h_inode != h_dinode)
21862+ continue;
21863+
21864+ err = 0;
21865+ gen = au_iigen(inode, &igflags);
21866+ if (gen == au_digen(dentry)
21867+ && !au_ig_ftest(igflags, HALF_REFRESHED))
21868+ break;
21869+
21870+ /* fully refresh inode using dentry */
21871+ err = au_refresh_hinode(inode, dentry);
21872+ if (!err)
21873+ au_update_iigen(inode, /*half*/0);
21874+ break;
21875+ }
21876+
21877+ if (unlikely(err))
21878+ ii_write_unlock(inode);
21879+out:
4a4d8108
AM
21880+ return err;
21881+}
1facf9fc 21882+
0b1ff5c3
JR
21883+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
21884+ unsigned int d_type, ino_t *ino)
4a4d8108 21885+{
0b1ff5c3
JR
21886+ int err, idx;
21887+ const int isnondir = d_type != DT_DIR;
1facf9fc 21888+
0b1ff5c3
JR
21889+ /* prevent hardlinked inode number from race condition */
21890+ if (isnondir) {
21891+ err = au_xinondir_enter(sb, bindex, h_ino, &idx);
f2c43d5f 21892+ if (unlikely(err))
4a4d8108 21893+ goto out;
4a4d8108 21894+ }
1facf9fc 21895+
0b1ff5c3
JR
21896+ err = au_xino_read(sb, bindex, h_ino, ino);
21897+ if (unlikely(err))
21898+ goto out_xinondir;
21899+
21900+ if (!*ino) {
21901+ err = -EIO;
21902+ *ino = au_xino_new_ino(sb);
21903+ if (unlikely(!*ino))
21904+ goto out_xinondir;
21905+ err = au_xino_write(sb, bindex, h_ino, *ino);
4a4d8108 21906+ if (unlikely(err))
0b1ff5c3 21907+ goto out_xinondir;
f2c43d5f 21908+ }
dece6358 21909+
0b1ff5c3
JR
21910+out_xinondir:
21911+ if (isnondir && idx >= 0)
21912+ au_xinondir_leave(sb, bindex, h_ino, idx);
f2c43d5f
AM
21913+out:
21914+ return err;
21915+}
21916+
0b1ff5c3
JR
21917+/* successful returns with iinfo write_locked */
21918+/* todo: return with unlocked? */
21919+struct inode *au_new_inode(struct dentry *dentry, int must_new)
f2c43d5f 21920+{
0b1ff5c3
JR
21921+ struct inode *inode, *h_inode;
21922+ struct dentry *h_dentry;
21923+ struct super_block *sb;
21924+ ino_t h_ino, ino;
21925+ int err, idx, hlinked;
21926+ aufs_bindex_t btop;
f2c43d5f 21927+
0b1ff5c3
JR
21928+ sb = dentry->d_sb;
21929+ btop = au_dbtop(dentry);
21930+ h_dentry = au_h_dptr(dentry, btop);
21931+ h_inode = d_inode(h_dentry);
21932+ h_ino = h_inode->i_ino;
21933+ hlinked = !d_is_dir(h_dentry) && h_inode->i_nlink > 1;
f2c43d5f 21934+
0b1ff5c3
JR
21935+new_ino:
21936+ /*
21937+ * stop 'race'-ing between hardlinks under different
21938+ * parents.
21939+ */
21940+ if (hlinked) {
21941+ err = au_xinondir_enter(sb, btop, h_ino, &idx);
21942+ inode = ERR_PTR(err);
21943+ if (unlikely(err))
21944+ goto out;
21945+ }
f2c43d5f 21946+
0b1ff5c3
JR
21947+ err = au_xino_read(sb, btop, h_ino, &ino);
21948+ inode = ERR_PTR(err);
21949+ if (unlikely(err))
21950+ goto out_xinondir;
f2c43d5f 21951+
0b1ff5c3
JR
21952+ if (!ino) {
21953+ ino = au_xino_new_ino(sb);
21954+ if (unlikely(!ino)) {
21955+ inode = ERR_PTR(-EIO);
21956+ goto out_xinondir;
f2c43d5f 21957+ }
4a4d8108 21958+ }
1facf9fc 21959+
0b1ff5c3
JR
21960+ AuDbg("i%lu\n", (unsigned long)ino);
21961+ inode = au_iget_locked(sb, ino);
21962+ err = PTR_ERR(inode);
21963+ if (IS_ERR(inode))
21964+ goto out_xinondir;
1facf9fc 21965+
0b1ff5c3
JR
21966+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
21967+ if (inode->i_state & I_NEW) {
21968+ ii_write_lock_new_child(inode);
21969+ err = set_inode(inode, dentry);
21970+ if (!err) {
21971+ unlock_new_inode(inode);
21972+ goto out_xinondir; /* success */
21973+ }
1308ab2a 21974+
0b1ff5c3
JR
21975+ /*
21976+ * iget_failed() calls iput(), but we need to call
21977+ * ii_write_unlock() after iget_failed(). so dirty hack for
21978+ * i_count.
21979+ */
21980+ atomic_inc(&inode->i_count);
21981+ iget_failed(inode);
21982+ ii_write_unlock(inode);
21983+ au_xino_write(sb, btop, h_ino, /*ino*/0);
21984+ /* ignore this error */
21985+ goto out_iput;
21986+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) {
21987+ /*
21988+ * horrible race condition between lookup, readdir and copyup
21989+ * (or something).
21990+ */
21991+ if (hlinked && idx >= 0)
21992+ au_xinondir_leave(sb, btop, h_ino, idx);
21993+ err = reval_inode(inode, dentry);
21994+ if (unlikely(err < 0)) {
21995+ hlinked = 0;
21996+ goto out_iput;
21997+ }
21998+ if (!err)
21999+ goto out; /* success */
22000+ else if (hlinked && idx >= 0) {
22001+ err = au_xinondir_enter(sb, btop, h_ino, &idx);
22002+ if (unlikely(err)) {
22003+ iput(inode);
22004+ inode = ERR_PTR(err);
22005+ goto out;
22006+ }
22007+ }
22008+ }
1308ab2a 22009+
0b1ff5c3
JR
22010+ if (unlikely(au_test_fs_unique_ino(h_inode)))
22011+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
22012+ " b%d, %s, %pd, hi%lu, i%lu.\n",
22013+ btop, au_sbtype(h_dentry->d_sb), dentry,
22014+ (unsigned long)h_ino, (unsigned long)ino);
22015+ ino = 0;
22016+ err = au_xino_write(sb, btop, h_ino, /*ino*/0);
22017+ if (!err) {
22018+ iput(inode);
22019+ if (hlinked && idx >= 0)
22020+ au_xinondir_leave(sb, btop, h_ino, idx);
22021+ goto new_ino;
f2c43d5f 22022+ }
1facf9fc 22023+
0b1ff5c3
JR
22024+out_iput:
22025+ iput(inode);
22026+ inode = ERR_PTR(err);
22027+out_xinondir:
22028+ if (hlinked && idx >= 0)
22029+ au_xinondir_leave(sb, btop, h_ino, idx);
22030+out:
22031+ return inode;
22032+}
1facf9fc 22033+
0b1ff5c3 22034+/* ---------------------------------------------------------------------- */
1308ab2a 22035+
0b1ff5c3
JR
22036+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
22037+ struct inode *inode)
22038+{
22039+ int err;
22040+ struct inode *hi;
4a4d8108 22041+
0b1ff5c3
JR
22042+ err = au_br_rdonly(au_sbr(sb, bindex));
22043+
22044+ /* pseudo-link after flushed may happen out of bounds */
22045+ if (!err
22046+ && inode
22047+ && au_ibtop(inode) <= bindex
22048+ && bindex <= au_ibbot(inode)) {
22049+ /*
22050+ * permission check is unnecessary since vfsub routine
22051+ * will be called later
22052+ */
22053+ hi = au_h_iptr(inode, bindex);
22054+ if (hi)
22055+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
4a4d8108 22056+ }
0b1ff5c3 22057+
4a4d8108 22058+ return err;
dece6358 22059+}
1facf9fc 22060+
0b1ff5c3
JR
22061+int au_test_h_perm(struct inode *h_inode, int mask)
22062+{
22063+ if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID))
22064+ return 0;
22065+ return inode_permission(h_inode, mask);
22066+}
1facf9fc 22067+
0b1ff5c3 22068+int au_test_h_perm_sio(struct inode *h_inode, int mask)
1308ab2a 22069+{
0b1ff5c3
JR
22070+ if (au_test_nfs(h_inode->i_sb)
22071+ && (mask & MAY_WRITE)
22072+ && S_ISDIR(h_inode->i_mode))
22073+ mask |= MAY_READ; /* force permission check */
22074+ return au_test_h_perm(h_inode, mask);
1308ab2a 22075+}
0b1ff5c3
JR
22076diff -urNp -x '*.orig' linux-4.14/fs/aufs/inode.h linux-4.14/fs/aufs/inode.h
22077--- linux-4.14/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
22078+++ linux-4.14/fs/aufs/inode.h 2021-02-24 21:42:43.444448075 +0100
22079@@ -0,0 +1,695 @@
22080+/*
22081+ * Copyright (C) 2005-2017 Junjiro R. Okajima
22082+ *
22083+ * This program, aufs is free software; you can redistribute it and/or modify
22084+ * it under the terms of the GNU General Public License as published by
22085+ * the Free Software Foundation; either version 2 of the License, or
22086+ * (at your option) any later version.
22087+ *
22088+ * This program is distributed in the hope that it will be useful,
22089+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22090+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22091+ * GNU General Public License for more details.
22092+ *
22093+ * You should have received a copy of the GNU General Public License
22094+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
22095+ */
1facf9fc 22096+
4a4d8108 22097+/*
0b1ff5c3 22098+ * inode operations
4a4d8108 22099+ */
1facf9fc 22100+
0b1ff5c3
JR
22101+#ifndef __AUFS_INODE_H__
22102+#define __AUFS_INODE_H__
8b6a4947 22103+
0b1ff5c3 22104+#ifdef __KERNEL__
dece6358 22105+
0b1ff5c3
JR
22106+#include <linux/fsnotify.h>
22107+#include "rwsem.h"
dece6358 22108+
0b1ff5c3
JR
22109+struct vfsmount;
22110+
22111+struct au_hnotify {
22112+#ifdef CONFIG_AUFS_HNOTIFY
22113+#ifdef CONFIG_AUFS_HFSNOTIFY
22114+ /* never use fsnotify_add_vfsmount_mark() */
22115+ struct fsnotify_mark hn_mark;
22116+#endif
22117+ struct inode *hn_aufs_inode; /* no get/put */
22118+#endif
22119+} ____cacheline_aligned_in_smp;
22120+
22121+struct au_hinode {
22122+ struct inode *hi_inode;
22123+ aufs_bindex_t hi_id;
22124+#ifdef CONFIG_AUFS_HNOTIFY
22125+ struct au_hnotify *hi_notify;
22126+#endif
22127+
22128+ /* reference to the copied-up whiteout with get/put */
22129+ struct dentry *hi_whdentry;
22130+};
22131+
22132+/* ig_flags */
22133+#define AuIG_HALF_REFRESHED 1
22134+#define au_ig_ftest(flags, name) ((flags) & AuIG_##name)
22135+#define au_ig_fset(flags, name) \
22136+ do { (flags) |= AuIG_##name; } while (0)
22137+#define au_ig_fclr(flags, name) \
22138+ do { (flags) &= ~AuIG_##name; } while (0)
22139+
22140+struct au_iigen {
22141+ spinlock_t ig_spin;
22142+ __u32 ig_generation, ig_flags;
22143+};
22144+
22145+struct au_vdir;
22146+struct au_iinfo {
22147+ struct au_iigen ii_generation;
22148+ struct super_block *ii_hsb1; /* no get/put */
22149+
22150+ struct au_rwsem ii_rwsem;
22151+ aufs_bindex_t ii_btop, ii_bbot;
22152+ __u32 ii_higen;
22153+ struct au_hinode *ii_hinode;
22154+ struct au_vdir *ii_vdir;
22155+};
22156+
22157+struct au_icntnr {
22158+ struct au_iinfo iinfo;
22159+ struct inode vfs_inode;
22160+ struct hlist_bl_node plink;
22161+} ____cacheline_aligned_in_smp;
22162+
22163+/* au_pin flags */
22164+#define AuPin_DI_LOCKED 1
22165+#define AuPin_MNT_WRITE (1 << 1)
22166+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
22167+#define au_fset_pin(flags, name) \
22168+ do { (flags) |= AuPin_##name; } while (0)
22169+#define au_fclr_pin(flags, name) \
22170+ do { (flags) &= ~AuPin_##name; } while (0)
22171+
22172+struct au_pin {
22173+ /* input */
22174+ struct dentry *dentry;
22175+ unsigned int udba;
22176+ unsigned char lsc_di, lsc_hi, flags;
22177+ aufs_bindex_t bindex;
22178+
22179+ /* output */
22180+ struct dentry *parent;
22181+ struct au_hinode *hdir;
22182+ struct vfsmount *h_mnt;
22183+
22184+ /* temporary unlock/relock for copyup */
22185+ struct dentry *h_dentry, *h_parent;
22186+ struct au_branch *br;
22187+ struct task_struct *task;
22188+};
22189+
22190+void au_pin_hdir_unlock(struct au_pin *p);
22191+int au_pin_hdir_lock(struct au_pin *p);
22192+int au_pin_hdir_relock(struct au_pin *p);
22193+void au_pin_hdir_acquire_nest(struct au_pin *p);
22194+void au_pin_hdir_release(struct au_pin *p);
dece6358 22195+
0b1ff5c3 22196+/* ---------------------------------------------------------------------- */
1facf9fc 22197+
0b1ff5c3
JR
22198+static inline struct au_iinfo *au_ii(struct inode *inode)
22199+{
22200+ BUG_ON(is_bad_inode(inode));
22201+ return &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
4a4d8108 22202+}
1308ab2a 22203+
0b1ff5c3
JR
22204+/* ---------------------------------------------------------------------- */
22205+
22206+/* inode.c */
22207+struct inode *au_igrab(struct inode *inode);
22208+void au_refresh_iop(struct inode *inode, int force_getattr);
22209+int au_refresh_hinode_self(struct inode *inode);
22210+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
22211+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
22212+ unsigned int d_type, ino_t *ino);
22213+struct inode *au_new_inode(struct dentry *dentry, int must_new);
22214+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
22215+ struct inode *inode);
22216+int au_test_h_perm(struct inode *h_inode, int mask);
22217+int au_test_h_perm_sio(struct inode *h_inode, int mask);
22218+
22219+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
22220+ ino_t h_ino, unsigned int d_type, ino_t *ino)
1308ab2a 22221+{
0b1ff5c3
JR
22222+#ifdef CONFIG_AUFS_SHWH
22223+ return au_ino(sb, bindex, h_ino, d_type, ino);
22224+#else
22225+ return 0;
22226+#endif
22227+}
1facf9fc 22228+
0b1ff5c3
JR
22229+/* i_op.c */
22230+enum {
22231+ AuIop_SYMLINK,
22232+ AuIop_DIR,
22233+ AuIop_OTHER,
22234+ AuIop_Last
22235+};
22236+extern struct inode_operations aufs_iop[AuIop_Last],
22237+ aufs_iop_nogetattr[AuIop_Last];
1facf9fc 22238+
0b1ff5c3
JR
22239+/* au_wr_dir flags */
22240+#define AuWrDir_ADD_ENTRY 1
22241+#define AuWrDir_ISDIR (1 << 1)
22242+#define AuWrDir_TMPFILE (1 << 2)
22243+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
22244+#define au_fset_wrdir(flags, name) \
22245+ do { (flags) |= AuWrDir_##name; } while (0)
22246+#define au_fclr_wrdir(flags, name) \
22247+ do { (flags) &= ~AuWrDir_##name; } while (0)
1308ab2a 22248+
0b1ff5c3
JR
22249+struct au_wr_dir_args {
22250+ aufs_bindex_t force_btgt;
22251+ unsigned char flags;
22252+};
22253+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
22254+ struct au_wr_dir_args *args);
4a4d8108 22255+
0b1ff5c3
JR
22256+struct dentry *au_pinned_h_parent(struct au_pin *pin);
22257+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
22258+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
22259+ unsigned int udba, unsigned char flags);
22260+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
22261+ unsigned int udba, unsigned char flags) __must_check;
22262+int au_do_pin(struct au_pin *pin) __must_check;
22263+void au_unpin(struct au_pin *pin);
22264+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen);
1facf9fc 22265+
0b1ff5c3
JR
22266+#define AuIcpup_DID_CPUP 1
22267+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
22268+#define au_fset_icpup(flags, name) \
22269+ do { (flags) |= AuIcpup_##name; } while (0)
22270+#define au_fclr_icpup(flags, name) \
22271+ do { (flags) &= ~AuIcpup_##name; } while (0)
1facf9fc 22272+
0b1ff5c3
JR
22273+struct au_icpup_args {
22274+ unsigned char flags;
22275+ unsigned char pin_flags;
22276+ aufs_bindex_t btgt;
22277+ unsigned int udba;
22278+ struct au_pin pin;
22279+ struct path h_path;
4a4d8108 22280+ struct inode *h_inode;
0b1ff5c3 22281+};
1facf9fc 22282+
0b1ff5c3
JR
22283+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
22284+ struct au_icpup_args *a);
1facf9fc 22285+
0b1ff5c3
JR
22286+int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path,
22287+ int locked);
1facf9fc 22288+
0b1ff5c3
JR
22289+/* i_op_add.c */
22290+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
22291+ struct dentry *h_parent, int isdir);
22292+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
22293+ dev_t dev);
22294+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
22295+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
22296+ bool want_excl);
22297+struct vfsub_aopen_args;
22298+int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
22299+ struct vfsub_aopen_args *args);
22300+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode);
22301+int aufs_link(struct dentry *src_dentry, struct inode *dir,
22302+ struct dentry *dentry);
22303+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
027c5e7a 22304+
0b1ff5c3
JR
22305+/* i_op_del.c */
22306+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
22307+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
22308+ struct dentry *h_parent, int isdir);
22309+int aufs_unlink(struct inode *dir, struct dentry *dentry);
22310+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1facf9fc 22311+
0b1ff5c3
JR
22312+/* i_op_ren.c */
22313+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
22314+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
22315+ struct inode *dir, struct dentry *dentry,
22316+ unsigned int flags);
1facf9fc 22317+
0b1ff5c3
JR
22318+/* iinfo.c */
22319+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
22320+void au_hiput(struct au_hinode *hinode);
22321+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
22322+ struct dentry *h_wh);
22323+unsigned int au_hi_flags(struct inode *inode, int isdir);
1facf9fc 22324+
0b1ff5c3
JR
22325+/* hinode flags */
22326+#define AuHi_XINO 1
22327+#define AuHi_HNOTIFY (1 << 1)
22328+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
22329+#define au_fset_hi(flags, name) \
22330+ do { (flags) |= AuHi_##name; } while (0)
22331+#define au_fclr_hi(flags, name) \
22332+ do { (flags) &= ~AuHi_##name; } while (0)
1308ab2a 22333+
0b1ff5c3
JR
22334+#ifndef CONFIG_AUFS_HNOTIFY
22335+#undef AuHi_HNOTIFY
22336+#define AuHi_HNOTIFY 0
22337+#endif
1308ab2a 22338+
0b1ff5c3
JR
22339+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
22340+ struct inode *h_inode, unsigned int flags);
86dc4139 22341+
0b1ff5c3
JR
22342+void au_update_iigen(struct inode *inode, int half);
22343+void au_update_ibrange(struct inode *inode, int do_put_zero);
8b6a4947 22344+
0b1ff5c3
JR
22345+void au_icntnr_init_once(void *_c);
22346+void au_hinode_init(struct au_hinode *hinode);
22347+int au_iinfo_init(struct inode *inode);
22348+void au_iinfo_fin(struct inode *inode);
22349+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink);
4a4d8108 22350+
0b1ff5c3
JR
22351+#ifdef CONFIG_PROC_FS
22352+/* plink.c */
22353+int au_plink_maint(struct super_block *sb, int flags);
22354+struct au_sbinfo;
22355+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
22356+int au_plink_maint_enter(struct super_block *sb);
22357+#ifdef CONFIG_AUFS_DEBUG
22358+void au_plink_list(struct super_block *sb);
22359+#else
22360+AuStubVoid(au_plink_list, struct super_block *sb)
22361+#endif
22362+int au_plink_test(struct inode *inode);
22363+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
22364+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
22365+ struct dentry *h_dentry);
22366+void au_plink_put(struct super_block *sb, int verbose);
22367+void au_plink_clean(struct super_block *sb, int verbose);
22368+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
22369+#else
22370+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
22371+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
22372+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
22373+AuStubVoid(au_plink_list, struct super_block *sb);
22374+AuStubInt0(au_plink_test, struct inode *inode);
22375+AuStub(struct dentry *, au_plink_lkup, return NULL,
22376+ struct inode *inode, aufs_bindex_t bindex);
22377+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
22378+ struct dentry *h_dentry);
22379+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
22380+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
22381+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
22382+#endif /* CONFIG_PROC_FS */
86dc4139 22383+
0b1ff5c3
JR
22384+#ifdef CONFIG_AUFS_XATTR
22385+/* xattr.c */
22386+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags,
22387+ unsigned int verbose);
22388+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size);
22389+void au_xattr_init(struct super_block *sb);
22390+#else
22391+AuStubInt0(au_cpup_xattr, struct dentry *h_dst, struct dentry *h_src,
22392+ int ignore_flags, unsigned int verbose);
22393+AuStubVoid(au_xattr_init, struct super_block *sb);
22394+#endif
1facf9fc 22395+
0b1ff5c3
JR
22396+#ifdef CONFIG_FS_POSIX_ACL
22397+struct posix_acl *aufs_get_acl(struct inode *inode, int type);
22398+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
22399+#endif
1facf9fc 22400+
0b1ff5c3
JR
22401+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
22402+enum {
22403+ AU_XATTR_SET,
22404+ AU_ACL_SET
22405+};
dece6358 22406+
0b1ff5c3
JR
22407+struct au_sxattr {
22408+ int type;
22409+ union {
22410+ struct {
22411+ const char *name;
22412+ const void *value;
22413+ size_t size;
22414+ int flags;
22415+ } set;
22416+ struct {
22417+ struct posix_acl *acl;
22418+ int type;
22419+ } acl_set;
22420+ } u;
22421+};
22422+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode,
22423+ struct au_sxattr *arg);
22424+#endif
dece6358 22425+
0b1ff5c3 22426+/* ---------------------------------------------------------------------- */
f2c43d5f 22427+
0b1ff5c3
JR
22428+/* lock subclass for iinfo */
22429+enum {
22430+ AuLsc_II_CHILD, /* child first */
22431+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
22432+ AuLsc_II_CHILD3, /* copyup dirs */
22433+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
22434+ AuLsc_II_PARENT2,
22435+ AuLsc_II_PARENT3, /* copyup dirs */
22436+ AuLsc_II_NEW_CHILD
22437+};
dece6358 22438+
0b1ff5c3
JR
22439+/*
22440+ * ii_read_lock_child, ii_write_lock_child,
22441+ * ii_read_lock_child2, ii_write_lock_child2,
22442+ * ii_read_lock_child3, ii_write_lock_child3,
22443+ * ii_read_lock_parent, ii_write_lock_parent,
22444+ * ii_read_lock_parent2, ii_write_lock_parent2,
22445+ * ii_read_lock_parent3, ii_write_lock_parent3,
22446+ * ii_read_lock_new_child, ii_write_lock_new_child,
22447+ */
22448+#define AuReadLockFunc(name, lsc) \
22449+static inline void ii_read_lock_##name(struct inode *i) \
22450+{ \
22451+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
1facf9fc 22452+}
22453+
0b1ff5c3
JR
22454+#define AuWriteLockFunc(name, lsc) \
22455+static inline void ii_write_lock_##name(struct inode *i) \
22456+{ \
22457+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
22458+}
dece6358 22459+
0b1ff5c3
JR
22460+#define AuRWLockFuncs(name, lsc) \
22461+ AuReadLockFunc(name, lsc) \
22462+ AuWriteLockFunc(name, lsc)
027c5e7a 22463+
0b1ff5c3
JR
22464+AuRWLockFuncs(child, CHILD);
22465+AuRWLockFuncs(child2, CHILD2);
22466+AuRWLockFuncs(child3, CHILD3);
22467+AuRWLockFuncs(parent, PARENT);
22468+AuRWLockFuncs(parent2, PARENT2);
22469+AuRWLockFuncs(parent3, PARENT3);
22470+AuRWLockFuncs(new_child, NEW_CHILD);
027c5e7a 22471+
0b1ff5c3
JR
22472+#undef AuReadLockFunc
22473+#undef AuWriteLockFunc
22474+#undef AuRWLockFuncs
8b6a4947 22475+
0b1ff5c3
JR
22476+#define ii_read_unlock(i) au_rw_read_unlock(&au_ii(i)->ii_rwsem)
22477+#define ii_write_unlock(i) au_rw_write_unlock(&au_ii(i)->ii_rwsem)
22478+#define ii_downgrade_lock(i) au_rw_dgrade_lock(&au_ii(i)->ii_rwsem)
4a4d8108 22479+
0b1ff5c3
JR
22480+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
22481+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
22482+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
4a4d8108 22483+
0b1ff5c3
JR
22484+/* ---------------------------------------------------------------------- */
22485+
22486+static inline void au_icntnr_init(struct au_icntnr *c)
22487+{
22488+#ifdef CONFIG_AUFS_DEBUG
22489+ c->vfs_inode.i_mode = 0;
22490+#endif
1308ab2a 22491+}
dece6358 22492+
0b1ff5c3
JR
22493+static inline unsigned int au_iigen(struct inode *inode, unsigned int *igflags)
22494+{
22495+ unsigned int gen;
22496+ struct au_iinfo *iinfo;
22497+ struct au_iigen *iigen;
4a4d8108 22498+
0b1ff5c3
JR
22499+ iinfo = au_ii(inode);
22500+ iigen = &iinfo->ii_generation;
22501+ spin_lock(&iigen->ig_spin);
22502+ if (igflags)
22503+ *igflags = iigen->ig_flags;
22504+ gen = iigen->ig_generation;
22505+ spin_unlock(&iigen->ig_spin);
22506+
22507+ return gen;
22508+}
22509+
22510+/* tiny test for inode number */
22511+/* tmpfs generation is too rough */
22512+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
1308ab2a 22513+{
0b1ff5c3 22514+ struct au_iinfo *iinfo;
4a4d8108 22515+
0b1ff5c3
JR
22516+ iinfo = au_ii(inode);
22517+ AuRwMustAnyLock(&iinfo->ii_rwsem);
22518+ return !(iinfo->ii_hsb1 == h_inode->i_sb
22519+ && iinfo->ii_higen == h_inode->i_generation);
22520+}
4a4d8108 22521+
0b1ff5c3
JR
22522+static inline void au_iigen_dec(struct inode *inode)
22523+{
22524+ struct au_iinfo *iinfo;
22525+ struct au_iigen *iigen;
4a4d8108 22526+
0b1ff5c3
JR
22527+ iinfo = au_ii(inode);
22528+ iigen = &iinfo->ii_generation;
22529+ spin_lock(&iigen->ig_spin);
22530+ iigen->ig_generation--;
22531+ spin_unlock(&iigen->ig_spin);
1facf9fc 22532+}
22533+
0b1ff5c3 22534+static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
1facf9fc 22535+{
4a4d8108 22536+ int err;
dece6358 22537+
0b1ff5c3
JR
22538+ err = 0;
22539+ if (unlikely(inode && au_iigen(inode, NULL) != sigen))
22540+ err = -EIO;
dece6358 22541+
4a4d8108 22542+ return err;
1facf9fc 22543+}
22544+
0b1ff5c3
JR
22545+/* ---------------------------------------------------------------------- */
22546+
22547+static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo,
22548+ aufs_bindex_t bindex)
1facf9fc 22549+{
0b1ff5c3
JR
22550+ return iinfo->ii_hinode + bindex;
22551+}
1facf9fc 22552+
0b1ff5c3
JR
22553+static inline int au_is_bad_inode(struct inode *inode)
22554+{
22555+ return !!(is_bad_inode(inode) || !au_hinode(au_ii(inode), 0));
22556+}
dece6358 22557+
0b1ff5c3
JR
22558+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
22559+ aufs_bindex_t bindex)
22560+{
22561+ IiMustAnyLock(inode);
22562+ return au_hinode(au_ii(inode), bindex)->hi_id;
1308ab2a 22563+}
dece6358 22564+
0b1ff5c3 22565+static inline aufs_bindex_t au_ibtop(struct inode *inode)
1308ab2a 22566+{
0b1ff5c3
JR
22567+ IiMustAnyLock(inode);
22568+ return au_ii(inode)->ii_btop;
22569+}
4a4d8108 22570+
0b1ff5c3
JR
22571+static inline aufs_bindex_t au_ibbot(struct inode *inode)
22572+{
22573+ IiMustAnyLock(inode);
22574+ return au_ii(inode)->ii_bbot;
22575+}
4a4d8108 22576+
0b1ff5c3
JR
22577+static inline struct au_vdir *au_ivdir(struct inode *inode)
22578+{
22579+ IiMustAnyLock(inode);
22580+ return au_ii(inode)->ii_vdir;
22581+}
4a4d8108 22582+
0b1ff5c3
JR
22583+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
22584+{
22585+ IiMustAnyLock(inode);
22586+ return au_hinode(au_ii(inode), bindex)->hi_whdentry;
22587+}
22588+
22589+static inline void au_set_ibtop(struct inode *inode, aufs_bindex_t bindex)
22590+{
22591+ IiMustWriteLock(inode);
22592+ au_ii(inode)->ii_btop = bindex;
22593+}
22594+
22595+static inline void au_set_ibbot(struct inode *inode, aufs_bindex_t bindex)
22596+{
22597+ IiMustWriteLock(inode);
22598+ au_ii(inode)->ii_bbot = bindex;
22599+}
22600+
22601+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
22602+{
22603+ IiMustWriteLock(inode);
22604+ au_ii(inode)->ii_vdir = vdir;
22605+}
22606+
22607+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
22608+{
22609+ IiMustAnyLock(inode);
22610+ return au_hinode(au_ii(inode), bindex);
1facf9fc 22611+}
22612+
4a4d8108
AM
22613+/* ---------------------------------------------------------------------- */
22614+
0b1ff5c3 22615+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
1facf9fc 22616+{
0b1ff5c3
JR
22617+ if (pin)
22618+ return pin->parent;
22619+ return NULL;
22620+}
4a4d8108 22621+
0b1ff5c3
JR
22622+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
22623+{
22624+ if (pin && pin->hdir)
22625+ return pin->hdir->hi_inode;
22626+ return NULL;
22627+}
4a4d8108 22628+
0b1ff5c3
JR
22629+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
22630+{
22631+ if (pin)
22632+ return pin->hdir;
22633+ return NULL;
22634+}
f2c43d5f 22635+
0b1ff5c3
JR
22636+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
22637+{
22638+ if (pin)
22639+ pin->dentry = dentry;
22640+}
4a4d8108 22641+
0b1ff5c3
JR
22642+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
22643+ unsigned char lflag)
22644+{
22645+ if (pin) {
22646+ if (lflag)
22647+ au_fset_pin(pin->flags, DI_LOCKED);
22648+ else
22649+ au_fclr_pin(pin->flags, DI_LOCKED);
1facf9fc 22650+ }
0b1ff5c3 22651+}
1facf9fc 22652+
0b1ff5c3
JR
22653+#if 0 /* reserved */
22654+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
22655+{
22656+ if (pin) {
22657+ dput(pin->parent);
22658+ pin->parent = dget(parent);
b95c5147 22659+ }
0b1ff5c3
JR
22660+}
22661+#endif
1facf9fc 22662+
0b1ff5c3
JR
22663+/* ---------------------------------------------------------------------- */
22664+
22665+struct au_branch;
22666+#ifdef CONFIG_AUFS_HNOTIFY
22667+struct au_hnotify_op {
22668+ void (*ctl)(struct au_hinode *hinode, int do_set);
22669+ int (*alloc)(struct au_hinode *hinode);
027c5e7a 22670+
7eafdf33 22671+ /*
0b1ff5c3
JR
22672+ * if it returns true, the the caller should free hinode->hi_notify,
22673+ * otherwise ->free() frees it.
7eafdf33 22674+ */
0b1ff5c3
JR
22675+ int (*free)(struct au_hinode *hinode,
22676+ struct au_hnotify *hn) __must_check;
7eafdf33 22677+
0b1ff5c3
JR
22678+ void (*fin)(void);
22679+ int (*init)(void);
1facf9fc 22680+
0b1ff5c3
JR
22681+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm);
22682+ void (*fin_br)(struct au_branch *br);
22683+ int (*init_br)(struct au_branch *br, int perm);
22684+};
1facf9fc 22685+
0b1ff5c3
JR
22686+/* hnotify.c */
22687+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode);
22688+void au_hn_free(struct au_hinode *hinode);
22689+void au_hn_ctl(struct au_hinode *hinode, int do_set);
22690+void au_hn_reset(struct inode *inode, unsigned int flags);
22691+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
22692+ struct qstr *h_child_qstr, struct inode *h_child_inode);
22693+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm);
22694+int au_hnotify_init_br(struct au_branch *br, int perm);
22695+void au_hnotify_fin_br(struct au_branch *br);
22696+int __init au_hnotify_init(void);
22697+void au_hnotify_fin(void);
1facf9fc 22698+
0b1ff5c3
JR
22699+/* hfsnotify.c */
22700+extern const struct au_hnotify_op au_hnotify_op;
1facf9fc 22701+
0b1ff5c3
JR
22702+static inline
22703+void au_hn_init(struct au_hinode *hinode)
22704+{
22705+ hinode->hi_notify = NULL;
22706+}
1facf9fc 22707+
0b1ff5c3
JR
22708+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
22709+{
22710+ return hinode->hi_notify;
22711+}
f2c43d5f 22712+
0b1ff5c3
JR
22713+#else
22714+AuStub(int, au_hn_alloc, return -EOPNOTSUPP,
22715+ struct au_hinode *hinode __maybe_unused,
22716+ struct inode *inode __maybe_unused)
22717+AuStub(struct au_hnotify *, au_hn, return NULL, struct au_hinode *hinode)
22718+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
22719+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
22720+ int do_set __maybe_unused)
22721+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
22722+ unsigned int flags __maybe_unused)
22723+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused,
22724+ struct au_branch *br __maybe_unused,
22725+ int perm __maybe_unused)
22726+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused,
22727+ int perm __maybe_unused)
22728+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused)
22729+AuStubInt0(__init au_hnotify_init, void)
22730+AuStubVoid(au_hnotify_fin, void)
22731+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
22732+#endif /* CONFIG_AUFS_HNOTIFY */
22733+
22734+static inline void au_hn_suspend(struct au_hinode *hdir)
22735+{
22736+ au_hn_ctl(hdir, /*do_set*/0);
22737+}
22738+
22739+static inline void au_hn_resume(struct au_hinode *hdir)
22740+{
22741+ au_hn_ctl(hdir, /*do_set*/1);
22742+}
22743+
22744+static inline void au_hn_inode_lock(struct au_hinode *hdir)
22745+{
22746+ inode_lock(hdir->hi_inode);
22747+ au_hn_suspend(hdir);
22748+}
22749+
22750+static inline void au_hn_inode_lock_nested(struct au_hinode *hdir,
22751+ unsigned int sc __maybe_unused)
22752+{
22753+ inode_lock_nested(hdir->hi_inode, sc);
22754+ au_hn_suspend(hdir);
22755+}
22756+
22757+#if 0 /* unused */
22758+#include "vfsub.h"
22759+static inline void au_hn_inode_lock_shared_nested(struct au_hinode *hdir,
22760+ unsigned int sc)
22761+{
22762+ vfsub_inode_lock_shared_nested(hdir->hi_inode, sc);
22763+ au_hn_suspend(hdir);
22764+}
22765+#endif
22766+
22767+static inline void au_hn_inode_unlock(struct au_hinode *hdir)
22768+{
22769+ au_hn_resume(hdir);
22770+ inode_unlock(hdir->hi_inode);
22771+}
22772+
22773+#endif /* __KERNEL__ */
22774+#endif /* __AUFS_INODE_H__ */
22775diff -urNp -x '*.orig' linux-4.14/fs/aufs/ioctl.c linux-4.14/fs/aufs/ioctl.c
22776--- linux-4.14/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
22777+++ linux-4.14/fs/aufs/ioctl.c 2021-02-24 21:42:43.444448075 +0100
22778@@ -0,0 +1,219 @@
22779+/*
22780+ * Copyright (C) 2005-2017 Junjiro R. Okajima
22781+ *
22782+ * This program, aufs is free software; you can redistribute it and/or modify
22783+ * it under the terms of the GNU General Public License as published by
22784+ * the Free Software Foundation; either version 2 of the License, or
22785+ * (at your option) any later version.
22786+ *
22787+ * This program is distributed in the hope that it will be useful,
22788+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22789+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22790+ * GNU General Public License for more details.
22791+ *
22792+ * You should have received a copy of the GNU General Public License
22793+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
22794+ */
86dc4139 22795+
0b1ff5c3
JR
22796+/*
22797+ * ioctl
22798+ * plink-management and readdir in userspace.
22799+ * assist the pathconf(3) wrapper library.
22800+ * move-down
22801+ * File-based Hierarchical Storage Management.
22802+ */
1facf9fc 22803+
0b1ff5c3
JR
22804+#include <linux/compat.h>
22805+#include <linux/file.h>
22806+#include "aufs.h"
1facf9fc 22807+
0b1ff5c3
JR
22808+static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg)
22809+{
22810+ int err, fd;
22811+ aufs_bindex_t wbi, bindex, bbot;
22812+ struct file *h_file;
22813+ struct super_block *sb;
22814+ struct dentry *root;
22815+ struct au_branch *br;
22816+ struct aufs_wbr_fd wbrfd = {
22817+ .oflags = au_dir_roflags,
22818+ .brid = -1
22819+ };
22820+ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY
22821+ | O_NOATIME | O_CLOEXEC;
1facf9fc 22822+
0b1ff5c3 22823+ AuDebugOn(wbrfd.oflags & ~valid);
8b6a4947 22824+
0b1ff5c3
JR
22825+ if (arg) {
22826+ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd));
22827+ if (unlikely(err)) {
22828+ err = -EFAULT;
22829+ goto out;
22830+ }
8b6a4947 22831+
0b1ff5c3
JR
22832+ err = -EINVAL;
22833+ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid);
22834+ wbrfd.oflags |= au_dir_roflags;
22835+ AuDbg("0%o\n", wbrfd.oflags);
22836+ if (unlikely(wbrfd.oflags & ~valid))
22837+ goto out;
22838+ }
4a4d8108 22839+
0b1ff5c3
JR
22840+ fd = get_unused_fd_flags(0);
22841+ err = fd;
22842+ if (unlikely(fd < 0))
22843+ goto out;
4a4d8108 22844+
0b1ff5c3
JR
22845+ h_file = ERR_PTR(-EINVAL);
22846+ wbi = 0;
22847+ br = NULL;
22848+ sb = path->dentry->d_sb;
22849+ root = sb->s_root;
22850+ aufs_read_lock(root, AuLock_IR);
22851+ bbot = au_sbbot(sb);
22852+ if (wbrfd.brid >= 0) {
22853+ wbi = au_br_index(sb, wbrfd.brid);
22854+ if (unlikely(wbi < 0 || wbi > bbot))
22855+ goto out_unlock;
22856+ }
4a4d8108 22857+
0b1ff5c3
JR
22858+ h_file = ERR_PTR(-ENOENT);
22859+ br = au_sbr(sb, wbi);
22860+ if (!au_br_writable(br->br_perm)) {
22861+ if (arg)
22862+ goto out_unlock;
4a4d8108 22863+
0b1ff5c3
JR
22864+ bindex = wbi + 1;
22865+ wbi = -1;
22866+ for (; bindex <= bbot; bindex++) {
22867+ br = au_sbr(sb, bindex);
22868+ if (au_br_writable(br->br_perm)) {
22869+ wbi = bindex;
22870+ br = au_sbr(sb, wbi);
22871+ break;
22872+ }
8b6a4947 22873+ }
027c5e7a 22874+ }
0b1ff5c3
JR
22875+ AuDbg("wbi %d\n", wbi);
22876+ if (wbi >= 0)
22877+ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL,
22878+ /*force_wr*/0);
22879+
027c5e7a 22880+out_unlock:
0b1ff5c3
JR
22881+ aufs_read_unlock(root, AuLock_IR);
22882+ err = PTR_ERR(h_file);
22883+ if (IS_ERR(h_file))
22884+ goto out_fd;
22885+
22886+ au_br_put(br); /* cf. au_h_open() */
22887+ fd_install(fd, h_file);
22888+ err = fd;
22889+ goto out; /* success */
22890+
22891+out_fd:
22892+ put_unused_fd(fd);
4f0767ce 22893+out:
4a4d8108
AM
22894+ AuTraceErr(err);
22895+ return err;
1308ab2a 22896+}
1facf9fc 22897+
0b1ff5c3 22898+/* ---------------------------------------------------------------------- */
1facf9fc 22899+
0b1ff5c3
JR
22900+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
22901+{
22902+ long err;
22903+ struct dentry *dentry;
e49829fe 22904+
0b1ff5c3
JR
22905+ switch (cmd) {
22906+ case AUFS_CTL_RDU:
22907+ case AUFS_CTL_RDU_INO:
22908+ err = au_rdu_ioctl(file, cmd, arg);
22909+ break;
dece6358 22910+
0b1ff5c3
JR
22911+ case AUFS_CTL_WBR_FD:
22912+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
22913+ break;
1facf9fc 22914+
0b1ff5c3
JR
22915+ case AUFS_CTL_IBUSY:
22916+ err = au_ibusy_ioctl(file, arg);
22917+ break;
1facf9fc 22918+
0b1ff5c3
JR
22919+ case AUFS_CTL_BRINFO:
22920+ err = au_brinfo_ioctl(file, arg);
22921+ break;
1facf9fc 22922+
0b1ff5c3
JR
22923+ case AUFS_CTL_FHSM_FD:
22924+ dentry = file->f_path.dentry;
22925+ if (IS_ROOT(dentry))
22926+ err = au_fhsm_fd(dentry->d_sb, arg);
22927+ else
22928+ err = -ENOTTY;
22929+ break;
c1595e42 22930+
0b1ff5c3
JR
22931+ default:
22932+ /* do not call the lower */
22933+ AuDbg("0x%x\n", cmd);
22934+ err = -ENOTTY;
22935+ }
076b876e 22936+
0b1ff5c3
JR
22937+ AuTraceErr(err);
22938+ return err;
22939+}
1facf9fc 22940+
0b1ff5c3
JR
22941+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
22942+{
22943+ long err;
8b6a4947 22944+
0b1ff5c3
JR
22945+ switch (cmd) {
22946+ case AUFS_CTL_MVDOWN:
22947+ err = au_mvdown(file->f_path.dentry, (void __user *)arg);
22948+ break;
1facf9fc 22949+
0b1ff5c3
JR
22950+ case AUFS_CTL_WBR_FD:
22951+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
22952+ break;
1facf9fc 22953+
0b1ff5c3
JR
22954+ default:
22955+ /* do not call the lower */
22956+ AuDbg("0x%x\n", cmd);
22957+ err = -ENOTTY;
22958+ }
1facf9fc 22959+
0b1ff5c3
JR
22960+ AuTraceErr(err);
22961+ return err;
22962+}
1facf9fc 22963+
0b1ff5c3
JR
22964+#ifdef CONFIG_COMPAT
22965+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
22966+ unsigned long arg)
22967+{
22968+ long err;
1facf9fc 22969+
0b1ff5c3
JR
22970+ switch (cmd) {
22971+ case AUFS_CTL_RDU:
22972+ case AUFS_CTL_RDU_INO:
22973+ err = au_rdu_compat_ioctl(file, cmd, arg);
22974+ break;
1308ab2a 22975+
0b1ff5c3
JR
22976+ case AUFS_CTL_IBUSY:
22977+ err = au_ibusy_compat_ioctl(file, arg);
22978+ break;
4a4d8108 22979+
0b1ff5c3
JR
22980+ case AUFS_CTL_BRINFO:
22981+ err = au_brinfo_compat_ioctl(file, arg);
22982+ break;
22983+
22984+ default:
22985+ err = aufs_ioctl_dir(file, cmd, arg);
22986+ }
22987+
22988+ AuTraceErr(err);
22989+ return err;
22990+}
22991+
22992+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
22993+ unsigned long arg)
22994+{
22995+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
22996+}
22997+#endif
22998diff -urNp -x '*.orig' linux-4.14/fs/aufs/loop.c linux-4.14/fs/aufs/loop.c
22999--- linux-4.14/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
23000+++ linux-4.14/fs/aufs/loop.c 2021-02-24 21:42:43.447781402 +0100
23001@@ -0,0 +1,163 @@
1facf9fc 23002+/*
a2654f78 23003+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 23004+ *
23005+ * This program, aufs is free software; you can redistribute it and/or modify
23006+ * it under the terms of the GNU General Public License as published by
23007+ * the Free Software Foundation; either version 2 of the License, or
23008+ * (at your option) any later version.
dece6358
AM
23009+ *
23010+ * This program is distributed in the hope that it will be useful,
23011+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23012+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23013+ * GNU General Public License for more details.
23014+ *
23015+ * You should have received a copy of the GNU General Public License
523b37e3 23016+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 23017+ */
23018+
23019+/*
23020+ * support for loopback block device as a branch
23021+ */
23022+
1facf9fc 23023+#include "aufs.h"
23024+
392086de
AM
23025+/* added into drivers/block/loop.c */
23026+static struct file *(*backing_file_func)(struct super_block *sb);
23027+
1facf9fc 23028+/*
23029+ * test if two lower dentries have overlapping branches.
23030+ */
b752ccd1 23031+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 23032+{
b752ccd1 23033+ struct super_block *h_sb;
392086de
AM
23034+ struct file *backing_file;
23035+
23036+ if (unlikely(!backing_file_func)) {
23037+ /* don't load "loop" module here */
23038+ backing_file_func = symbol_get(loop_backing_file);
23039+ if (unlikely(!backing_file_func))
23040+ /* "loop" module is not loaded */
23041+ return 0;
23042+ }
1facf9fc 23043+
b752ccd1 23044+ h_sb = h_adding->d_sb;
392086de
AM
23045+ backing_file = backing_file_func(h_sb);
23046+ if (!backing_file)
1facf9fc 23047+ return 0;
23048+
2000de60 23049+ h_adding = backing_file->f_path.dentry;
b752ccd1
AM
23050+ /*
23051+ * h_adding can be local NFS.
23052+ * in this case aufs cannot detect the loop.
23053+ */
23054+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 23055+ return 1;
b752ccd1 23056+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 23057+}
23058+
23059+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
23060+int au_test_loopback_kthread(void)
23061+{
b752ccd1
AM
23062+ int ret;
23063+ struct task_struct *tsk = current;
a2a7ad62 23064+ char c, comm[sizeof(tsk->comm)];
b752ccd1
AM
23065+
23066+ ret = 0;
23067+ if (tsk->flags & PF_KTHREAD) {
a2a7ad62
AM
23068+ get_task_comm(comm, tsk);
23069+ c = comm[4];
b752ccd1 23070+ ret = ('0' <= c && c <= '9'
a2a7ad62 23071+ && !strncmp(comm, "loop", 4));
b752ccd1 23072+ }
1facf9fc 23073+
b752ccd1 23074+ return ret;
1facf9fc 23075+}
87a755f4
AM
23076+
23077+/* ---------------------------------------------------------------------- */
23078+
23079+#define au_warn_loopback_step 16
23080+static int au_warn_loopback_nelem = au_warn_loopback_step;
23081+static unsigned long *au_warn_loopback_array;
23082+
23083+void au_warn_loopback(struct super_block *h_sb)
23084+{
23085+ int i, new_nelem;
23086+ unsigned long *a, magic;
23087+ static DEFINE_SPINLOCK(spin);
23088+
23089+ magic = h_sb->s_magic;
23090+ spin_lock(&spin);
23091+ a = au_warn_loopback_array;
23092+ for (i = 0; i < au_warn_loopback_nelem && *a; i++)
23093+ if (a[i] == magic) {
23094+ spin_unlock(&spin);
23095+ return;
23096+ }
23097+
23098+ /* h_sb is new to us, print it */
23099+ if (i < au_warn_loopback_nelem) {
23100+ a[i] = magic;
23101+ goto pr;
23102+ }
23103+
23104+ /* expand the array */
23105+ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step;
23106+ a = au_kzrealloc(au_warn_loopback_array,
23107+ au_warn_loopback_nelem * sizeof(unsigned long),
e2f27e51
AM
23108+ new_nelem * sizeof(unsigned long), GFP_ATOMIC,
23109+ /*may_shrink*/0);
87a755f4
AM
23110+ if (a) {
23111+ au_warn_loopback_nelem = new_nelem;
23112+ au_warn_loopback_array = a;
23113+ a[i] = magic;
23114+ goto pr;
23115+ }
23116+
23117+ spin_unlock(&spin);
23118+ AuWarn1("realloc failed, ignored\n");
23119+ return;
23120+
23121+pr:
23122+ spin_unlock(&spin);
0c3ec466
AM
23123+ pr_warn("you may want to try another patch for loopback file "
23124+ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic);
87a755f4
AM
23125+}
23126+
23127+int au_loopback_init(void)
23128+{
23129+ int err;
23130+ struct super_block *sb __maybe_unused;
23131+
79b8bda9 23132+ BUILD_BUG_ON(sizeof(sb->s_magic) != sizeof(unsigned long));
87a755f4
AM
23133+
23134+ err = 0;
23135+ au_warn_loopback_array = kcalloc(au_warn_loopback_step,
23136+ sizeof(unsigned long), GFP_NOFS);
23137+ if (unlikely(!au_warn_loopback_array))
23138+ err = -ENOMEM;
23139+
23140+ return err;
23141+}
23142+
23143+void au_loopback_fin(void)
23144+{
79b8bda9
AM
23145+ if (backing_file_func)
23146+ symbol_put(loop_backing_file);
1c60b727 23147+ kfree(au_warn_loopback_array);
87a755f4 23148+}
0b1ff5c3
JR
23149+
23150+/* ---------------------------------------------------------------------- */
23151+
23152+/* support the loopback block device insude aufs */
23153+
23154+struct file *aufs_real_loop(struct file *file)
23155+{
23156+ struct file *f;
23157+
23158+ BUG_ON(!au_test_aufs(file->f_path.dentry->d_sb));
23159+ fi_read_lock(file);
23160+ f = au_hf_top(file);
23161+ fi_read_unlock(file);
23162+ AuDebugOn(!f);
23163+ return f;
23164+}
23165diff -urNp -x '*.orig' linux-4.14/fs/aufs/loop.h linux-4.14/fs/aufs/loop.h
23166--- linux-4.14/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
23167+++ linux-4.14/fs/aufs/loop.h 2021-02-24 21:42:43.447781402 +0100
23168@@ -0,0 +1,58 @@
1facf9fc 23169+/*
a2654f78 23170+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 23171+ *
23172+ * This program, aufs is free software; you can redistribute it and/or modify
23173+ * it under the terms of the GNU General Public License as published by
23174+ * the Free Software Foundation; either version 2 of the License, or
23175+ * (at your option) any later version.
dece6358
AM
23176+ *
23177+ * This program is distributed in the hope that it will be useful,
23178+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23179+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23180+ * GNU General Public License for more details.
23181+ *
23182+ * You should have received a copy of the GNU General Public License
523b37e3 23183+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 23184+ */
23185+
23186+/*
23187+ * support for loopback mount as a branch
23188+ */
23189+
23190+#ifndef __AUFS_LOOP_H__
23191+#define __AUFS_LOOP_H__
23192+
23193+#ifdef __KERNEL__
23194+
dece6358
AM
23195+struct dentry;
23196+struct super_block;
1facf9fc 23197+
23198+#ifdef CONFIG_AUFS_BDEV_LOOP
392086de
AM
23199+/* drivers/block/loop.c */
23200+struct file *loop_backing_file(struct super_block *sb);
23201+
1facf9fc 23202+/* loop.c */
b752ccd1 23203+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 23204+int au_test_loopback_kthread(void);
87a755f4
AM
23205+void au_warn_loopback(struct super_block *h_sb);
23206+
23207+int au_loopback_init(void);
23208+void au_loopback_fin(void);
0b1ff5c3
JR
23209+
23210+struct file *aufs_real_loop(struct file *file);
1facf9fc 23211+#else
0b1ff5c3
JR
23212+AuStub(struct file *, loop_backing_file, return NULL)
23213+
4a4d8108 23214+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 23215+ struct dentry *h_adding)
4a4d8108 23216+AuStubInt0(au_test_loopback_kthread, void)
87a755f4
AM
23217+AuStubVoid(au_warn_loopback, struct super_block *h_sb)
23218+
23219+AuStubInt0(au_loopback_init, void)
23220+AuStubVoid(au_loopback_fin, void)
0b1ff5c3
JR
23221+
23222+AuStub(struct file *, aufs_real_loop, return NULL, struct file *file)
1facf9fc 23223+#endif /* BLK_DEV_LOOP */
23224+
23225+#endif /* __KERNEL__ */
23226+#endif /* __AUFS_LOOP_H__ */
0b1ff5c3
JR
23227diff -urNp -x '*.orig' linux-4.14/fs/aufs/magic.mk linux-4.14/fs/aufs/magic.mk
23228--- linux-4.14/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
23229+++ linux-4.14/fs/aufs/magic.mk 2021-02-24 21:42:43.444448075 +0100
7e9cd9fe 23230@@ -0,0 +1,30 @@
1facf9fc 23231+
23232+# defined in ${srctree}/fs/fuse/inode.c
23233+# tristate
23234+ifdef CONFIG_FUSE_FS
23235+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
23236+endif
23237+
1facf9fc 23238+# defined in ${srctree}/fs/xfs/xfs_sb.h
23239+# tristate
23240+ifdef CONFIG_XFS_FS
23241+ccflags-y += -DXFS_SB_MAGIC=0x58465342
23242+endif
23243+
23244+# defined in ${srctree}/fs/configfs/mount.c
23245+# tristate
23246+ifdef CONFIG_CONFIGFS_FS
23247+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
23248+endif
23249+
1facf9fc 23250+# defined in ${srctree}/fs/ubifs/ubifs.h
23251+# tristate
23252+ifdef CONFIG_UBIFS_FS
23253+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
23254+endif
4a4d8108
AM
23255+
23256+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
23257+# tristate
23258+ifdef CONFIG_HFSPLUS_FS
23259+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
23260+endif
0b1ff5c3
JR
23261diff -urNp -x '*.orig' linux-4.14/fs/aufs/module.c linux-4.14/fs/aufs/module.c
23262--- linux-4.14/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
23263+++ linux-4.14/fs/aufs/module.c 2021-02-24 21:42:43.444448075 +0100
1c60b727 23264@@ -0,0 +1,266 @@
1facf9fc 23265+/*
a2654f78 23266+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 23267+ *
23268+ * This program, aufs is free software; you can redistribute it and/or modify
23269+ * it under the terms of the GNU General Public License as published by
23270+ * the Free Software Foundation; either version 2 of the License, or
23271+ * (at your option) any later version.
dece6358
AM
23272+ *
23273+ * This program is distributed in the hope that it will be useful,
23274+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23275+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23276+ * GNU General Public License for more details.
23277+ *
23278+ * You should have received a copy of the GNU General Public License
523b37e3 23279+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 23280+ */
23281+
23282+/*
23283+ * module global variables and operations
23284+ */
23285+
23286+#include <linux/module.h>
23287+#include <linux/seq_file.h>
23288+#include "aufs.h"
23289+
e2f27e51
AM
23290+/* shrinkable realloc */
23291+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink)
1facf9fc 23292+{
e2f27e51
AM
23293+ size_t sz;
23294+ int diff;
1facf9fc 23295+
e2f27e51
AM
23296+ sz = 0;
23297+ diff = -1;
23298+ if (p) {
23299+#if 0 /* unused */
23300+ if (!new_sz) {
1c60b727 23301+ kfree(p);
e2f27e51
AM
23302+ p = NULL;
23303+ goto out;
23304+ }
23305+#else
23306+ AuDebugOn(!new_sz);
23307+#endif
23308+ sz = ksize(p);
23309+ diff = au_kmidx_sub(sz, new_sz);
23310+ }
23311+ if (sz && !diff)
23312+ goto out;
23313+
23314+ if (sz < new_sz)
23315+ /* expand or SLOB */
23316+ p = krealloc(p, new_sz, gfp);
23317+ else if (new_sz < sz && may_shrink) {
23318+ /* shrink */
23319+ void *q;
23320+
23321+ q = kmalloc(new_sz, gfp);
23322+ if (q) {
23323+ if (p) {
23324+ memcpy(q, p, new_sz);
1c60b727 23325+ kfree(p);
e2f27e51
AM
23326+ }
23327+ p = q;
23328+ } else
23329+ p = NULL;
23330+ }
23331+
23332+out:
23333+ return p;
23334+}
23335+
23336+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp,
23337+ int may_shrink)
23338+{
23339+ p = au_krealloc(p, new_sz, gfp, may_shrink);
23340+ if (p && new_sz > nused)
1facf9fc 23341+ memset(p + nused, 0, new_sz - nused);
23342+ return p;
23343+}
23344+
23345+/* ---------------------------------------------------------------------- */
1facf9fc 23346+/*
23347+ * aufs caches
23348+ */
1c60b727 23349+struct kmem_cache *au_cache[AuCache_Last];
5afbbe0d
AM
23350+
23351+static void au_cache_fin(void)
23352+{
23353+ int i;
23354+
23355+ /*
23356+ * Make sure all delayed rcu free inodes are flushed before we
23357+ * destroy cache.
23358+ */
23359+ rcu_barrier();
23360+
23361+ /* excluding AuCache_HNOTIFY */
23362+ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last);
23363+ for (i = 0; i < AuCache_HNOTIFY; i++) {
1c60b727
AM
23364+ kmem_cache_destroy(au_cache[i]);
23365+ au_cache[i] = NULL;
5afbbe0d
AM
23366+ }
23367+}
23368+
1facf9fc 23369+static int __init au_cache_init(void)
23370+{
1c60b727
AM
23371+ au_cache[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
23372+ if (au_cache[AuCache_DINFO])
027c5e7a 23373+ /* SLAB_DESTROY_BY_RCU */
1c60b727 23374+ au_cache[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
f0c0a007 23375+ au_icntnr_init_once);
1c60b727
AM
23376+ if (au_cache[AuCache_ICNTNR])
23377+ au_cache[AuCache_FINFO] = AuCacheCtor(au_finfo,
f0c0a007 23378+ au_fi_init_once);
1c60b727
AM
23379+ if (au_cache[AuCache_FINFO])
23380+ au_cache[AuCache_VDIR] = AuCache(au_vdir);
23381+ if (au_cache[AuCache_VDIR])
23382+ au_cache[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
23383+ if (au_cache[AuCache_DEHSTR])
1facf9fc 23384+ return 0;
23385+
5afbbe0d 23386+ au_cache_fin();
1facf9fc 23387+ return -ENOMEM;
23388+}
23389+
1facf9fc 23390+/* ---------------------------------------------------------------------- */
23391+
23392+int au_dir_roflags;
23393+
e49829fe 23394+#ifdef CONFIG_AUFS_SBILIST
1e00d052
AM
23395+/*
23396+ * iterate_supers_type() doesn't protect us from
23397+ * remounting (branch management)
23398+ */
8b6a4947 23399+struct hlist_bl_head au_sbilist;
e49829fe
JR
23400+#endif
23401+
1facf9fc 23402+/*
23403+ * functions for module interface.
23404+ */
23405+MODULE_LICENSE("GPL");
23406+/* MODULE_LICENSE("GPL v2"); */
dece6358 23407+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 23408+MODULE_DESCRIPTION(AUFS_NAME
23409+ " -- Advanced multi layered unification filesystem");
23410+MODULE_VERSION(AUFS_VERSION);
c06a8ce3 23411+MODULE_ALIAS_FS(AUFS_NAME);
1facf9fc 23412+
1facf9fc 23413+/* this module parameter has no meaning when SYSFS is disabled */
23414+int sysaufs_brs = 1;
23415+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
23416+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
23417+
076b876e 23418+/* this module parameter has no meaning when USER_NS is disabled */
8cdd5066 23419+bool au_userns;
076b876e
AM
23420+MODULE_PARM_DESC(allow_userns, "allow unprivileged to mount under userns");
23421+module_param_named(allow_userns, au_userns, bool, S_IRUGO);
23422+
1facf9fc 23423+/* ---------------------------------------------------------------------- */
23424+
23425+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
23426+
23427+int au_seq_path(struct seq_file *seq, struct path *path)
23428+{
79b8bda9
AM
23429+ int err;
23430+
23431+ err = seq_path(seq, path, au_esc_chars);
1c60b727 23432+ if (err >= 0)
79b8bda9 23433+ err = 0;
1c60b727 23434+ else
79b8bda9
AM
23435+ err = -ENOMEM;
23436+
23437+ return err;
1facf9fc 23438+}
23439+
23440+/* ---------------------------------------------------------------------- */
23441+
23442+static int __init aufs_init(void)
23443+{
23444+ int err, i;
23445+ char *p;
23446+
23447+ p = au_esc_chars;
23448+ for (i = 1; i <= ' '; i++)
23449+ *p++ = i;
23450+ *p++ = '\\';
23451+ *p++ = '\x7f';
23452+ *p = 0;
23453+
23454+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
23455+
b95c5147
AM
23456+ memcpy(aufs_iop_nogetattr, aufs_iop, sizeof(aufs_iop));
23457+ for (i = 0; i < AuIop_Last; i++)
23458+ aufs_iop_nogetattr[i].getattr = NULL;
23459+
1c60b727 23460+ memset(au_cache, 0, sizeof(au_cache)); /* including hnotify */
f0c0a007 23461+
e49829fe 23462+ au_sbilist_init();
1facf9fc 23463+ sysaufs_brs_init();
23464+ au_debug_init();
4a4d8108 23465+ au_dy_init();
1facf9fc 23466+ err = sysaufs_init();
23467+ if (unlikely(err))
23468+ goto out;
e49829fe 23469+ err = au_procfs_init();
4f0767ce 23470+ if (unlikely(err))
953406b4 23471+ goto out_sysaufs;
e49829fe
JR
23472+ err = au_wkq_init();
23473+ if (unlikely(err))
23474+ goto out_procfs;
87a755f4 23475+ err = au_loopback_init();
1facf9fc 23476+ if (unlikely(err))
23477+ goto out_wkq;
87a755f4
AM
23478+ err = au_hnotify_init();
23479+ if (unlikely(err))
23480+ goto out_loopback;
1facf9fc 23481+ err = au_sysrq_init();
23482+ if (unlikely(err))
23483+ goto out_hin;
23484+ err = au_cache_init();
23485+ if (unlikely(err))
23486+ goto out_sysrq;
076b876e
AM
23487+
23488+ aufs_fs_type.fs_flags |= au_userns ? FS_USERNS_MOUNT : 0;
1facf9fc 23489+ err = register_filesystem(&aufs_fs_type);
23490+ if (unlikely(err))
23491+ goto out_cache;
076b876e 23492+
4a4d8108
AM
23493+ /* since we define pr_fmt, call printk directly */
23494+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 23495+ goto out; /* success */
23496+
4f0767ce 23497+out_cache:
1facf9fc 23498+ au_cache_fin();
4f0767ce 23499+out_sysrq:
1facf9fc 23500+ au_sysrq_fin();
4f0767ce 23501+out_hin:
4a4d8108 23502+ au_hnotify_fin();
87a755f4
AM
23503+out_loopback:
23504+ au_loopback_fin();
4f0767ce 23505+out_wkq:
1facf9fc 23506+ au_wkq_fin();
e49829fe
JR
23507+out_procfs:
23508+ au_procfs_fin();
4f0767ce 23509+out_sysaufs:
1facf9fc 23510+ sysaufs_fin();
4a4d8108 23511+ au_dy_fin();
4f0767ce 23512+out:
1facf9fc 23513+ return err;
23514+}
23515+
23516+static void __exit aufs_exit(void)
23517+{
23518+ unregister_filesystem(&aufs_fs_type);
23519+ au_cache_fin();
23520+ au_sysrq_fin();
4a4d8108 23521+ au_hnotify_fin();
87a755f4 23522+ au_loopback_fin();
1facf9fc 23523+ au_wkq_fin();
e49829fe 23524+ au_procfs_fin();
1facf9fc 23525+ sysaufs_fin();
4a4d8108 23526+ au_dy_fin();
1facf9fc 23527+}
23528+
23529+module_init(aufs_init);
23530+module_exit(aufs_exit);
0b1ff5c3
JR
23531diff -urNp -x '*.orig' linux-4.14/fs/aufs/module.h linux-4.14/fs/aufs/module.h
23532--- linux-4.14/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
23533+++ linux-4.14/fs/aufs/module.h 2021-02-24 21:42:43.444448075 +0100
1c60b727 23534@@ -0,0 +1,101 @@
1facf9fc 23535+/*
a2654f78 23536+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 23537+ *
23538+ * This program, aufs is free software; you can redistribute it and/or modify
23539+ * it under the terms of the GNU General Public License as published by
23540+ * the Free Software Foundation; either version 2 of the License, or
23541+ * (at your option) any later version.
dece6358
AM
23542+ *
23543+ * This program is distributed in the hope that it will be useful,
23544+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23545+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23546+ * GNU General Public License for more details.
23547+ *
23548+ * You should have received a copy of the GNU General Public License
523b37e3 23549+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 23550+ */
23551+
23552+/*
23553+ * module initialization and module-global
23554+ */
23555+
23556+#ifndef __AUFS_MODULE_H__
23557+#define __AUFS_MODULE_H__
23558+
23559+#ifdef __KERNEL__
23560+
23561+#include <linux/slab.h>
23562+
dece6358
AM
23563+struct path;
23564+struct seq_file;
23565+
1facf9fc 23566+/* module parameters */
1facf9fc 23567+extern int sysaufs_brs;
8cdd5066 23568+extern bool au_userns;
1facf9fc 23569+
23570+/* ---------------------------------------------------------------------- */
23571+
23572+extern int au_dir_roflags;
23573+
e2f27e51
AM
23574+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink);
23575+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp,
23576+ int may_shrink);
23577+
23578+static inline int au_kmidx_sub(size_t sz, size_t new_sz)
23579+{
23580+#ifndef CONFIG_SLOB
23581+ return kmalloc_index(sz) - kmalloc_index(new_sz);
23582+#else
23583+ return -1; /* SLOB is untested */
23584+#endif
23585+}
23586+
1facf9fc 23587+int au_seq_path(struct seq_file *seq, struct path *path);
23588+
e49829fe
JR
23589+#ifdef CONFIG_PROC_FS
23590+/* procfs.c */
23591+int __init au_procfs_init(void);
23592+void au_procfs_fin(void);
23593+#else
23594+AuStubInt0(au_procfs_init, void);
23595+AuStubVoid(au_procfs_fin, void);
23596+#endif
23597+
4f0767ce
JR
23598+/* ---------------------------------------------------------------------- */
23599+
1c60b727 23600+/* kmem cache */
1facf9fc 23601+enum {
23602+ AuCache_DINFO,
23603+ AuCache_ICNTNR,
23604+ AuCache_FINFO,
23605+ AuCache_VDIR,
23606+ AuCache_DEHSTR,
7eafdf33 23607+ AuCache_HNOTIFY, /* must be last */
1facf9fc 23608+ AuCache_Last
23609+};
23610+
1c60b727 23611+extern struct kmem_cache *au_cache[AuCache_Last];
f0c0a007 23612+
4a4d8108
AM
23613+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
23614+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
23615+#define AuCacheCtor(type, ctor) \
23616+ kmem_cache_create(#type, sizeof(struct type), \
23617+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 23618+
1facf9fc 23619+#define AuCacheFuncs(name, index) \
4a4d8108 23620+static inline struct au_##name *au_cache_alloc_##name(void) \
1c60b727 23621+{ return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); } \
4a4d8108 23622+static inline void au_cache_free_##name(struct au_##name *p) \
1c60b727 23623+{ kmem_cache_free(au_cache[AuCache_##index], p); }
1facf9fc 23624+
23625+AuCacheFuncs(dinfo, DINFO);
23626+AuCacheFuncs(icntnr, ICNTNR);
23627+AuCacheFuncs(finfo, FINFO);
23628+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
23629+AuCacheFuncs(vdir_dehstr, DEHSTR);
23630+#ifdef CONFIG_AUFS_HNOTIFY
23631+AuCacheFuncs(hnotify, HNOTIFY);
23632+#endif
1facf9fc 23633+
4a4d8108
AM
23634+#endif /* __KERNEL__ */
23635+#endif /* __AUFS_MODULE_H__ */
0b1ff5c3
JR
23636diff -urNp -x '*.orig' linux-4.14/fs/aufs/mvdown.c linux-4.14/fs/aufs/mvdown.c
23637--- linux-4.14/fs/aufs/mvdown.c 1970-01-01 01:00:00.000000000 +0100
23638+++ linux-4.14/fs/aufs/mvdown.c 2021-02-24 21:42:43.444448075 +0100
5afbbe0d 23639@@ -0,0 +1,704 @@
c2b27bf2 23640+/*
a2654f78 23641+ * Copyright (C) 2011-2017 Junjiro R. Okajima
c2b27bf2
AM
23642+ *
23643+ * This program, aufs is free software; you can redistribute it and/or modify
23644+ * it under the terms of the GNU General Public License as published by
23645+ * the Free Software Foundation; either version 2 of the License, or
23646+ * (at your option) any later version.
23647+ *
23648+ * This program is distributed in the hope that it will be useful,
23649+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23650+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23651+ * GNU General Public License for more details.
23652+ *
23653+ * You should have received a copy of the GNU General Public License
523b37e3
AM
23654+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
23655+ */
23656+
23657+/*
23658+ * move-down, opposite of copy-up
c2b27bf2
AM
23659+ */
23660+
23661+#include "aufs.h"
23662+
c2b27bf2
AM
23663+struct au_mvd_args {
23664+ struct {
c2b27bf2
AM
23665+ struct super_block *h_sb;
23666+ struct dentry *h_parent;
23667+ struct au_hinode *hdir;
392086de 23668+ struct inode *h_dir, *h_inode;
c1595e42 23669+ struct au_pin pin;
c2b27bf2
AM
23670+ } info[AUFS_MVDOWN_NARRAY];
23671+
23672+ struct aufs_mvdown mvdown;
23673+ struct dentry *dentry, *parent;
23674+ struct inode *inode, *dir;
23675+ struct super_block *sb;
23676+ aufs_bindex_t bopq, bwh, bfound;
23677+ unsigned char rename_lock;
c2b27bf2
AM
23678+};
23679+
392086de 23680+#define mvd_errno mvdown.au_errno
076b876e
AM
23681+#define mvd_bsrc mvdown.stbr[AUFS_MVDOWN_UPPER].bindex
23682+#define mvd_src_brid mvdown.stbr[AUFS_MVDOWN_UPPER].brid
23683+#define mvd_bdst mvdown.stbr[AUFS_MVDOWN_LOWER].bindex
23684+#define mvd_dst_brid mvdown.stbr[AUFS_MVDOWN_LOWER].brid
c2b27bf2 23685+
392086de
AM
23686+#define mvd_h_src_sb info[AUFS_MVDOWN_UPPER].h_sb
23687+#define mvd_h_src_parent info[AUFS_MVDOWN_UPPER].h_parent
23688+#define mvd_hdir_src info[AUFS_MVDOWN_UPPER].hdir
23689+#define mvd_h_src_dir info[AUFS_MVDOWN_UPPER].h_dir
23690+#define mvd_h_src_inode info[AUFS_MVDOWN_UPPER].h_inode
c1595e42 23691+#define mvd_pin_src info[AUFS_MVDOWN_UPPER].pin
392086de
AM
23692+
23693+#define mvd_h_dst_sb info[AUFS_MVDOWN_LOWER].h_sb
23694+#define mvd_h_dst_parent info[AUFS_MVDOWN_LOWER].h_parent
23695+#define mvd_hdir_dst info[AUFS_MVDOWN_LOWER].hdir
23696+#define mvd_h_dst_dir info[AUFS_MVDOWN_LOWER].h_dir
23697+#define mvd_h_dst_inode info[AUFS_MVDOWN_LOWER].h_inode
c1595e42 23698+#define mvd_pin_dst info[AUFS_MVDOWN_LOWER].pin
c2b27bf2
AM
23699+
23700+#define AU_MVD_PR(flag, ...) do { \
23701+ if (flag) \
23702+ pr_err(__VA_ARGS__); \
23703+ } while (0)
23704+
076b876e
AM
23705+static int find_lower_writable(struct au_mvd_args *a)
23706+{
23707+ struct super_block *sb;
5afbbe0d 23708+ aufs_bindex_t bindex, bbot;
076b876e
AM
23709+ struct au_branch *br;
23710+
23711+ sb = a->sb;
23712+ bindex = a->mvd_bsrc;
5afbbe0d 23713+ bbot = au_sbbot(sb);
076b876e 23714+ if (a->mvdown.flags & AUFS_MVDOWN_FHSM_LOWER)
5afbbe0d 23715+ for (bindex++; bindex <= bbot; bindex++) {
076b876e
AM
23716+ br = au_sbr(sb, bindex);
23717+ if (au_br_fhsm(br->br_perm)
8b6a4947 23718+ && !sb_rdonly(au_br_sb(br)))
076b876e
AM
23719+ return bindex;
23720+ }
23721+ else if (!(a->mvdown.flags & AUFS_MVDOWN_ROLOWER))
5afbbe0d 23722+ for (bindex++; bindex <= bbot; bindex++) {
076b876e
AM
23723+ br = au_sbr(sb, bindex);
23724+ if (!au_br_rdonly(br))
23725+ return bindex;
23726+ }
23727+ else
5afbbe0d 23728+ for (bindex++; bindex <= bbot; bindex++) {
076b876e 23729+ br = au_sbr(sb, bindex);
8b6a4947 23730+ if (!sb_rdonly(au_br_sb(br))) {
076b876e
AM
23731+ if (au_br_rdonly(br))
23732+ a->mvdown.flags
23733+ |= AUFS_MVDOWN_ROLOWER_R;
23734+ return bindex;
23735+ }
23736+ }
23737+
23738+ return -1;
23739+}
23740+
c2b27bf2 23741+/* make the parent dir on bdst */
392086de 23742+static int au_do_mkdir(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
23743+{
23744+ int err;
23745+
23746+ err = 0;
23747+ a->mvd_hdir_src = au_hi(a->dir, a->mvd_bsrc);
23748+ a->mvd_hdir_dst = au_hi(a->dir, a->mvd_bdst);
23749+ a->mvd_h_src_parent = au_h_dptr(a->parent, a->mvd_bsrc);
23750+ a->mvd_h_dst_parent = NULL;
5afbbe0d 23751+ if (au_dbbot(a->parent) >= a->mvd_bdst)
c2b27bf2
AM
23752+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
23753+ if (!a->mvd_h_dst_parent) {
23754+ err = au_cpdown_dirs(a->dentry, a->mvd_bdst);
23755+ if (unlikely(err)) {
392086de 23756+ AU_MVD_PR(dmsg, "cpdown_dirs failed\n");
c2b27bf2
AM
23757+ goto out;
23758+ }
23759+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
23760+ }
23761+
23762+out:
23763+ AuTraceErr(err);
23764+ return err;
23765+}
23766+
23767+/* lock them all */
392086de 23768+static int au_do_lock(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
23769+{
23770+ int err;
23771+ struct dentry *h_trap;
23772+
23773+ a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc);
23774+ a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst);
c1595e42
JR
23775+ err = au_pin(&a->mvd_pin_dst, a->dentry, a->mvd_bdst,
23776+ au_opt_udba(a->sb),
23777+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
23778+ AuTraceErr(err);
23779+ if (unlikely(err)) {
23780+ AU_MVD_PR(dmsg, "pin_dst failed\n");
23781+ goto out;
23782+ }
23783+
c2b27bf2
AM
23784+ if (a->mvd_h_src_sb != a->mvd_h_dst_sb) {
23785+ a->rename_lock = 0;
c1595e42
JR
23786+ au_pin_init(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
23787+ AuLsc_DI_PARENT, AuLsc_I_PARENT3,
23788+ au_opt_udba(a->sb),
23789+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
23790+ err = au_do_pin(&a->mvd_pin_src);
23791+ AuTraceErr(err);
5527c038 23792+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
c1595e42
JR
23793+ if (unlikely(err)) {
23794+ AU_MVD_PR(dmsg, "pin_src failed\n");
23795+ goto out_dst;
23796+ }
23797+ goto out; /* success */
c2b27bf2
AM
23798+ }
23799+
c2b27bf2 23800+ a->rename_lock = 1;
c1595e42
JR
23801+ au_pin_hdir_unlock(&a->mvd_pin_dst);
23802+ err = au_pin(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
23803+ au_opt_udba(a->sb),
23804+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
23805+ AuTraceErr(err);
5527c038 23806+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
c1595e42
JR
23807+ if (unlikely(err)) {
23808+ AU_MVD_PR(dmsg, "pin_src failed\n");
23809+ au_pin_hdir_lock(&a->mvd_pin_dst);
23810+ goto out_dst;
23811+ }
23812+ au_pin_hdir_unlock(&a->mvd_pin_src);
c2b27bf2
AM
23813+ h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
23814+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
23815+ if (h_trap) {
23816+ err = (h_trap != a->mvd_h_src_parent);
23817+ if (err)
23818+ err = (h_trap != a->mvd_h_dst_parent);
23819+ }
23820+ BUG_ON(err); /* it should never happen */
c1595e42
JR
23821+ if (unlikely(a->mvd_h_src_dir != au_pinned_h_dir(&a->mvd_pin_src))) {
23822+ err = -EBUSY;
23823+ AuTraceErr(err);
23824+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
23825+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
23826+ au_pin_hdir_lock(&a->mvd_pin_src);
23827+ au_unpin(&a->mvd_pin_src);
23828+ au_pin_hdir_lock(&a->mvd_pin_dst);
23829+ goto out_dst;
23830+ }
23831+ goto out; /* success */
c2b27bf2 23832+
c1595e42
JR
23833+out_dst:
23834+ au_unpin(&a->mvd_pin_dst);
c2b27bf2
AM
23835+out:
23836+ AuTraceErr(err);
23837+ return err;
23838+}
23839+
392086de 23840+static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2 23841+{
c1595e42
JR
23842+ if (!a->rename_lock)
23843+ au_unpin(&a->mvd_pin_src);
23844+ else {
c2b27bf2
AM
23845+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
23846+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
c1595e42
JR
23847+ au_pin_hdir_lock(&a->mvd_pin_src);
23848+ au_unpin(&a->mvd_pin_src);
23849+ au_pin_hdir_lock(&a->mvd_pin_dst);
23850+ }
23851+ au_unpin(&a->mvd_pin_dst);
c2b27bf2
AM
23852+}
23853+
23854+/* copy-down the file */
392086de 23855+static int au_do_cpdown(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
23856+{
23857+ int err;
23858+ struct au_cp_generic cpg = {
23859+ .dentry = a->dentry,
23860+ .bdst = a->mvd_bdst,
23861+ .bsrc = a->mvd_bsrc,
23862+ .len = -1,
c1595e42 23863+ .pin = &a->mvd_pin_dst,
c2b27bf2
AM
23864+ .flags = AuCpup_DTIME | AuCpup_HOPEN
23865+ };
23866+
23867+ AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst);
392086de
AM
23868+ if (a->mvdown.flags & AUFS_MVDOWN_OWLOWER)
23869+ au_fset_cpup(cpg.flags, OVERWRITE);
23870+ if (a->mvdown.flags & AUFS_MVDOWN_ROLOWER)
23871+ au_fset_cpup(cpg.flags, RWDST);
c2b27bf2
AM
23872+ err = au_sio_cpdown_simple(&cpg);
23873+ if (unlikely(err))
392086de 23874+ AU_MVD_PR(dmsg, "cpdown failed\n");
c2b27bf2
AM
23875+
23876+ AuTraceErr(err);
23877+ return err;
23878+}
23879+
23880+/*
23881+ * unlink the whiteout on bdst if exist which may be created by UDBA while we
23882+ * were sleeping
23883+ */
392086de 23884+static int au_do_unlink_wh(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
23885+{
23886+ int err;
23887+ struct path h_path;
23888+ struct au_branch *br;
523b37e3 23889+ struct inode *delegated;
c2b27bf2
AM
23890+
23891+ br = au_sbr(a->sb, a->mvd_bdst);
23892+ h_path.dentry = au_wh_lkup(a->mvd_h_dst_parent, &a->dentry->d_name, br);
23893+ err = PTR_ERR(h_path.dentry);
23894+ if (IS_ERR(h_path.dentry)) {
392086de 23895+ AU_MVD_PR(dmsg, "wh_lkup failed\n");
c2b27bf2
AM
23896+ goto out;
23897+ }
23898+
23899+ err = 0;
5527c038 23900+ if (d_is_positive(h_path.dentry)) {
c2b27bf2 23901+ h_path.mnt = au_br_mnt(br);
523b37e3 23902+ delegated = NULL;
5527c038 23903+ err = vfsub_unlink(d_inode(a->mvd_h_dst_parent), &h_path,
523b37e3
AM
23904+ &delegated, /*force*/0);
23905+ if (unlikely(err == -EWOULDBLOCK)) {
23906+ pr_warn("cannot retry for NFSv4 delegation"
23907+ " for an internal unlink\n");
23908+ iput(delegated);
23909+ }
c2b27bf2 23910+ if (unlikely(err))
392086de 23911+ AU_MVD_PR(dmsg, "wh_unlink failed\n");
c2b27bf2
AM
23912+ }
23913+ dput(h_path.dentry);
23914+
23915+out:
23916+ AuTraceErr(err);
23917+ return err;
23918+}
23919+
23920+/*
23921+ * unlink the topmost h_dentry
c2b27bf2 23922+ */
392086de 23923+static int au_do_unlink(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
23924+{
23925+ int err;
23926+ struct path h_path;
523b37e3 23927+ struct inode *delegated;
c2b27bf2
AM
23928+
23929+ h_path.mnt = au_sbr_mnt(a->sb, a->mvd_bsrc);
23930+ h_path.dentry = au_h_dptr(a->dentry, a->mvd_bsrc);
523b37e3
AM
23931+ delegated = NULL;
23932+ err = vfsub_unlink(a->mvd_h_src_dir, &h_path, &delegated, /*force*/0);
23933+ if (unlikely(err == -EWOULDBLOCK)) {
23934+ pr_warn("cannot retry for NFSv4 delegation"
23935+ " for an internal unlink\n");
23936+ iput(delegated);
23937+ }
c2b27bf2 23938+ if (unlikely(err))
392086de 23939+ AU_MVD_PR(dmsg, "unlink failed\n");
c2b27bf2
AM
23940+
23941+ AuTraceErr(err);
23942+ return err;
23943+}
23944+
076b876e
AM
23945+/* Since mvdown succeeded, we ignore an error of this function */
23946+static void au_do_stfs(const unsigned char dmsg, struct au_mvd_args *a)
23947+{
23948+ int err;
23949+ struct au_branch *br;
23950+
23951+ a->mvdown.flags |= AUFS_MVDOWN_STFS_FAILED;
23952+ br = au_sbr(a->sb, a->mvd_bsrc);
23953+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_UPPER].stfs);
23954+ if (!err) {
23955+ br = au_sbr(a->sb, a->mvd_bdst);
23956+ a->mvdown.stbr[AUFS_MVDOWN_LOWER].brid = br->br_id;
23957+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_LOWER].stfs);
23958+ }
23959+ if (!err)
23960+ a->mvdown.flags &= ~AUFS_MVDOWN_STFS_FAILED;
23961+ else
23962+ AU_MVD_PR(dmsg, "statfs failed (%d), ignored\n", err);
23963+}
23964+
c2b27bf2
AM
23965+/*
23966+ * copy-down the file and unlink the bsrc file.
23967+ * - unlink the bdst whout if exist
23968+ * - copy-down the file (with whtmp name and rename)
23969+ * - unlink the bsrc file
23970+ */
392086de 23971+static int au_do_mvdown(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
23972+{
23973+ int err;
23974+
392086de 23975+ err = au_do_mkdir(dmsg, a);
c2b27bf2 23976+ if (!err)
392086de 23977+ err = au_do_lock(dmsg, a);
c2b27bf2
AM
23978+ if (unlikely(err))
23979+ goto out;
23980+
23981+ /*
23982+ * do not revert the activities we made on bdst since they should be
23983+ * harmless in aufs.
23984+ */
23985+
392086de 23986+ err = au_do_cpdown(dmsg, a);
c2b27bf2 23987+ if (!err)
392086de
AM
23988+ err = au_do_unlink_wh(dmsg, a);
23989+ if (!err && !(a->mvdown.flags & AUFS_MVDOWN_KUPPER))
23990+ err = au_do_unlink(dmsg, a);
c2b27bf2
AM
23991+ if (unlikely(err))
23992+ goto out_unlock;
23993+
c1595e42
JR
23994+ AuDbg("%pd2, 0x%x, %d --> %d\n",
23995+ a->dentry, a->mvdown.flags, a->mvd_bsrc, a->mvd_bdst);
076b876e
AM
23996+ if (find_lower_writable(a) < 0)
23997+ a->mvdown.flags |= AUFS_MVDOWN_BOTTOM;
23998+
23999+ if (a->mvdown.flags & AUFS_MVDOWN_STFS)
24000+ au_do_stfs(dmsg, a);
24001+
c2b27bf2 24002+ /* maintain internal array */
392086de
AM
24003+ if (!(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) {
24004+ au_set_h_dptr(a->dentry, a->mvd_bsrc, NULL);
5afbbe0d 24005+ au_set_dbtop(a->dentry, a->mvd_bdst);
392086de 24006+ au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0);
5afbbe0d 24007+ au_set_ibtop(a->inode, a->mvd_bdst);
79b8bda9
AM
24008+ } else {
24009+ /* hide the lower */
24010+ au_set_h_dptr(a->dentry, a->mvd_bdst, NULL);
5afbbe0d 24011+ au_set_dbbot(a->dentry, a->mvd_bsrc);
79b8bda9 24012+ au_set_h_iptr(a->inode, a->mvd_bdst, NULL, /*flags*/0);
5afbbe0d 24013+ au_set_ibbot(a->inode, a->mvd_bsrc);
392086de 24014+ }
5afbbe0d
AM
24015+ if (au_dbbot(a->dentry) < a->mvd_bdst)
24016+ au_set_dbbot(a->dentry, a->mvd_bdst);
24017+ if (au_ibbot(a->inode) < a->mvd_bdst)
24018+ au_set_ibbot(a->inode, a->mvd_bdst);
c2b27bf2
AM
24019+
24020+out_unlock:
392086de 24021+ au_do_unlock(dmsg, a);
c2b27bf2
AM
24022+out:
24023+ AuTraceErr(err);
24024+ return err;
24025+}
24026+
24027+/* ---------------------------------------------------------------------- */
24028+
c2b27bf2 24029+/* make sure the file is idle */
392086de 24030+static int au_mvd_args_busy(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
24031+{
24032+ int err, plinked;
c2b27bf2
AM
24033+
24034+ err = 0;
c2b27bf2 24035+ plinked = !!au_opt_test(au_mntflags(a->sb), PLINK);
5afbbe0d 24036+ if (au_dbtop(a->dentry) == a->mvd_bsrc
c1595e42 24037+ && au_dcount(a->dentry) == 1
c2b27bf2 24038+ && atomic_read(&a->inode->i_count) == 1
392086de 24039+ /* && a->mvd_h_src_inode->i_nlink == 1 */
c2b27bf2
AM
24040+ && (!plinked || !au_plink_test(a->inode))
24041+ && a->inode->i_nlink == 1)
24042+ goto out;
24043+
24044+ err = -EBUSY;
392086de 24045+ AU_MVD_PR(dmsg,
c1595e42 24046+ "b%d, d{b%d, c%d?}, i{c%d?, l%u}, hi{l%u}, p{%d, %d}\n",
5afbbe0d 24047+ a->mvd_bsrc, au_dbtop(a->dentry), au_dcount(a->dentry),
c2b27bf2 24048+ atomic_read(&a->inode->i_count), a->inode->i_nlink,
392086de 24049+ a->mvd_h_src_inode->i_nlink,
c2b27bf2
AM
24050+ plinked, plinked ? au_plink_test(a->inode) : 0);
24051+
24052+out:
24053+ AuTraceErr(err);
24054+ return err;
24055+}
24056+
24057+/* make sure the parent dir is fine */
392086de 24058+static int au_mvd_args_parent(const unsigned char dmsg,
c2b27bf2
AM
24059+ struct au_mvd_args *a)
24060+{
24061+ int err;
24062+ aufs_bindex_t bindex;
24063+
24064+ err = 0;
24065+ if (unlikely(au_alive_dir(a->parent))) {
24066+ err = -ENOENT;
392086de 24067+ AU_MVD_PR(dmsg, "parent dir is dead\n");
c2b27bf2
AM
24068+ goto out;
24069+ }
24070+
24071+ a->bopq = au_dbdiropq(a->parent);
24072+ bindex = au_wbr_nonopq(a->dentry, a->mvd_bdst);
24073+ AuDbg("b%d\n", bindex);
24074+ if (unlikely((bindex >= 0 && bindex < a->mvd_bdst)
24075+ || (a->bopq != -1 && a->bopq < a->mvd_bdst))) {
24076+ err = -EINVAL;
392086de
AM
24077+ a->mvd_errno = EAU_MVDOWN_OPAQUE;
24078+ AU_MVD_PR(dmsg, "ancestor is opaque b%d, b%d\n",
c2b27bf2
AM
24079+ a->bopq, a->mvd_bdst);
24080+ }
24081+
24082+out:
24083+ AuTraceErr(err);
24084+ return err;
24085+}
24086+
392086de 24087+static int au_mvd_args_intermediate(const unsigned char dmsg,
c2b27bf2
AM
24088+ struct au_mvd_args *a)
24089+{
24090+ int err;
24091+ struct au_dinfo *dinfo, *tmp;
24092+
24093+ /* lookup the next lower positive entry */
24094+ err = -ENOMEM;
24095+ tmp = au_di_alloc(a->sb, AuLsc_DI_TMP);
24096+ if (unlikely(!tmp))
24097+ goto out;
24098+
24099+ a->bfound = -1;
24100+ a->bwh = -1;
24101+ dinfo = au_di(a->dentry);
24102+ au_di_cp(tmp, dinfo);
24103+ au_di_swap(tmp, dinfo);
24104+
24105+ /* returns the number of positive dentries */
5afbbe0d
AM
24106+ err = au_lkup_dentry(a->dentry, a->mvd_bsrc + 1,
24107+ /* AuLkup_IGNORE_PERM */ 0);
c2b27bf2
AM
24108+ if (!err)
24109+ a->bwh = au_dbwh(a->dentry);
24110+ else if (err > 0)
5afbbe0d 24111+ a->bfound = au_dbtop(a->dentry);
c2b27bf2
AM
24112+
24113+ au_di_swap(tmp, dinfo);
24114+ au_rw_write_unlock(&tmp->di_rwsem);
24115+ au_di_free(tmp);
24116+ if (unlikely(err < 0))
392086de 24117+ AU_MVD_PR(dmsg, "failed look-up lower\n");
c2b27bf2
AM
24118+
24119+ /*
24120+ * here, we have these cases.
24121+ * bfound == -1
24122+ * no positive dentry under bsrc. there are more sub-cases.
24123+ * bwh < 0
24124+ * there no whiteout, we can safely move-down.
24125+ * bwh <= bsrc
24126+ * impossible
24127+ * bsrc < bwh && bwh < bdst
24128+ * there is a whiteout on RO branch. cannot proceed.
24129+ * bwh == bdst
24130+ * there is a whiteout on the RW target branch. it should
24131+ * be removed.
24132+ * bdst < bwh
24133+ * there is a whiteout somewhere unrelated branch.
24134+ * -1 < bfound && bfound <= bsrc
24135+ * impossible.
24136+ * bfound < bdst
24137+ * found, but it is on RO branch between bsrc and bdst. cannot
24138+ * proceed.
24139+ * bfound == bdst
24140+ * found, replace it if AUFS_MVDOWN_FORCE is set. otherwise return
24141+ * error.
24142+ * bdst < bfound
24143+ * found, after we create the file on bdst, it will be hidden.
24144+ */
24145+
24146+ AuDebugOn(a->bfound == -1
24147+ && a->bwh != -1
24148+ && a->bwh <= a->mvd_bsrc);
24149+ AuDebugOn(-1 < a->bfound
24150+ && a->bfound <= a->mvd_bsrc);
24151+
24152+ err = -EINVAL;
24153+ if (a->bfound == -1
24154+ && a->mvd_bsrc < a->bwh
24155+ && a->bwh != -1
24156+ && a->bwh < a->mvd_bdst) {
392086de
AM
24157+ a->mvd_errno = EAU_MVDOWN_WHITEOUT;
24158+ AU_MVD_PR(dmsg, "bsrc %d, bdst %d, bfound %d, bwh %d\n",
c2b27bf2
AM
24159+ a->mvd_bsrc, a->mvd_bdst, a->bfound, a->bwh);
24160+ goto out;
24161+ } else if (a->bfound != -1 && a->bfound < a->mvd_bdst) {
392086de
AM
24162+ a->mvd_errno = EAU_MVDOWN_UPPER;
24163+ AU_MVD_PR(dmsg, "bdst %d, bfound %d\n",
c2b27bf2
AM
24164+ a->mvd_bdst, a->bfound);
24165+ goto out;
24166+ }
24167+
24168+ err = 0; /* success */
24169+
24170+out:
24171+ AuTraceErr(err);
24172+ return err;
24173+}
24174+
392086de 24175+static int au_mvd_args_exist(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
24176+{
24177+ int err;
24178+
392086de
AM
24179+ err = 0;
24180+ if (!(a->mvdown.flags & AUFS_MVDOWN_OWLOWER)
24181+ && a->bfound == a->mvd_bdst)
24182+ err = -EEXIST;
c2b27bf2
AM
24183+ AuTraceErr(err);
24184+ return err;
24185+}
24186+
392086de 24187+static int au_mvd_args(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
24188+{
24189+ int err;
24190+ struct au_branch *br;
24191+
24192+ err = -EISDIR;
24193+ if (unlikely(S_ISDIR(a->inode->i_mode)))
24194+ goto out;
24195+
24196+ err = -EINVAL;
392086de 24197+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_UPPER))
5afbbe0d 24198+ a->mvd_bsrc = au_ibtop(a->inode);
392086de
AM
24199+ else {
24200+ a->mvd_bsrc = au_br_index(a->sb, a->mvd_src_brid);
24201+ if (unlikely(a->mvd_bsrc < 0
5afbbe0d
AM
24202+ || (a->mvd_bsrc < au_dbtop(a->dentry)
24203+ || au_dbbot(a->dentry) < a->mvd_bsrc
392086de 24204+ || !au_h_dptr(a->dentry, a->mvd_bsrc))
5afbbe0d
AM
24205+ || (a->mvd_bsrc < au_ibtop(a->inode)
24206+ || au_ibbot(a->inode) < a->mvd_bsrc
392086de
AM
24207+ || !au_h_iptr(a->inode, a->mvd_bsrc)))) {
24208+ a->mvd_errno = EAU_MVDOWN_NOUPPER;
24209+ AU_MVD_PR(dmsg, "no upper\n");
24210+ goto out;
24211+ }
24212+ }
5afbbe0d 24213+ if (unlikely(a->mvd_bsrc == au_sbbot(a->sb))) {
392086de
AM
24214+ a->mvd_errno = EAU_MVDOWN_BOTTOM;
24215+ AU_MVD_PR(dmsg, "on the bottom\n");
c2b27bf2
AM
24216+ goto out;
24217+ }
392086de 24218+ a->mvd_h_src_inode = au_h_iptr(a->inode, a->mvd_bsrc);
c2b27bf2
AM
24219+ br = au_sbr(a->sb, a->mvd_bsrc);
24220+ err = au_br_rdonly(br);
392086de
AM
24221+ if (!(a->mvdown.flags & AUFS_MVDOWN_ROUPPER)) {
24222+ if (unlikely(err))
24223+ goto out;
24224+ } else if (!(vfsub_native_ro(a->mvd_h_src_inode)
24225+ || IS_APPEND(a->mvd_h_src_inode))) {
24226+ if (err)
24227+ a->mvdown.flags |= AUFS_MVDOWN_ROUPPER_R;
24228+ /* go on */
24229+ } else
c2b27bf2
AM
24230+ goto out;
24231+
24232+ err = -EINVAL;
392086de
AM
24233+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_LOWER)) {
24234+ a->mvd_bdst = find_lower_writable(a);
24235+ if (unlikely(a->mvd_bdst < 0)) {
24236+ a->mvd_errno = EAU_MVDOWN_BOTTOM;
24237+ AU_MVD_PR(dmsg, "no writable lower branch\n");
24238+ goto out;
24239+ }
24240+ } else {
24241+ a->mvd_bdst = au_br_index(a->sb, a->mvd_dst_brid);
24242+ if (unlikely(a->mvd_bdst < 0
5afbbe0d 24243+ || au_sbbot(a->sb) < a->mvd_bdst)) {
392086de
AM
24244+ a->mvd_errno = EAU_MVDOWN_NOLOWERBR;
24245+ AU_MVD_PR(dmsg, "no lower brid\n");
24246+ goto out;
24247+ }
c2b27bf2
AM
24248+ }
24249+
392086de 24250+ err = au_mvd_args_busy(dmsg, a);
c2b27bf2 24251+ if (!err)
392086de 24252+ err = au_mvd_args_parent(dmsg, a);
c2b27bf2 24253+ if (!err)
392086de 24254+ err = au_mvd_args_intermediate(dmsg, a);
c2b27bf2 24255+ if (!err)
392086de 24256+ err = au_mvd_args_exist(dmsg, a);
c2b27bf2
AM
24257+ if (!err)
24258+ AuDbg("b%d, b%d\n", a->mvd_bsrc, a->mvd_bdst);
24259+
24260+out:
24261+ AuTraceErr(err);
24262+ return err;
24263+}
24264+
24265+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *uarg)
24266+{
392086de
AM
24267+ int err, e;
24268+ unsigned char dmsg;
24269+ struct au_mvd_args *args;
79b8bda9 24270+ struct inode *inode;
c2b27bf2 24271+
79b8bda9 24272+ inode = d_inode(dentry);
c2b27bf2
AM
24273+ err = -EPERM;
24274+ if (unlikely(!capable(CAP_SYS_ADMIN)))
24275+ goto out;
24276+
392086de
AM
24277+ err = -ENOMEM;
24278+ args = kmalloc(sizeof(*args), GFP_NOFS);
24279+ if (unlikely(!args))
24280+ goto out;
24281+
24282+ err = copy_from_user(&args->mvdown, uarg, sizeof(args->mvdown));
24283+ if (!err)
24284+ err = !access_ok(VERIFY_WRITE, uarg, sizeof(*uarg));
c2b27bf2
AM
24285+ if (unlikely(err)) {
24286+ err = -EFAULT;
392086de
AM
24287+ AuTraceErr(err);
24288+ goto out_free;
c2b27bf2 24289+ }
392086de
AM
24290+ AuDbg("flags 0x%x\n", args->mvdown.flags);
24291+ args->mvdown.flags &= ~(AUFS_MVDOWN_ROLOWER_R | AUFS_MVDOWN_ROUPPER_R);
24292+ args->mvdown.au_errno = 0;
24293+ args->dentry = dentry;
79b8bda9 24294+ args->inode = inode;
392086de 24295+ args->sb = dentry->d_sb;
c2b27bf2 24296+
392086de
AM
24297+ err = -ENOENT;
24298+ dmsg = !!(args->mvdown.flags & AUFS_MVDOWN_DMSG);
24299+ args->parent = dget_parent(dentry);
5527c038 24300+ args->dir = d_inode(args->parent);
febd17d6 24301+ inode_lock_nested(args->dir, I_MUTEX_PARENT);
392086de
AM
24302+ dput(args->parent);
24303+ if (unlikely(args->parent != dentry->d_parent)) {
24304+ AU_MVD_PR(dmsg, "parent dir is moved\n");
c2b27bf2
AM
24305+ goto out_dir;
24306+ }
24307+
febd17d6 24308+ inode_lock_nested(inode, I_MUTEX_CHILD);
b95c5147 24309+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_NOPLMW);
c2b27bf2
AM
24310+ if (unlikely(err))
24311+ goto out_inode;
24312+
392086de
AM
24313+ di_write_lock_parent(args->parent);
24314+ err = au_mvd_args(dmsg, args);
c2b27bf2
AM
24315+ if (unlikely(err))
24316+ goto out_parent;
24317+
392086de 24318+ err = au_do_mvdown(dmsg, args);
c2b27bf2
AM
24319+ if (unlikely(err))
24320+ goto out_parent;
c2b27bf2 24321+
392086de 24322+ au_cpup_attr_timesizes(args->dir);
79b8bda9
AM
24323+ au_cpup_attr_timesizes(inode);
24324+ if (!(args->mvdown.flags & AUFS_MVDOWN_KUPPER))
24325+ au_cpup_igen(inode, au_h_iptr(inode, args->mvd_bdst));
c2b27bf2
AM
24326+ /* au_digen_dec(dentry); */
24327+
24328+out_parent:
392086de 24329+ di_write_unlock(args->parent);
c2b27bf2
AM
24330+ aufs_read_unlock(dentry, AuLock_DW);
24331+out_inode:
febd17d6 24332+ inode_unlock(inode);
c2b27bf2 24333+out_dir:
febd17d6 24334+ inode_unlock(args->dir);
392086de
AM
24335+out_free:
24336+ e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown));
24337+ if (unlikely(e))
24338+ err = -EFAULT;
1c60b727 24339+ kfree(args);
c2b27bf2
AM
24340+out:
24341+ AuTraceErr(err);
24342+ return err;
24343+}
0b1ff5c3
JR
24344diff -urNp -x '*.orig' linux-4.14/fs/aufs/opts.c linux-4.14/fs/aufs/opts.c
24345--- linux-4.14/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
24346+++ linux-4.14/fs/aufs/opts.c 2021-02-24 21:42:43.444448075 +0100
8b6a4947 24347@@ -0,0 +1,1891 @@
1facf9fc 24348+/*
a2654f78 24349+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 24350+ *
24351+ * This program, aufs is free software; you can redistribute it and/or modify
24352+ * it under the terms of the GNU General Public License as published by
24353+ * the Free Software Foundation; either version 2 of the License, or
24354+ * (at your option) any later version.
dece6358
AM
24355+ *
24356+ * This program is distributed in the hope that it will be useful,
24357+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24358+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24359+ * GNU General Public License for more details.
24360+ *
24361+ * You should have received a copy of the GNU General Public License
523b37e3 24362+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24363+ */
24364+
24365+/*
24366+ * mount options/flags
24367+ */
24368+
dece6358 24369+#include <linux/namei.h>
1facf9fc 24370+#include <linux/types.h> /* a distribution requires */
24371+#include <linux/parser.h>
24372+#include "aufs.h"
24373+
24374+/* ---------------------------------------------------------------------- */
24375+
24376+enum {
24377+ Opt_br,
7e9cd9fe
AM
24378+ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend,
24379+ Opt_idel, Opt_imod,
24380+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash,
dece6358 24381+ Opt_rdblk_def, Opt_rdhash_def,
7e9cd9fe 24382+ Opt_xino, Opt_noxino,
1facf9fc 24383+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
24384+ Opt_trunc_xino_path, Opt_itrunc_xino,
24385+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 24386+ Opt_shwh, Opt_noshwh,
1facf9fc 24387+ Opt_plink, Opt_noplink, Opt_list_plink,
24388+ Opt_udba,
4a4d8108 24389+ Opt_dio, Opt_nodio,
1facf9fc 24390+ Opt_diropq_a, Opt_diropq_w,
24391+ Opt_warn_perm, Opt_nowarn_perm,
24392+ Opt_wbr_copyup, Opt_wbr_create,
076b876e 24393+ Opt_fhsm_sec,
1facf9fc 24394+ Opt_verbose, Opt_noverbose,
24395+ Opt_sum, Opt_nosum, Opt_wsum,
076b876e 24396+ Opt_dirperm1, Opt_nodirperm1,
8b6a4947 24397+ Opt_dirren, Opt_nodirren,
c1595e42 24398+ Opt_acl, Opt_noacl,
1facf9fc 24399+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
24400+};
24401+
24402+static match_table_t options = {
24403+ {Opt_br, "br=%s"},
24404+ {Opt_br, "br:%s"},
24405+
24406+ {Opt_add, "add=%d:%s"},
24407+ {Opt_add, "add:%d:%s"},
24408+ {Opt_add, "ins=%d:%s"},
24409+ {Opt_add, "ins:%d:%s"},
24410+ {Opt_append, "append=%s"},
24411+ {Opt_append, "append:%s"},
24412+ {Opt_prepend, "prepend=%s"},
24413+ {Opt_prepend, "prepend:%s"},
24414+
24415+ {Opt_del, "del=%s"},
24416+ {Opt_del, "del:%s"},
24417+ /* {Opt_idel, "idel:%d"}, */
24418+ {Opt_mod, "mod=%s"},
24419+ {Opt_mod, "mod:%s"},
24420+ /* {Opt_imod, "imod:%d:%s"}, */
24421+
24422+ {Opt_dirwh, "dirwh=%d"},
24423+
24424+ {Opt_xino, "xino=%s"},
24425+ {Opt_noxino, "noxino"},
24426+ {Opt_trunc_xino, "trunc_xino"},
24427+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
24428+ {Opt_notrunc_xino, "notrunc_xino"},
24429+ {Opt_trunc_xino_path, "trunc_xino=%s"},
24430+ {Opt_itrunc_xino, "itrunc_xino=%d"},
24431+ /* {Opt_zxino, "zxino=%s"}, */
24432+ {Opt_trunc_xib, "trunc_xib"},
24433+ {Opt_notrunc_xib, "notrunc_xib"},
24434+
e49829fe 24435+#ifdef CONFIG_PROC_FS
1facf9fc 24436+ {Opt_plink, "plink"},
e49829fe
JR
24437+#else
24438+ {Opt_ignore_silent, "plink"},
24439+#endif
24440+
1facf9fc 24441+ {Opt_noplink, "noplink"},
e49829fe 24442+
1facf9fc 24443+#ifdef CONFIG_AUFS_DEBUG
24444+ {Opt_list_plink, "list_plink"},
24445+#endif
24446+
24447+ {Opt_udba, "udba=%s"},
24448+
4a4d8108
AM
24449+ {Opt_dio, "dio"},
24450+ {Opt_nodio, "nodio"},
24451+
8b6a4947
AM
24452+#ifdef CONFIG_AUFS_DIRREN
24453+ {Opt_dirren, "dirren"},
24454+ {Opt_nodirren, "nodirren"},
24455+#else
24456+ {Opt_ignore, "dirren"},
24457+ {Opt_ignore_silent, "nodirren"},
24458+#endif
24459+
076b876e
AM
24460+#ifdef CONFIG_AUFS_FHSM
24461+ {Opt_fhsm_sec, "fhsm_sec=%d"},
24462+#else
8b6a4947 24463+ {Opt_ignore, "fhsm_sec=%d"},
076b876e
AM
24464+#endif
24465+
1facf9fc 24466+ {Opt_diropq_a, "diropq=always"},
24467+ {Opt_diropq_a, "diropq=a"},
24468+ {Opt_diropq_w, "diropq=whiteouted"},
24469+ {Opt_diropq_w, "diropq=w"},
24470+
24471+ {Opt_warn_perm, "warn_perm"},
24472+ {Opt_nowarn_perm, "nowarn_perm"},
24473+
24474+ /* keep them temporary */
1facf9fc 24475+ {Opt_ignore_silent, "nodlgt"},
8b6a4947 24476+ {Opt_ignore, "clean_plink"},
1facf9fc 24477+
dece6358
AM
24478+#ifdef CONFIG_AUFS_SHWH
24479+ {Opt_shwh, "shwh"},
24480+#endif
24481+ {Opt_noshwh, "noshwh"},
24482+
076b876e
AM
24483+ {Opt_dirperm1, "dirperm1"},
24484+ {Opt_nodirperm1, "nodirperm1"},
24485+
1facf9fc 24486+ {Opt_verbose, "verbose"},
24487+ {Opt_verbose, "v"},
24488+ {Opt_noverbose, "noverbose"},
24489+ {Opt_noverbose, "quiet"},
24490+ {Opt_noverbose, "q"},
24491+ {Opt_noverbose, "silent"},
24492+
24493+ {Opt_sum, "sum"},
24494+ {Opt_nosum, "nosum"},
24495+ {Opt_wsum, "wsum"},
24496+
24497+ {Opt_rdcache, "rdcache=%d"},
24498+ {Opt_rdblk, "rdblk=%d"},
dece6358 24499+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 24500+ {Opt_rdhash, "rdhash=%d"},
dece6358 24501+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 24502+
24503+ {Opt_wbr_create, "create=%s"},
24504+ {Opt_wbr_create, "create_policy=%s"},
24505+ {Opt_wbr_copyup, "cpup=%s"},
24506+ {Opt_wbr_copyup, "copyup=%s"},
24507+ {Opt_wbr_copyup, "copyup_policy=%s"},
24508+
c1595e42
JR
24509+ /* generic VFS flag */
24510+#ifdef CONFIG_FS_POSIX_ACL
24511+ {Opt_acl, "acl"},
24512+ {Opt_noacl, "noacl"},
24513+#else
8b6a4947 24514+ {Opt_ignore, "acl"},
c1595e42
JR
24515+ {Opt_ignore_silent, "noacl"},
24516+#endif
24517+
1facf9fc 24518+ /* internal use for the scripts */
24519+ {Opt_ignore_silent, "si=%s"},
24520+
24521+ {Opt_br, "dirs=%s"},
24522+ {Opt_ignore, "debug=%d"},
24523+ {Opt_ignore, "delete=whiteout"},
24524+ {Opt_ignore, "delete=all"},
24525+ {Opt_ignore, "imap=%s"},
24526+
1308ab2a 24527+ /* temporary workaround, due to old mount(8)? */
24528+ {Opt_ignore_silent, "relatime"},
24529+
1facf9fc 24530+ {Opt_err, NULL}
24531+};
24532+
24533+/* ---------------------------------------------------------------------- */
24534+
076b876e 24535+static const char *au_parser_pattern(int val, match_table_t tbl)
1facf9fc 24536+{
076b876e
AM
24537+ struct match_token *p;
24538+
24539+ p = tbl;
24540+ while (p->pattern) {
24541+ if (p->token == val)
24542+ return p->pattern;
24543+ p++;
1facf9fc 24544+ }
24545+ BUG();
24546+ return "??";
24547+}
24548+
076b876e
AM
24549+static const char *au_optstr(int *val, match_table_t tbl)
24550+{
24551+ struct match_token *p;
24552+ int v;
24553+
24554+ v = *val;
2000de60
JR
24555+ if (!v)
24556+ goto out;
076b876e 24557+ p = tbl;
2000de60
JR
24558+ while (p->pattern) {
24559+ if (p->token
24560+ && (v & p->token) == p->token) {
076b876e
AM
24561+ *val &= ~p->token;
24562+ return p->pattern;
24563+ }
24564+ p++;
24565+ }
2000de60
JR
24566+
24567+out:
076b876e
AM
24568+ return NULL;
24569+}
24570+
1facf9fc 24571+/* ---------------------------------------------------------------------- */
24572+
1e00d052 24573+static match_table_t brperm = {
1facf9fc 24574+ {AuBrPerm_RO, AUFS_BRPERM_RO},
24575+ {AuBrPerm_RR, AUFS_BRPERM_RR},
24576+ {AuBrPerm_RW, AUFS_BRPERM_RW},
1e00d052
AM
24577+ {0, NULL}
24578+};
1facf9fc 24579+
86dc4139 24580+static match_table_t brattr = {
076b876e
AM
24581+ /* general */
24582+ {AuBrAttr_COO_REG, AUFS_BRATTR_COO_REG},
24583+ {AuBrAttr_COO_ALL, AUFS_BRATTR_COO_ALL},
c1595e42 24584+ /* 'unpin' attrib is meaningless since linux-3.18-rc1 */
86dc4139 24585+ {AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN},
2000de60 24586+#ifdef CONFIG_AUFS_FHSM
076b876e 24587+ {AuBrAttr_FHSM, AUFS_BRATTR_FHSM},
2000de60
JR
24588+#endif
24589+#ifdef CONFIG_AUFS_XATTR
c1595e42
JR
24590+ {AuBrAttr_ICEX, AUFS_BRATTR_ICEX},
24591+ {AuBrAttr_ICEX_SEC, AUFS_BRATTR_ICEX_SEC},
24592+ {AuBrAttr_ICEX_SYS, AUFS_BRATTR_ICEX_SYS},
24593+ {AuBrAttr_ICEX_TR, AUFS_BRATTR_ICEX_TR},
24594+ {AuBrAttr_ICEX_USR, AUFS_BRATTR_ICEX_USR},
24595+ {AuBrAttr_ICEX_OTH, AUFS_BRATTR_ICEX_OTH},
2000de60 24596+#endif
076b876e
AM
24597+
24598+ /* ro/rr branch */
1e00d052 24599+ {AuBrRAttr_WH, AUFS_BRRATTR_WH},
076b876e
AM
24600+
24601+ /* rw branch */
24602+ {AuBrWAttr_MOO, AUFS_BRWATTR_MOO},
1e00d052 24603+ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH},
076b876e 24604+
1e00d052 24605+ {0, NULL}
1facf9fc 24606+};
24607+
1e00d052
AM
24608+static int br_attr_val(char *str, match_table_t table, substring_t args[])
24609+{
24610+ int attr, v;
24611+ char *p;
24612+
24613+ attr = 0;
24614+ do {
24615+ p = strchr(str, '+');
24616+ if (p)
24617+ *p = 0;
24618+ v = match_token(str, table, args);
076b876e
AM
24619+ if (v) {
24620+ if (v & AuBrAttr_CMOO_Mask)
24621+ attr &= ~AuBrAttr_CMOO_Mask;
1e00d052 24622+ attr |= v;
076b876e 24623+ } else {
1e00d052
AM
24624+ if (p)
24625+ *p = '+';
0c3ec466 24626+ pr_warn("ignored branch attribute %s\n", str);
1e00d052
AM
24627+ break;
24628+ }
24629+ if (p)
24630+ str = p + 1;
24631+ } while (p);
24632+
24633+ return attr;
24634+}
24635+
076b876e
AM
24636+static int au_do_optstr_br_attr(au_br_perm_str_t *str, int perm)
24637+{
24638+ int sz;
24639+ const char *p;
24640+ char *q;
24641+
076b876e
AM
24642+ q = str->a;
24643+ *q = 0;
24644+ p = au_optstr(&perm, brattr);
24645+ if (p) {
24646+ sz = strlen(p);
24647+ memcpy(q, p, sz + 1);
24648+ q += sz;
24649+ } else
24650+ goto out;
24651+
24652+ do {
24653+ p = au_optstr(&perm, brattr);
24654+ if (p) {
24655+ *q++ = '+';
24656+ sz = strlen(p);
24657+ memcpy(q, p, sz + 1);
24658+ q += sz;
24659+ }
24660+ } while (p);
24661+
24662+out:
c1595e42 24663+ return q - str->a;
076b876e
AM
24664+}
24665+
4a4d8108 24666+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 24667+{
076b876e
AM
24668+ int val, bad, sz;
24669+ char *p;
1facf9fc 24670+ substring_t args[MAX_OPT_ARGS];
076b876e 24671+ au_br_perm_str_t attr;
1facf9fc 24672+
1e00d052
AM
24673+ p = strchr(perm, '+');
24674+ if (p)
24675+ *p = 0;
24676+ val = match_token(perm, brperm, args);
24677+ if (!val) {
24678+ if (p)
24679+ *p = '+';
0c3ec466 24680+ pr_warn("ignored branch permission %s\n", perm);
1e00d052
AM
24681+ val = AuBrPerm_RO;
24682+ goto out;
24683+ }
24684+ if (!p)
24685+ goto out;
24686+
076b876e
AM
24687+ val |= br_attr_val(p + 1, brattr, args);
24688+
24689+ bad = 0;
86dc4139 24690+ switch (val & AuBrPerm_Mask) {
1e00d052
AM
24691+ case AuBrPerm_RO:
24692+ case AuBrPerm_RR:
076b876e
AM
24693+ bad = val & AuBrWAttr_Mask;
24694+ val &= ~AuBrWAttr_Mask;
1e00d052
AM
24695+ break;
24696+ case AuBrPerm_RW:
076b876e
AM
24697+ bad = val & AuBrRAttr_Mask;
24698+ val &= ~AuBrRAttr_Mask;
1e00d052
AM
24699+ break;
24700+ }
c1595e42
JR
24701+
24702+ /*
24703+ * 'unpin' attrib becomes meaningless since linux-3.18-rc1, but aufs
24704+ * does not treat it as an error, just warning.
24705+ * this is a tiny guard for the user operation.
24706+ */
24707+ if (val & AuBrAttr_UNPIN) {
24708+ bad |= AuBrAttr_UNPIN;
24709+ val &= ~AuBrAttr_UNPIN;
24710+ }
24711+
076b876e
AM
24712+ if (unlikely(bad)) {
24713+ sz = au_do_optstr_br_attr(&attr, bad);
24714+ AuDebugOn(!sz);
24715+ pr_warn("ignored branch attribute %s\n", attr.a);
24716+ }
1e00d052
AM
24717+
24718+out:
1facf9fc 24719+ return val;
24720+}
24721+
076b876e 24722+void au_optstr_br_perm(au_br_perm_str_t *str, int perm)
1facf9fc 24723+{
076b876e
AM
24724+ au_br_perm_str_t attr;
24725+ const char *p;
24726+ char *q;
1e00d052
AM
24727+ int sz;
24728+
076b876e
AM
24729+ q = str->a;
24730+ p = au_optstr(&perm, brperm);
24731+ AuDebugOn(!p || !*p);
24732+ sz = strlen(p);
24733+ memcpy(q, p, sz + 1);
24734+ q += sz;
1e00d052 24735+
076b876e
AM
24736+ sz = au_do_optstr_br_attr(&attr, perm);
24737+ if (sz) {
24738+ *q++ = '+';
24739+ memcpy(q, attr.a, sz + 1);
1e00d052
AM
24740+ }
24741+
076b876e 24742+ AuDebugOn(strlen(str->a) >= sizeof(str->a));
1facf9fc 24743+}
24744+
24745+/* ---------------------------------------------------------------------- */
24746+
24747+static match_table_t udbalevel = {
24748+ {AuOpt_UDBA_REVAL, "reval"},
24749+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
24750+#ifdef CONFIG_AUFS_HNOTIFY
24751+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
24752+#ifdef CONFIG_AUFS_HFSNOTIFY
24753+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 24754+#endif
1facf9fc 24755+#endif
24756+ {-1, NULL}
24757+};
24758+
4a4d8108 24759+static int noinline_for_stack udba_val(char *str)
1facf9fc 24760+{
24761+ substring_t args[MAX_OPT_ARGS];
24762+
7f207e10 24763+ return match_token(str, udbalevel, args);
1facf9fc 24764+}
24765+
24766+const char *au_optstr_udba(int udba)
24767+{
076b876e 24768+ return au_parser_pattern(udba, udbalevel);
1facf9fc 24769+}
24770+
24771+/* ---------------------------------------------------------------------- */
24772+
24773+static match_table_t au_wbr_create_policy = {
24774+ {AuWbrCreate_TDP, "tdp"},
24775+ {AuWbrCreate_TDP, "top-down-parent"},
24776+ {AuWbrCreate_RR, "rr"},
24777+ {AuWbrCreate_RR, "round-robin"},
24778+ {AuWbrCreate_MFS, "mfs"},
24779+ {AuWbrCreate_MFS, "most-free-space"},
24780+ {AuWbrCreate_MFSV, "mfs:%d"},
24781+ {AuWbrCreate_MFSV, "most-free-space:%d"},
24782+
f2c43d5f
AM
24783+ /* top-down regardless the parent, and then mfs */
24784+ {AuWbrCreate_TDMFS, "tdmfs:%d"},
24785+ {AuWbrCreate_TDMFSV, "tdmfs:%d:%d"},
24786+
1facf9fc 24787+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
24788+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
24789+ {AuWbrCreate_PMFS, "pmfs"},
24790+ {AuWbrCreate_PMFSV, "pmfs:%d"},
392086de
AM
24791+ {AuWbrCreate_PMFSRR, "pmfsrr:%d"},
24792+ {AuWbrCreate_PMFSRRV, "pmfsrr:%d:%d"},
1facf9fc 24793+
24794+ {-1, NULL}
24795+};
24796+
1facf9fc 24797+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
24798+ struct au_opt_wbr_create *create)
24799+{
24800+ int err;
24801+ unsigned long long ull;
24802+
24803+ err = 0;
a2654f78 24804+ if (!match_u64(arg, &ull))
1facf9fc 24805+ create->mfsrr_watermark = ull;
24806+ else {
4a4d8108 24807+ pr_err("bad integer in %s\n", str);
1facf9fc 24808+ err = -EINVAL;
24809+ }
24810+
24811+ return err;
24812+}
24813+
24814+static int au_wbr_mfs_sec(substring_t *arg, char *str,
24815+ struct au_opt_wbr_create *create)
24816+{
24817+ int n, err;
24818+
24819+ err = 0;
027c5e7a 24820+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
1facf9fc 24821+ create->mfs_second = n;
24822+ else {
4a4d8108 24823+ pr_err("bad integer in %s\n", str);
1facf9fc 24824+ err = -EINVAL;
24825+ }
24826+
24827+ return err;
24828+}
24829+
4a4d8108
AM
24830+static int noinline_for_stack
24831+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 24832+{
24833+ int err, e;
24834+ substring_t args[MAX_OPT_ARGS];
24835+
24836+ err = match_token(str, au_wbr_create_policy, args);
24837+ create->wbr_create = err;
24838+ switch (err) {
24839+ case AuWbrCreate_MFSRRV:
f2c43d5f 24840+ case AuWbrCreate_TDMFSV:
392086de 24841+ case AuWbrCreate_PMFSRRV:
1facf9fc 24842+ e = au_wbr_mfs_wmark(&args[0], str, create);
24843+ if (!e)
24844+ e = au_wbr_mfs_sec(&args[1], str, create);
24845+ if (unlikely(e))
24846+ err = e;
24847+ break;
24848+ case AuWbrCreate_MFSRR:
f2c43d5f 24849+ case AuWbrCreate_TDMFS:
392086de 24850+ case AuWbrCreate_PMFSRR:
1facf9fc 24851+ e = au_wbr_mfs_wmark(&args[0], str, create);
24852+ if (unlikely(e)) {
24853+ err = e;
24854+ break;
24855+ }
24856+ /*FALLTHROUGH*/
24857+ case AuWbrCreate_MFS:
24858+ case AuWbrCreate_PMFS:
027c5e7a 24859+ create->mfs_second = AUFS_MFS_DEF_SEC;
1facf9fc 24860+ break;
24861+ case AuWbrCreate_MFSV:
24862+ case AuWbrCreate_PMFSV:
24863+ e = au_wbr_mfs_sec(&args[0], str, create);
24864+ if (unlikely(e))
24865+ err = e;
24866+ break;
24867+ }
24868+
24869+ return err;
24870+}
24871+
24872+const char *au_optstr_wbr_create(int wbr_create)
24873+{
076b876e 24874+ return au_parser_pattern(wbr_create, au_wbr_create_policy);
1facf9fc 24875+}
24876+
24877+static match_table_t au_wbr_copyup_policy = {
24878+ {AuWbrCopyup_TDP, "tdp"},
24879+ {AuWbrCopyup_TDP, "top-down-parent"},
24880+ {AuWbrCopyup_BUP, "bup"},
24881+ {AuWbrCopyup_BUP, "bottom-up-parent"},
24882+ {AuWbrCopyup_BU, "bu"},
24883+ {AuWbrCopyup_BU, "bottom-up"},
24884+ {-1, NULL}
24885+};
24886+
4a4d8108 24887+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 24888+{
24889+ substring_t args[MAX_OPT_ARGS];
24890+
24891+ return match_token(str, au_wbr_copyup_policy, args);
24892+}
24893+
24894+const char *au_optstr_wbr_copyup(int wbr_copyup)
24895+{
076b876e 24896+ return au_parser_pattern(wbr_copyup, au_wbr_copyup_policy);
1facf9fc 24897+}
24898+
24899+/* ---------------------------------------------------------------------- */
24900+
24901+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
24902+
24903+static void dump_opts(struct au_opts *opts)
24904+{
24905+#ifdef CONFIG_AUFS_DEBUG
24906+ /* reduce stack space */
24907+ union {
24908+ struct au_opt_add *add;
24909+ struct au_opt_del *del;
24910+ struct au_opt_mod *mod;
24911+ struct au_opt_xino *xino;
24912+ struct au_opt_xino_itrunc *xino_itrunc;
24913+ struct au_opt_wbr_create *create;
24914+ } u;
24915+ struct au_opt *opt;
24916+
24917+ opt = opts->opt;
24918+ while (opt->type != Opt_tail) {
24919+ switch (opt->type) {
24920+ case Opt_add:
24921+ u.add = &opt->add;
24922+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
24923+ u.add->bindex, u.add->pathname, u.add->perm,
24924+ u.add->path.dentry);
24925+ break;
24926+ case Opt_del:
24927+ case Opt_idel:
24928+ u.del = &opt->del;
24929+ AuDbg("del {%s, %p}\n",
24930+ u.del->pathname, u.del->h_path.dentry);
24931+ break;
24932+ case Opt_mod:
24933+ case Opt_imod:
24934+ u.mod = &opt->mod;
24935+ AuDbg("mod {%s, 0x%x, %p}\n",
24936+ u.mod->path, u.mod->perm, u.mod->h_root);
24937+ break;
24938+ case Opt_append:
24939+ u.add = &opt->add;
24940+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
24941+ u.add->bindex, u.add->pathname, u.add->perm,
24942+ u.add->path.dentry);
24943+ break;
24944+ case Opt_prepend:
24945+ u.add = &opt->add;
24946+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
24947+ u.add->bindex, u.add->pathname, u.add->perm,
24948+ u.add->path.dentry);
24949+ break;
24950+ case Opt_dirwh:
24951+ AuDbg("dirwh %d\n", opt->dirwh);
24952+ break;
24953+ case Opt_rdcache:
24954+ AuDbg("rdcache %d\n", opt->rdcache);
24955+ break;
24956+ case Opt_rdblk:
24957+ AuDbg("rdblk %u\n", opt->rdblk);
24958+ break;
dece6358
AM
24959+ case Opt_rdblk_def:
24960+ AuDbg("rdblk_def\n");
24961+ break;
1facf9fc 24962+ case Opt_rdhash:
24963+ AuDbg("rdhash %u\n", opt->rdhash);
24964+ break;
dece6358
AM
24965+ case Opt_rdhash_def:
24966+ AuDbg("rdhash_def\n");
24967+ break;
1facf9fc 24968+ case Opt_xino:
24969+ u.xino = &opt->xino;
523b37e3 24970+ AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file);
1facf9fc 24971+ break;
24972+ case Opt_trunc_xino:
24973+ AuLabel(trunc_xino);
24974+ break;
24975+ case Opt_notrunc_xino:
24976+ AuLabel(notrunc_xino);
24977+ break;
24978+ case Opt_trunc_xino_path:
24979+ case Opt_itrunc_xino:
24980+ u.xino_itrunc = &opt->xino_itrunc;
24981+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
24982+ break;
1facf9fc 24983+ case Opt_noxino:
24984+ AuLabel(noxino);
24985+ break;
24986+ case Opt_trunc_xib:
24987+ AuLabel(trunc_xib);
24988+ break;
24989+ case Opt_notrunc_xib:
24990+ AuLabel(notrunc_xib);
24991+ break;
dece6358
AM
24992+ case Opt_shwh:
24993+ AuLabel(shwh);
24994+ break;
24995+ case Opt_noshwh:
24996+ AuLabel(noshwh);
24997+ break;
076b876e
AM
24998+ case Opt_dirperm1:
24999+ AuLabel(dirperm1);
25000+ break;
25001+ case Opt_nodirperm1:
25002+ AuLabel(nodirperm1);
25003+ break;
1facf9fc 25004+ case Opt_plink:
25005+ AuLabel(plink);
25006+ break;
25007+ case Opt_noplink:
25008+ AuLabel(noplink);
25009+ break;
25010+ case Opt_list_plink:
25011+ AuLabel(list_plink);
25012+ break;
25013+ case Opt_udba:
25014+ AuDbg("udba %d, %s\n",
25015+ opt->udba, au_optstr_udba(opt->udba));
25016+ break;
4a4d8108
AM
25017+ case Opt_dio:
25018+ AuLabel(dio);
25019+ break;
25020+ case Opt_nodio:
25021+ AuLabel(nodio);
25022+ break;
1facf9fc 25023+ case Opt_diropq_a:
25024+ AuLabel(diropq_a);
25025+ break;
25026+ case Opt_diropq_w:
25027+ AuLabel(diropq_w);
25028+ break;
25029+ case Opt_warn_perm:
25030+ AuLabel(warn_perm);
25031+ break;
25032+ case Opt_nowarn_perm:
25033+ AuLabel(nowarn_perm);
25034+ break;
1facf9fc 25035+ case Opt_verbose:
25036+ AuLabel(verbose);
25037+ break;
25038+ case Opt_noverbose:
25039+ AuLabel(noverbose);
25040+ break;
25041+ case Opt_sum:
25042+ AuLabel(sum);
25043+ break;
25044+ case Opt_nosum:
25045+ AuLabel(nosum);
25046+ break;
25047+ case Opt_wsum:
25048+ AuLabel(wsum);
25049+ break;
25050+ case Opt_wbr_create:
25051+ u.create = &opt->wbr_create;
25052+ AuDbg("create %d, %s\n", u.create->wbr_create,
25053+ au_optstr_wbr_create(u.create->wbr_create));
25054+ switch (u.create->wbr_create) {
25055+ case AuWbrCreate_MFSV:
25056+ case AuWbrCreate_PMFSV:
25057+ AuDbg("%d sec\n", u.create->mfs_second);
25058+ break;
25059+ case AuWbrCreate_MFSRR:
f2c43d5f 25060+ case AuWbrCreate_TDMFS:
1facf9fc 25061+ AuDbg("%llu watermark\n",
25062+ u.create->mfsrr_watermark);
25063+ break;
25064+ case AuWbrCreate_MFSRRV:
f2c43d5f 25065+ case AuWbrCreate_TDMFSV:
392086de 25066+ case AuWbrCreate_PMFSRRV:
1facf9fc 25067+ AuDbg("%llu watermark, %d sec\n",
25068+ u.create->mfsrr_watermark,
25069+ u.create->mfs_second);
25070+ break;
25071+ }
25072+ break;
25073+ case Opt_wbr_copyup:
25074+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
25075+ au_optstr_wbr_copyup(opt->wbr_copyup));
25076+ break;
076b876e
AM
25077+ case Opt_fhsm_sec:
25078+ AuDbg("fhsm_sec %u\n", opt->fhsm_second);
25079+ break;
8b6a4947
AM
25080+ case Opt_dirren:
25081+ AuLabel(dirren);
25082+ break;
25083+ case Opt_nodirren:
25084+ AuLabel(nodirren);
25085+ break;
c1595e42
JR
25086+ case Opt_acl:
25087+ AuLabel(acl);
25088+ break;
25089+ case Opt_noacl:
25090+ AuLabel(noacl);
25091+ break;
1facf9fc 25092+ default:
25093+ BUG();
25094+ }
25095+ opt++;
25096+ }
25097+#endif
25098+}
25099+
25100+void au_opts_free(struct au_opts *opts)
25101+{
25102+ struct au_opt *opt;
25103+
25104+ opt = opts->opt;
25105+ while (opt->type != Opt_tail) {
25106+ switch (opt->type) {
25107+ case Opt_add:
25108+ case Opt_append:
25109+ case Opt_prepend:
25110+ path_put(&opt->add.path);
25111+ break;
25112+ case Opt_del:
25113+ case Opt_idel:
25114+ path_put(&opt->del.h_path);
25115+ break;
25116+ case Opt_mod:
25117+ case Opt_imod:
25118+ dput(opt->mod.h_root);
25119+ break;
25120+ case Opt_xino:
25121+ fput(opt->xino.file);
25122+ break;
25123+ }
25124+ opt++;
25125+ }
25126+}
25127+
25128+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
25129+ aufs_bindex_t bindex)
25130+{
25131+ int err;
25132+ struct au_opt_add *add = &opt->add;
25133+ char *p;
25134+
25135+ add->bindex = bindex;
1e00d052 25136+ add->perm = AuBrPerm_RO;
1facf9fc 25137+ add->pathname = opt_str;
25138+ p = strchr(opt_str, '=');
25139+ if (p) {
25140+ *p++ = 0;
25141+ if (*p)
25142+ add->perm = br_perm_val(p);
25143+ }
25144+
25145+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
25146+ if (!err) {
25147+ if (!p) {
25148+ add->perm = AuBrPerm_RO;
25149+ if (au_test_fs_rr(add->path.dentry->d_sb))
25150+ add->perm = AuBrPerm_RR;
25151+ else if (!bindex && !(sb_flags & MS_RDONLY))
25152+ add->perm = AuBrPerm_RW;
25153+ }
25154+ opt->type = Opt_add;
25155+ goto out;
25156+ }
4a4d8108 25157+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 25158+ err = -EINVAL;
25159+
4f0767ce 25160+out:
1facf9fc 25161+ return err;
25162+}
25163+
25164+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
25165+{
25166+ int err;
25167+
25168+ del->pathname = args[0].from;
25169+ AuDbg("del path %s\n", del->pathname);
25170+
25171+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
25172+ if (unlikely(err))
4a4d8108 25173+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 25174+
25175+ return err;
25176+}
25177+
25178+#if 0 /* reserved for future use */
25179+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
25180+ struct au_opt_del *del, substring_t args[])
25181+{
25182+ int err;
25183+ struct dentry *root;
25184+
25185+ err = -EINVAL;
25186+ root = sb->s_root;
25187+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 25188+ if (bindex < 0 || au_sbbot(sb) < bindex) {
4a4d8108 25189+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 25190+ goto out;
25191+ }
25192+
25193+ err = 0;
25194+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
25195+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
25196+
4f0767ce 25197+out:
1facf9fc 25198+ aufs_read_unlock(root, !AuLock_IR);
25199+ return err;
25200+}
25201+#endif
25202+
4a4d8108
AM
25203+static int noinline_for_stack
25204+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 25205+{
25206+ int err;
25207+ struct path path;
25208+ char *p;
25209+
25210+ err = -EINVAL;
25211+ mod->path = args[0].from;
25212+ p = strchr(mod->path, '=');
25213+ if (unlikely(!p)) {
4a4d8108 25214+ pr_err("no permssion %s\n", args[0].from);
1facf9fc 25215+ goto out;
25216+ }
25217+
25218+ *p++ = 0;
25219+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
25220+ if (unlikely(err)) {
4a4d8108 25221+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 25222+ goto out;
25223+ }
25224+
25225+ mod->perm = br_perm_val(p);
25226+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
25227+ mod->h_root = dget(path.dentry);
25228+ path_put(&path);
25229+
4f0767ce 25230+out:
1facf9fc 25231+ return err;
25232+}
25233+
25234+#if 0 /* reserved for future use */
25235+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
25236+ struct au_opt_mod *mod, substring_t args[])
25237+{
25238+ int err;
25239+ struct dentry *root;
25240+
25241+ err = -EINVAL;
25242+ root = sb->s_root;
25243+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 25244+ if (bindex < 0 || au_sbbot(sb) < bindex) {
4a4d8108 25245+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 25246+ goto out;
25247+ }
25248+
25249+ err = 0;
25250+ mod->perm = br_perm_val(args[1].from);
25251+ AuDbg("mod path %s, perm 0x%x, %s\n",
25252+ mod->path, mod->perm, args[1].from);
25253+ mod->h_root = dget(au_h_dptr(root, bindex));
25254+
4f0767ce 25255+out:
1facf9fc 25256+ aufs_read_unlock(root, !AuLock_IR);
25257+ return err;
25258+}
25259+#endif
25260+
25261+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
25262+ substring_t args[])
25263+{
25264+ int err;
25265+ struct file *file;
25266+
25267+ file = au_xino_create(sb, args[0].from, /*silent*/0);
25268+ err = PTR_ERR(file);
25269+ if (IS_ERR(file))
25270+ goto out;
25271+
25272+ err = -EINVAL;
2000de60 25273+ if (unlikely(file->f_path.dentry->d_sb == sb)) {
1facf9fc 25274+ fput(file);
4a4d8108 25275+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 25276+ goto out;
25277+ }
25278+
25279+ err = 0;
25280+ xino->file = file;
25281+ xino->path = args[0].from;
25282+
4f0767ce 25283+out:
1facf9fc 25284+ return err;
25285+}
25286+
4a4d8108
AM
25287+static int noinline_for_stack
25288+au_opts_parse_xino_itrunc_path(struct super_block *sb,
25289+ struct au_opt_xino_itrunc *xino_itrunc,
25290+ substring_t args[])
1facf9fc 25291+{
25292+ int err;
5afbbe0d 25293+ aufs_bindex_t bbot, bindex;
1facf9fc 25294+ struct path path;
25295+ struct dentry *root;
25296+
25297+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
25298+ if (unlikely(err)) {
4a4d8108 25299+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 25300+ goto out;
25301+ }
25302+
25303+ xino_itrunc->bindex = -1;
25304+ root = sb->s_root;
25305+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d
AM
25306+ bbot = au_sbbot(sb);
25307+ for (bindex = 0; bindex <= bbot; bindex++) {
1facf9fc 25308+ if (au_h_dptr(root, bindex) == path.dentry) {
25309+ xino_itrunc->bindex = bindex;
25310+ break;
25311+ }
25312+ }
25313+ aufs_read_unlock(root, !AuLock_IR);
25314+ path_put(&path);
25315+
25316+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 25317+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 25318+ err = -EINVAL;
25319+ }
25320+
4f0767ce 25321+out:
1facf9fc 25322+ return err;
25323+}
25324+
25325+/* called without aufs lock */
25326+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
25327+{
25328+ int err, n, token;
25329+ aufs_bindex_t bindex;
25330+ unsigned char skipped;
25331+ struct dentry *root;
25332+ struct au_opt *opt, *opt_tail;
25333+ char *opt_str;
25334+ /* reduce the stack space */
25335+ union {
25336+ struct au_opt_xino_itrunc *xino_itrunc;
25337+ struct au_opt_wbr_create *create;
25338+ } u;
25339+ struct {
25340+ substring_t args[MAX_OPT_ARGS];
25341+ } *a;
25342+
25343+ err = -ENOMEM;
25344+ a = kmalloc(sizeof(*a), GFP_NOFS);
25345+ if (unlikely(!a))
25346+ goto out;
25347+
25348+ root = sb->s_root;
25349+ err = 0;
25350+ bindex = 0;
25351+ opt = opts->opt;
25352+ opt_tail = opt + opts->max_opt - 1;
25353+ opt->type = Opt_tail;
25354+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
25355+ err = -EINVAL;
25356+ skipped = 0;
25357+ token = match_token(opt_str, options, a->args);
25358+ switch (token) {
25359+ case Opt_br:
25360+ err = 0;
25361+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
25362+ && *opt_str) {
25363+ err = opt_add(opt, opt_str, opts->sb_flags,
25364+ bindex++);
25365+ if (unlikely(!err && ++opt > opt_tail)) {
25366+ err = -E2BIG;
25367+ break;
25368+ }
25369+ opt->type = Opt_tail;
25370+ skipped = 1;
25371+ }
25372+ break;
25373+ case Opt_add:
25374+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 25375+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 25376+ break;
25377+ }
25378+ bindex = n;
25379+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
25380+ bindex);
25381+ if (!err)
25382+ opt->type = token;
25383+ break;
25384+ case Opt_append:
25385+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
25386+ /*dummy bindex*/1);
25387+ if (!err)
25388+ opt->type = token;
25389+ break;
25390+ case Opt_prepend:
25391+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
25392+ /*bindex*/0);
25393+ if (!err)
25394+ opt->type = token;
25395+ break;
25396+ case Opt_del:
25397+ err = au_opts_parse_del(&opt->del, a->args);
25398+ if (!err)
25399+ opt->type = token;
25400+ break;
25401+#if 0 /* reserved for future use */
25402+ case Opt_idel:
25403+ del->pathname = "(indexed)";
25404+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 25405+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 25406+ break;
25407+ }
25408+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
25409+ if (!err)
25410+ opt->type = token;
25411+ break;
25412+#endif
25413+ case Opt_mod:
25414+ err = au_opts_parse_mod(&opt->mod, a->args);
25415+ if (!err)
25416+ opt->type = token;
25417+ break;
25418+#ifdef IMOD /* reserved for future use */
25419+ case Opt_imod:
25420+ u.mod->path = "(indexed)";
25421+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 25422+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 25423+ break;
25424+ }
25425+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
25426+ if (!err)
25427+ opt->type = token;
25428+ break;
25429+#endif
25430+ case Opt_xino:
25431+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
25432+ if (!err)
25433+ opt->type = token;
25434+ break;
25435+
25436+ case Opt_trunc_xino_path:
25437+ err = au_opts_parse_xino_itrunc_path
25438+ (sb, &opt->xino_itrunc, a->args);
25439+ if (!err)
25440+ opt->type = token;
25441+ break;
25442+
25443+ case Opt_itrunc_xino:
25444+ u.xino_itrunc = &opt->xino_itrunc;
25445+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 25446+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 25447+ break;
25448+ }
25449+ u.xino_itrunc->bindex = n;
25450+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 25451+ if (n < 0 || au_sbbot(sb) < n) {
4a4d8108 25452+ pr_err("out of bounds, %d\n", n);
1facf9fc 25453+ aufs_read_unlock(root, !AuLock_IR);
25454+ break;
25455+ }
25456+ aufs_read_unlock(root, !AuLock_IR);
25457+ err = 0;
25458+ opt->type = token;
25459+ break;
25460+
25461+ case Opt_dirwh:
25462+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
25463+ break;
25464+ err = 0;
25465+ opt->type = token;
25466+ break;
25467+
25468+ case Opt_rdcache:
027c5e7a
AM
25469+ if (unlikely(match_int(&a->args[0], &n))) {
25470+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 25471+ break;
027c5e7a
AM
25472+ }
25473+ if (unlikely(n > AUFS_RDCACHE_MAX)) {
25474+ pr_err("rdcache must be smaller than %d\n",
25475+ AUFS_RDCACHE_MAX);
25476+ break;
25477+ }
25478+ opt->rdcache = n;
1facf9fc 25479+ err = 0;
25480+ opt->type = token;
25481+ break;
25482+ case Opt_rdblk:
25483+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 25484+ || n < 0
1facf9fc 25485+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 25486+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 25487+ break;
25488+ }
1308ab2a 25489+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
25490+ pr_err("rdblk must be larger than %d\n",
25491+ NAME_MAX);
1facf9fc 25492+ break;
25493+ }
25494+ opt->rdblk = n;
25495+ err = 0;
25496+ opt->type = token;
25497+ break;
25498+ case Opt_rdhash:
25499+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 25500+ || n < 0
1facf9fc 25501+ || n * sizeof(struct hlist_head)
25502+ > KMALLOC_MAX_SIZE)) {
4a4d8108 25503+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 25504+ break;
25505+ }
25506+ opt->rdhash = n;
25507+ err = 0;
25508+ opt->type = token;
25509+ break;
25510+
25511+ case Opt_trunc_xino:
25512+ case Opt_notrunc_xino:
25513+ case Opt_noxino:
25514+ case Opt_trunc_xib:
25515+ case Opt_notrunc_xib:
dece6358
AM
25516+ case Opt_shwh:
25517+ case Opt_noshwh:
076b876e
AM
25518+ case Opt_dirperm1:
25519+ case Opt_nodirperm1:
1facf9fc 25520+ case Opt_plink:
25521+ case Opt_noplink:
25522+ case Opt_list_plink:
4a4d8108
AM
25523+ case Opt_dio:
25524+ case Opt_nodio:
1facf9fc 25525+ case Opt_diropq_a:
25526+ case Opt_diropq_w:
25527+ case Opt_warn_perm:
25528+ case Opt_nowarn_perm:
1facf9fc 25529+ case Opt_verbose:
25530+ case Opt_noverbose:
25531+ case Opt_sum:
25532+ case Opt_nosum:
25533+ case Opt_wsum:
dece6358
AM
25534+ case Opt_rdblk_def:
25535+ case Opt_rdhash_def:
8b6a4947
AM
25536+ case Opt_dirren:
25537+ case Opt_nodirren:
c1595e42
JR
25538+ case Opt_acl:
25539+ case Opt_noacl:
1facf9fc 25540+ err = 0;
25541+ opt->type = token;
25542+ break;
25543+
25544+ case Opt_udba:
25545+ opt->udba = udba_val(a->args[0].from);
25546+ if (opt->udba >= 0) {
25547+ err = 0;
25548+ opt->type = token;
25549+ } else
4a4d8108 25550+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 25551+ break;
25552+
25553+ case Opt_wbr_create:
25554+ u.create = &opt->wbr_create;
25555+ u.create->wbr_create
25556+ = au_wbr_create_val(a->args[0].from, u.create);
25557+ if (u.create->wbr_create >= 0) {
25558+ err = 0;
25559+ opt->type = token;
25560+ } else
4a4d8108 25561+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 25562+ break;
25563+ case Opt_wbr_copyup:
25564+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
25565+ if (opt->wbr_copyup >= 0) {
25566+ err = 0;
25567+ opt->type = token;
25568+ } else
4a4d8108 25569+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 25570+ break;
25571+
076b876e
AM
25572+ case Opt_fhsm_sec:
25573+ if (unlikely(match_int(&a->args[0], &n)
25574+ || n < 0)) {
25575+ pr_err("bad integer in %s\n", opt_str);
25576+ break;
25577+ }
25578+ if (sysaufs_brs) {
25579+ opt->fhsm_second = n;
25580+ opt->type = token;
25581+ } else
25582+ pr_warn("ignored %s\n", opt_str);
25583+ err = 0;
25584+ break;
25585+
1facf9fc 25586+ case Opt_ignore:
0c3ec466 25587+ pr_warn("ignored %s\n", opt_str);
1facf9fc 25588+ /*FALLTHROUGH*/
25589+ case Opt_ignore_silent:
25590+ skipped = 1;
25591+ err = 0;
25592+ break;
25593+ case Opt_err:
4a4d8108 25594+ pr_err("unknown option %s\n", opt_str);
1facf9fc 25595+ break;
25596+ }
25597+
25598+ if (!err && !skipped) {
25599+ if (unlikely(++opt > opt_tail)) {
25600+ err = -E2BIG;
25601+ opt--;
25602+ opt->type = Opt_tail;
25603+ break;
25604+ }
25605+ opt->type = Opt_tail;
25606+ }
25607+ }
25608+
1c60b727 25609+ kfree(a);
1facf9fc 25610+ dump_opts(opts);
25611+ if (unlikely(err))
25612+ au_opts_free(opts);
25613+
4f0767ce 25614+out:
1facf9fc 25615+ return err;
25616+}
25617+
25618+static int au_opt_wbr_create(struct super_block *sb,
25619+ struct au_opt_wbr_create *create)
25620+{
25621+ int err;
25622+ struct au_sbinfo *sbinfo;
25623+
dece6358
AM
25624+ SiMustWriteLock(sb);
25625+
1facf9fc 25626+ err = 1; /* handled */
25627+ sbinfo = au_sbi(sb);
25628+ if (sbinfo->si_wbr_create_ops->fin) {
25629+ err = sbinfo->si_wbr_create_ops->fin(sb);
25630+ if (!err)
25631+ err = 1;
25632+ }
25633+
25634+ sbinfo->si_wbr_create = create->wbr_create;
25635+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
25636+ switch (create->wbr_create) {
25637+ case AuWbrCreate_MFSRRV:
25638+ case AuWbrCreate_MFSRR:
f2c43d5f
AM
25639+ case AuWbrCreate_TDMFS:
25640+ case AuWbrCreate_TDMFSV:
392086de
AM
25641+ case AuWbrCreate_PMFSRR:
25642+ case AuWbrCreate_PMFSRRV:
1facf9fc 25643+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
25644+ /*FALLTHROUGH*/
25645+ case AuWbrCreate_MFS:
25646+ case AuWbrCreate_MFSV:
25647+ case AuWbrCreate_PMFS:
25648+ case AuWbrCreate_PMFSV:
e49829fe
JR
25649+ sbinfo->si_wbr_mfs.mfs_expire
25650+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 25651+ break;
25652+ }
25653+
25654+ if (sbinfo->si_wbr_create_ops->init)
25655+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
25656+
25657+ return err;
25658+}
25659+
25660+/*
25661+ * returns,
25662+ * plus: processed without an error
25663+ * zero: unprocessed
25664+ */
25665+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
25666+ struct au_opts *opts)
25667+{
25668+ int err;
25669+ struct au_sbinfo *sbinfo;
25670+
dece6358
AM
25671+ SiMustWriteLock(sb);
25672+
1facf9fc 25673+ err = 1; /* handled */
25674+ sbinfo = au_sbi(sb);
25675+ switch (opt->type) {
25676+ case Opt_udba:
25677+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
25678+ sbinfo->si_mntflags |= opt->udba;
25679+ opts->given_udba |= opt->udba;
25680+ break;
25681+
25682+ case Opt_plink:
25683+ au_opt_set(sbinfo->si_mntflags, PLINK);
25684+ break;
25685+ case Opt_noplink:
25686+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 25687+ au_plink_put(sb, /*verbose*/1);
1facf9fc 25688+ au_opt_clr(sbinfo->si_mntflags, PLINK);
25689+ break;
25690+ case Opt_list_plink:
25691+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
25692+ au_plink_list(sb);
25693+ break;
25694+
4a4d8108
AM
25695+ case Opt_dio:
25696+ au_opt_set(sbinfo->si_mntflags, DIO);
25697+ au_fset_opts(opts->flags, REFRESH_DYAOP);
25698+ break;
25699+ case Opt_nodio:
25700+ au_opt_clr(sbinfo->si_mntflags, DIO);
25701+ au_fset_opts(opts->flags, REFRESH_DYAOP);
25702+ break;
25703+
076b876e
AM
25704+ case Opt_fhsm_sec:
25705+ au_fhsm_set(sbinfo, opt->fhsm_second);
25706+ break;
25707+
1facf9fc 25708+ case Opt_diropq_a:
25709+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
25710+ break;
25711+ case Opt_diropq_w:
25712+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
25713+ break;
25714+
25715+ case Opt_warn_perm:
25716+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
25717+ break;
25718+ case Opt_nowarn_perm:
25719+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
25720+ break;
25721+
1facf9fc 25722+ case Opt_verbose:
25723+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
25724+ break;
25725+ case Opt_noverbose:
25726+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
25727+ break;
25728+
25729+ case Opt_sum:
25730+ au_opt_set(sbinfo->si_mntflags, SUM);
25731+ break;
25732+ case Opt_wsum:
25733+ au_opt_clr(sbinfo->si_mntflags, SUM);
25734+ au_opt_set(sbinfo->si_mntflags, SUM_W);
25735+ case Opt_nosum:
25736+ au_opt_clr(sbinfo->si_mntflags, SUM);
25737+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
25738+ break;
25739+
25740+ case Opt_wbr_create:
25741+ err = au_opt_wbr_create(sb, &opt->wbr_create);
25742+ break;
25743+ case Opt_wbr_copyup:
25744+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
25745+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
25746+ break;
25747+
25748+ case Opt_dirwh:
25749+ sbinfo->si_dirwh = opt->dirwh;
25750+ break;
25751+
25752+ case Opt_rdcache:
e49829fe
JR
25753+ sbinfo->si_rdcache
25754+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 25755+ break;
25756+ case Opt_rdblk:
25757+ sbinfo->si_rdblk = opt->rdblk;
25758+ break;
dece6358
AM
25759+ case Opt_rdblk_def:
25760+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
25761+ break;
1facf9fc 25762+ case Opt_rdhash:
25763+ sbinfo->si_rdhash = opt->rdhash;
25764+ break;
dece6358
AM
25765+ case Opt_rdhash_def:
25766+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
25767+ break;
25768+
25769+ case Opt_shwh:
25770+ au_opt_set(sbinfo->si_mntflags, SHWH);
25771+ break;
25772+ case Opt_noshwh:
25773+ au_opt_clr(sbinfo->si_mntflags, SHWH);
25774+ break;
1facf9fc 25775+
076b876e
AM
25776+ case Opt_dirperm1:
25777+ au_opt_set(sbinfo->si_mntflags, DIRPERM1);
25778+ break;
25779+ case Opt_nodirperm1:
25780+ au_opt_clr(sbinfo->si_mntflags, DIRPERM1);
25781+ break;
25782+
1facf9fc 25783+ case Opt_trunc_xino:
25784+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
25785+ break;
25786+ case Opt_notrunc_xino:
25787+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
25788+ break;
25789+
25790+ case Opt_trunc_xino_path:
25791+ case Opt_itrunc_xino:
25792+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
25793+ if (!err)
25794+ err = 1;
25795+ break;
25796+
25797+ case Opt_trunc_xib:
25798+ au_fset_opts(opts->flags, TRUNC_XIB);
25799+ break;
25800+ case Opt_notrunc_xib:
25801+ au_fclr_opts(opts->flags, TRUNC_XIB);
25802+ break;
25803+
8b6a4947
AM
25804+ case Opt_dirren:
25805+ err = 1;
25806+ if (!au_opt_test(sbinfo->si_mntflags, DIRREN)) {
25807+ err = au_dr_opt_set(sb);
25808+ if (!err)
25809+ err = 1;
25810+ }
25811+ if (err == 1)
25812+ au_opt_set(sbinfo->si_mntflags, DIRREN);
25813+ break;
25814+ case Opt_nodirren:
25815+ err = 1;
25816+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) {
25817+ err = au_dr_opt_clr(sb, au_ftest_opts(opts->flags,
25818+ DR_FLUSHED));
25819+ if (!err)
25820+ err = 1;
25821+ }
25822+ if (err == 1)
25823+ au_opt_clr(sbinfo->si_mntflags, DIRREN);
25824+ break;
25825+
c1595e42
JR
25826+ case Opt_acl:
25827+ sb->s_flags |= MS_POSIXACL;
25828+ break;
25829+ case Opt_noacl:
25830+ sb->s_flags &= ~MS_POSIXACL;
25831+ break;
25832+
1facf9fc 25833+ default:
25834+ err = 0;
25835+ break;
25836+ }
25837+
25838+ return err;
25839+}
25840+
25841+/*
25842+ * returns tri-state.
25843+ * plus: processed without an error
25844+ * zero: unprocessed
25845+ * minus: error
25846+ */
25847+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
25848+ struct au_opts *opts)
25849+{
25850+ int err, do_refresh;
25851+
25852+ err = 0;
25853+ switch (opt->type) {
25854+ case Opt_append:
5afbbe0d 25855+ opt->add.bindex = au_sbbot(sb) + 1;
1facf9fc 25856+ if (opt->add.bindex < 0)
25857+ opt->add.bindex = 0;
25858+ goto add;
25859+ case Opt_prepend:
25860+ opt->add.bindex = 0;
f6b6e03d 25861+ add: /* indented label */
1facf9fc 25862+ case Opt_add:
25863+ err = au_br_add(sb, &opt->add,
25864+ au_ftest_opts(opts->flags, REMOUNT));
25865+ if (!err) {
25866+ err = 1;
027c5e7a 25867+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 25868+ }
25869+ break;
25870+
25871+ case Opt_del:
25872+ case Opt_idel:
25873+ err = au_br_del(sb, &opt->del,
25874+ au_ftest_opts(opts->flags, REMOUNT));
25875+ if (!err) {
25876+ err = 1;
25877+ au_fset_opts(opts->flags, TRUNC_XIB);
027c5e7a 25878+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 25879+ }
25880+ break;
25881+
25882+ case Opt_mod:
25883+ case Opt_imod:
25884+ err = au_br_mod(sb, &opt->mod,
25885+ au_ftest_opts(opts->flags, REMOUNT),
25886+ &do_refresh);
25887+ if (!err) {
25888+ err = 1;
027c5e7a
AM
25889+ if (do_refresh)
25890+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 25891+ }
25892+ break;
25893+ }
1facf9fc 25894+ return err;
25895+}
25896+
25897+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
25898+ struct au_opt_xino **opt_xino,
25899+ struct au_opts *opts)
25900+{
25901+ int err;
5afbbe0d 25902+ aufs_bindex_t bbot, bindex;
1facf9fc 25903+ struct dentry *root, *parent, *h_root;
25904+
25905+ err = 0;
25906+ switch (opt->type) {
25907+ case Opt_xino:
25908+ err = au_xino_set(sb, &opt->xino,
25909+ !!au_ftest_opts(opts->flags, REMOUNT));
25910+ if (unlikely(err))
25911+ break;
25912+
25913+ *opt_xino = &opt->xino;
25914+ au_xino_brid_set(sb, -1);
25915+
25916+ /* safe d_parent access */
2000de60 25917+ parent = opt->xino.file->f_path.dentry->d_parent;
1facf9fc 25918+ root = sb->s_root;
5afbbe0d
AM
25919+ bbot = au_sbbot(sb);
25920+ for (bindex = 0; bindex <= bbot; bindex++) {
1facf9fc 25921+ h_root = au_h_dptr(root, bindex);
25922+ if (h_root == parent) {
25923+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
25924+ break;
25925+ }
25926+ }
25927+ break;
25928+
25929+ case Opt_noxino:
25930+ au_xino_clr(sb);
25931+ au_xino_brid_set(sb, -1);
25932+ *opt_xino = (void *)-1;
25933+ break;
25934+ }
25935+
25936+ return err;
25937+}
25938+
25939+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
25940+ unsigned int pending)
25941+{
076b876e 25942+ int err, fhsm;
5afbbe0d 25943+ aufs_bindex_t bindex, bbot;
79b8bda9 25944+ unsigned char do_plink, skip, do_free, can_no_dreval;
1facf9fc 25945+ struct au_branch *br;
25946+ struct au_wbr *wbr;
79b8bda9 25947+ struct dentry *root, *dentry;
1facf9fc 25948+ struct inode *dir, *h_dir;
25949+ struct au_sbinfo *sbinfo;
25950+ struct au_hinode *hdir;
25951+
dece6358
AM
25952+ SiMustAnyLock(sb);
25953+
1facf9fc 25954+ sbinfo = au_sbi(sb);
25955+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
25956+
dece6358
AM
25957+ if (!(sb_flags & MS_RDONLY)) {
25958+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
0c3ec466 25959+ pr_warn("first branch should be rw\n");
dece6358 25960+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
febd17d6 25961+ pr_warn_once("shwh should be used with ro\n");
dece6358 25962+ }
1facf9fc 25963+
4a4d8108 25964+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 25965+ && !au_opt_test(sbinfo->si_mntflags, XINO))
febd17d6 25966+ pr_warn_once("udba=*notify requires xino\n");
1facf9fc 25967+
076b876e 25968+ if (au_opt_test(sbinfo->si_mntflags, DIRPERM1))
febd17d6
JR
25969+ pr_warn_once("dirperm1 breaks the protection"
25970+ " by the permission bits on the lower branch\n");
076b876e 25971+
1facf9fc 25972+ err = 0;
076b876e 25973+ fhsm = 0;
1facf9fc 25974+ root = sb->s_root;
5527c038 25975+ dir = d_inode(root);
1facf9fc 25976+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
79b8bda9
AM
25977+ can_no_dreval = !!au_opt_test((sbinfo->si_mntflags | pending),
25978+ UDBA_NONE);
5afbbe0d
AM
25979+ bbot = au_sbbot(sb);
25980+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
1facf9fc 25981+ skip = 0;
25982+ h_dir = au_h_iptr(dir, bindex);
25983+ br = au_sbr(sb, bindex);
1facf9fc 25984+
c1595e42
JR
25985+ if ((br->br_perm & AuBrAttr_ICEX)
25986+ && !h_dir->i_op->listxattr)
25987+ br->br_perm &= ~AuBrAttr_ICEX;
25988+#if 0
25989+ if ((br->br_perm & AuBrAttr_ICEX_SEC)
25990+ && (au_br_sb(br)->s_flags & MS_NOSEC))
25991+ br->br_perm &= ~AuBrAttr_ICEX_SEC;
25992+#endif
25993+
25994+ do_free = 0;
1facf9fc 25995+ wbr = br->br_wbr;
25996+ if (wbr)
25997+ wbr_wh_read_lock(wbr);
25998+
1e00d052 25999+ if (!au_br_writable(br->br_perm)) {
1facf9fc 26000+ do_free = !!wbr;
26001+ skip = (!wbr
26002+ || (!wbr->wbr_whbase
26003+ && !wbr->wbr_plink
26004+ && !wbr->wbr_orph));
1e00d052 26005+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 26006+ /* skip = (!br->br_whbase && !br->br_orph); */
26007+ skip = (!wbr || !wbr->wbr_whbase);
26008+ if (skip && wbr) {
26009+ if (do_plink)
26010+ skip = !!wbr->wbr_plink;
26011+ else
26012+ skip = !wbr->wbr_plink;
26013+ }
1e00d052 26014+ } else {
1facf9fc 26015+ /* skip = (br->br_whbase && br->br_ohph); */
26016+ skip = (wbr && wbr->wbr_whbase);
26017+ if (skip) {
26018+ if (do_plink)
26019+ skip = !!wbr->wbr_plink;
26020+ else
26021+ skip = !wbr->wbr_plink;
26022+ }
1facf9fc 26023+ }
26024+ if (wbr)
26025+ wbr_wh_read_unlock(wbr);
26026+
79b8bda9
AM
26027+ if (can_no_dreval) {
26028+ dentry = br->br_path.dentry;
26029+ spin_lock(&dentry->d_lock);
26030+ if (dentry->d_flags &
26031+ (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE))
26032+ can_no_dreval = 0;
26033+ spin_unlock(&dentry->d_lock);
26034+ }
26035+
076b876e
AM
26036+ if (au_br_fhsm(br->br_perm)) {
26037+ fhsm++;
26038+ AuDebugOn(!br->br_fhsm);
26039+ }
26040+
1facf9fc 26041+ if (skip)
26042+ continue;
26043+
26044+ hdir = au_hi(dir, bindex);
5afbbe0d 26045+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 26046+ if (wbr)
26047+ wbr_wh_write_lock(wbr);
86dc4139 26048+ err = au_wh_init(br, sb);
1facf9fc 26049+ if (wbr)
26050+ wbr_wh_write_unlock(wbr);
5afbbe0d 26051+ au_hn_inode_unlock(hdir);
1facf9fc 26052+
26053+ if (!err && do_free) {
1c60b727 26054+ kfree(wbr);
1facf9fc 26055+ br->br_wbr = NULL;
26056+ }
26057+ }
26058+
79b8bda9
AM
26059+ if (can_no_dreval)
26060+ au_fset_si(sbinfo, NO_DREVAL);
26061+ else
26062+ au_fclr_si(sbinfo, NO_DREVAL);
26063+
c1595e42 26064+ if (fhsm >= 2) {
076b876e 26065+ au_fset_si(sbinfo, FHSM);
5afbbe0d 26066+ for (bindex = bbot; bindex >= 0; bindex--) {
c1595e42
JR
26067+ br = au_sbr(sb, bindex);
26068+ if (au_br_fhsm(br->br_perm)) {
26069+ au_fhsm_set_bottom(sb, bindex);
26070+ break;
26071+ }
26072+ }
26073+ } else {
076b876e 26074+ au_fclr_si(sbinfo, FHSM);
c1595e42
JR
26075+ au_fhsm_set_bottom(sb, -1);
26076+ }
076b876e 26077+
1facf9fc 26078+ return err;
26079+}
26080+
26081+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
26082+{
26083+ int err;
26084+ unsigned int tmp;
5afbbe0d 26085+ aufs_bindex_t bindex, bbot;
1facf9fc 26086+ struct au_opt *opt;
26087+ struct au_opt_xino *opt_xino, xino;
26088+ struct au_sbinfo *sbinfo;
027c5e7a 26089+ struct au_branch *br;
076b876e 26090+ struct inode *dir;
1facf9fc 26091+
dece6358
AM
26092+ SiMustWriteLock(sb);
26093+
1facf9fc 26094+ err = 0;
26095+ opt_xino = NULL;
26096+ opt = opts->opt;
26097+ while (err >= 0 && opt->type != Opt_tail)
26098+ err = au_opt_simple(sb, opt++, opts);
26099+ if (err > 0)
26100+ err = 0;
26101+ else if (unlikely(err < 0))
26102+ goto out;
26103+
26104+ /* disable xino and udba temporary */
26105+ sbinfo = au_sbi(sb);
26106+ tmp = sbinfo->si_mntflags;
26107+ au_opt_clr(sbinfo->si_mntflags, XINO);
26108+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
26109+
26110+ opt = opts->opt;
26111+ while (err >= 0 && opt->type != Opt_tail)
26112+ err = au_opt_br(sb, opt++, opts);
26113+ if (err > 0)
26114+ err = 0;
26115+ else if (unlikely(err < 0))
26116+ goto out;
26117+
5afbbe0d
AM
26118+ bbot = au_sbbot(sb);
26119+ if (unlikely(bbot < 0)) {
1facf9fc 26120+ err = -EINVAL;
4a4d8108 26121+ pr_err("no branches\n");
1facf9fc 26122+ goto out;
26123+ }
26124+
26125+ if (au_opt_test(tmp, XINO))
26126+ au_opt_set(sbinfo->si_mntflags, XINO);
26127+ opt = opts->opt;
26128+ while (!err && opt->type != Opt_tail)
26129+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
26130+ if (unlikely(err))
26131+ goto out;
26132+
26133+ err = au_opts_verify(sb, sb->s_flags, tmp);
26134+ if (unlikely(err))
26135+ goto out;
26136+
26137+ /* restore xino */
26138+ if (au_opt_test(tmp, XINO) && !opt_xino) {
26139+ xino.file = au_xino_def(sb);
26140+ err = PTR_ERR(xino.file);
26141+ if (IS_ERR(xino.file))
26142+ goto out;
26143+
26144+ err = au_xino_set(sb, &xino, /*remount*/0);
26145+ fput(xino.file);
26146+ if (unlikely(err))
26147+ goto out;
26148+ }
26149+
26150+ /* restore udba */
027c5e7a 26151+ tmp &= AuOptMask_UDBA;
1facf9fc 26152+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
027c5e7a 26153+ sbinfo->si_mntflags |= tmp;
5afbbe0d
AM
26154+ bbot = au_sbbot(sb);
26155+ for (bindex = 0; bindex <= bbot; bindex++) {
027c5e7a
AM
26156+ br = au_sbr(sb, bindex);
26157+ err = au_hnotify_reset_br(tmp, br, br->br_perm);
26158+ if (unlikely(err))
26159+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
26160+ bindex, err);
26161+ /* go on even if err */
26162+ }
4a4d8108 26163+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
5527c038 26164+ dir = d_inode(sb->s_root);
4a4d8108 26165+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 26166+ }
26167+
4f0767ce 26168+out:
1facf9fc 26169+ return err;
26170+}
26171+
26172+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
26173+{
26174+ int err, rerr;
79b8bda9 26175+ unsigned char no_dreval;
1facf9fc 26176+ struct inode *dir;
26177+ struct au_opt_xino *opt_xino;
26178+ struct au_opt *opt;
26179+ struct au_sbinfo *sbinfo;
26180+
dece6358
AM
26181+ SiMustWriteLock(sb);
26182+
8b6a4947
AM
26183+ err = au_dr_opt_flush(sb);
26184+ if (unlikely(err))
26185+ goto out;
26186+ au_fset_opts(opts->flags, DR_FLUSHED);
26187+
5527c038 26188+ dir = d_inode(sb->s_root);
1facf9fc 26189+ sbinfo = au_sbi(sb);
1facf9fc 26190+ opt_xino = NULL;
26191+ opt = opts->opt;
26192+ while (err >= 0 && opt->type != Opt_tail) {
26193+ err = au_opt_simple(sb, opt, opts);
26194+ if (!err)
26195+ err = au_opt_br(sb, opt, opts);
26196+ if (!err)
26197+ err = au_opt_xino(sb, opt, &opt_xino, opts);
26198+ opt++;
26199+ }
26200+ if (err > 0)
26201+ err = 0;
26202+ AuTraceErr(err);
26203+ /* go on even err */
26204+
79b8bda9 26205+ no_dreval = !!au_ftest_si(sbinfo, NO_DREVAL);
1facf9fc 26206+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
26207+ if (unlikely(rerr && !err))
26208+ err = rerr;
26209+
79b8bda9 26210+ if (no_dreval != !!au_ftest_si(sbinfo, NO_DREVAL))
b95c5147 26211+ au_fset_opts(opts->flags, REFRESH_IDOP);
79b8bda9 26212+
1facf9fc 26213+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
26214+ rerr = au_xib_trunc(sb);
26215+ if (unlikely(rerr && !err))
26216+ err = rerr;
26217+ }
26218+
26219+ /* will be handled by the caller */
027c5e7a 26220+ if (!au_ftest_opts(opts->flags, REFRESH)
79b8bda9
AM
26221+ && (opts->given_udba
26222+ || au_opt_test(sbinfo->si_mntflags, XINO)
b95c5147 26223+ || au_ftest_opts(opts->flags, REFRESH_IDOP)
79b8bda9 26224+ ))
027c5e7a 26225+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 26226+
26227+ AuDbg("status 0x%x\n", opts->flags);
8b6a4947
AM
26228+
26229+out:
1facf9fc 26230+ return err;
26231+}
26232+
26233+/* ---------------------------------------------------------------------- */
26234+
26235+unsigned int au_opt_udba(struct super_block *sb)
26236+{
26237+ return au_mntflags(sb) & AuOptMask_UDBA;
26238+}
0b1ff5c3
JR
26239diff -urNp -x '*.orig' linux-4.14/fs/aufs/opts.h linux-4.14/fs/aufs/opts.h
26240--- linux-4.14/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
26241+++ linux-4.14/fs/aufs/opts.h 2021-02-24 21:42:43.444448075 +0100
8b6a4947 26242@@ -0,0 +1,224 @@
1facf9fc 26243+/*
a2654f78 26244+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 26245+ *
26246+ * This program, aufs is free software; you can redistribute it and/or modify
26247+ * it under the terms of the GNU General Public License as published by
26248+ * the Free Software Foundation; either version 2 of the License, or
26249+ * (at your option) any later version.
dece6358
AM
26250+ *
26251+ * This program is distributed in the hope that it will be useful,
26252+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26253+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26254+ * GNU General Public License for more details.
26255+ *
26256+ * You should have received a copy of the GNU General Public License
523b37e3 26257+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 26258+ */
26259+
26260+/*
26261+ * mount options/flags
26262+ */
26263+
26264+#ifndef __AUFS_OPTS_H__
26265+#define __AUFS_OPTS_H__
26266+
26267+#ifdef __KERNEL__
26268+
dece6358 26269+#include <linux/path.h>
1facf9fc 26270+
dece6358 26271+struct file;
dece6358 26272+
1facf9fc 26273+/* ---------------------------------------------------------------------- */
26274+
26275+/* mount flags */
26276+#define AuOpt_XINO 1 /* external inode number bitmap
26277+ and translation table */
26278+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
26279+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
26280+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 26281+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
26282+#define AuOpt_SHWH (1 << 5) /* show whiteout */
26283+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
076b876e
AM
26284+#define AuOpt_DIRPERM1 (1 << 7) /* ignore the lower dir's perm
26285+ bits */
dece6358
AM
26286+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
26287+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
26288+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
26289+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
26290+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
4a4d8108 26291+#define AuOpt_DIO (1 << 14) /* direct io */
8b6a4947 26292+#define AuOpt_DIRREN (1 << 15) /* directory rename */
1facf9fc 26293+
4a4d8108
AM
26294+#ifndef CONFIG_AUFS_HNOTIFY
26295+#undef AuOpt_UDBA_HNOTIFY
26296+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 26297+#endif
8b6a4947
AM
26298+#ifndef CONFIG_AUFS_DIRREN
26299+#undef AuOpt_DIRREN
26300+#define AuOpt_DIRREN 0
26301+#endif
dece6358
AM
26302+#ifndef CONFIG_AUFS_SHWH
26303+#undef AuOpt_SHWH
26304+#define AuOpt_SHWH 0
26305+#endif
1facf9fc 26306+
26307+#define AuOpt_Def (AuOpt_XINO \
26308+ | AuOpt_UDBA_REVAL \
26309+ | AuOpt_PLINK \
26310+ /* | AuOpt_DIRPERM1 */ \
26311+ | AuOpt_WARN_PERM)
26312+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
26313+ | AuOpt_UDBA_REVAL \
4a4d8108 26314+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 26315+
26316+#define au_opt_test(flags, name) (flags & AuOpt_##name)
26317+#define au_opt_set(flags, name) do { \
26318+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
26319+ ((flags) |= AuOpt_##name); \
26320+} while (0)
26321+#define au_opt_set_udba(flags, name) do { \
26322+ (flags) &= ~AuOptMask_UDBA; \
26323+ ((flags) |= AuOpt_##name); \
26324+} while (0)
7f207e10
AM
26325+#define au_opt_clr(flags, name) do { \
26326+ ((flags) &= ~AuOpt_##name); \
26327+} while (0)
1facf9fc 26328+
e49829fe
JR
26329+static inline unsigned int au_opts_plink(unsigned int mntflags)
26330+{
26331+#ifdef CONFIG_PROC_FS
26332+ return mntflags;
26333+#else
26334+ return mntflags & ~AuOpt_PLINK;
26335+#endif
26336+}
26337+
1facf9fc 26338+/* ---------------------------------------------------------------------- */
26339+
26340+/* policies to select one among multiple writable branches */
26341+enum {
26342+ AuWbrCreate_TDP, /* top down parent */
26343+ AuWbrCreate_RR, /* round robin */
26344+ AuWbrCreate_MFS, /* most free space */
26345+ AuWbrCreate_MFSV, /* mfs with seconds */
26346+ AuWbrCreate_MFSRR, /* mfs then rr */
26347+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
f2c43d5f
AM
26348+ AuWbrCreate_TDMFS, /* top down regardless parent and mfs */
26349+ AuWbrCreate_TDMFSV, /* top down regardless parent and mfs */
1facf9fc 26350+ AuWbrCreate_PMFS, /* parent and mfs */
26351+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
392086de
AM
26352+ AuWbrCreate_PMFSRR, /* parent, mfs and round-robin */
26353+ AuWbrCreate_PMFSRRV, /* plus seconds */
1facf9fc 26354+
26355+ AuWbrCreate_Def = AuWbrCreate_TDP
26356+};
26357+
26358+enum {
26359+ AuWbrCopyup_TDP, /* top down parent */
26360+ AuWbrCopyup_BUP, /* bottom up parent */
26361+ AuWbrCopyup_BU, /* bottom up */
26362+
26363+ AuWbrCopyup_Def = AuWbrCopyup_TDP
26364+};
26365+
26366+/* ---------------------------------------------------------------------- */
26367+
26368+struct au_opt_add {
26369+ aufs_bindex_t bindex;
26370+ char *pathname;
26371+ int perm;
26372+ struct path path;
26373+};
26374+
26375+struct au_opt_del {
26376+ char *pathname;
26377+ struct path h_path;
26378+};
26379+
26380+struct au_opt_mod {
26381+ char *path;
26382+ int perm;
26383+ struct dentry *h_root;
26384+};
26385+
26386+struct au_opt_xino {
26387+ char *path;
26388+ struct file *file;
26389+};
26390+
26391+struct au_opt_xino_itrunc {
26392+ aufs_bindex_t bindex;
26393+};
26394+
26395+struct au_opt_wbr_create {
26396+ int wbr_create;
26397+ int mfs_second;
26398+ unsigned long long mfsrr_watermark;
26399+};
26400+
26401+struct au_opt {
26402+ int type;
26403+ union {
26404+ struct au_opt_xino xino;
26405+ struct au_opt_xino_itrunc xino_itrunc;
26406+ struct au_opt_add add;
26407+ struct au_opt_del del;
26408+ struct au_opt_mod mod;
26409+ int dirwh;
26410+ int rdcache;
26411+ unsigned int rdblk;
26412+ unsigned int rdhash;
26413+ int udba;
26414+ struct au_opt_wbr_create wbr_create;
26415+ int wbr_copyup;
076b876e 26416+ unsigned int fhsm_second;
1facf9fc 26417+ };
26418+};
26419+
26420+/* opts flags */
26421+#define AuOpts_REMOUNT 1
027c5e7a
AM
26422+#define AuOpts_REFRESH (1 << 1)
26423+#define AuOpts_TRUNC_XIB (1 << 2)
26424+#define AuOpts_REFRESH_DYAOP (1 << 3)
b95c5147 26425+#define AuOpts_REFRESH_IDOP (1 << 4)
8b6a4947 26426+#define AuOpts_DR_FLUSHED (1 << 5)
1facf9fc 26427+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
7f207e10
AM
26428+#define au_fset_opts(flags, name) \
26429+ do { (flags) |= AuOpts_##name; } while (0)
26430+#define au_fclr_opts(flags, name) \
26431+ do { (flags) &= ~AuOpts_##name; } while (0)
1facf9fc 26432+
8b6a4947
AM
26433+#ifndef CONFIG_AUFS_DIRREN
26434+#undef AuOpts_DR_FLUSHED
26435+#define AuOpts_DR_FLUSHED 0
26436+#endif
26437+
1facf9fc 26438+struct au_opts {
26439+ struct au_opt *opt;
26440+ int max_opt;
26441+
26442+ unsigned int given_udba;
26443+ unsigned int flags;
26444+ unsigned long sb_flags;
26445+};
26446+
26447+/* ---------------------------------------------------------------------- */
26448+
7e9cd9fe 26449+/* opts.c */
076b876e 26450+void au_optstr_br_perm(au_br_perm_str_t *str, int perm);
1facf9fc 26451+const char *au_optstr_udba(int udba);
26452+const char *au_optstr_wbr_copyup(int wbr_copyup);
26453+const char *au_optstr_wbr_create(int wbr_create);
26454+
26455+void au_opts_free(struct au_opts *opts);
3c1bdaff 26456+struct super_block;
1facf9fc 26457+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
26458+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
26459+ unsigned int pending);
26460+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
26461+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
26462+
26463+unsigned int au_opt_udba(struct super_block *sb);
26464+
1facf9fc 26465+#endif /* __KERNEL__ */
26466+#endif /* __AUFS_OPTS_H__ */
0b1ff5c3
JR
26467diff -urNp -x '*.orig' linux-4.14/fs/aufs/plink.c linux-4.14/fs/aufs/plink.c
26468--- linux-4.14/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
26469+++ linux-4.14/fs/aufs/plink.c 2021-02-24 21:42:43.444448075 +0100
8b6a4947 26470@@ -0,0 +1,515 @@
1facf9fc 26471+/*
a2654f78 26472+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 26473+ *
26474+ * This program, aufs is free software; you can redistribute it and/or modify
26475+ * it under the terms of the GNU General Public License as published by
26476+ * the Free Software Foundation; either version 2 of the License, or
26477+ * (at your option) any later version.
dece6358
AM
26478+ *
26479+ * This program is distributed in the hope that it will be useful,
26480+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26481+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26482+ * GNU General Public License for more details.
26483+ *
26484+ * You should have received a copy of the GNU General Public License
523b37e3 26485+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 26486+ */
26487+
26488+/*
26489+ * pseudo-link
26490+ */
26491+
26492+#include "aufs.h"
26493+
26494+/*
e49829fe 26495+ * the pseudo-link maintenance mode.
1facf9fc 26496+ * during a user process maintains the pseudo-links,
26497+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
26498+ *
26499+ * Flags
26500+ * NOPLM:
26501+ * For entry functions which will handle plink, and i_mutex is already held
26502+ * in VFS.
26503+ * They cannot wait and should return an error at once.
26504+ * Callers has to check the error.
26505+ * NOPLMW:
26506+ * For entry functions which will handle plink, but i_mutex is not held
26507+ * in VFS.
26508+ * They can wait the plink maintenance mode to finish.
26509+ *
26510+ * They behave like F_SETLK and F_SETLKW.
26511+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 26512+ */
e49829fe
JR
26513+
26514+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 26515+{
e49829fe
JR
26516+ int err;
26517+ pid_t pid, ppid;
f0c0a007 26518+ struct task_struct *parent, *prev;
e49829fe 26519+ struct au_sbinfo *sbi;
dece6358
AM
26520+
26521+ SiMustAnyLock(sb);
26522+
e49829fe
JR
26523+ err = 0;
26524+ if (!au_opt_test(au_mntflags(sb), PLINK))
26525+ goto out;
26526+
26527+ sbi = au_sbi(sb);
26528+ pid = sbi->si_plink_maint_pid;
26529+ if (!pid || pid == current->pid)
26530+ goto out;
26531+
26532+ /* todo: it highly depends upon /sbin/mount.aufs */
f0c0a007
AM
26533+ prev = NULL;
26534+ parent = current;
26535+ ppid = 0;
e49829fe 26536+ rcu_read_lock();
f0c0a007
AM
26537+ while (1) {
26538+ parent = rcu_dereference(parent->real_parent);
26539+ if (parent == prev)
26540+ break;
26541+ ppid = task_pid_vnr(parent);
26542+ if (pid == ppid) {
26543+ rcu_read_unlock();
26544+ goto out;
26545+ }
26546+ prev = parent;
26547+ }
e49829fe 26548+ rcu_read_unlock();
e49829fe
JR
26549+
26550+ if (au_ftest_lock(flags, NOPLMW)) {
027c5e7a
AM
26551+ /* if there is no i_mutex lock in VFS, we don't need to wait */
26552+ /* AuDebugOn(!lockdep_depth(current)); */
e49829fe
JR
26553+ while (sbi->si_plink_maint_pid) {
26554+ si_read_unlock(sb);
26555+ /* gave up wake_up_bit() */
26556+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
26557+
26558+ if (au_ftest_lock(flags, FLUSH))
26559+ au_nwt_flush(&sbi->si_nowait);
26560+ si_noflush_read_lock(sb);
26561+ }
26562+ } else if (au_ftest_lock(flags, NOPLM)) {
26563+ AuDbg("ppid %d, pid %d\n", ppid, pid);
26564+ err = -EAGAIN;
26565+ }
26566+
26567+out:
26568+ return err;
4a4d8108
AM
26569+}
26570+
e49829fe 26571+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 26572+{
4a4d8108 26573+ spin_lock(&sbinfo->si_plink_maint_lock);
027c5e7a 26574+ sbinfo->si_plink_maint_pid = 0;
4a4d8108 26575+ spin_unlock(&sbinfo->si_plink_maint_lock);
027c5e7a 26576+ wake_up_all(&sbinfo->si_plink_wq);
4a4d8108
AM
26577+}
26578+
e49829fe 26579+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
26580+{
26581+ int err;
4a4d8108
AM
26582+ struct au_sbinfo *sbinfo;
26583+
26584+ err = 0;
4a4d8108
AM
26585+ sbinfo = au_sbi(sb);
26586+ /* make sure i am the only one in this fs */
e49829fe
JR
26587+ si_write_lock(sb, AuLock_FLUSH);
26588+ if (au_opt_test(au_mntflags(sb), PLINK)) {
26589+ spin_lock(&sbinfo->si_plink_maint_lock);
26590+ if (!sbinfo->si_plink_maint_pid)
26591+ sbinfo->si_plink_maint_pid = current->pid;
26592+ else
26593+ err = -EBUSY;
26594+ spin_unlock(&sbinfo->si_plink_maint_lock);
26595+ }
4a4d8108
AM
26596+ si_write_unlock(sb);
26597+
26598+ return err;
1facf9fc 26599+}
26600+
26601+/* ---------------------------------------------------------------------- */
26602+
1facf9fc 26603+#ifdef CONFIG_AUFS_DEBUG
26604+void au_plink_list(struct super_block *sb)
26605+{
86dc4139 26606+ int i;
1facf9fc 26607+ struct au_sbinfo *sbinfo;
8b6a4947
AM
26608+ struct hlist_bl_head *hbl;
26609+ struct hlist_bl_node *pos;
5afbbe0d 26610+ struct au_icntnr *icntnr;
1facf9fc 26611+
dece6358
AM
26612+ SiMustAnyLock(sb);
26613+
1facf9fc 26614+ sbinfo = au_sbi(sb);
26615+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 26616+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 26617+
86dc4139 26618+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
26619+ hbl = sbinfo->si_plink + i;
26620+ hlist_bl_lock(hbl);
26621+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink)
5afbbe0d 26622+ AuDbg("%lu\n", icntnr->vfs_inode.i_ino);
8b6a4947 26623+ hlist_bl_unlock(hbl);
86dc4139 26624+ }
1facf9fc 26625+}
26626+#endif
26627+
26628+/* is the inode pseudo-linked? */
26629+int au_plink_test(struct inode *inode)
26630+{
86dc4139 26631+ int found, i;
1facf9fc 26632+ struct au_sbinfo *sbinfo;
8b6a4947
AM
26633+ struct hlist_bl_head *hbl;
26634+ struct hlist_bl_node *pos;
5afbbe0d 26635+ struct au_icntnr *icntnr;
1facf9fc 26636+
26637+ sbinfo = au_sbi(inode->i_sb);
dece6358 26638+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 26639+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 26640+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 26641+
26642+ found = 0;
86dc4139 26643+ i = au_plink_hash(inode->i_ino);
8b6a4947
AM
26644+ hbl = sbinfo->si_plink + i;
26645+ hlist_bl_lock(hbl);
26646+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink)
5afbbe0d 26647+ if (&icntnr->vfs_inode == inode) {
1facf9fc 26648+ found = 1;
26649+ break;
26650+ }
8b6a4947 26651+ hlist_bl_unlock(hbl);
1facf9fc 26652+ return found;
26653+}
26654+
26655+/* ---------------------------------------------------------------------- */
26656+
26657+/*
26658+ * generate a name for plink.
26659+ * the file will be stored under AUFS_WH_PLINKDIR.
26660+ */
26661+/* 20 is max digits length of ulong 64 */
26662+#define PLINK_NAME_LEN ((20 + 1) * 2)
26663+
26664+static int plink_name(char *name, int len, struct inode *inode,
26665+ aufs_bindex_t bindex)
26666+{
26667+ int rlen;
26668+ struct inode *h_inode;
26669+
26670+ h_inode = au_h_iptr(inode, bindex);
26671+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
26672+ return rlen;
26673+}
26674+
7f207e10
AM
26675+struct au_do_plink_lkup_args {
26676+ struct dentry **errp;
26677+ struct qstr *tgtname;
26678+ struct dentry *h_parent;
26679+ struct au_branch *br;
26680+};
26681+
26682+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
26683+ struct dentry *h_parent,
26684+ struct au_branch *br)
26685+{
26686+ struct dentry *h_dentry;
febd17d6 26687+ struct inode *h_inode;
7f207e10 26688+
febd17d6 26689+ h_inode = d_inode(h_parent);
3c1bdaff 26690+ vfsub_inode_lock_shared_nested(h_inode, AuLsc_I_CHILD2);
b4510431 26691+ h_dentry = vfsub_lkup_one(tgtname, h_parent);
3c1bdaff 26692+ inode_unlock_shared(h_inode);
7f207e10
AM
26693+ return h_dentry;
26694+}
26695+
26696+static void au_call_do_plink_lkup(void *args)
26697+{
26698+ struct au_do_plink_lkup_args *a = args;
26699+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
26700+}
26701+
1facf9fc 26702+/* lookup the plink-ed @inode under the branch at @bindex */
26703+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
26704+{
26705+ struct dentry *h_dentry, *h_parent;
26706+ struct au_branch *br;
7f207e10 26707+ int wkq_err;
1facf9fc 26708+ char a[PLINK_NAME_LEN];
0c3ec466 26709+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 26710+
e49829fe
JR
26711+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
26712+
1facf9fc 26713+ br = au_sbr(inode->i_sb, bindex);
26714+ h_parent = br->br_wbr->wbr_plink;
1facf9fc 26715+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
26716+
2dfbb274 26717+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
7f207e10
AM
26718+ struct au_do_plink_lkup_args args = {
26719+ .errp = &h_dentry,
26720+ .tgtname = &tgtname,
26721+ .h_parent = h_parent,
26722+ .br = br
26723+ };
26724+
26725+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
26726+ if (unlikely(wkq_err))
26727+ h_dentry = ERR_PTR(wkq_err);
26728+ } else
26729+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
26730+
1facf9fc 26731+ return h_dentry;
26732+}
26733+
26734+/* create a pseudo-link */
26735+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
26736+ struct dentry *h_dentry, struct au_branch *br)
26737+{
26738+ int err;
26739+ struct path h_path = {
86dc4139 26740+ .mnt = au_br_mnt(br)
1facf9fc 26741+ };
523b37e3 26742+ struct inode *h_dir, *delegated;
1facf9fc 26743+
5527c038 26744+ h_dir = d_inode(h_parent);
febd17d6 26745+ inode_lock_nested(h_dir, AuLsc_I_CHILD2);
4f0767ce 26746+again:
b4510431 26747+ h_path.dentry = vfsub_lkup_one(tgt, h_parent);
1facf9fc 26748+ err = PTR_ERR(h_path.dentry);
26749+ if (IS_ERR(h_path.dentry))
26750+ goto out;
26751+
26752+ err = 0;
26753+ /* wh.plink dir is not monitored */
7f207e10 26754+ /* todo: is it really safe? */
5527c038
JR
26755+ if (d_is_positive(h_path.dentry)
26756+ && d_inode(h_path.dentry) != d_inode(h_dentry)) {
523b37e3
AM
26757+ delegated = NULL;
26758+ err = vfsub_unlink(h_dir, &h_path, &delegated, /*force*/0);
26759+ if (unlikely(err == -EWOULDBLOCK)) {
26760+ pr_warn("cannot retry for NFSv4 delegation"
26761+ " for an internal unlink\n");
26762+ iput(delegated);
26763+ }
1facf9fc 26764+ dput(h_path.dentry);
26765+ h_path.dentry = NULL;
26766+ if (!err)
26767+ goto again;
26768+ }
5527c038 26769+ if (!err && d_is_negative(h_path.dentry)) {
523b37e3
AM
26770+ delegated = NULL;
26771+ err = vfsub_link(h_dentry, h_dir, &h_path, &delegated);
26772+ if (unlikely(err == -EWOULDBLOCK)) {
26773+ pr_warn("cannot retry for NFSv4 delegation"
26774+ " for an internal link\n");
26775+ iput(delegated);
26776+ }
26777+ }
1facf9fc 26778+ dput(h_path.dentry);
26779+
4f0767ce 26780+out:
febd17d6 26781+ inode_unlock(h_dir);
1facf9fc 26782+ return err;
26783+}
26784+
26785+struct do_whplink_args {
26786+ int *errp;
26787+ struct qstr *tgt;
26788+ struct dentry *h_parent;
26789+ struct dentry *h_dentry;
26790+ struct au_branch *br;
26791+};
26792+
26793+static void call_do_whplink(void *args)
26794+{
26795+ struct do_whplink_args *a = args;
26796+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
26797+}
26798+
26799+static int whplink(struct dentry *h_dentry, struct inode *inode,
26800+ aufs_bindex_t bindex, struct au_branch *br)
26801+{
26802+ int err, wkq_err;
26803+ struct au_wbr *wbr;
26804+ struct dentry *h_parent;
1facf9fc 26805+ char a[PLINK_NAME_LEN];
0c3ec466 26806+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 26807+
26808+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
26809+ h_parent = wbr->wbr_plink;
1facf9fc 26810+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
26811+
26812+ /* always superio. */
2dfbb274 26813+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
1facf9fc 26814+ struct do_whplink_args args = {
26815+ .errp = &err,
26816+ .tgt = &tgtname,
26817+ .h_parent = h_parent,
26818+ .h_dentry = h_dentry,
26819+ .br = br
26820+ };
26821+ wkq_err = au_wkq_wait(call_do_whplink, &args);
26822+ if (unlikely(wkq_err))
26823+ err = wkq_err;
26824+ } else
26825+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
1facf9fc 26826+
26827+ return err;
26828+}
26829+
1facf9fc 26830+/*
26831+ * create a new pseudo-link for @h_dentry on @bindex.
26832+ * the linked inode is held in aufs @inode.
26833+ */
26834+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
26835+ struct dentry *h_dentry)
26836+{
26837+ struct super_block *sb;
26838+ struct au_sbinfo *sbinfo;
8b6a4947
AM
26839+ struct hlist_bl_head *hbl;
26840+ struct hlist_bl_node *pos;
5afbbe0d 26841+ struct au_icntnr *icntnr;
86dc4139 26842+ int found, err, cnt, i;
1facf9fc 26843+
26844+ sb = inode->i_sb;
26845+ sbinfo = au_sbi(sb);
26846+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 26847+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 26848+
86dc4139 26849+ found = au_plink_test(inode);
4a4d8108 26850+ if (found)
1facf9fc 26851+ return;
4a4d8108 26852+
86dc4139 26853+ i = au_plink_hash(inode->i_ino);
8b6a4947 26854+ hbl = sbinfo->si_plink + i;
5afbbe0d 26855+ au_igrab(inode);
1facf9fc 26856+
8b6a4947
AM
26857+ hlist_bl_lock(hbl);
26858+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) {
5afbbe0d 26859+ if (&icntnr->vfs_inode == inode) {
4a4d8108
AM
26860+ found = 1;
26861+ break;
26862+ }
1facf9fc 26863+ }
5afbbe0d
AM
26864+ if (!found) {
26865+ icntnr = container_of(inode, struct au_icntnr, vfs_inode);
8b6a4947 26866+ hlist_bl_add_head(&icntnr->plink, hbl);
5afbbe0d 26867+ }
8b6a4947 26868+ hlist_bl_unlock(hbl);
4a4d8108 26869+ if (!found) {
8b6a4947 26870+ cnt = au_hbl_count(hbl);
86dc4139
AM
26871+#define msg "unexpectedly unblanced or too many pseudo-links"
26872+ if (cnt > AUFS_PLINK_WARN)
26873+ AuWarn1(msg ", %d\n", cnt);
26874+#undef msg
1facf9fc 26875+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
5afbbe0d
AM
26876+ if (unlikely(err)) {
26877+ pr_warn("err %d, damaged pseudo link.\n", err);
8b6a4947 26878+ au_hbl_del(&icntnr->plink, hbl);
5afbbe0d 26879+ iput(&icntnr->vfs_inode);
4a4d8108 26880+ }
5afbbe0d
AM
26881+ } else
26882+ iput(&icntnr->vfs_inode);
1facf9fc 26883+}
26884+
26885+/* free all plinks */
e49829fe 26886+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 26887+{
86dc4139 26888+ int i, warned;
1facf9fc 26889+ struct au_sbinfo *sbinfo;
8b6a4947
AM
26890+ struct hlist_bl_head *hbl;
26891+ struct hlist_bl_node *pos, *tmp;
5afbbe0d 26892+ struct au_icntnr *icntnr;
1facf9fc 26893+
dece6358
AM
26894+ SiMustWriteLock(sb);
26895+
1facf9fc 26896+ sbinfo = au_sbi(sb);
26897+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 26898+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 26899+
1facf9fc 26900+ /* no spin_lock since sbinfo is write-locked */
86dc4139
AM
26901+ warned = 0;
26902+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
26903+ hbl = sbinfo->si_plink + i;
26904+ if (!warned && verbose && !hlist_bl_empty(hbl)) {
86dc4139
AM
26905+ pr_warn("pseudo-link is not flushed");
26906+ warned = 1;
26907+ }
8b6a4947 26908+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink)
5afbbe0d 26909+ iput(&icntnr->vfs_inode);
8b6a4947 26910+ INIT_HLIST_BL_HEAD(hbl);
86dc4139 26911+ }
1facf9fc 26912+}
26913+
e49829fe
JR
26914+void au_plink_clean(struct super_block *sb, int verbose)
26915+{
26916+ struct dentry *root;
26917+
26918+ root = sb->s_root;
26919+ aufs_write_lock(root);
26920+ if (au_opt_test(au_mntflags(sb), PLINK))
26921+ au_plink_put(sb, verbose);
26922+ aufs_write_unlock(root);
26923+}
26924+
86dc4139
AM
26925+static int au_plink_do_half_refresh(struct inode *inode, aufs_bindex_t br_id)
26926+{
26927+ int do_put;
5afbbe0d 26928+ aufs_bindex_t btop, bbot, bindex;
86dc4139
AM
26929+
26930+ do_put = 0;
5afbbe0d
AM
26931+ btop = au_ibtop(inode);
26932+ bbot = au_ibbot(inode);
26933+ if (btop >= 0) {
26934+ for (bindex = btop; bindex <= bbot; bindex++) {
86dc4139
AM
26935+ if (!au_h_iptr(inode, bindex)
26936+ || au_ii_br_id(inode, bindex) != br_id)
26937+ continue;
26938+ au_set_h_iptr(inode, bindex, NULL, 0);
26939+ do_put = 1;
26940+ break;
26941+ }
26942+ if (do_put)
5afbbe0d 26943+ for (bindex = btop; bindex <= bbot; bindex++)
86dc4139
AM
26944+ if (au_h_iptr(inode, bindex)) {
26945+ do_put = 0;
26946+ break;
26947+ }
26948+ } else
26949+ do_put = 1;
26950+
26951+ return do_put;
26952+}
26953+
1facf9fc 26954+/* free the plinks on a branch specified by @br_id */
26955+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
26956+{
26957+ struct au_sbinfo *sbinfo;
8b6a4947
AM
26958+ struct hlist_bl_head *hbl;
26959+ struct hlist_bl_node *pos, *tmp;
5afbbe0d 26960+ struct au_icntnr *icntnr;
1facf9fc 26961+ struct inode *inode;
86dc4139 26962+ int i, do_put;
1facf9fc 26963+
dece6358
AM
26964+ SiMustWriteLock(sb);
26965+
1facf9fc 26966+ sbinfo = au_sbi(sb);
26967+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 26968+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 26969+
8b6a4947 26970+ /* no bit_lock since sbinfo is write-locked */
86dc4139 26971+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
26972+ hbl = sbinfo->si_plink + i;
26973+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) {
5afbbe0d 26974+ inode = au_igrab(&icntnr->vfs_inode);
86dc4139
AM
26975+ ii_write_lock_child(inode);
26976+ do_put = au_plink_do_half_refresh(inode, br_id);
5afbbe0d 26977+ if (do_put) {
8b6a4947 26978+ hlist_bl_del(&icntnr->plink);
5afbbe0d
AM
26979+ iput(inode);
26980+ }
86dc4139
AM
26981+ ii_write_unlock(inode);
26982+ iput(inode);
dece6358 26983+ }
dece6358
AM
26984+ }
26985+}
0b1ff5c3
JR
26986diff -urNp -x '*.orig' linux-4.14/fs/aufs/poll.c linux-4.14/fs/aufs/poll.c
26987--- linux-4.14/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
26988+++ linux-4.14/fs/aufs/poll.c 2021-02-24 21:42:43.444448075 +0100
b912730e 26989@@ -0,0 +1,52 @@
dece6358 26990+/*
a2654f78 26991+ * Copyright (C) 2005-2017 Junjiro R. Okajima
dece6358
AM
26992+ *
26993+ * This program, aufs is free software; you can redistribute it and/or modify
26994+ * it under the terms of the GNU General Public License as published by
26995+ * the Free Software Foundation; either version 2 of the License, or
26996+ * (at your option) any later version.
26997+ *
26998+ * This program is distributed in the hope that it will be useful,
26999+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27000+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27001+ * GNU General Public License for more details.
27002+ *
27003+ * You should have received a copy of the GNU General Public License
523b37e3 27004+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358
AM
27005+ */
27006+
1308ab2a 27007+/*
27008+ * poll operation
27009+ * There is only one filesystem which implements ->poll operation, currently.
27010+ */
27011+
27012+#include "aufs.h"
27013+
27014+unsigned int aufs_poll(struct file *file, poll_table *wait)
27015+{
27016+ unsigned int mask;
27017+ int err;
27018+ struct file *h_file;
1308ab2a 27019+ struct super_block *sb;
27020+
27021+ /* We should pretend an error happened. */
27022+ mask = POLLERR /* | POLLIN | POLLOUT */;
b912730e 27023+ sb = file->f_path.dentry->d_sb;
e49829fe 27024+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 27025+
521ced18 27026+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
b912730e
AM
27027+ err = PTR_ERR(h_file);
27028+ if (IS_ERR(h_file))
1308ab2a 27029+ goto out;
27030+
27031+ /* it is not an error if h_file has no operation */
27032+ mask = DEFAULT_POLLMASK;
523b37e3 27033+ if (h_file->f_op->poll)
1308ab2a 27034+ mask = h_file->f_op->poll(h_file, wait);
b912730e 27035+ fput(h_file); /* instead of au_read_post() */
1308ab2a 27036+
4f0767ce 27037+out:
1308ab2a 27038+ si_read_unlock(sb);
27039+ AuTraceErr((int)mask);
27040+ return mask;
27041+}
0b1ff5c3
JR
27042diff -urNp -x '*.orig' linux-4.14/fs/aufs/posix_acl.c linux-4.14/fs/aufs/posix_acl.c
27043--- linux-4.14/fs/aufs/posix_acl.c 1970-01-01 01:00:00.000000000 +0100
27044+++ linux-4.14/fs/aufs/posix_acl.c 2021-02-24 21:42:43.444448075 +0100
a2654f78 27045@@ -0,0 +1,102 @@
c1595e42 27046+/*
a2654f78 27047+ * Copyright (C) 2014-2017 Junjiro R. Okajima
c1595e42
JR
27048+ *
27049+ * This program, aufs is free software; you can redistribute it and/or modify
27050+ * it under the terms of the GNU General Public License as published by
27051+ * the Free Software Foundation; either version 2 of the License, or
27052+ * (at your option) any later version.
27053+ *
27054+ * This program is distributed in the hope that it will be useful,
27055+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27056+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27057+ * GNU General Public License for more details.
27058+ *
27059+ * You should have received a copy of the GNU General Public License
27060+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
27061+ */
27062+
27063+/*
27064+ * posix acl operations
27065+ */
27066+
27067+#include <linux/fs.h>
c1595e42
JR
27068+#include "aufs.h"
27069+
27070+struct posix_acl *aufs_get_acl(struct inode *inode, int type)
27071+{
27072+ struct posix_acl *acl;
27073+ int err;
27074+ aufs_bindex_t bindex;
27075+ struct inode *h_inode;
27076+ struct super_block *sb;
27077+
27078+ acl = NULL;
27079+ sb = inode->i_sb;
27080+ si_read_lock(sb, AuLock_FLUSH);
27081+ ii_read_lock_child(inode);
27082+ if (!(sb->s_flags & MS_POSIXACL))
27083+ goto out;
27084+
5afbbe0d 27085+ bindex = au_ibtop(inode);
c1595e42
JR
27086+ h_inode = au_h_iptr(inode, bindex);
27087+ if (unlikely(!h_inode
27088+ || ((h_inode->i_mode & S_IFMT)
27089+ != (inode->i_mode & S_IFMT)))) {
27090+ err = au_busy_or_stale();
27091+ acl = ERR_PTR(err);
27092+ goto out;
27093+ }
27094+
27095+ /* always topmost only */
27096+ acl = get_acl(h_inode, type);
a2654f78
AM
27097+ if (!IS_ERR_OR_NULL(acl))
27098+ set_cached_acl(inode, type, acl);
c1595e42
JR
27099+
27100+out:
27101+ ii_read_unlock(inode);
27102+ si_read_unlock(sb);
27103+
27104+ AuTraceErrPtr(acl);
27105+ return acl;
27106+}
27107+
27108+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
27109+{
27110+ int err;
27111+ ssize_t ssz;
27112+ struct dentry *dentry;
f2c43d5f 27113+ struct au_sxattr arg = {
c1595e42
JR
27114+ .type = AU_ACL_SET,
27115+ .u.acl_set = {
27116+ .acl = acl,
27117+ .type = type
27118+ },
27119+ };
27120+
5afbbe0d
AM
27121+ IMustLock(inode);
27122+
c1595e42
JR
27123+ if (inode->i_ino == AUFS_ROOT_INO)
27124+ dentry = dget(inode->i_sb->s_root);
27125+ else {
27126+ dentry = d_find_alias(inode);
27127+ if (!dentry)
27128+ dentry = d_find_any_alias(inode);
27129+ if (!dentry) {
27130+ pr_warn("cannot handle this inode, "
27131+ "please report to aufs-users ML\n");
27132+ err = -ENOENT;
27133+ goto out;
27134+ }
27135+ }
27136+
f2c43d5f 27137+ ssz = au_sxattr(dentry, inode, &arg);
c1595e42
JR
27138+ dput(dentry);
27139+ err = ssz;
a2654f78 27140+ if (ssz >= 0) {
c1595e42 27141+ err = 0;
a2654f78
AM
27142+ set_cached_acl(inode, type, acl);
27143+ }
c1595e42
JR
27144+
27145+out:
c1595e42
JR
27146+ return err;
27147+}
0b1ff5c3
JR
27148diff -urNp -x '*.orig' linux-4.14/fs/aufs/procfs.c linux-4.14/fs/aufs/procfs.c
27149--- linux-4.14/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100
27150+++ linux-4.14/fs/aufs/procfs.c 2021-02-24 21:42:43.444448075 +0100
8b6a4947 27151@@ -0,0 +1,170 @@
e49829fe 27152+/*
a2654f78 27153+ * Copyright (C) 2010-2017 Junjiro R. Okajima
e49829fe
JR
27154+ *
27155+ * This program, aufs is free software; you can redistribute it and/or modify
27156+ * it under the terms of the GNU General Public License as published by
27157+ * the Free Software Foundation; either version 2 of the License, or
27158+ * (at your option) any later version.
27159+ *
27160+ * This program is distributed in the hope that it will be useful,
27161+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27162+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27163+ * GNU General Public License for more details.
27164+ *
27165+ * You should have received a copy of the GNU General Public License
523b37e3 27166+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
e49829fe
JR
27167+ */
27168+
27169+/*
27170+ * procfs interfaces
27171+ */
27172+
27173+#include <linux/proc_fs.h>
27174+#include "aufs.h"
27175+
27176+static int au_procfs_plm_release(struct inode *inode, struct file *file)
27177+{
27178+ struct au_sbinfo *sbinfo;
27179+
27180+ sbinfo = file->private_data;
27181+ if (sbinfo) {
27182+ au_plink_maint_leave(sbinfo);
27183+ kobject_put(&sbinfo->si_kobj);
27184+ }
27185+
27186+ return 0;
27187+}
27188+
27189+static void au_procfs_plm_write_clean(struct file *file)
27190+{
27191+ struct au_sbinfo *sbinfo;
27192+
27193+ sbinfo = file->private_data;
27194+ if (sbinfo)
27195+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
27196+}
27197+
27198+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
27199+{
27200+ int err;
27201+ struct super_block *sb;
27202+ struct au_sbinfo *sbinfo;
8b6a4947 27203+ struct hlist_bl_node *pos;
e49829fe
JR
27204+
27205+ err = -EBUSY;
27206+ if (unlikely(file->private_data))
27207+ goto out;
27208+
27209+ sb = NULL;
53392da6 27210+ /* don't use au_sbilist_lock() here */
8b6a4947
AM
27211+ hlist_bl_lock(&au_sbilist);
27212+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list)
e49829fe
JR
27213+ if (id == sysaufs_si_id(sbinfo)) {
27214+ kobject_get(&sbinfo->si_kobj);
27215+ sb = sbinfo->si_sb;
27216+ break;
27217+ }
8b6a4947 27218+ hlist_bl_unlock(&au_sbilist);
e49829fe
JR
27219+
27220+ err = -EINVAL;
27221+ if (unlikely(!sb))
27222+ goto out;
27223+
27224+ err = au_plink_maint_enter(sb);
27225+ if (!err)
27226+ /* keep kobject_get() */
27227+ file->private_data = sbinfo;
27228+ else
27229+ kobject_put(&sbinfo->si_kobj);
27230+out:
27231+ return err;
27232+}
27233+
27234+/*
27235+ * Accept a valid "si=xxxx" only.
27236+ * Once it is accepted successfully, accept "clean" too.
27237+ */
27238+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
27239+ size_t count, loff_t *ppos)
27240+{
27241+ ssize_t err;
27242+ unsigned long id;
27243+ /* last newline is allowed */
27244+ char buf[3 + sizeof(unsigned long) * 2 + 1];
27245+
27246+ err = -EACCES;
27247+ if (unlikely(!capable(CAP_SYS_ADMIN)))
27248+ goto out;
27249+
27250+ err = -EINVAL;
27251+ if (unlikely(count > sizeof(buf)))
27252+ goto out;
27253+
27254+ err = copy_from_user(buf, ubuf, count);
27255+ if (unlikely(err)) {
27256+ err = -EFAULT;
27257+ goto out;
27258+ }
27259+ buf[count] = 0;
27260+
27261+ err = -EINVAL;
27262+ if (!strcmp("clean", buf)) {
27263+ au_procfs_plm_write_clean(file);
27264+ goto out_success;
27265+ } else if (unlikely(strncmp("si=", buf, 3)))
27266+ goto out;
27267+
9dbd164d 27268+ err = kstrtoul(buf + 3, 16, &id);
e49829fe
JR
27269+ if (unlikely(err))
27270+ goto out;
27271+
27272+ err = au_procfs_plm_write_si(file, id);
27273+ if (unlikely(err))
27274+ goto out;
27275+
27276+out_success:
27277+ err = count; /* success */
27278+out:
27279+ return err;
27280+}
27281+
27282+static const struct file_operations au_procfs_plm_fop = {
27283+ .write = au_procfs_plm_write,
27284+ .release = au_procfs_plm_release,
27285+ .owner = THIS_MODULE
27286+};
27287+
27288+/* ---------------------------------------------------------------------- */
27289+
27290+static struct proc_dir_entry *au_procfs_dir;
27291+
27292+void au_procfs_fin(void)
27293+{
27294+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
27295+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
27296+}
27297+
27298+int __init au_procfs_init(void)
27299+{
27300+ int err;
27301+ struct proc_dir_entry *entry;
27302+
27303+ err = -ENOMEM;
27304+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
27305+ if (unlikely(!au_procfs_dir))
27306+ goto out;
27307+
27308+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | S_IWUSR,
27309+ au_procfs_dir, &au_procfs_plm_fop);
27310+ if (unlikely(!entry))
27311+ goto out_dir;
27312+
27313+ err = 0;
27314+ goto out; /* success */
27315+
27316+
27317+out_dir:
27318+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
27319+out:
27320+ return err;
27321+}
0b1ff5c3
JR
27322diff -urNp -x '*.orig' linux-4.14/fs/aufs/rdu.c linux-4.14/fs/aufs/rdu.c
27323--- linux-4.14/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
27324+++ linux-4.14/fs/aufs/rdu.c 2021-02-24 21:42:43.444448075 +0100
5afbbe0d 27325@@ -0,0 +1,381 @@
1308ab2a 27326+/*
a2654f78 27327+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1308ab2a 27328+ *
27329+ * This program, aufs is free software; you can redistribute it and/or modify
27330+ * it under the terms of the GNU General Public License as published by
27331+ * the Free Software Foundation; either version 2 of the License, or
27332+ * (at your option) any later version.
27333+ *
27334+ * This program is distributed in the hope that it will be useful,
27335+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27336+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27337+ * GNU General Public License for more details.
27338+ *
27339+ * You should have received a copy of the GNU General Public License
523b37e3 27340+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1308ab2a 27341+ */
27342+
27343+/*
27344+ * readdir in userspace.
27345+ */
27346+
b752ccd1 27347+#include <linux/compat.h>
4a4d8108 27348+#include <linux/fs_stack.h>
1308ab2a 27349+#include <linux/security.h>
1308ab2a 27350+#include "aufs.h"
27351+
27352+/* bits for struct aufs_rdu.flags */
27353+#define AuRdu_CALLED 1
27354+#define AuRdu_CONT (1 << 1)
27355+#define AuRdu_FULL (1 << 2)
27356+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
7f207e10
AM
27357+#define au_fset_rdu(flags, name) \
27358+ do { (flags) |= AuRdu_##name; } while (0)
27359+#define au_fclr_rdu(flags, name) \
27360+ do { (flags) &= ~AuRdu_##name; } while (0)
1308ab2a 27361+
27362+struct au_rdu_arg {
392086de 27363+ struct dir_context ctx;
1308ab2a 27364+ struct aufs_rdu *rdu;
27365+ union au_rdu_ent_ul ent;
27366+ unsigned long end;
27367+
27368+ struct super_block *sb;
27369+ int err;
27370+};
27371+
392086de 27372+static int au_rdu_fill(struct dir_context *ctx, const char *name, int nlen,
1308ab2a 27373+ loff_t offset, u64 h_ino, unsigned int d_type)
27374+{
27375+ int err, len;
392086de 27376+ struct au_rdu_arg *arg = container_of(ctx, struct au_rdu_arg, ctx);
1308ab2a 27377+ struct aufs_rdu *rdu = arg->rdu;
27378+ struct au_rdu_ent ent;
27379+
27380+ err = 0;
27381+ arg->err = 0;
27382+ au_fset_rdu(rdu->cookie.flags, CALLED);
27383+ len = au_rdu_len(nlen);
27384+ if (arg->ent.ul + len < arg->end) {
27385+ ent.ino = h_ino;
27386+ ent.bindex = rdu->cookie.bindex;
27387+ ent.type = d_type;
27388+ ent.nlen = nlen;
4a4d8108
AM
27389+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
27390+ ent.type = DT_UNKNOWN;
1308ab2a 27391+
9dbd164d 27392+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 27393+ err = -EFAULT;
27394+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
27395+ goto out;
27396+ if (copy_to_user(arg->ent.e->name, name, nlen))
27397+ goto out;
27398+ /* the terminating NULL */
27399+ if (__put_user(0, arg->ent.e->name + nlen))
27400+ goto out;
27401+ err = 0;
27402+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
27403+ arg->ent.ul += len;
27404+ rdu->rent++;
27405+ } else {
27406+ err = -EFAULT;
27407+ au_fset_rdu(rdu->cookie.flags, FULL);
27408+ rdu->full = 1;
27409+ rdu->tail = arg->ent;
27410+ }
27411+
4f0767ce 27412+out:
1308ab2a 27413+ /* AuTraceErr(err); */
27414+ return err;
27415+}
27416+
27417+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
27418+{
27419+ int err;
27420+ loff_t offset;
27421+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
27422+
92d182d2 27423+ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */
1308ab2a 27424+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
27425+ err = offset;
27426+ if (unlikely(offset != cookie->h_pos))
27427+ goto out;
27428+
27429+ err = 0;
27430+ do {
27431+ arg->err = 0;
27432+ au_fclr_rdu(cookie->flags, CALLED);
27433+ /* smp_mb(); */
392086de 27434+ err = vfsub_iterate_dir(h_file, &arg->ctx);
1308ab2a 27435+ if (err >= 0)
27436+ err = arg->err;
27437+ } while (!err
27438+ && au_ftest_rdu(cookie->flags, CALLED)
27439+ && !au_ftest_rdu(cookie->flags, FULL));
27440+ cookie->h_pos = h_file->f_pos;
27441+
4f0767ce 27442+out:
1308ab2a 27443+ AuTraceErr(err);
27444+ return err;
27445+}
27446+
27447+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
27448+{
27449+ int err;
5afbbe0d 27450+ aufs_bindex_t bbot;
392086de
AM
27451+ struct au_rdu_arg arg = {
27452+ .ctx = {
2000de60 27453+ .actor = au_rdu_fill
392086de
AM
27454+ }
27455+ };
1308ab2a 27456+ struct dentry *dentry;
27457+ struct inode *inode;
27458+ struct file *h_file;
27459+ struct au_rdu_cookie *cookie = &rdu->cookie;
27460+
27461+ err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
27462+ if (unlikely(err)) {
27463+ err = -EFAULT;
27464+ AuTraceErr(err);
27465+ goto out;
27466+ }
27467+ rdu->rent = 0;
27468+ rdu->tail = rdu->ent;
27469+ rdu->full = 0;
27470+ arg.rdu = rdu;
27471+ arg.ent = rdu->ent;
27472+ arg.end = arg.ent.ul;
27473+ arg.end += rdu->sz;
27474+
27475+ err = -ENOTDIR;
5afbbe0d 27476+ if (unlikely(!file->f_op->iterate && !file->f_op->iterate_shared))
1308ab2a 27477+ goto out;
27478+
27479+ err = security_file_permission(file, MAY_READ);
27480+ AuTraceErr(err);
27481+ if (unlikely(err))
27482+ goto out;
27483+
2000de60 27484+ dentry = file->f_path.dentry;
5527c038 27485+ inode = d_inode(dentry);
5afbbe0d 27486+ inode_lock_shared(inode);
1308ab2a 27487+
27488+ arg.sb = inode->i_sb;
e49829fe
JR
27489+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
27490+ if (unlikely(err))
27491+ goto out_mtx;
027c5e7a
AM
27492+ err = au_alive_dir(dentry);
27493+ if (unlikely(err))
27494+ goto out_si;
e49829fe 27495+ /* todo: reval? */
1308ab2a 27496+ fi_read_lock(file);
27497+
27498+ err = -EAGAIN;
27499+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
27500+ && cookie->generation != au_figen(file)))
27501+ goto out_unlock;
27502+
27503+ err = 0;
27504+ if (!rdu->blk) {
27505+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
27506+ if (!rdu->blk)
27507+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
27508+ }
5afbbe0d
AM
27509+ bbot = au_fbtop(file);
27510+ if (cookie->bindex < bbot)
27511+ cookie->bindex = bbot;
27512+ bbot = au_fbbot_dir(file);
27513+ /* AuDbg("b%d, b%d\n", cookie->bindex, bbot); */
27514+ for (; !err && cookie->bindex <= bbot;
1308ab2a 27515+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 27516+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 27517+ if (!h_file)
27518+ continue;
27519+
27520+ au_fclr_rdu(cookie->flags, FULL);
27521+ err = au_rdu_do(h_file, &arg);
27522+ AuTraceErr(err);
27523+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
27524+ break;
27525+ }
27526+ AuDbg("rent %llu\n", rdu->rent);
27527+
27528+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
27529+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
27530+ au_fset_rdu(cookie->flags, CONT);
27531+ cookie->generation = au_figen(file);
27532+ }
27533+
27534+ ii_read_lock_child(inode);
5afbbe0d 27535+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibtop(inode)));
1308ab2a 27536+ ii_read_unlock(inode);
27537+
4f0767ce 27538+out_unlock:
1308ab2a 27539+ fi_read_unlock(file);
027c5e7a 27540+out_si:
1308ab2a 27541+ si_read_unlock(arg.sb);
4f0767ce 27542+out_mtx:
5afbbe0d 27543+ inode_unlock_shared(inode);
4f0767ce 27544+out:
1308ab2a 27545+ AuTraceErr(err);
27546+ return err;
27547+}
27548+
27549+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
27550+{
27551+ int err;
27552+ ino_t ino;
27553+ unsigned long long nent;
27554+ union au_rdu_ent_ul *u;
27555+ struct au_rdu_ent ent;
27556+ struct super_block *sb;
27557+
27558+ err = 0;
27559+ nent = rdu->nent;
27560+ u = &rdu->ent;
2000de60 27561+ sb = file->f_path.dentry->d_sb;
1308ab2a 27562+ si_read_lock(sb, AuLock_FLUSH);
27563+ while (nent-- > 0) {
9dbd164d 27564+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 27565+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108
AM
27566+ if (!err)
27567+ err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
1308ab2a 27568+ if (unlikely(err)) {
27569+ err = -EFAULT;
27570+ AuTraceErr(err);
27571+ break;
27572+ }
27573+
27574+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
27575+ if (!ent.wh)
27576+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
27577+ else
27578+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
27579+ &ino);
27580+ if (unlikely(err)) {
27581+ AuTraceErr(err);
27582+ break;
27583+ }
27584+
27585+ err = __put_user(ino, &u->e->ino);
27586+ if (unlikely(err)) {
27587+ err = -EFAULT;
27588+ AuTraceErr(err);
27589+ break;
27590+ }
27591+ u->ul += au_rdu_len(ent.nlen);
27592+ }
27593+ si_read_unlock(sb);
27594+
27595+ return err;
27596+}
27597+
27598+/* ---------------------------------------------------------------------- */
27599+
27600+static int au_rdu_verify(struct aufs_rdu *rdu)
27601+{
b752ccd1 27602+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 27603+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 27604+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 27605+ rdu->blk,
27606+ rdu->rent, rdu->shwh, rdu->full,
27607+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
27608+ rdu->cookie.generation);
dece6358 27609+
b752ccd1 27610+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 27611+ return 0;
dece6358 27612+
b752ccd1
AM
27613+ AuDbg("%u:%u\n",
27614+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 27615+ return -EINVAL;
27616+}
27617+
27618+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 27619+{
1308ab2a 27620+ long err, e;
27621+ struct aufs_rdu rdu;
27622+ void __user *p = (void __user *)arg;
dece6358 27623+
1308ab2a 27624+ err = copy_from_user(&rdu, p, sizeof(rdu));
27625+ if (unlikely(err)) {
27626+ err = -EFAULT;
27627+ AuTraceErr(err);
27628+ goto out;
27629+ }
27630+ err = au_rdu_verify(&rdu);
dece6358
AM
27631+ if (unlikely(err))
27632+ goto out;
27633+
1308ab2a 27634+ switch (cmd) {
27635+ case AUFS_CTL_RDU:
27636+ err = au_rdu(file, &rdu);
27637+ if (unlikely(err))
27638+ break;
dece6358 27639+
1308ab2a 27640+ e = copy_to_user(p, &rdu, sizeof(rdu));
27641+ if (unlikely(e)) {
27642+ err = -EFAULT;
27643+ AuTraceErr(err);
27644+ }
27645+ break;
27646+ case AUFS_CTL_RDU_INO:
27647+ err = au_rdu_ino(file, &rdu);
27648+ break;
27649+
27650+ default:
4a4d8108 27651+ /* err = -ENOTTY; */
1308ab2a 27652+ err = -EINVAL;
27653+ }
dece6358 27654+
4f0767ce 27655+out:
1308ab2a 27656+ AuTraceErr(err);
27657+ return err;
1facf9fc 27658+}
b752ccd1
AM
27659+
27660+#ifdef CONFIG_COMPAT
27661+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
27662+{
27663+ long err, e;
27664+ struct aufs_rdu rdu;
27665+ void __user *p = compat_ptr(arg);
27666+
27667+ /* todo: get_user()? */
27668+ err = copy_from_user(&rdu, p, sizeof(rdu));
27669+ if (unlikely(err)) {
27670+ err = -EFAULT;
27671+ AuTraceErr(err);
27672+ goto out;
27673+ }
27674+ rdu.ent.e = compat_ptr(rdu.ent.ul);
27675+ err = au_rdu_verify(&rdu);
27676+ if (unlikely(err))
27677+ goto out;
27678+
27679+ switch (cmd) {
27680+ case AUFS_CTL_RDU:
27681+ err = au_rdu(file, &rdu);
27682+ if (unlikely(err))
27683+ break;
27684+
27685+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
27686+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
27687+ e = copy_to_user(p, &rdu, sizeof(rdu));
27688+ if (unlikely(e)) {
27689+ err = -EFAULT;
27690+ AuTraceErr(err);
27691+ }
27692+ break;
27693+ case AUFS_CTL_RDU_INO:
27694+ err = au_rdu_ino(file, &rdu);
27695+ break;
27696+
27697+ default:
27698+ /* err = -ENOTTY; */
27699+ err = -EINVAL;
27700+ }
27701+
4f0767ce 27702+out:
b752ccd1
AM
27703+ AuTraceErr(err);
27704+ return err;
27705+}
27706+#endif
0b1ff5c3
JR
27707diff -urNp -x '*.orig' linux-4.14/fs/aufs/rwsem.h linux-4.14/fs/aufs/rwsem.h
27708--- linux-4.14/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
27709+++ linux-4.14/fs/aufs/rwsem.h 2021-02-24 21:42:43.444448075 +0100
8b6a4947 27710@@ -0,0 +1,72 @@
1facf9fc 27711+/*
a2654f78 27712+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 27713+ *
27714+ * This program, aufs is free software; you can redistribute it and/or modify
27715+ * it under the terms of the GNU General Public License as published by
27716+ * the Free Software Foundation; either version 2 of the License, or
27717+ * (at your option) any later version.
dece6358
AM
27718+ *
27719+ * This program is distributed in the hope that it will be useful,
27720+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27721+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27722+ * GNU General Public License for more details.
27723+ *
27724+ * You should have received a copy of the GNU General Public License
523b37e3 27725+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 27726+ */
27727+
27728+/*
27729+ * simple read-write semaphore wrappers
27730+ */
27731+
27732+#ifndef __AUFS_RWSEM_H__
27733+#define __AUFS_RWSEM_H__
27734+
27735+#ifdef __KERNEL__
27736+
4a4d8108 27737+#include "debug.h"
dece6358 27738+
8b6a4947
AM
27739+/* in the futre, the name 'au_rwsem' will be totally gone */
27740+#define au_rwsem rw_semaphore
dece6358
AM
27741+
27742+/* to debug easier, do not make them inlined functions */
8b6a4947 27743+#define AuRwMustNoWaiters(rw) AuDebugOn(rwsem_is_contended(rw))
dece6358 27744+/* rwsem_is_locked() is unusable */
8b6a4947
AM
27745+#define AuRwMustReadLock(rw) AuDebugOn(!lockdep_recursing(current) \
27746+ && debug_locks \
27747+ && !lockdep_is_held_type(rw, 1))
27748+#define AuRwMustWriteLock(rw) AuDebugOn(!lockdep_recursing(current) \
27749+ && debug_locks \
27750+ && !lockdep_is_held_type(rw, 0))
27751+#define AuRwMustAnyLock(rw) AuDebugOn(!lockdep_recursing(current) \
27752+ && debug_locks \
27753+ && !lockdep_is_held(rw))
27754+#define AuRwDestroy(rw) AuDebugOn(!lockdep_recursing(current) \
27755+ && debug_locks \
27756+ && lockdep_is_held(rw))
27757+
27758+#define au_rw_init(rw) init_rwsem(rw)
dece6358 27759+
5afbbe0d
AM
27760+#define au_rw_init_wlock(rw) do { \
27761+ au_rw_init(rw); \
8b6a4947 27762+ down_write(rw); \
5afbbe0d 27763+ } while (0)
dece6358 27764+
8b6a4947
AM
27765+#define au_rw_init_wlock_nested(rw, lsc) do { \
27766+ au_rw_init(rw); \
27767+ down_write_nested(rw, lsc); \
5afbbe0d 27768+ } while (0)
dece6358 27769+
8b6a4947
AM
27770+#define au_rw_read_lock(rw) down_read(rw)
27771+#define au_rw_read_lock_nested(rw, lsc) down_read_nested(rw, lsc)
27772+#define au_rw_read_unlock(rw) up_read(rw)
27773+#define au_rw_dgrade_lock(rw) downgrade_write(rw)
27774+#define au_rw_write_lock(rw) down_write(rw)
27775+#define au_rw_write_lock_nested(rw, lsc) down_write_nested(rw, lsc)
27776+#define au_rw_write_unlock(rw) up_write(rw)
27777+/* why is not _nested version defined? */
27778+#define au_rw_read_trylock(rw) down_read_trylock(rw)
27779+#define au_rw_write_trylock(rw) down_write_trylock(rw)
1facf9fc 27780+
27781+#endif /* __KERNEL__ */
27782+#endif /* __AUFS_RWSEM_H__ */
0b1ff5c3
JR
27783diff -urNp -x '*.orig' linux-4.14/fs/aufs/sbinfo.c linux-4.14/fs/aufs/sbinfo.c
27784--- linux-4.14/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
27785+++ linux-4.14/fs/aufs/sbinfo.c 2021-02-24 21:42:43.444448075 +0100
a2654f78 27786@@ -0,0 +1,304 @@
1facf9fc 27787+/*
a2654f78 27788+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 27789+ *
27790+ * This program, aufs is free software; you can redistribute it and/or modify
27791+ * it under the terms of the GNU General Public License as published by
27792+ * the Free Software Foundation; either version 2 of the License, or
27793+ * (at your option) any later version.
dece6358
AM
27794+ *
27795+ * This program is distributed in the hope that it will be useful,
27796+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27797+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27798+ * GNU General Public License for more details.
27799+ *
27800+ * You should have received a copy of the GNU General Public License
523b37e3 27801+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 27802+ */
27803+
27804+/*
27805+ * superblock private data
27806+ */
27807+
27808+#include "aufs.h"
27809+
27810+/*
27811+ * they are necessary regardless sysfs is disabled.
27812+ */
27813+void au_si_free(struct kobject *kobj)
27814+{
86dc4139 27815+ int i;
1facf9fc 27816+ struct au_sbinfo *sbinfo;
b752ccd1 27817+ char *locked __maybe_unused; /* debug only */
1facf9fc 27818+
27819+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
86dc4139 27820+ for (i = 0; i < AuPlink_NHASH; i++)
8b6a4947 27821+ AuDebugOn(!hlist_bl_empty(sbinfo->si_plink + i));
f0c0a007 27822+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
5afbbe0d
AM
27823+
27824+ AuDebugOn(percpu_counter_sum(&sbinfo->si_ninodes));
27825+ percpu_counter_destroy(&sbinfo->si_ninodes);
27826+ AuDebugOn(percpu_counter_sum(&sbinfo->si_nfiles));
27827+ percpu_counter_destroy(&sbinfo->si_nfiles);
1facf9fc 27828+
e49829fe 27829+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 27830+ au_br_free(sbinfo);
e49829fe 27831+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1 27832+
1c60b727 27833+ kfree(sbinfo->si_branch);
1facf9fc 27834+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 27835+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 27836+
1c60b727 27837+ kfree(sbinfo);
1facf9fc 27838+}
27839+
27840+int au_si_alloc(struct super_block *sb)
27841+{
86dc4139 27842+ int err, i;
1facf9fc 27843+ struct au_sbinfo *sbinfo;
27844+
27845+ err = -ENOMEM;
4a4d8108 27846+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 27847+ if (unlikely(!sbinfo))
27848+ goto out;
27849+
27850+ /* will be reallocated separately */
27851+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
27852+ if (unlikely(!sbinfo->si_branch))
febd17d6 27853+ goto out_sbinfo;
1facf9fc 27854+
1facf9fc 27855+ err = sysaufs_si_init(sbinfo);
27856+ if (unlikely(err))
27857+ goto out_br;
27858+
27859+ au_nwt_init(&sbinfo->si_nowait);
dece6358 27860+ au_rw_init_wlock(&sbinfo->si_rwsem);
b752ccd1 27861+
5afbbe0d
AM
27862+ percpu_counter_init(&sbinfo->si_ninodes, 0, GFP_NOFS);
27863+ percpu_counter_init(&sbinfo->si_nfiles, 0, GFP_NOFS);
7f207e10 27864+
5afbbe0d 27865+ sbinfo->si_bbot = -1;
392086de 27866+ sbinfo->si_last_br_id = AUFS_BRANCH_MAX / 2;
1facf9fc 27867+
27868+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
27869+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
27870+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
27871+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 27872+
076b876e
AM
27873+ au_fhsm_init(sbinfo);
27874+
e49829fe 27875+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 27876+
392086de
AM
27877+ sbinfo->si_xino_jiffy = jiffies;
27878+ sbinfo->si_xino_expire
27879+ = msecs_to_jiffies(AUFS_XINO_DEF_SEC * MSEC_PER_SEC);
1facf9fc 27880+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 27881+ sbinfo->si_xino_brid = -1;
27882+ /* leave si_xib_last_pindex and si_xib_next_bit */
27883+
8b6a4947 27884+ INIT_HLIST_BL_HEAD(&sbinfo->si_aopen);
b912730e 27885+
e49829fe 27886+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 27887+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
27888+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
27889+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
27890+
86dc4139 27891+ for (i = 0; i < AuPlink_NHASH; i++)
8b6a4947 27892+ INIT_HLIST_BL_HEAD(sbinfo->si_plink + i);
1facf9fc 27893+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 27894+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 27895+
8b6a4947 27896+ INIT_HLIST_BL_HEAD(&sbinfo->si_files);
523b37e3 27897+
b95c5147
AM
27898+ /* with getattr by default */
27899+ sbinfo->si_iop_array = aufs_iop;
27900+
1facf9fc 27901+ /* leave other members for sysaufs and si_mnt. */
27902+ sbinfo->si_sb = sb;
27903+ sb->s_fs_info = sbinfo;
b752ccd1 27904+ si_pid_set(sb);
1facf9fc 27905+ return 0; /* success */
27906+
4f0767ce 27907+out_br:
1c60b727 27908+ kfree(sbinfo->si_branch);
4f0767ce 27909+out_sbinfo:
1c60b727 27910+ kfree(sbinfo);
4f0767ce 27911+out:
1facf9fc 27912+ return err;
27913+}
27914+
e2f27e51 27915+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink)
1facf9fc 27916+{
27917+ int err, sz;
27918+ struct au_branch **brp;
27919+
dece6358
AM
27920+ AuRwMustWriteLock(&sbinfo->si_rwsem);
27921+
1facf9fc 27922+ err = -ENOMEM;
5afbbe0d 27923+ sz = sizeof(*brp) * (sbinfo->si_bbot + 1);
1facf9fc 27924+ if (unlikely(!sz))
27925+ sz = sizeof(*brp);
e2f27e51
AM
27926+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS,
27927+ may_shrink);
1facf9fc 27928+ if (brp) {
27929+ sbinfo->si_branch = brp;
27930+ err = 0;
27931+ }
27932+
27933+ return err;
27934+}
27935+
27936+/* ---------------------------------------------------------------------- */
27937+
27938+unsigned int au_sigen_inc(struct super_block *sb)
27939+{
27940+ unsigned int gen;
5527c038 27941+ struct inode *inode;
1facf9fc 27942+
dece6358
AM
27943+ SiMustWriteLock(sb);
27944+
1facf9fc 27945+ gen = ++au_sbi(sb)->si_generation;
27946+ au_update_digen(sb->s_root);
5527c038
JR
27947+ inode = d_inode(sb->s_root);
27948+ au_update_iigen(inode, /*half*/0);
27949+ inode->i_version++;
1facf9fc 27950+ return gen;
27951+}
27952+
27953+aufs_bindex_t au_new_br_id(struct super_block *sb)
27954+{
27955+ aufs_bindex_t br_id;
27956+ int i;
27957+ struct au_sbinfo *sbinfo;
27958+
dece6358
AM
27959+ SiMustWriteLock(sb);
27960+
1facf9fc 27961+ sbinfo = au_sbi(sb);
27962+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
27963+ br_id = ++sbinfo->si_last_br_id;
7f207e10 27964+ AuDebugOn(br_id < 0);
1facf9fc 27965+ if (br_id && au_br_index(sb, br_id) < 0)
27966+ return br_id;
27967+ }
27968+
27969+ return -1;
27970+}
27971+
27972+/* ---------------------------------------------------------------------- */
27973+
e49829fe
JR
27974+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
27975+int si_read_lock(struct super_block *sb, int flags)
27976+{
27977+ int err;
27978+
27979+ err = 0;
27980+ if (au_ftest_lock(flags, FLUSH))
27981+ au_nwt_flush(&au_sbi(sb)->si_nowait);
27982+
27983+ si_noflush_read_lock(sb);
27984+ err = au_plink_maint(sb, flags);
27985+ if (unlikely(err))
27986+ si_read_unlock(sb);
27987+
27988+ return err;
27989+}
27990+
27991+int si_write_lock(struct super_block *sb, int flags)
27992+{
27993+ int err;
27994+
27995+ if (au_ftest_lock(flags, FLUSH))
27996+ au_nwt_flush(&au_sbi(sb)->si_nowait);
27997+
27998+ si_noflush_write_lock(sb);
27999+ err = au_plink_maint(sb, flags);
28000+ if (unlikely(err))
28001+ si_write_unlock(sb);
28002+
28003+ return err;
28004+}
28005+
1facf9fc 28006+/* dentry and super_block lock. call at entry point */
e49829fe 28007+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 28008+{
e49829fe 28009+ int err;
027c5e7a 28010+ struct super_block *sb;
e49829fe 28011+
027c5e7a
AM
28012+ sb = dentry->d_sb;
28013+ err = si_read_lock(sb, flags);
28014+ if (unlikely(err))
28015+ goto out;
28016+
28017+ if (au_ftest_lock(flags, DW))
28018+ di_write_lock_child(dentry);
28019+ else
28020+ di_read_lock_child(dentry, flags);
28021+
28022+ if (au_ftest_lock(flags, GEN)) {
28023+ err = au_digen_test(dentry, au_sigen(sb));
79b8bda9
AM
28024+ if (!au_opt_test(au_mntflags(sb), UDBA_NONE))
28025+ AuDebugOn(!err && au_dbrange_test(dentry));
28026+ else if (!err)
28027+ err = au_dbrange_test(dentry);
027c5e7a
AM
28028+ if (unlikely(err))
28029+ aufs_read_unlock(dentry, flags);
e49829fe
JR
28030+ }
28031+
027c5e7a 28032+out:
e49829fe 28033+ return err;
1facf9fc 28034+}
28035+
28036+void aufs_read_unlock(struct dentry *dentry, int flags)
28037+{
28038+ if (au_ftest_lock(flags, DW))
28039+ di_write_unlock(dentry);
28040+ else
28041+ di_read_unlock(dentry, flags);
28042+ si_read_unlock(dentry->d_sb);
28043+}
28044+
28045+void aufs_write_lock(struct dentry *dentry)
28046+{
e49829fe 28047+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 28048+ di_write_lock_child(dentry);
28049+}
28050+
28051+void aufs_write_unlock(struct dentry *dentry)
28052+{
28053+ di_write_unlock(dentry);
28054+ si_write_unlock(dentry->d_sb);
28055+}
28056+
e49829fe 28057+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 28058+{
e49829fe 28059+ int err;
027c5e7a
AM
28060+ unsigned int sigen;
28061+ struct super_block *sb;
e49829fe 28062+
027c5e7a
AM
28063+ sb = d1->d_sb;
28064+ err = si_read_lock(sb, flags);
28065+ if (unlikely(err))
28066+ goto out;
28067+
b95c5147 28068+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIRS));
027c5e7a
AM
28069+
28070+ if (au_ftest_lock(flags, GEN)) {
28071+ sigen = au_sigen(sb);
28072+ err = au_digen_test(d1, sigen);
28073+ AuDebugOn(!err && au_dbrange_test(d1));
28074+ if (!err) {
28075+ err = au_digen_test(d2, sigen);
28076+ AuDebugOn(!err && au_dbrange_test(d2));
28077+ }
28078+ if (unlikely(err))
28079+ aufs_read_and_write_unlock2(d1, d2);
28080+ }
28081+
28082+out:
e49829fe 28083+ return err;
1facf9fc 28084+}
28085+
28086+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
28087+{
28088+ di_write_unlock2(d1, d2);
28089+ si_read_unlock(d1->d_sb);
28090+}
0b1ff5c3
JR
28091diff -urNp -x '*.orig' linux-4.14/fs/aufs/super.c linux-4.14/fs/aufs/super.c
28092--- linux-4.14/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
28093+++ linux-4.14/fs/aufs/super.c 2021-02-24 21:42:43.447781402 +0100
28094@@ -0,0 +1,1049 @@
1facf9fc 28095+/*
a2654f78 28096+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 28097+ *
28098+ * This program, aufs is free software; you can redistribute it and/or modify
28099+ * it under the terms of the GNU General Public License as published by
28100+ * the Free Software Foundation; either version 2 of the License, or
28101+ * (at your option) any later version.
dece6358
AM
28102+ *
28103+ * This program is distributed in the hope that it will be useful,
28104+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28105+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28106+ * GNU General Public License for more details.
28107+ *
28108+ * You should have received a copy of the GNU General Public License
523b37e3 28109+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 28110+ */
28111+
28112+/*
28113+ * mount and super_block operations
28114+ */
28115+
f6c5ef8b 28116+#include <linux/mm.h>
1facf9fc 28117+#include <linux/seq_file.h>
28118+#include <linux/statfs.h>
7f207e10 28119+#include <linux/vmalloc.h>
1facf9fc 28120+#include "aufs.h"
28121+
28122+/*
28123+ * super_operations
28124+ */
28125+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
28126+{
28127+ struct au_icntnr *c;
28128+
28129+ c = au_cache_alloc_icntnr();
28130+ if (c) {
027c5e7a 28131+ au_icntnr_init(c);
1facf9fc 28132+ c->vfs_inode.i_version = 1; /* sigen(sb); */
28133+ c->iinfo.ii_hinode = NULL;
28134+ return &c->vfs_inode;
28135+ }
28136+ return NULL;
28137+}
28138+
027c5e7a
AM
28139+static void aufs_destroy_inode_cb(struct rcu_head *head)
28140+{
28141+ struct inode *inode = container_of(head, struct inode, i_rcu);
28142+
1c60b727 28143+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
027c5e7a
AM
28144+}
28145+
1facf9fc 28146+static void aufs_destroy_inode(struct inode *inode)
28147+{
5afbbe0d
AM
28148+ if (!au_is_bad_inode(inode))
28149+ au_iinfo_fin(inode);
027c5e7a 28150+ call_rcu(&inode->i_rcu, aufs_destroy_inode_cb);
1facf9fc 28151+}
28152+
28153+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
28154+{
28155+ struct inode *inode;
28156+ int err;
28157+
28158+ inode = iget_locked(sb, ino);
28159+ if (unlikely(!inode)) {
28160+ inode = ERR_PTR(-ENOMEM);
28161+ goto out;
28162+ }
28163+ if (!(inode->i_state & I_NEW))
28164+ goto out;
28165+
28166+ err = au_xigen_new(inode);
28167+ if (!err)
28168+ err = au_iinfo_init(inode);
28169+ if (!err)
28170+ inode->i_version++;
28171+ else {
28172+ iget_failed(inode);
28173+ inode = ERR_PTR(err);
28174+ }
28175+
4f0767ce 28176+out:
1facf9fc 28177+ /* never return NULL */
28178+ AuDebugOn(!inode);
28179+ AuTraceErrPtr(inode);
28180+ return inode;
28181+}
28182+
28183+/* lock free root dinfo */
28184+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
28185+{
28186+ int err;
5afbbe0d 28187+ aufs_bindex_t bindex, bbot;
1facf9fc 28188+ struct path path;
4a4d8108 28189+ struct au_hdentry *hdp;
1facf9fc 28190+ struct au_branch *br;
076b876e 28191+ au_br_perm_str_t perm;
1facf9fc 28192+
28193+ err = 0;
5afbbe0d
AM
28194+ bbot = au_sbbot(sb);
28195+ bindex = 0;
28196+ hdp = au_hdentry(au_di(sb->s_root), bindex);
28197+ for (; !err && bindex <= bbot; bindex++, hdp++) {
1facf9fc 28198+ br = au_sbr(sb, bindex);
86dc4139 28199+ path.mnt = au_br_mnt(br);
5afbbe0d 28200+ path.dentry = hdp->hd_dentry;
1facf9fc 28201+ err = au_seq_path(seq, &path);
79b8bda9 28202+ if (!err) {
076b876e 28203+ au_optstr_br_perm(&perm, br->br_perm);
79b8bda9 28204+ seq_printf(seq, "=%s", perm.a);
5afbbe0d 28205+ if (bindex != bbot)
79b8bda9 28206+ seq_putc(seq, ':');
1e00d052 28207+ }
1facf9fc 28208+ }
79b8bda9
AM
28209+ if (unlikely(err || seq_has_overflowed(seq)))
28210+ err = -E2BIG;
1facf9fc 28211+
28212+ return err;
28213+}
28214+
f2c43d5f
AM
28215+static void au_gen_fmt(char *fmt, int len __maybe_unused, const char *pat,
28216+ const char *append)
28217+{
28218+ char *p;
28219+
28220+ p = fmt;
28221+ while (*pat != ':')
28222+ *p++ = *pat++;
28223+ *p++ = *pat++;
28224+ strcpy(p, append);
28225+ AuDebugOn(strlen(fmt) >= len);
28226+}
28227+
1facf9fc 28228+static void au_show_wbr_create(struct seq_file *m, int v,
28229+ struct au_sbinfo *sbinfo)
28230+{
28231+ const char *pat;
f2c43d5f
AM
28232+ char fmt[32];
28233+ struct au_wbr_mfs *mfs;
1facf9fc 28234+
dece6358
AM
28235+ AuRwMustAnyLock(&sbinfo->si_rwsem);
28236+
c2b27bf2 28237+ seq_puts(m, ",create=");
1facf9fc 28238+ pat = au_optstr_wbr_create(v);
f2c43d5f 28239+ mfs = &sbinfo->si_wbr_mfs;
1facf9fc 28240+ switch (v) {
28241+ case AuWbrCreate_TDP:
28242+ case AuWbrCreate_RR:
28243+ case AuWbrCreate_MFS:
28244+ case AuWbrCreate_PMFS:
c2b27bf2 28245+ seq_puts(m, pat);
1facf9fc 28246+ break;
f2c43d5f
AM
28247+ case AuWbrCreate_MFSRR:
28248+ case AuWbrCreate_TDMFS:
28249+ case AuWbrCreate_PMFSRR:
28250+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu");
28251+ seq_printf(m, fmt, mfs->mfsrr_watermark);
1facf9fc 28252+ break;
f2c43d5f 28253+ case AuWbrCreate_MFSV:
1facf9fc 28254+ case AuWbrCreate_PMFSV:
f2c43d5f
AM
28255+ au_gen_fmt(fmt, sizeof(fmt), pat, "%lu");
28256+ seq_printf(m, fmt,
28257+ jiffies_to_msecs(mfs->mfs_expire)
e49829fe 28258+ / MSEC_PER_SEC);
1facf9fc 28259+ break;
1facf9fc 28260+ case AuWbrCreate_MFSRRV:
f2c43d5f 28261+ case AuWbrCreate_TDMFSV:
392086de 28262+ case AuWbrCreate_PMFSRRV:
f2c43d5f
AM
28263+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu:%lu");
28264+ seq_printf(m, fmt, mfs->mfsrr_watermark,
28265+ jiffies_to_msecs(mfs->mfs_expire) / MSEC_PER_SEC);
392086de 28266+ break;
f2c43d5f
AM
28267+ default:
28268+ BUG();
1facf9fc 28269+ }
28270+}
28271+
7eafdf33 28272+static int au_show_xino(struct seq_file *seq, struct super_block *sb)
1facf9fc 28273+{
28274+#ifdef CONFIG_SYSFS
28275+ return 0;
28276+#else
28277+ int err;
28278+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
28279+ aufs_bindex_t bindex, brid;
1facf9fc 28280+ struct qstr *name;
28281+ struct file *f;
28282+ struct dentry *d, *h_root;
28283+
dece6358
AM
28284+ AuRwMustAnyLock(&sbinfo->si_rwsem);
28285+
1facf9fc 28286+ err = 0;
1facf9fc 28287+ f = au_sbi(sb)->si_xib;
28288+ if (!f)
28289+ goto out;
28290+
28291+ /* stop printing the default xino path on the first writable branch */
28292+ h_root = NULL;
28293+ brid = au_xino_brid(sb);
28294+ if (brid >= 0) {
28295+ bindex = au_br_index(sb, brid);
5afbbe0d 28296+ h_root = au_hdentry(au_di(sb->s_root), bindex)->hd_dentry;
1facf9fc 28297+ }
2000de60 28298+ d = f->f_path.dentry;
1facf9fc 28299+ name = &d->d_name;
28300+ /* safe ->d_parent because the file is unlinked */
28301+ if (d->d_parent == h_root
28302+ && name->len == len
28303+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
28304+ goto out;
28305+
28306+ seq_puts(seq, ",xino=");
28307+ err = au_xino_path(seq, f);
28308+
4f0767ce 28309+out:
1facf9fc 28310+ return err;
28311+#endif
28312+}
28313+
28314+/* seq_file will re-call me in case of too long string */
7eafdf33 28315+static int aufs_show_options(struct seq_file *m, struct dentry *dentry)
1facf9fc 28316+{
027c5e7a 28317+ int err;
1facf9fc 28318+ unsigned int mnt_flags, v;
28319+ struct super_block *sb;
28320+ struct au_sbinfo *sbinfo;
28321+
28322+#define AuBool(name, str) do { \
28323+ v = au_opt_test(mnt_flags, name); \
28324+ if (v != au_opt_test(AuOpt_Def, name)) \
28325+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
28326+} while (0)
28327+
28328+#define AuStr(name, str) do { \
28329+ v = mnt_flags & AuOptMask_##name; \
28330+ if (v != (AuOpt_Def & AuOptMask_##name)) \
28331+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
28332+} while (0)
28333+
28334+#define AuUInt(name, str, val) do { \
28335+ if (val != AUFS_##name##_DEF) \
28336+ seq_printf(m, "," #str "=%u", val); \
28337+} while (0)
28338+
7eafdf33 28339+ sb = dentry->d_sb;
c1595e42
JR
28340+ if (sb->s_flags & MS_POSIXACL)
28341+ seq_puts(m, ",acl");
28342+
28343+ /* lock free root dinfo */
1facf9fc 28344+ si_noflush_read_lock(sb);
28345+ sbinfo = au_sbi(sb);
28346+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
28347+
28348+ mnt_flags = au_mntflags(sb);
28349+ if (au_opt_test(mnt_flags, XINO)) {
7eafdf33 28350+ err = au_show_xino(m, sb);
1facf9fc 28351+ if (unlikely(err))
28352+ goto out;
28353+ } else
28354+ seq_puts(m, ",noxino");
28355+
28356+ AuBool(TRUNC_XINO, trunc_xino);
28357+ AuStr(UDBA, udba);
dece6358 28358+ AuBool(SHWH, shwh);
1facf9fc 28359+ AuBool(PLINK, plink);
4a4d8108 28360+ AuBool(DIO, dio);
076b876e 28361+ AuBool(DIRPERM1, dirperm1);
1facf9fc 28362+
28363+ v = sbinfo->si_wbr_create;
28364+ if (v != AuWbrCreate_Def)
28365+ au_show_wbr_create(m, v, sbinfo);
28366+
28367+ v = sbinfo->si_wbr_copyup;
28368+ if (v != AuWbrCopyup_Def)
28369+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
28370+
28371+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
28372+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
28373+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
28374+
28375+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
28376+
027c5e7a
AM
28377+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
28378+ AuUInt(RDCACHE, rdcache, v);
1facf9fc 28379+
28380+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
28381+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
28382+
076b876e
AM
28383+ au_fhsm_show(m, sbinfo);
28384+
8b6a4947 28385+ AuBool(DIRREN, dirren);
1facf9fc 28386+ AuBool(SUM, sum);
28387+ /* AuBool(SUM_W, wsum); */
28388+ AuBool(WARN_PERM, warn_perm);
28389+ AuBool(VERBOSE, verbose);
28390+
4f0767ce 28391+out:
1facf9fc 28392+ /* be sure to print "br:" last */
28393+ if (!sysaufs_brs) {
28394+ seq_puts(m, ",br:");
28395+ au_show_brs(m, sb);
28396+ }
28397+ si_read_unlock(sb);
28398+ return 0;
28399+
1facf9fc 28400+#undef AuBool
28401+#undef AuStr
4a4d8108 28402+#undef AuUInt
1facf9fc 28403+}
28404+
28405+/* ---------------------------------------------------------------------- */
28406+
28407+/* sum mode which returns the summation for statfs(2) */
28408+
28409+static u64 au_add_till_max(u64 a, u64 b)
28410+{
28411+ u64 old;
28412+
28413+ old = a;
28414+ a += b;
92d182d2
AM
28415+ if (old <= a)
28416+ return a;
28417+ return ULLONG_MAX;
28418+}
28419+
28420+static u64 au_mul_till_max(u64 a, long mul)
28421+{
28422+ u64 old;
28423+
28424+ old = a;
28425+ a *= mul;
28426+ if (old <= a)
1facf9fc 28427+ return a;
28428+ return ULLONG_MAX;
28429+}
28430+
28431+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
28432+{
28433+ int err;
92d182d2 28434+ long bsize, factor;
1facf9fc 28435+ u64 blocks, bfree, bavail, files, ffree;
5afbbe0d 28436+ aufs_bindex_t bbot, bindex, i;
1facf9fc 28437+ unsigned char shared;
7f207e10 28438+ struct path h_path;
1facf9fc 28439+ struct super_block *h_sb;
28440+
92d182d2
AM
28441+ err = 0;
28442+ bsize = LONG_MAX;
28443+ files = 0;
28444+ ffree = 0;
1facf9fc 28445+ blocks = 0;
28446+ bfree = 0;
28447+ bavail = 0;
5afbbe0d
AM
28448+ bbot = au_sbbot(sb);
28449+ for (bindex = 0; bindex <= bbot; bindex++) {
7f207e10
AM
28450+ h_path.mnt = au_sbr_mnt(sb, bindex);
28451+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 28452+ shared = 0;
92d182d2 28453+ for (i = 0; !shared && i < bindex; i++)
1facf9fc 28454+ shared = (au_sbr_sb(sb, i) == h_sb);
28455+ if (shared)
28456+ continue;
28457+
28458+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
28459+ h_path.dentry = h_path.mnt->mnt_root;
28460+ err = vfs_statfs(&h_path, buf);
1facf9fc 28461+ if (unlikely(err))
28462+ goto out;
28463+
92d182d2
AM
28464+ if (bsize > buf->f_bsize) {
28465+ /*
28466+ * we will reduce bsize, so we have to expand blocks
28467+ * etc. to match them again
28468+ */
28469+ factor = (bsize / buf->f_bsize);
28470+ blocks = au_mul_till_max(blocks, factor);
28471+ bfree = au_mul_till_max(bfree, factor);
28472+ bavail = au_mul_till_max(bavail, factor);
28473+ bsize = buf->f_bsize;
28474+ }
28475+
28476+ factor = (buf->f_bsize / bsize);
28477+ blocks = au_add_till_max(blocks,
28478+ au_mul_till_max(buf->f_blocks, factor));
28479+ bfree = au_add_till_max(bfree,
28480+ au_mul_till_max(buf->f_bfree, factor));
28481+ bavail = au_add_till_max(bavail,
28482+ au_mul_till_max(buf->f_bavail, factor));
1facf9fc 28483+ files = au_add_till_max(files, buf->f_files);
28484+ ffree = au_add_till_max(ffree, buf->f_ffree);
28485+ }
28486+
92d182d2 28487+ buf->f_bsize = bsize;
1facf9fc 28488+ buf->f_blocks = blocks;
28489+ buf->f_bfree = bfree;
28490+ buf->f_bavail = bavail;
28491+ buf->f_files = files;
28492+ buf->f_ffree = ffree;
92d182d2 28493+ buf->f_frsize = 0;
1facf9fc 28494+
4f0767ce 28495+out:
1facf9fc 28496+ return err;
28497+}
28498+
28499+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
28500+{
28501+ int err;
7f207e10 28502+ struct path h_path;
1facf9fc 28503+ struct super_block *sb;
28504+
28505+ /* lock free root dinfo */
28506+ sb = dentry->d_sb;
28507+ si_noflush_read_lock(sb);
7f207e10 28508+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 28509+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
28510+ h_path.mnt = au_sbr_mnt(sb, 0);
28511+ h_path.dentry = h_path.mnt->mnt_root;
28512+ err = vfs_statfs(&h_path, buf);
28513+ } else
1facf9fc 28514+ err = au_statfs_sum(sb, buf);
28515+ si_read_unlock(sb);
28516+
28517+ if (!err) {
28518+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 28519+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 28520+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
28521+ }
28522+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
28523+
28524+ return err;
28525+}
28526+
28527+/* ---------------------------------------------------------------------- */
28528+
537831f9
AM
28529+static int aufs_sync_fs(struct super_block *sb, int wait)
28530+{
28531+ int err, e;
5afbbe0d 28532+ aufs_bindex_t bbot, bindex;
537831f9
AM
28533+ struct au_branch *br;
28534+ struct super_block *h_sb;
28535+
28536+ err = 0;
28537+ si_noflush_read_lock(sb);
5afbbe0d
AM
28538+ bbot = au_sbbot(sb);
28539+ for (bindex = 0; bindex <= bbot; bindex++) {
537831f9
AM
28540+ br = au_sbr(sb, bindex);
28541+ if (!au_br_writable(br->br_perm))
28542+ continue;
28543+
28544+ h_sb = au_sbr_sb(sb, bindex);
a2654f78
AM
28545+ e = vfsub_sync_filesystem(h_sb, wait);
28546+ if (unlikely(e && !err))
28547+ err = e;
28548+ /* go on even if an error happens */
537831f9
AM
28549+ }
28550+ si_read_unlock(sb);
28551+
28552+ return err;
28553+}
28554+
28555+/* ---------------------------------------------------------------------- */
28556+
1facf9fc 28557+/* final actions when unmounting a file system */
28558+static void aufs_put_super(struct super_block *sb)
28559+{
28560+ struct au_sbinfo *sbinfo;
28561+
28562+ sbinfo = au_sbi(sb);
28563+ if (!sbinfo)
28564+ return;
28565+
1facf9fc 28566+ dbgaufs_si_fin(sbinfo);
28567+ kobject_put(&sbinfo->si_kobj);
28568+}
28569+
28570+/* ---------------------------------------------------------------------- */
28571+
79b8bda9
AM
28572+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb,
28573+ struct super_block *sb, void *arg)
7f207e10
AM
28574+{
28575+ void *array;
076b876e 28576+ unsigned long long n, sz;
7f207e10
AM
28577+
28578+ array = NULL;
28579+ n = 0;
28580+ if (!*hint)
28581+ goto out;
28582+
28583+ if (*hint > ULLONG_MAX / sizeof(array)) {
28584+ array = ERR_PTR(-EMFILE);
28585+ pr_err("hint %llu\n", *hint);
28586+ goto out;
28587+ }
28588+
076b876e
AM
28589+ sz = sizeof(array) * *hint;
28590+ array = kzalloc(sz, GFP_NOFS);
7f207e10 28591+ if (unlikely(!array))
076b876e 28592+ array = vzalloc(sz);
7f207e10
AM
28593+ if (unlikely(!array)) {
28594+ array = ERR_PTR(-ENOMEM);
28595+ goto out;
28596+ }
28597+
79b8bda9 28598+ n = cb(sb, array, *hint, arg);
7f207e10
AM
28599+ AuDebugOn(n > *hint);
28600+
28601+out:
28602+ *hint = n;
28603+ return array;
28604+}
28605+
79b8bda9 28606+static unsigned long long au_iarray_cb(struct super_block *sb, void *a,
7f207e10
AM
28607+ unsigned long long max __maybe_unused,
28608+ void *arg)
28609+{
28610+ unsigned long long n;
28611+ struct inode **p, *inode;
28612+ struct list_head *head;
28613+
28614+ n = 0;
28615+ p = a;
28616+ head = arg;
79b8bda9 28617+ spin_lock(&sb->s_inode_list_lock);
7f207e10 28618+ list_for_each_entry(inode, head, i_sb_list) {
5afbbe0d
AM
28619+ if (!au_is_bad_inode(inode)
28620+ && au_ii(inode)->ii_btop >= 0) {
2cbb1c4b
JR
28621+ spin_lock(&inode->i_lock);
28622+ if (atomic_read(&inode->i_count)) {
28623+ au_igrab(inode);
28624+ *p++ = inode;
28625+ n++;
28626+ AuDebugOn(n > max);
28627+ }
28628+ spin_unlock(&inode->i_lock);
7f207e10
AM
28629+ }
28630+ }
79b8bda9 28631+ spin_unlock(&sb->s_inode_list_lock);
7f207e10
AM
28632+
28633+ return n;
28634+}
28635+
28636+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
28637+{
5afbbe0d 28638+ *max = au_ninodes(sb);
79b8bda9 28639+ return au_array_alloc(max, au_iarray_cb, sb, &sb->s_inodes);
7f207e10
AM
28640+}
28641+
28642+void au_iarray_free(struct inode **a, unsigned long long max)
28643+{
28644+ unsigned long long ull;
28645+
28646+ for (ull = 0; ull < max; ull++)
28647+ iput(a[ull]);
be52b249 28648+ kvfree(a);
7f207e10
AM
28649+}
28650+
28651+/* ---------------------------------------------------------------------- */
28652+
1facf9fc 28653+/*
28654+ * refresh dentry and inode at remount time.
28655+ */
027c5e7a
AM
28656+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */
28657+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
28658+ struct dentry *parent)
1facf9fc 28659+{
28660+ int err;
1facf9fc 28661+
28662+ di_write_lock_child(dentry);
1facf9fc 28663+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
28664+ err = au_refresh_dentry(dentry, parent);
28665+ if (!err && dir_flags)
5527c038 28666+ au_hn_reset(d_inode(dentry), dir_flags);
1facf9fc 28667+ di_read_unlock(parent, AuLock_IR);
1facf9fc 28668+ di_write_unlock(dentry);
28669+
28670+ return err;
28671+}
28672+
027c5e7a
AM
28673+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
28674+ struct au_sbinfo *sbinfo,
b95c5147 28675+ const unsigned int dir_flags, unsigned int do_idop)
1facf9fc 28676+{
027c5e7a
AM
28677+ int err;
28678+ struct dentry *parent;
027c5e7a
AM
28679+
28680+ err = 0;
28681+ parent = dget_parent(dentry);
28682+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) {
5527c038
JR
28683+ if (d_really_is_positive(dentry)) {
28684+ if (!d_is_dir(dentry))
027c5e7a
AM
28685+ err = au_do_refresh(dentry, /*dir_flags*/0,
28686+ parent);
28687+ else {
28688+ err = au_do_refresh(dentry, dir_flags, parent);
28689+ if (unlikely(err))
28690+ au_fset_si(sbinfo, FAILED_REFRESH_DIR);
28691+ }
28692+ } else
28693+ err = au_do_refresh(dentry, /*dir_flags*/0, parent);
28694+ AuDbgDentry(dentry);
28695+ }
28696+ dput(parent);
28697+
79b8bda9 28698+ if (!err) {
b95c5147 28699+ if (do_idop)
79b8bda9
AM
28700+ au_refresh_dop(dentry, /*force_reval*/0);
28701+ } else
28702+ au_refresh_dop(dentry, /*force_reval*/1);
28703+
027c5e7a
AM
28704+ AuTraceErr(err);
28705+ return err;
1facf9fc 28706+}
28707+
b95c5147 28708+static int au_refresh_d(struct super_block *sb, unsigned int do_idop)
1facf9fc 28709+{
28710+ int err, i, j, ndentry, e;
027c5e7a 28711+ unsigned int sigen;
1facf9fc 28712+ struct au_dcsub_pages dpages;
28713+ struct au_dpage *dpage;
027c5e7a
AM
28714+ struct dentry **dentries, *d;
28715+ struct au_sbinfo *sbinfo;
28716+ struct dentry *root = sb->s_root;
5527c038 28717+ const unsigned int dir_flags = au_hi_flags(d_inode(root), /*isdir*/1);
1facf9fc 28718+
b95c5147 28719+ if (do_idop)
79b8bda9
AM
28720+ au_refresh_dop(root, /*force_reval*/0);
28721+
027c5e7a
AM
28722+ err = au_dpages_init(&dpages, GFP_NOFS);
28723+ if (unlikely(err))
1facf9fc 28724+ goto out;
027c5e7a
AM
28725+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
28726+ if (unlikely(err))
1facf9fc 28727+ goto out_dpages;
1facf9fc 28728+
027c5e7a
AM
28729+ sigen = au_sigen(sb);
28730+ sbinfo = au_sbi(sb);
28731+ for (i = 0; i < dpages.ndpage; i++) {
1facf9fc 28732+ dpage = dpages.dpages + i;
28733+ dentries = dpage->dentries;
28734+ ndentry = dpage->ndentry;
027c5e7a 28735+ for (j = 0; j < ndentry; j++) {
1facf9fc 28736+ d = dentries[j];
79b8bda9 28737+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags,
b95c5147 28738+ do_idop);
027c5e7a
AM
28739+ if (unlikely(e && !err))
28740+ err = e;
28741+ /* go on even err */
1facf9fc 28742+ }
28743+ }
28744+
4f0767ce 28745+out_dpages:
1facf9fc 28746+ au_dpages_free(&dpages);
4f0767ce 28747+out:
1facf9fc 28748+ return err;
28749+}
28750+
b95c5147 28751+static int au_refresh_i(struct super_block *sb, unsigned int do_idop)
1facf9fc 28752+{
027c5e7a
AM
28753+ int err, e;
28754+ unsigned int sigen;
28755+ unsigned long long max, ull;
28756+ struct inode *inode, **array;
1facf9fc 28757+
027c5e7a
AM
28758+ array = au_iarray_alloc(sb, &max);
28759+ err = PTR_ERR(array);
28760+ if (IS_ERR(array))
28761+ goto out;
1facf9fc 28762+
28763+ err = 0;
027c5e7a
AM
28764+ sigen = au_sigen(sb);
28765+ for (ull = 0; ull < max; ull++) {
28766+ inode = array[ull];
076b876e
AM
28767+ if (unlikely(!inode))
28768+ break;
b95c5147
AM
28769+
28770+ e = 0;
28771+ ii_write_lock_child(inode);
537831f9 28772+ if (au_iigen(inode, NULL) != sigen) {
027c5e7a 28773+ e = au_refresh_hinode_self(inode);
1facf9fc 28774+ if (unlikely(e)) {
b95c5147 28775+ au_refresh_iop(inode, /*force_getattr*/1);
027c5e7a 28776+ pr_err("error %d, i%lu\n", e, inode->i_ino);
1facf9fc 28777+ if (!err)
28778+ err = e;
28779+ /* go on even if err */
28780+ }
28781+ }
b95c5147
AM
28782+ if (!e && do_idop)
28783+ au_refresh_iop(inode, /*force_getattr*/0);
28784+ ii_write_unlock(inode);
1facf9fc 28785+ }
28786+
027c5e7a 28787+ au_iarray_free(array, max);
1facf9fc 28788+
4f0767ce 28789+out:
1facf9fc 28790+ return err;
28791+}
28792+
b95c5147 28793+static void au_remount_refresh(struct super_block *sb, unsigned int do_idop)
1facf9fc 28794+{
027c5e7a
AM
28795+ int err, e;
28796+ unsigned int udba;
5afbbe0d 28797+ aufs_bindex_t bindex, bbot;
1facf9fc 28798+ struct dentry *root;
28799+ struct inode *inode;
027c5e7a 28800+ struct au_branch *br;
79b8bda9 28801+ struct au_sbinfo *sbi;
1facf9fc 28802+
28803+ au_sigen_inc(sb);
79b8bda9
AM
28804+ sbi = au_sbi(sb);
28805+ au_fclr_si(sbi, FAILED_REFRESH_DIR);
1facf9fc 28806+
28807+ root = sb->s_root;
28808+ DiMustNoWaiters(root);
5527c038 28809+ inode = d_inode(root);
1facf9fc 28810+ IiMustNoWaiters(inode);
1facf9fc 28811+
027c5e7a 28812+ udba = au_opt_udba(sb);
5afbbe0d
AM
28813+ bbot = au_sbbot(sb);
28814+ for (bindex = 0; bindex <= bbot; bindex++) {
027c5e7a
AM
28815+ br = au_sbr(sb, bindex);
28816+ err = au_hnotify_reset_br(udba, br, br->br_perm);
1facf9fc 28817+ if (unlikely(err))
027c5e7a
AM
28818+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
28819+ bindex, err);
28820+ /* go on even if err */
1facf9fc 28821+ }
027c5e7a 28822+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 28823+
b95c5147 28824+ if (do_idop) {
79b8bda9
AM
28825+ if (au_ftest_si(sbi, NO_DREVAL)) {
28826+ AuDebugOn(sb->s_d_op == &aufs_dop_noreval);
28827+ sb->s_d_op = &aufs_dop_noreval;
b95c5147
AM
28828+ AuDebugOn(sbi->si_iop_array == aufs_iop_nogetattr);
28829+ sbi->si_iop_array = aufs_iop_nogetattr;
79b8bda9
AM
28830+ } else {
28831+ AuDebugOn(sb->s_d_op == &aufs_dop);
28832+ sb->s_d_op = &aufs_dop;
b95c5147
AM
28833+ AuDebugOn(sbi->si_iop_array == aufs_iop);
28834+ sbi->si_iop_array = aufs_iop;
79b8bda9 28835+ }
b95c5147
AM
28836+ pr_info("reset to %pf and %pf\n",
28837+ sb->s_d_op, sbi->si_iop_array);
79b8bda9
AM
28838+ }
28839+
027c5e7a 28840+ di_write_unlock(root);
b95c5147
AM
28841+ err = au_refresh_d(sb, do_idop);
28842+ e = au_refresh_i(sb, do_idop);
027c5e7a
AM
28843+ if (unlikely(e && !err))
28844+ err = e;
1facf9fc 28845+ /* aufs_write_lock() calls ..._child() */
28846+ di_write_lock_child(root);
027c5e7a
AM
28847+
28848+ au_cpup_attr_all(inode, /*force*/1);
28849+
28850+ if (unlikely(err))
28851+ AuIOErr("refresh failed, ignored, %d\n", err);
1facf9fc 28852+}
28853+
28854+/* stop extra interpretation of errno in mount(8), and strange error messages */
28855+static int cvt_err(int err)
28856+{
28857+ AuTraceErr(err);
28858+
28859+ switch (err) {
28860+ case -ENOENT:
28861+ case -ENOTDIR:
28862+ case -EEXIST:
28863+ case -EIO:
28864+ err = -EINVAL;
28865+ }
28866+ return err;
28867+}
28868+
28869+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
28870+{
4a4d8108
AM
28871+ int err, do_dx;
28872+ unsigned int mntflags;
be52b249
AM
28873+ struct au_opts opts = {
28874+ .opt = NULL
28875+ };
1facf9fc 28876+ struct dentry *root;
28877+ struct inode *inode;
28878+ struct au_sbinfo *sbinfo;
28879+
28880+ err = 0;
28881+ root = sb->s_root;
28882+ if (!data || !*data) {
e49829fe
JR
28883+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
28884+ if (!err) {
28885+ di_write_lock_child(root);
28886+ err = au_opts_verify(sb, *flags, /*pending*/0);
28887+ aufs_write_unlock(root);
28888+ }
1facf9fc 28889+ goto out;
28890+ }
28891+
28892+ err = -ENOMEM;
1facf9fc 28893+ opts.opt = (void *)__get_free_page(GFP_NOFS);
28894+ if (unlikely(!opts.opt))
28895+ goto out;
28896+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
28897+ opts.flags = AuOpts_REMOUNT;
28898+ opts.sb_flags = *flags;
28899+
28900+ /* parse it before aufs lock */
28901+ err = au_opts_parse(sb, data, &opts);
28902+ if (unlikely(err))
28903+ goto out_opts;
28904+
28905+ sbinfo = au_sbi(sb);
5527c038 28906+ inode = d_inode(root);
febd17d6 28907+ inode_lock(inode);
e49829fe
JR
28908+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
28909+ if (unlikely(err))
28910+ goto out_mtx;
28911+ di_write_lock_child(root);
1facf9fc 28912+
28913+ /* au_opts_remount() may return an error */
28914+ err = au_opts_remount(sb, &opts);
28915+ au_opts_free(&opts);
28916+
027c5e7a 28917+ if (au_ftest_opts(opts.flags, REFRESH))
b95c5147 28918+ au_remount_refresh(sb, au_ftest_opts(opts.flags, REFRESH_IDOP));
1facf9fc 28919+
4a4d8108
AM
28920+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
28921+ mntflags = au_mntflags(sb);
28922+ do_dx = !!au_opt_test(mntflags, DIO);
28923+ au_dy_arefresh(do_dx);
28924+ }
28925+
076b876e 28926+ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */
1facf9fc 28927+ aufs_write_unlock(root);
953406b4 28928+
e49829fe 28929+out_mtx:
febd17d6 28930+ inode_unlock(inode);
4f0767ce 28931+out_opts:
1c60b727 28932+ free_page((unsigned long)opts.opt);
4f0767ce 28933+out:
1facf9fc 28934+ err = cvt_err(err);
28935+ AuTraceErr(err);
28936+ return err;
28937+}
28938+
4a4d8108 28939+static const struct super_operations aufs_sop = {
1facf9fc 28940+ .alloc_inode = aufs_alloc_inode,
28941+ .destroy_inode = aufs_destroy_inode,
b752ccd1 28942+ /* always deleting, no clearing */
1facf9fc 28943+ .drop_inode = generic_delete_inode,
28944+ .show_options = aufs_show_options,
28945+ .statfs = aufs_statfs,
28946+ .put_super = aufs_put_super,
537831f9 28947+ .sync_fs = aufs_sync_fs,
0b1ff5c3
JR
28948+ .remount_fs = aufs_remount_fs,
28949+#ifdef CONFIG_AUFS_BDEV_LOOP
28950+ .real_loop = aufs_real_loop
28951+#endif
1facf9fc 28952+};
28953+
28954+/* ---------------------------------------------------------------------- */
28955+
28956+static int alloc_root(struct super_block *sb)
28957+{
28958+ int err;
28959+ struct inode *inode;
28960+ struct dentry *root;
28961+
28962+ err = -ENOMEM;
28963+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
28964+ err = PTR_ERR(inode);
28965+ if (IS_ERR(inode))
28966+ goto out;
28967+
b95c5147 28968+ inode->i_op = aufs_iop + AuIop_DIR; /* with getattr by default */
1facf9fc 28969+ inode->i_fop = &aufs_dir_fop;
28970+ inode->i_mode = S_IFDIR;
9dbd164d 28971+ set_nlink(inode, 2);
1facf9fc 28972+ unlock_new_inode(inode);
28973+
92d182d2 28974+ root = d_make_root(inode);
1facf9fc 28975+ if (unlikely(!root))
92d182d2 28976+ goto out;
1facf9fc 28977+ err = PTR_ERR(root);
28978+ if (IS_ERR(root))
92d182d2 28979+ goto out;
1facf9fc 28980+
4a4d8108 28981+ err = au_di_init(root);
1facf9fc 28982+ if (!err) {
28983+ sb->s_root = root;
28984+ return 0; /* success */
28985+ }
28986+ dput(root);
1facf9fc 28987+
4f0767ce 28988+out:
1facf9fc 28989+ return err;
1facf9fc 28990+}
28991+
28992+static int aufs_fill_super(struct super_block *sb, void *raw_data,
28993+ int silent __maybe_unused)
28994+{
28995+ int err;
be52b249
AM
28996+ struct au_opts opts = {
28997+ .opt = NULL
28998+ };
79b8bda9 28999+ struct au_sbinfo *sbinfo;
1facf9fc 29000+ struct dentry *root;
29001+ struct inode *inode;
29002+ char *arg = raw_data;
29003+
29004+ if (unlikely(!arg || !*arg)) {
29005+ err = -EINVAL;
4a4d8108 29006+ pr_err("no arg\n");
1facf9fc 29007+ goto out;
29008+ }
29009+
29010+ err = -ENOMEM;
1facf9fc 29011+ opts.opt = (void *)__get_free_page(GFP_NOFS);
29012+ if (unlikely(!opts.opt))
29013+ goto out;
29014+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
29015+ opts.sb_flags = sb->s_flags;
29016+
29017+ err = au_si_alloc(sb);
29018+ if (unlikely(err))
29019+ goto out_opts;
79b8bda9 29020+ sbinfo = au_sbi(sb);
1facf9fc 29021+
29022+ /* all timestamps always follow the ones on the branch */
29023+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
29024+ sb->s_op = &aufs_sop;
027c5e7a 29025+ sb->s_d_op = &aufs_dop;
1facf9fc 29026+ sb->s_magic = AUFS_SUPER_MAGIC;
29027+ sb->s_maxbytes = 0;
c1595e42 29028+ sb->s_stack_depth = 1;
1facf9fc 29029+ au_export_init(sb);
f2c43d5f 29030+ au_xattr_init(sb);
1facf9fc 29031+
29032+ err = alloc_root(sb);
29033+ if (unlikely(err)) {
29034+ si_write_unlock(sb);
29035+ goto out_info;
29036+ }
29037+ root = sb->s_root;
5527c038 29038+ inode = d_inode(root);
1facf9fc 29039+
29040+ /*
29041+ * actually we can parse options regardless aufs lock here.
29042+ * but at remount time, parsing must be done before aufs lock.
29043+ * so we follow the same rule.
29044+ */
29045+ ii_write_lock_parent(inode);
29046+ aufs_write_unlock(root);
29047+ err = au_opts_parse(sb, arg, &opts);
29048+ if (unlikely(err))
29049+ goto out_root;
29050+
29051+ /* lock vfs_inode first, then aufs. */
febd17d6 29052+ inode_lock(inode);
1facf9fc 29053+ aufs_write_lock(root);
29054+ err = au_opts_mount(sb, &opts);
29055+ au_opts_free(&opts);
79b8bda9
AM
29056+ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) {
29057+ sb->s_d_op = &aufs_dop_noreval;
29058+ pr_info("%pf\n", sb->s_d_op);
29059+ au_refresh_dop(root, /*force_reval*/0);
b95c5147
AM
29060+ sbinfo->si_iop_array = aufs_iop_nogetattr;
29061+ au_refresh_iop(inode, /*force_getattr*/0);
79b8bda9 29062+ }
1facf9fc 29063+ aufs_write_unlock(root);
febd17d6 29064+ inode_unlock(inode);
4a4d8108
AM
29065+ if (!err)
29066+ goto out_opts; /* success */
1facf9fc 29067+
4f0767ce 29068+out_root:
1facf9fc 29069+ dput(root);
29070+ sb->s_root = NULL;
4f0767ce 29071+out_info:
79b8bda9
AM
29072+ dbgaufs_si_fin(sbinfo);
29073+ kobject_put(&sbinfo->si_kobj);
1facf9fc 29074+ sb->s_fs_info = NULL;
4f0767ce 29075+out_opts:
1c60b727 29076+ free_page((unsigned long)opts.opt);
4f0767ce 29077+out:
1facf9fc 29078+ AuTraceErr(err);
29079+ err = cvt_err(err);
29080+ AuTraceErr(err);
29081+ return err;
29082+}
29083+
29084+/* ---------------------------------------------------------------------- */
29085+
027c5e7a
AM
29086+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
29087+ const char *dev_name __maybe_unused,
29088+ void *raw_data)
1facf9fc 29089+{
027c5e7a 29090+ struct dentry *root;
1facf9fc 29091+ struct super_block *sb;
29092+
29093+ /* all timestamps always follow the ones on the branch */
29094+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
027c5e7a
AM
29095+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
29096+ if (IS_ERR(root))
29097+ goto out;
29098+
29099+ sb = root->d_sb;
29100+ si_write_lock(sb, !AuLock_FLUSH);
29101+ sysaufs_brs_add(sb, 0);
29102+ si_write_unlock(sb);
29103+ au_sbilist_add(sb);
29104+
29105+out:
29106+ return root;
1facf9fc 29107+}
29108+
e49829fe
JR
29109+static void aufs_kill_sb(struct super_block *sb)
29110+{
29111+ struct au_sbinfo *sbinfo;
29112+
29113+ sbinfo = au_sbi(sb);
29114+ if (sbinfo) {
29115+ au_sbilist_del(sb);
29116+ aufs_write_lock(sb->s_root);
076b876e 29117+ au_fhsm_fin(sb);
e49829fe
JR
29118+ if (sbinfo->si_wbr_create_ops->fin)
29119+ sbinfo->si_wbr_create_ops->fin(sb);
29120+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
29121+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
b95c5147 29122+ au_remount_refresh(sb, /*do_idop*/0);
e49829fe
JR
29123+ }
29124+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
29125+ au_plink_put(sb, /*verbose*/1);
29126+ au_xino_clr(sb);
8b6a4947 29127+ au_dr_opt_flush(sb);
1e00d052 29128+ sbinfo->si_sb = NULL;
e49829fe 29129+ aufs_write_unlock(sb->s_root);
e49829fe
JR
29130+ au_nwt_flush(&sbinfo->si_nowait);
29131+ }
98d9a5b1 29132+ kill_anon_super(sb);
e49829fe
JR
29133+}
29134+
1facf9fc 29135+struct file_system_type aufs_fs_type = {
29136+ .name = AUFS_FSTYPE,
c06a8ce3
AM
29137+ /* a race between rename and others */
29138+ .fs_flags = FS_RENAME_DOES_D_MOVE,
027c5e7a 29139+ .mount = aufs_mount,
e49829fe 29140+ .kill_sb = aufs_kill_sb,
1facf9fc 29141+ /* no need to __module_get() and module_put(). */
29142+ .owner = THIS_MODULE,
29143+};
0b1ff5c3
JR
29144diff -urNp -x '*.orig' linux-4.14/fs/aufs/super.h linux-4.14/fs/aufs/super.h
29145--- linux-4.14/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
29146+++ linux-4.14/fs/aufs/super.h 2021-02-24 21:42:43.444448075 +0100
8b6a4947 29147@@ -0,0 +1,626 @@
1facf9fc 29148+/*
a2654f78 29149+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 29150+ *
29151+ * This program, aufs is free software; you can redistribute it and/or modify
29152+ * it under the terms of the GNU General Public License as published by
29153+ * the Free Software Foundation; either version 2 of the License, or
29154+ * (at your option) any later version.
dece6358
AM
29155+ *
29156+ * This program is distributed in the hope that it will be useful,
29157+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29158+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29159+ * GNU General Public License for more details.
29160+ *
29161+ * You should have received a copy of the GNU General Public License
523b37e3 29162+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29163+ */
29164+
29165+/*
29166+ * super_block operations
29167+ */
29168+
29169+#ifndef __AUFS_SUPER_H__
29170+#define __AUFS_SUPER_H__
29171+
29172+#ifdef __KERNEL__
29173+
29174+#include <linux/fs.h>
5527c038 29175+#include <linux/kobject.h>
8b6a4947 29176+#include "hbl.h"
1facf9fc 29177+#include "rwsem.h"
1facf9fc 29178+#include "wkq.h"
29179+
1facf9fc 29180+/* policies to select one among multiple writable branches */
29181+struct au_wbr_copyup_operations {
29182+ int (*copyup)(struct dentry *dentry);
29183+};
29184+
392086de
AM
29185+#define AuWbr_DIR 1 /* target is a dir */
29186+#define AuWbr_PARENT (1 << 1) /* always require a parent */
29187+
29188+#define au_ftest_wbr(flags, name) ((flags) & AuWbr_##name)
29189+#define au_fset_wbr(flags, name) { (flags) |= AuWbr_##name; }
29190+#define au_fclr_wbr(flags, name) { (flags) &= ~AuWbr_##name; }
29191+
1facf9fc 29192+struct au_wbr_create_operations {
392086de 29193+ int (*create)(struct dentry *dentry, unsigned int flags);
1facf9fc 29194+ int (*init)(struct super_block *sb);
29195+ int (*fin)(struct super_block *sb);
29196+};
29197+
29198+struct au_wbr_mfs {
29199+ struct mutex mfs_lock; /* protect this structure */
29200+ unsigned long mfs_jiffy;
29201+ unsigned long mfs_expire;
29202+ aufs_bindex_t mfs_bindex;
29203+
29204+ unsigned long long mfsrr_bytes;
29205+ unsigned long long mfsrr_watermark;
29206+};
29207+
86dc4139
AM
29208+#define AuPlink_NHASH 100
29209+static inline int au_plink_hash(ino_t ino)
29210+{
29211+ return ino % AuPlink_NHASH;
29212+}
29213+
076b876e
AM
29214+/* File-based Hierarchical Storage Management */
29215+struct au_fhsm {
29216+#ifdef CONFIG_AUFS_FHSM
29217+ /* allow only one process who can receive the notification */
29218+ spinlock_t fhsm_spin;
29219+ pid_t fhsm_pid;
29220+ wait_queue_head_t fhsm_wqh;
29221+ atomic_t fhsm_readable;
29222+
c1595e42 29223+ /* these are protected by si_rwsem */
076b876e 29224+ unsigned long fhsm_expire;
c1595e42 29225+ aufs_bindex_t fhsm_bottom;
076b876e
AM
29226+#endif
29227+};
29228+
1facf9fc 29229+struct au_branch;
29230+struct au_sbinfo {
29231+ /* nowait tasks in the system-wide workqueue */
29232+ struct au_nowait_tasks si_nowait;
29233+
b752ccd1
AM
29234+ /*
29235+ * tried sb->s_umount, but failed due to the dependecy between i_mutex.
29236+ * rwsem for au_sbinfo is necessary.
29237+ */
dece6358 29238+ struct au_rwsem si_rwsem;
1facf9fc 29239+
7f207e10 29240+ /*
523b37e3
AM
29241+ * dirty approach to protect sb->sb_inodes and ->s_files (gone) from
29242+ * remount.
7f207e10 29243+ */
5afbbe0d 29244+ struct percpu_counter si_ninodes, si_nfiles;
7f207e10 29245+
1facf9fc 29246+ /* branch management */
29247+ unsigned int si_generation;
29248+
2000de60 29249+ /* see AuSi_ flags */
1facf9fc 29250+ unsigned char au_si_status;
29251+
5afbbe0d 29252+ aufs_bindex_t si_bbot;
7f207e10
AM
29253+
29254+ /* dirty trick to keep br_id plus */
29255+ unsigned int si_last_br_id :
29256+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
1facf9fc 29257+ struct au_branch **si_branch;
29258+
29259+ /* policy to select a writable branch */
29260+ unsigned char si_wbr_copyup;
29261+ unsigned char si_wbr_create;
29262+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
29263+ struct au_wbr_create_operations *si_wbr_create_ops;
29264+
29265+ /* round robin */
29266+ atomic_t si_wbr_rr_next;
29267+
29268+ /* most free space */
29269+ struct au_wbr_mfs si_wbr_mfs;
29270+
076b876e
AM
29271+ /* File-based Hierarchical Storage Management */
29272+ struct au_fhsm si_fhsm;
29273+
1facf9fc 29274+ /* mount flags */
29275+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
29276+ unsigned int si_mntflags;
29277+
29278+ /* external inode number (bitmap and translation table) */
5527c038
JR
29279+ vfs_readf_t si_xread;
29280+ vfs_writef_t si_xwrite;
1facf9fc 29281+ struct file *si_xib;
29282+ struct mutex si_xib_mtx; /* protect xib members */
29283+ unsigned long *si_xib_buf;
29284+ unsigned long si_xib_last_pindex;
29285+ int si_xib_next_bit;
29286+ aufs_bindex_t si_xino_brid;
392086de
AM
29287+ unsigned long si_xino_jiffy;
29288+ unsigned long si_xino_expire;
1facf9fc 29289+ /* reserved for future use */
29290+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
29291+
29292+#ifdef CONFIG_AUFS_EXPORT
29293+ /* i_generation */
29294+ struct file *si_xigen;
29295+ atomic_t si_xigen_next;
29296+#endif
29297+
b912730e 29298+ /* dirty trick to suppoer atomic_open */
8b6a4947 29299+ struct hlist_bl_head si_aopen;
b912730e 29300+
1facf9fc 29301+ /* vdir parameters */
e49829fe 29302+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 29303+ unsigned int si_rdblk; /* deblk size */
29304+ unsigned int si_rdhash; /* hash size */
29305+
29306+ /*
29307+ * If the number of whiteouts are larger than si_dirwh, leave all of
29308+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
29309+ * future fsck.aufs or kernel thread will remove them later.
29310+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
29311+ */
29312+ unsigned int si_dirwh;
29313+
1facf9fc 29314+ /* pseudo_link list */
8b6a4947 29315+ struct hlist_bl_head si_plink[AuPlink_NHASH];
1facf9fc 29316+ wait_queue_head_t si_plink_wq;
4a4d8108 29317+ spinlock_t si_plink_maint_lock;
e49829fe 29318+ pid_t si_plink_maint_pid;
1facf9fc 29319+
523b37e3 29320+ /* file list */
8b6a4947 29321+ struct hlist_bl_head si_files;
523b37e3 29322+
b95c5147
AM
29323+ /* with/without getattr, brother of sb->s_d_op */
29324+ struct inode_operations *si_iop_array;
29325+
1facf9fc 29326+ /*
29327+ * sysfs and lifetime management.
29328+ * this is not a small structure and it may be a waste of memory in case
29329+ * of sysfs is disabled, particulary when many aufs-es are mounted.
29330+ * but using sysfs is majority.
29331+ */
29332+ struct kobject si_kobj;
29333+#ifdef CONFIG_DEBUG_FS
86dc4139
AM
29334+ struct dentry *si_dbgaufs;
29335+ struct dentry *si_dbgaufs_plink;
29336+ struct dentry *si_dbgaufs_xib;
1facf9fc 29337+#ifdef CONFIG_AUFS_EXPORT
29338+ struct dentry *si_dbgaufs_xigen;
29339+#endif
29340+#endif
29341+
e49829fe 29342+#ifdef CONFIG_AUFS_SBILIST
8b6a4947 29343+ struct hlist_bl_node si_list;
e49829fe
JR
29344+#endif
29345+
1facf9fc 29346+ /* dirty, necessary for unmounting, sysfs and sysrq */
29347+ struct super_block *si_sb;
29348+};
29349+
dece6358
AM
29350+/* sbinfo status flags */
29351+/*
29352+ * set true when refresh_dirs() failed at remount time.
29353+ * then try refreshing dirs at access time again.
29354+ * if it is false, refreshing dirs at access time is unnecesary
29355+ */
027c5e7a 29356+#define AuSi_FAILED_REFRESH_DIR 1
076b876e 29357+#define AuSi_FHSM (1 << 1) /* fhsm is active now */
79b8bda9 29358+#define AuSi_NO_DREVAL (1 << 2) /* disable all d_revalidate */
076b876e
AM
29359+
29360+#ifndef CONFIG_AUFS_FHSM
29361+#undef AuSi_FHSM
29362+#define AuSi_FHSM 0
29363+#endif
29364+
dece6358
AM
29365+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
29366+ unsigned int flag)
29367+{
29368+ AuRwMustAnyLock(&sbi->si_rwsem);
29369+ return sbi->au_si_status & flag;
29370+}
29371+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
29372+#define au_fset_si(sbinfo, name) do { \
29373+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
29374+ (sbinfo)->au_si_status |= AuSi_##name; \
29375+} while (0)
29376+#define au_fclr_si(sbinfo, name) do { \
29377+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
29378+ (sbinfo)->au_si_status &= ~AuSi_##name; \
29379+} while (0)
29380+
1facf9fc 29381+/* ---------------------------------------------------------------------- */
29382+
29383+/* policy to select one among writable branches */
4a4d8108
AM
29384+#define AuWbrCopyup(sbinfo, ...) \
29385+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
29386+#define AuWbrCreate(sbinfo, ...) \
29387+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 29388+
29389+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
29390+#define AuLock_DW 1 /* write-lock dentry */
29391+#define AuLock_IR (1 << 1) /* read-lock inode */
29392+#define AuLock_IW (1 << 2) /* write-lock inode */
29393+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
b95c5147 29394+#define AuLock_DIRS (1 << 4) /* target is a pair of dirs */
f2c43d5f 29395+ /* except RENAME_EXCHANGE */
e49829fe
JR
29396+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
29397+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
027c5e7a 29398+#define AuLock_GEN (1 << 7) /* test digen/iigen */
1facf9fc 29399+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
7f207e10
AM
29400+#define au_fset_lock(flags, name) \
29401+ do { (flags) |= AuLock_##name; } while (0)
29402+#define au_fclr_lock(flags, name) \
29403+ do { (flags) &= ~AuLock_##name; } while (0)
1facf9fc 29404+
29405+/* ---------------------------------------------------------------------- */
29406+
29407+/* super.c */
29408+extern struct file_system_type aufs_fs_type;
29409+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
79b8bda9
AM
29410+typedef unsigned long long (*au_arraycb_t)(struct super_block *sb, void *array,
29411+ unsigned long long max, void *arg);
79b8bda9
AM
29412+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb,
29413+ struct super_block *sb, void *arg);
7f207e10
AM
29414+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
29415+void au_iarray_free(struct inode **a, unsigned long long max);
1facf9fc 29416+
29417+/* sbinfo.c */
29418+void au_si_free(struct kobject *kobj);
29419+int au_si_alloc(struct super_block *sb);
e2f27e51 29420+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink);
1facf9fc 29421+
29422+unsigned int au_sigen_inc(struct super_block *sb);
29423+aufs_bindex_t au_new_br_id(struct super_block *sb);
29424+
e49829fe
JR
29425+int si_read_lock(struct super_block *sb, int flags);
29426+int si_write_lock(struct super_block *sb, int flags);
29427+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 29428+void aufs_read_unlock(struct dentry *dentry, int flags);
29429+void aufs_write_lock(struct dentry *dentry);
29430+void aufs_write_unlock(struct dentry *dentry);
e49829fe 29431+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 29432+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
29433+
29434+/* wbr_policy.c */
29435+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
29436+extern struct au_wbr_create_operations au_wbr_create_ops[];
29437+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
c2b27bf2 29438+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex);
5afbbe0d 29439+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop);
c2b27bf2
AM
29440+
29441+/* mvdown.c */
29442+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *arg);
1facf9fc 29443+
076b876e
AM
29444+#ifdef CONFIG_AUFS_FHSM
29445+/* fhsm.c */
29446+
29447+static inline pid_t au_fhsm_pid(struct au_fhsm *fhsm)
29448+{
29449+ pid_t pid;
29450+
29451+ spin_lock(&fhsm->fhsm_spin);
29452+ pid = fhsm->fhsm_pid;
29453+ spin_unlock(&fhsm->fhsm_spin);
29454+
29455+ return pid;
29456+}
29457+
29458+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force);
29459+void au_fhsm_wrote_all(struct super_block *sb, int force);
29460+int au_fhsm_fd(struct super_block *sb, int oflags);
29461+int au_fhsm_br_alloc(struct au_branch *br);
c1595e42 29462+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex);
076b876e
AM
29463+void au_fhsm_fin(struct super_block *sb);
29464+void au_fhsm_init(struct au_sbinfo *sbinfo);
29465+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec);
29466+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo);
29467+#else
29468+AuStubVoid(au_fhsm_wrote, struct super_block *sb, aufs_bindex_t bindex,
29469+ int force)
29470+AuStubVoid(au_fhsm_wrote_all, struct super_block *sb, int force)
29471+AuStub(int, au_fhsm_fd, return -EOPNOTSUPP, struct super_block *sb, int oflags)
c1595e42
JR
29472+AuStub(pid_t, au_fhsm_pid, return 0, struct au_fhsm *fhsm)
29473+AuStubInt0(au_fhsm_br_alloc, struct au_branch *br)
29474+AuStubVoid(au_fhsm_set_bottom, struct super_block *sb, aufs_bindex_t bindex)
076b876e
AM
29475+AuStubVoid(au_fhsm_fin, struct super_block *sb)
29476+AuStubVoid(au_fhsm_init, struct au_sbinfo *sbinfo)
29477+AuStubVoid(au_fhsm_set, struct au_sbinfo *sbinfo, unsigned int sec)
29478+AuStubVoid(au_fhsm_show, struct seq_file *seq, struct au_sbinfo *sbinfo)
29479+#endif
29480+
1facf9fc 29481+/* ---------------------------------------------------------------------- */
29482+
29483+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
29484+{
29485+ return sb->s_fs_info;
29486+}
29487+
29488+/* ---------------------------------------------------------------------- */
29489+
29490+#ifdef CONFIG_AUFS_EXPORT
a2a7ad62 29491+int au_test_nfsd(void);
1facf9fc 29492+void au_export_init(struct super_block *sb);
b752ccd1 29493+void au_xigen_inc(struct inode *inode);
1facf9fc 29494+int au_xigen_new(struct inode *inode);
29495+int au_xigen_set(struct super_block *sb, struct file *base);
29496+void au_xigen_clr(struct super_block *sb);
29497+
29498+static inline int au_busy_or_stale(void)
29499+{
b752ccd1 29500+ if (!au_test_nfsd())
1facf9fc 29501+ return -EBUSY;
29502+ return -ESTALE;
29503+}
29504+#else
b752ccd1 29505+AuStubInt0(au_test_nfsd, void)
a2a7ad62 29506+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1 29507+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108
AM
29508+AuStubInt0(au_xigen_new, struct inode *inode)
29509+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
29510+AuStubVoid(au_xigen_clr, struct super_block *sb)
c1595e42 29511+AuStub(int, au_busy_or_stale, return -EBUSY, void)
1facf9fc 29512+#endif /* CONFIG_AUFS_EXPORT */
29513+
29514+/* ---------------------------------------------------------------------- */
29515+
e49829fe
JR
29516+#ifdef CONFIG_AUFS_SBILIST
29517+/* module.c */
8b6a4947 29518+extern struct hlist_bl_head au_sbilist;
e49829fe
JR
29519+
29520+static inline void au_sbilist_init(void)
29521+{
8b6a4947 29522+ INIT_HLIST_BL_HEAD(&au_sbilist);
e49829fe
JR
29523+}
29524+
29525+static inline void au_sbilist_add(struct super_block *sb)
29526+{
8b6a4947 29527+ au_hbl_add(&au_sbi(sb)->si_list, &au_sbilist);
e49829fe
JR
29528+}
29529+
29530+static inline void au_sbilist_del(struct super_block *sb)
29531+{
8b6a4947 29532+ au_hbl_del(&au_sbi(sb)->si_list, &au_sbilist);
e49829fe 29533+}
53392da6
AM
29534+
29535+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
29536+static inline void au_sbilist_lock(void)
29537+{
8b6a4947 29538+ hlist_bl_lock(&au_sbilist);
53392da6
AM
29539+}
29540+
29541+static inline void au_sbilist_unlock(void)
29542+{
8b6a4947 29543+ hlist_bl_unlock(&au_sbilist);
53392da6
AM
29544+}
29545+#define AuGFP_SBILIST GFP_ATOMIC
29546+#else
29547+AuStubVoid(au_sbilist_lock, void)
29548+AuStubVoid(au_sbilist_unlock, void)
29549+#define AuGFP_SBILIST GFP_NOFS
29550+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
e49829fe
JR
29551+#else
29552+AuStubVoid(au_sbilist_init, void)
c1595e42
JR
29553+AuStubVoid(au_sbilist_add, struct super_block *sb)
29554+AuStubVoid(au_sbilist_del, struct super_block *sb)
53392da6
AM
29555+AuStubVoid(au_sbilist_lock, void)
29556+AuStubVoid(au_sbilist_unlock, void)
29557+#define AuGFP_SBILIST GFP_NOFS
e49829fe
JR
29558+#endif
29559+
29560+/* ---------------------------------------------------------------------- */
29561+
1facf9fc 29562+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
29563+{
dece6358 29564+ /*
c1595e42 29565+ * This function is a dynamic '__init' function actually,
dece6358
AM
29566+ * so the tiny check for si_rwsem is unnecessary.
29567+ */
29568+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 29569+#ifdef CONFIG_DEBUG_FS
29570+ sbinfo->si_dbgaufs = NULL;
86dc4139 29571+ sbinfo->si_dbgaufs_plink = NULL;
1facf9fc 29572+ sbinfo->si_dbgaufs_xib = NULL;
29573+#ifdef CONFIG_AUFS_EXPORT
29574+ sbinfo->si_dbgaufs_xigen = NULL;
29575+#endif
29576+#endif
29577+}
29578+
29579+/* ---------------------------------------------------------------------- */
29580+
a2654f78
AM
29581+/* current->atomic_flags */
29582+/* this value should never corrupt the ones defined in linux/sched.h */
29583+#define PFA_AUFS 7
29584+
29585+TASK_PFA_TEST(AUFS, test_aufs) /* task_test_aufs */
29586+TASK_PFA_SET(AUFS, aufs) /* task_set_aufs */
29587+TASK_PFA_CLEAR(AUFS, aufs) /* task_clear_aufs */
b752ccd1
AM
29588+
29589+static inline int si_pid_test(struct super_block *sb)
29590+{
a2654f78 29591+ return !!task_test_aufs(current);
b752ccd1
AM
29592+}
29593+
29594+static inline void si_pid_clr(struct super_block *sb)
29595+{
a2654f78
AM
29596+ AuDebugOn(!task_test_aufs(current));
29597+ task_clear_aufs(current);
b752ccd1
AM
29598+}
29599+
a2654f78
AM
29600+static inline void si_pid_set(struct super_block *sb)
29601+{
29602+ AuDebugOn(task_test_aufs(current));
29603+ task_set_aufs(current);
29604+}
febd17d6 29605+
b752ccd1
AM
29606+/* ---------------------------------------------------------------------- */
29607+
1facf9fc 29608+/* lock superblock. mainly for entry point functions */
8b6a4947
AM
29609+#define __si_read_lock(sb) au_rw_read_lock(&au_sbi(sb)->si_rwsem)
29610+#define __si_write_lock(sb) au_rw_write_lock(&au_sbi(sb)->si_rwsem)
29611+#define __si_read_trylock(sb) au_rw_read_trylock(&au_sbi(sb)->si_rwsem)
29612+#define __si_write_trylock(sb) au_rw_write_trylock(&au_sbi(sb)->si_rwsem)
29613+/*
29614+#define __si_read_trylock_nested(sb) \
29615+ au_rw_read_trylock_nested(&au_sbi(sb)->si_rwsem)
29616+#define __si_write_trylock_nested(sb) \
29617+ au_rw_write_trylock_nested(&au_sbi(sb)->si_rwsem)
29618+*/
29619+
29620+#define __si_read_unlock(sb) au_rw_read_unlock(&au_sbi(sb)->si_rwsem)
29621+#define __si_write_unlock(sb) au_rw_write_unlock(&au_sbi(sb)->si_rwsem)
29622+#define __si_downgrade_lock(sb) au_rw_dgrade_lock(&au_sbi(sb)->si_rwsem)
1facf9fc 29623+
dece6358
AM
29624+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
29625+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
29626+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
29627+
b752ccd1
AM
29628+static inline void si_noflush_read_lock(struct super_block *sb)
29629+{
29630+ __si_read_lock(sb);
29631+ si_pid_set(sb);
29632+}
29633+
29634+static inline int si_noflush_read_trylock(struct super_block *sb)
29635+{
076b876e
AM
29636+ int locked;
29637+
29638+ locked = __si_read_trylock(sb);
b752ccd1
AM
29639+ if (locked)
29640+ si_pid_set(sb);
29641+ return locked;
29642+}
29643+
29644+static inline void si_noflush_write_lock(struct super_block *sb)
29645+{
29646+ __si_write_lock(sb);
29647+ si_pid_set(sb);
29648+}
29649+
29650+static inline int si_noflush_write_trylock(struct super_block *sb)
29651+{
076b876e
AM
29652+ int locked;
29653+
29654+ locked = __si_write_trylock(sb);
b752ccd1
AM
29655+ if (locked)
29656+ si_pid_set(sb);
29657+ return locked;
29658+}
29659+
7e9cd9fe 29660+#if 0 /* reserved */
1facf9fc 29661+static inline int si_read_trylock(struct super_block *sb, int flags)
29662+{
29663+ if (au_ftest_lock(flags, FLUSH))
29664+ au_nwt_flush(&au_sbi(sb)->si_nowait);
29665+ return si_noflush_read_trylock(sb);
29666+}
e49829fe 29667+#endif
1facf9fc 29668+
b752ccd1
AM
29669+static inline void si_read_unlock(struct super_block *sb)
29670+{
29671+ si_pid_clr(sb);
29672+ __si_read_unlock(sb);
29673+}
29674+
7e9cd9fe 29675+#if 0 /* reserved */
1facf9fc 29676+static inline int si_write_trylock(struct super_block *sb, int flags)
29677+{
29678+ if (au_ftest_lock(flags, FLUSH))
29679+ au_nwt_flush(&au_sbi(sb)->si_nowait);
29680+ return si_noflush_write_trylock(sb);
29681+}
b752ccd1
AM
29682+#endif
29683+
29684+static inline void si_write_unlock(struct super_block *sb)
29685+{
29686+ si_pid_clr(sb);
29687+ __si_write_unlock(sb);
29688+}
29689+
7e9cd9fe 29690+#if 0 /* reserved */
b752ccd1
AM
29691+static inline void si_downgrade_lock(struct super_block *sb)
29692+{
29693+ __si_downgrade_lock(sb);
29694+}
29695+#endif
1facf9fc 29696+
29697+/* ---------------------------------------------------------------------- */
29698+
5afbbe0d 29699+static inline aufs_bindex_t au_sbbot(struct super_block *sb)
1facf9fc 29700+{
dece6358 29701+ SiMustAnyLock(sb);
5afbbe0d 29702+ return au_sbi(sb)->si_bbot;
1facf9fc 29703+}
29704+
29705+static inline unsigned int au_mntflags(struct super_block *sb)
29706+{
dece6358 29707+ SiMustAnyLock(sb);
1facf9fc 29708+ return au_sbi(sb)->si_mntflags;
29709+}
29710+
29711+static inline unsigned int au_sigen(struct super_block *sb)
29712+{
dece6358 29713+ SiMustAnyLock(sb);
1facf9fc 29714+ return au_sbi(sb)->si_generation;
29715+}
29716+
5afbbe0d
AM
29717+static inline unsigned long long au_ninodes(struct super_block *sb)
29718+{
29719+ s64 n = percpu_counter_sum(&au_sbi(sb)->si_ninodes);
29720+
29721+ BUG_ON(n < 0);
29722+ return n;
29723+}
29724+
7f207e10
AM
29725+static inline void au_ninodes_inc(struct super_block *sb)
29726+{
5afbbe0d 29727+ percpu_counter_inc(&au_sbi(sb)->si_ninodes);
7f207e10
AM
29728+}
29729+
29730+static inline void au_ninodes_dec(struct super_block *sb)
29731+{
5afbbe0d
AM
29732+ percpu_counter_dec(&au_sbi(sb)->si_ninodes);
29733+}
29734+
29735+static inline unsigned long long au_nfiles(struct super_block *sb)
29736+{
29737+ s64 n = percpu_counter_sum(&au_sbi(sb)->si_nfiles);
29738+
29739+ BUG_ON(n < 0);
29740+ return n;
7f207e10
AM
29741+}
29742+
29743+static inline void au_nfiles_inc(struct super_block *sb)
29744+{
5afbbe0d 29745+ percpu_counter_inc(&au_sbi(sb)->si_nfiles);
7f207e10
AM
29746+}
29747+
29748+static inline void au_nfiles_dec(struct super_block *sb)
29749+{
5afbbe0d 29750+ percpu_counter_dec(&au_sbi(sb)->si_nfiles);
7f207e10
AM
29751+}
29752+
1facf9fc 29753+static inline struct au_branch *au_sbr(struct super_block *sb,
29754+ aufs_bindex_t bindex)
29755+{
dece6358 29756+ SiMustAnyLock(sb);
1facf9fc 29757+ return au_sbi(sb)->si_branch[0 + bindex];
29758+}
29759+
29760+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
29761+{
dece6358 29762+ SiMustWriteLock(sb);
1facf9fc 29763+ au_sbi(sb)->si_xino_brid = brid;
29764+}
29765+
29766+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
29767+{
dece6358 29768+ SiMustAnyLock(sb);
1facf9fc 29769+ return au_sbi(sb)->si_xino_brid;
29770+}
29771+
29772+#endif /* __KERNEL__ */
29773+#endif /* __AUFS_SUPER_H__ */
0b1ff5c3
JR
29774diff -urNp -x '*.orig' linux-4.14/fs/aufs/sysaufs.c linux-4.14/fs/aufs/sysaufs.c
29775--- linux-4.14/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
29776+++ linux-4.14/fs/aufs/sysaufs.c 2021-02-24 21:42:43.444448075 +0100
523b37e3 29777@@ -0,0 +1,104 @@
1facf9fc 29778+/*
a2654f78 29779+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 29780+ *
29781+ * This program, aufs is free software; you can redistribute it and/or modify
29782+ * it under the terms of the GNU General Public License as published by
29783+ * the Free Software Foundation; either version 2 of the License, or
29784+ * (at your option) any later version.
dece6358
AM
29785+ *
29786+ * This program is distributed in the hope that it will be useful,
29787+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29788+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29789+ * GNU General Public License for more details.
29790+ *
29791+ * You should have received a copy of the GNU General Public License
523b37e3 29792+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29793+ */
29794+
29795+/*
29796+ * sysfs interface and lifetime management
29797+ * they are necessary regardless sysfs is disabled.
29798+ */
29799+
1facf9fc 29800+#include <linux/random.h>
1facf9fc 29801+#include "aufs.h"
29802+
29803+unsigned long sysaufs_si_mask;
e49829fe 29804+struct kset *sysaufs_kset;
1facf9fc 29805+
29806+#define AuSiAttr(_name) { \
29807+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
29808+ .show = sysaufs_si_##_name, \
29809+}
29810+
29811+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
29812+struct attribute *sysaufs_si_attrs[] = {
29813+ &sysaufs_si_attr_xi_path.attr,
29814+ NULL,
29815+};
29816+
4a4d8108 29817+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 29818+ .show = sysaufs_si_show
29819+};
29820+
29821+static struct kobj_type au_sbi_ktype = {
29822+ .release = au_si_free,
29823+ .sysfs_ops = &au_sbi_ops,
29824+ .default_attrs = sysaufs_si_attrs
29825+};
29826+
29827+/* ---------------------------------------------------------------------- */
29828+
29829+int sysaufs_si_init(struct au_sbinfo *sbinfo)
29830+{
29831+ int err;
29832+
e49829fe 29833+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 29834+ /* cf. sysaufs_name() */
29835+ err = kobject_init_and_add
e49829fe 29836+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 29837+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
29838+
29839+ dbgaufs_si_null(sbinfo);
29840+ if (!err) {
29841+ err = dbgaufs_si_init(sbinfo);
29842+ if (unlikely(err))
29843+ kobject_put(&sbinfo->si_kobj);
29844+ }
29845+ return err;
29846+}
29847+
29848+void sysaufs_fin(void)
29849+{
29850+ dbgaufs_fin();
e49829fe
JR
29851+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
29852+ kset_unregister(sysaufs_kset);
1facf9fc 29853+}
29854+
29855+int __init sysaufs_init(void)
29856+{
29857+ int err;
29858+
29859+ do {
29860+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
29861+ } while (!sysaufs_si_mask);
29862+
4a4d8108 29863+ err = -EINVAL;
e49829fe
JR
29864+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
29865+ if (unlikely(!sysaufs_kset))
4a4d8108 29866+ goto out;
e49829fe
JR
29867+ err = PTR_ERR(sysaufs_kset);
29868+ if (IS_ERR(sysaufs_kset))
1facf9fc 29869+ goto out;
e49829fe 29870+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
1facf9fc 29871+ if (unlikely(err)) {
e49829fe 29872+ kset_unregister(sysaufs_kset);
1facf9fc 29873+ goto out;
29874+ }
29875+
29876+ err = dbgaufs_init();
29877+ if (unlikely(err))
29878+ sysaufs_fin();
4f0767ce 29879+out:
1facf9fc 29880+ return err;
29881+}
0b1ff5c3
JR
29882diff -urNp -x '*.orig' linux-4.14/fs/aufs/sysaufs.h linux-4.14/fs/aufs/sysaufs.h
29883--- linux-4.14/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
29884+++ linux-4.14/fs/aufs/sysaufs.h 2021-02-24 21:42:43.444448075 +0100
c1595e42 29885@@ -0,0 +1,101 @@
1facf9fc 29886+/*
a2654f78 29887+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 29888+ *
29889+ * This program, aufs is free software; you can redistribute it and/or modify
29890+ * it under the terms of the GNU General Public License as published by
29891+ * the Free Software Foundation; either version 2 of the License, or
29892+ * (at your option) any later version.
dece6358
AM
29893+ *
29894+ * This program is distributed in the hope that it will be useful,
29895+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29896+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29897+ * GNU General Public License for more details.
29898+ *
29899+ * You should have received a copy of the GNU General Public License
523b37e3 29900+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29901+ */
29902+
29903+/*
29904+ * sysfs interface and mount lifetime management
29905+ */
29906+
29907+#ifndef __SYSAUFS_H__
29908+#define __SYSAUFS_H__
29909+
29910+#ifdef __KERNEL__
29911+
1facf9fc 29912+#include <linux/sysfs.h>
1facf9fc 29913+#include "module.h"
29914+
dece6358
AM
29915+struct super_block;
29916+struct au_sbinfo;
29917+
1facf9fc 29918+struct sysaufs_si_attr {
29919+ struct attribute attr;
29920+ int (*show)(struct seq_file *seq, struct super_block *sb);
29921+};
29922+
29923+/* ---------------------------------------------------------------------- */
29924+
29925+/* sysaufs.c */
29926+extern unsigned long sysaufs_si_mask;
e49829fe 29927+extern struct kset *sysaufs_kset;
1facf9fc 29928+extern struct attribute *sysaufs_si_attrs[];
29929+int sysaufs_si_init(struct au_sbinfo *sbinfo);
29930+int __init sysaufs_init(void);
29931+void sysaufs_fin(void);
29932+
29933+/* ---------------------------------------------------------------------- */
29934+
29935+/* some people doesn't like to show a pointer in kernel */
29936+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
29937+{
29938+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
29939+}
29940+
29941+#define SysaufsSiNamePrefix "si_"
29942+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
29943+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
29944+{
29945+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
29946+ sysaufs_si_id(sbinfo));
29947+}
29948+
29949+struct au_branch;
29950+#ifdef CONFIG_SYSFS
29951+/* sysfs.c */
29952+extern struct attribute_group *sysaufs_attr_group;
29953+
29954+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
29955+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
29956+ char *buf);
076b876e
AM
29957+long au_brinfo_ioctl(struct file *file, unsigned long arg);
29958+#ifdef CONFIG_COMPAT
29959+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg);
29960+#endif
1facf9fc 29961+
29962+void sysaufs_br_init(struct au_branch *br);
29963+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
29964+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
29965+
29966+#define sysaufs_brs_init() do {} while (0)
29967+
29968+#else
29969+#define sysaufs_attr_group NULL
29970+
4a4d8108 29971+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
c1595e42
JR
29972+AuStub(ssize_t, sysaufs_si_show, return 0, struct kobject *kobj,
29973+ struct attribute *attr, char *buf)
4a4d8108
AM
29974+AuStubVoid(sysaufs_br_init, struct au_branch *br)
29975+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
29976+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 29977+
29978+static inline void sysaufs_brs_init(void)
29979+{
29980+ sysaufs_brs = 0;
29981+}
29982+
29983+#endif /* CONFIG_SYSFS */
29984+
29985+#endif /* __KERNEL__ */
29986+#endif /* __SYSAUFS_H__ */
0b1ff5c3
JR
29987diff -urNp -x '*.orig' linux-4.14/fs/aufs/sysfs.c linux-4.14/fs/aufs/sysfs.c
29988--- linux-4.14/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
29989+++ linux-4.14/fs/aufs/sysfs.c 2021-02-24 21:42:43.444448075 +0100
79b8bda9 29990@@ -0,0 +1,376 @@
1facf9fc 29991+/*
a2654f78 29992+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 29993+ *
29994+ * This program, aufs is free software; you can redistribute it and/or modify
29995+ * it under the terms of the GNU General Public License as published by
29996+ * the Free Software Foundation; either version 2 of the License, or
29997+ * (at your option) any later version.
dece6358
AM
29998+ *
29999+ * This program is distributed in the hope that it will be useful,
30000+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30001+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30002+ * GNU General Public License for more details.
30003+ *
30004+ * You should have received a copy of the GNU General Public License
523b37e3 30005+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 30006+ */
30007+
30008+/*
30009+ * sysfs interface
30010+ */
30011+
076b876e 30012+#include <linux/compat.h>
1facf9fc 30013+#include <linux/seq_file.h>
1facf9fc 30014+#include "aufs.h"
30015+
4a4d8108
AM
30016+#ifdef CONFIG_AUFS_FS_MODULE
30017+/* this entry violates the "one line per file" policy of sysfs */
30018+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
30019+ char *buf)
30020+{
30021+ ssize_t err;
30022+ static char *conf =
30023+/* this file is generated at compiling */
30024+#include "conf.str"
30025+ ;
30026+
30027+ err = snprintf(buf, PAGE_SIZE, conf);
30028+ if (unlikely(err >= PAGE_SIZE))
30029+ err = -EFBIG;
30030+ return err;
30031+}
30032+
30033+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
30034+#endif
30035+
1facf9fc 30036+static struct attribute *au_attr[] = {
4a4d8108
AM
30037+#ifdef CONFIG_AUFS_FS_MODULE
30038+ &au_config_attr.attr,
30039+#endif
1facf9fc 30040+ NULL, /* need to NULL terminate the list of attributes */
30041+};
30042+
30043+static struct attribute_group sysaufs_attr_group_body = {
30044+ .attrs = au_attr
30045+};
30046+
30047+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
30048+
30049+/* ---------------------------------------------------------------------- */
30050+
30051+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
30052+{
30053+ int err;
30054+
dece6358
AM
30055+ SiMustAnyLock(sb);
30056+
1facf9fc 30057+ err = 0;
30058+ if (au_opt_test(au_mntflags(sb), XINO)) {
30059+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
30060+ seq_putc(seq, '\n');
30061+ }
30062+ return err;
30063+}
30064+
30065+/*
30066+ * the lifetime of branch is independent from the entry under sysfs.
30067+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
30068+ * unlinked.
30069+ */
30070+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
392086de 30071+ aufs_bindex_t bindex, int idx)
1facf9fc 30072+{
1e00d052 30073+ int err;
1facf9fc 30074+ struct path path;
30075+ struct dentry *root;
30076+ struct au_branch *br;
076b876e 30077+ au_br_perm_str_t perm;
1facf9fc 30078+
30079+ AuDbg("b%d\n", bindex);
30080+
1e00d052 30081+ err = 0;
1facf9fc 30082+ root = sb->s_root;
30083+ di_read_lock_parent(root, !AuLock_IR);
30084+ br = au_sbr(sb, bindex);
392086de
AM
30085+
30086+ switch (idx) {
30087+ case AuBrSysfs_BR:
30088+ path.mnt = au_br_mnt(br);
30089+ path.dentry = au_h_dptr(root, bindex);
79b8bda9
AM
30090+ err = au_seq_path(seq, &path);
30091+ if (!err) {
30092+ au_optstr_br_perm(&perm, br->br_perm);
30093+ seq_printf(seq, "=%s\n", perm.a);
30094+ }
392086de
AM
30095+ break;
30096+ case AuBrSysfs_BRID:
79b8bda9 30097+ seq_printf(seq, "%d\n", br->br_id);
392086de
AM
30098+ break;
30099+ }
076b876e 30100+ di_read_unlock(root, !AuLock_IR);
79b8bda9 30101+ if (unlikely(err || seq_has_overflowed(seq)))
076b876e 30102+ err = -E2BIG;
392086de 30103+
1e00d052 30104+ return err;
1facf9fc 30105+}
30106+
30107+/* ---------------------------------------------------------------------- */
30108+
30109+static struct seq_file *au_seq(char *p, ssize_t len)
30110+{
30111+ struct seq_file *seq;
30112+
30113+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
30114+ if (seq) {
30115+ /* mutex_init(&seq.lock); */
30116+ seq->buf = p;
30117+ seq->size = len;
30118+ return seq; /* success */
30119+ }
30120+
30121+ seq = ERR_PTR(-ENOMEM);
30122+ return seq;
30123+}
30124+
392086de
AM
30125+#define SysaufsBr_PREFIX "br"
30126+#define SysaufsBrid_PREFIX "brid"
1facf9fc 30127+
30128+/* todo: file size may exceed PAGE_SIZE */
30129+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 30130+ char *buf)
1facf9fc 30131+{
30132+ ssize_t err;
392086de 30133+ int idx;
1facf9fc 30134+ long l;
5afbbe0d 30135+ aufs_bindex_t bbot;
1facf9fc 30136+ struct au_sbinfo *sbinfo;
30137+ struct super_block *sb;
30138+ struct seq_file *seq;
30139+ char *name;
30140+ struct attribute **cattr;
30141+
30142+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
30143+ sb = sbinfo->si_sb;
1308ab2a 30144+
30145+ /*
30146+ * prevent a race condition between sysfs and aufs.
30147+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
30148+ * prohibits maintaining the sysfs entries.
30149+ * hew we acquire read lock after sysfs_get_active_two().
30150+ * on the other hand, the remount process may maintain the sysfs/aufs
30151+ * entries after acquiring write lock.
30152+ * it can cause a deadlock.
30153+ * simply we gave up processing read here.
30154+ */
30155+ err = -EBUSY;
30156+ if (unlikely(!si_noflush_read_trylock(sb)))
30157+ goto out;
1facf9fc 30158+
30159+ seq = au_seq(buf, PAGE_SIZE);
30160+ err = PTR_ERR(seq);
30161+ if (IS_ERR(seq))
1308ab2a 30162+ goto out_unlock;
1facf9fc 30163+
30164+ name = (void *)attr->name;
30165+ cattr = sysaufs_si_attrs;
30166+ while (*cattr) {
30167+ if (!strcmp(name, (*cattr)->name)) {
30168+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
30169+ ->show(seq, sb);
30170+ goto out_seq;
30171+ }
30172+ cattr++;
30173+ }
30174+
392086de
AM
30175+ if (!strncmp(name, SysaufsBrid_PREFIX,
30176+ sizeof(SysaufsBrid_PREFIX) - 1)) {
30177+ idx = AuBrSysfs_BRID;
30178+ name += sizeof(SysaufsBrid_PREFIX) - 1;
30179+ } else if (!strncmp(name, SysaufsBr_PREFIX,
30180+ sizeof(SysaufsBr_PREFIX) - 1)) {
30181+ idx = AuBrSysfs_BR;
1facf9fc 30182+ name += sizeof(SysaufsBr_PREFIX) - 1;
392086de
AM
30183+ } else
30184+ BUG();
30185+
30186+ err = kstrtol(name, 10, &l);
30187+ if (!err) {
5afbbe0d
AM
30188+ bbot = au_sbbot(sb);
30189+ if (l <= bbot)
392086de
AM
30190+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l, idx);
30191+ else
30192+ err = -ENOENT;
1facf9fc 30193+ }
1facf9fc 30194+
4f0767ce 30195+out_seq:
1facf9fc 30196+ if (!err) {
30197+ err = seq->count;
30198+ /* sysfs limit */
30199+ if (unlikely(err == PAGE_SIZE))
30200+ err = -EFBIG;
30201+ }
1c60b727 30202+ kfree(seq);
4f0767ce 30203+out_unlock:
1facf9fc 30204+ si_read_unlock(sb);
4f0767ce 30205+out:
1facf9fc 30206+ return err;
30207+}
30208+
30209+/* ---------------------------------------------------------------------- */
30210+
076b876e
AM
30211+static int au_brinfo(struct super_block *sb, union aufs_brinfo __user *arg)
30212+{
30213+ int err;
30214+ int16_t brid;
5afbbe0d 30215+ aufs_bindex_t bindex, bbot;
076b876e
AM
30216+ size_t sz;
30217+ char *buf;
30218+ struct seq_file *seq;
30219+ struct au_branch *br;
30220+
30221+ si_read_lock(sb, AuLock_FLUSH);
5afbbe0d
AM
30222+ bbot = au_sbbot(sb);
30223+ err = bbot + 1;
076b876e
AM
30224+ if (!arg)
30225+ goto out;
30226+
30227+ err = -ENOMEM;
30228+ buf = (void *)__get_free_page(GFP_NOFS);
30229+ if (unlikely(!buf))
30230+ goto out;
30231+
30232+ seq = au_seq(buf, PAGE_SIZE);
30233+ err = PTR_ERR(seq);
30234+ if (IS_ERR(seq))
30235+ goto out_buf;
30236+
30237+ sz = sizeof(*arg) - offsetof(union aufs_brinfo, path);
5afbbe0d 30238+ for (bindex = 0; bindex <= bbot; bindex++, arg++) {
076b876e
AM
30239+ err = !access_ok(VERIFY_WRITE, arg, sizeof(*arg));
30240+ if (unlikely(err))
30241+ break;
30242+
30243+ br = au_sbr(sb, bindex);
30244+ brid = br->br_id;
30245+ BUILD_BUG_ON(sizeof(brid) != sizeof(arg->id));
30246+ err = __put_user(brid, &arg->id);
30247+ if (unlikely(err))
30248+ break;
30249+
30250+ BUILD_BUG_ON(sizeof(br->br_perm) != sizeof(arg->perm));
30251+ err = __put_user(br->br_perm, &arg->perm);
30252+ if (unlikely(err))
30253+ break;
30254+
79b8bda9
AM
30255+ err = au_seq_path(seq, &br->br_path);
30256+ if (unlikely(err))
30257+ break;
30258+ seq_putc(seq, '\0');
30259+ if (!seq_has_overflowed(seq)) {
076b876e
AM
30260+ err = copy_to_user(arg->path, seq->buf, seq->count);
30261+ seq->count = 0;
30262+ if (unlikely(err))
30263+ break;
30264+ } else {
30265+ err = -E2BIG;
30266+ goto out_seq;
30267+ }
30268+ }
30269+ if (unlikely(err))
30270+ err = -EFAULT;
30271+
30272+out_seq:
1c60b727 30273+ kfree(seq);
076b876e 30274+out_buf:
1c60b727 30275+ free_page((unsigned long)buf);
076b876e
AM
30276+out:
30277+ si_read_unlock(sb);
30278+ return err;
30279+}
30280+
30281+long au_brinfo_ioctl(struct file *file, unsigned long arg)
30282+{
2000de60 30283+ return au_brinfo(file->f_path.dentry->d_sb, (void __user *)arg);
076b876e
AM
30284+}
30285+
30286+#ifdef CONFIG_COMPAT
30287+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg)
30288+{
2000de60 30289+ return au_brinfo(file->f_path.dentry->d_sb, compat_ptr(arg));
076b876e
AM
30290+}
30291+#endif
30292+
30293+/* ---------------------------------------------------------------------- */
30294+
1facf9fc 30295+void sysaufs_br_init(struct au_branch *br)
30296+{
392086de
AM
30297+ int i;
30298+ struct au_brsysfs *br_sysfs;
30299+ struct attribute *attr;
4a4d8108 30300+
392086de
AM
30301+ br_sysfs = br->br_sysfs;
30302+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
30303+ attr = &br_sysfs->attr;
30304+ sysfs_attr_init(attr);
30305+ attr->name = br_sysfs->name;
30306+ attr->mode = S_IRUGO;
30307+ br_sysfs++;
30308+ }
1facf9fc 30309+}
30310+
30311+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
30312+{
30313+ struct au_branch *br;
30314+ struct kobject *kobj;
392086de
AM
30315+ struct au_brsysfs *br_sysfs;
30316+ int i;
5afbbe0d 30317+ aufs_bindex_t bbot;
1facf9fc 30318+
30319+ dbgaufs_brs_del(sb, bindex);
30320+
30321+ if (!sysaufs_brs)
30322+ return;
30323+
30324+ kobj = &au_sbi(sb)->si_kobj;
5afbbe0d
AM
30325+ bbot = au_sbbot(sb);
30326+ for (; bindex <= bbot; bindex++) {
1facf9fc 30327+ br = au_sbr(sb, bindex);
392086de
AM
30328+ br_sysfs = br->br_sysfs;
30329+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
30330+ sysfs_remove_file(kobj, &br_sysfs->attr);
30331+ br_sysfs++;
30332+ }
1facf9fc 30333+ }
30334+}
30335+
30336+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
30337+{
392086de 30338+ int err, i;
5afbbe0d 30339+ aufs_bindex_t bbot;
1facf9fc 30340+ struct kobject *kobj;
30341+ struct au_branch *br;
392086de 30342+ struct au_brsysfs *br_sysfs;
1facf9fc 30343+
30344+ dbgaufs_brs_add(sb, bindex);
30345+
30346+ if (!sysaufs_brs)
30347+ return;
30348+
30349+ kobj = &au_sbi(sb)->si_kobj;
5afbbe0d
AM
30350+ bbot = au_sbbot(sb);
30351+ for (; bindex <= bbot; bindex++) {
1facf9fc 30352+ br = au_sbr(sb, bindex);
392086de
AM
30353+ br_sysfs = br->br_sysfs;
30354+ snprintf(br_sysfs[AuBrSysfs_BR].name, sizeof(br_sysfs->name),
30355+ SysaufsBr_PREFIX "%d", bindex);
30356+ snprintf(br_sysfs[AuBrSysfs_BRID].name, sizeof(br_sysfs->name),
30357+ SysaufsBrid_PREFIX "%d", bindex);
30358+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
30359+ err = sysfs_create_file(kobj, &br_sysfs->attr);
30360+ if (unlikely(err))
30361+ pr_warn("failed %s under sysfs(%d)\n",
30362+ br_sysfs->name, err);
30363+ br_sysfs++;
30364+ }
1facf9fc 30365+ }
30366+}
0b1ff5c3
JR
30367diff -urNp -x '*.orig' linux-4.14/fs/aufs/sysrq.c linux-4.14/fs/aufs/sysrq.c
30368--- linux-4.14/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
30369+++ linux-4.14/fs/aufs/sysrq.c 2021-02-24 21:42:43.444448075 +0100
8b6a4947 30370@@ -0,0 +1,159 @@
1facf9fc 30371+/*
a2654f78 30372+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 30373+ *
30374+ * This program, aufs is free software; you can redistribute it and/or modify
30375+ * it under the terms of the GNU General Public License as published by
30376+ * the Free Software Foundation; either version 2 of the License, or
30377+ * (at your option) any later version.
dece6358
AM
30378+ *
30379+ * This program is distributed in the hope that it will be useful,
30380+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30381+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30382+ * GNU General Public License for more details.
30383+ *
30384+ * You should have received a copy of the GNU General Public License
523b37e3 30385+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 30386+ */
30387+
30388+/*
30389+ * magic sysrq hanlder
30390+ */
30391+
1facf9fc 30392+/* #include <linux/sysrq.h> */
027c5e7a 30393+#include <linux/writeback.h>
1facf9fc 30394+#include "aufs.h"
30395+
30396+/* ---------------------------------------------------------------------- */
30397+
30398+static void sysrq_sb(struct super_block *sb)
30399+{
30400+ char *plevel;
30401+ struct au_sbinfo *sbinfo;
30402+ struct file *file;
8b6a4947
AM
30403+ struct hlist_bl_head *files;
30404+ struct hlist_bl_node *pos;
523b37e3 30405+ struct au_finfo *finfo;
1facf9fc 30406+
30407+ plevel = au_plevel;
30408+ au_plevel = KERN_WARNING;
1facf9fc 30409+
4a4d8108 30410+ /* since we define pr_fmt, call printk directly */
c06a8ce3
AM
30411+#define pr(str) printk(KERN_WARNING AUFS_NAME ": " str)
30412+
30413+ sbinfo = au_sbi(sb);
4a4d8108 30414+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
c06a8ce3 30415+ pr("superblock\n");
1facf9fc 30416+ au_dpri_sb(sb);
027c5e7a
AM
30417+
30418+#if 0
c06a8ce3 30419+ pr("root dentry\n");
1facf9fc 30420+ au_dpri_dentry(sb->s_root);
c06a8ce3 30421+ pr("root inode\n");
5527c038 30422+ au_dpri_inode(d_inode(sb->s_root));
027c5e7a
AM
30423+#endif
30424+
1facf9fc 30425+#if 0
027c5e7a
AM
30426+ do {
30427+ int err, i, j, ndentry;
30428+ struct au_dcsub_pages dpages;
30429+ struct au_dpage *dpage;
30430+
30431+ err = au_dpages_init(&dpages, GFP_ATOMIC);
30432+ if (unlikely(err))
30433+ break;
30434+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL);
30435+ if (!err)
30436+ for (i = 0; i < dpages.ndpage; i++) {
30437+ dpage = dpages.dpages + i;
30438+ ndentry = dpage->ndentry;
30439+ for (j = 0; j < ndentry; j++)
30440+ au_dpri_dentry(dpage->dentries[j]);
30441+ }
30442+ au_dpages_free(&dpages);
30443+ } while (0);
30444+#endif
30445+
30446+#if 1
30447+ {
30448+ struct inode *i;
076b876e 30449+
c06a8ce3 30450+ pr("isolated inode\n");
79b8bda9 30451+ spin_lock(&sb->s_inode_list_lock);
2cbb1c4b
JR
30452+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
30453+ spin_lock(&i->i_lock);
b4510431 30454+ if (1 || hlist_empty(&i->i_dentry))
027c5e7a 30455+ au_dpri_inode(i);
2cbb1c4b
JR
30456+ spin_unlock(&i->i_lock);
30457+ }
79b8bda9 30458+ spin_unlock(&sb->s_inode_list_lock);
027c5e7a 30459+ }
1facf9fc 30460+#endif
c06a8ce3 30461+ pr("files\n");
523b37e3 30462+ files = &au_sbi(sb)->si_files;
8b6a4947
AM
30463+ hlist_bl_lock(files);
30464+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) {
4a4d8108 30465+ umode_t mode;
076b876e 30466+
523b37e3 30467+ file = finfo->fi_file;
c06a8ce3 30468+ mode = file_inode(file)->i_mode;
38d290e6 30469+ if (!special_file(mode))
1facf9fc 30470+ au_dpri_file(file);
523b37e3 30471+ }
8b6a4947 30472+ hlist_bl_unlock(files);
c06a8ce3 30473+ pr("done\n");
1facf9fc 30474+
c06a8ce3 30475+#undef pr
1facf9fc 30476+ au_plevel = plevel;
1facf9fc 30477+}
30478+
30479+/* ---------------------------------------------------------------------- */
30480+
30481+/* module parameter */
30482+static char *aufs_sysrq_key = "a";
30483+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
30484+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
30485+
0c5527e5 30486+static void au_sysrq(int key __maybe_unused)
1facf9fc 30487+{
1facf9fc 30488+ struct au_sbinfo *sbinfo;
8b6a4947 30489+ struct hlist_bl_node *pos;
1facf9fc 30490+
027c5e7a 30491+ lockdep_off();
53392da6 30492+ au_sbilist_lock();
8b6a4947 30493+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list)
1facf9fc 30494+ sysrq_sb(sbinfo->si_sb);
53392da6 30495+ au_sbilist_unlock();
027c5e7a 30496+ lockdep_on();
1facf9fc 30497+}
30498+
30499+static struct sysrq_key_op au_sysrq_op = {
30500+ .handler = au_sysrq,
30501+ .help_msg = "Aufs",
30502+ .action_msg = "Aufs",
30503+ .enable_mask = SYSRQ_ENABLE_DUMP
30504+};
30505+
30506+/* ---------------------------------------------------------------------- */
30507+
30508+int __init au_sysrq_init(void)
30509+{
30510+ int err;
30511+ char key;
30512+
30513+ err = -1;
30514+ key = *aufs_sysrq_key;
30515+ if ('a' <= key && key <= 'z')
30516+ err = register_sysrq_key(key, &au_sysrq_op);
30517+ if (unlikely(err))
4a4d8108 30518+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 30519+ return err;
30520+}
30521+
30522+void au_sysrq_fin(void)
30523+{
30524+ int err;
076b876e 30525+
1facf9fc 30526+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
30527+ if (unlikely(err))
4a4d8108 30528+ pr_err("err %d (ignored)\n", err);
1facf9fc 30529+}
0b1ff5c3
JR
30530diff -urNp -x '*.orig' linux-4.14/fs/aufs/vdir.c linux-4.14/fs/aufs/vdir.c
30531--- linux-4.14/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
30532+++ linux-4.14/fs/aufs/vdir.c 2021-02-24 21:42:43.444448075 +0100
1c60b727 30533@@ -0,0 +1,892 @@
1facf9fc 30534+/*
a2654f78 30535+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 30536+ *
30537+ * This program, aufs is free software; you can redistribute it and/or modify
30538+ * it under the terms of the GNU General Public License as published by
30539+ * the Free Software Foundation; either version 2 of the License, or
30540+ * (at your option) any later version.
dece6358
AM
30541+ *
30542+ * This program is distributed in the hope that it will be useful,
30543+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30544+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30545+ * GNU General Public License for more details.
30546+ *
30547+ * You should have received a copy of the GNU General Public License
523b37e3 30548+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 30549+ */
30550+
30551+/*
30552+ * virtual or vertical directory
30553+ */
30554+
30555+#include "aufs.h"
30556+
dece6358 30557+static unsigned int calc_size(int nlen)
1facf9fc 30558+{
dece6358 30559+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 30560+}
30561+
30562+static int set_deblk_end(union au_vdir_deblk_p *p,
30563+ union au_vdir_deblk_p *deblk_end)
30564+{
30565+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
30566+ p->de->de_str.len = 0;
30567+ /* smp_mb(); */
30568+ return 0;
30569+ }
30570+ return -1; /* error */
30571+}
30572+
30573+/* returns true or false */
30574+static int is_deblk_end(union au_vdir_deblk_p *p,
30575+ union au_vdir_deblk_p *deblk_end)
30576+{
30577+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
30578+ return !p->de->de_str.len;
30579+ return 1;
30580+}
30581+
30582+static unsigned char *last_deblk(struct au_vdir *vdir)
30583+{
30584+ return vdir->vd_deblk[vdir->vd_nblk - 1];
30585+}
30586+
30587+/* ---------------------------------------------------------------------- */
30588+
79b8bda9 30589+/* estimate the appropriate size for name hash table */
1308ab2a 30590+unsigned int au_rdhash_est(loff_t sz)
30591+{
30592+ unsigned int n;
30593+
30594+ n = UINT_MAX;
30595+ sz >>= 10;
30596+ if (sz < n)
30597+ n = sz;
30598+ if (sz < AUFS_RDHASH_DEF)
30599+ n = AUFS_RDHASH_DEF;
4a4d8108 30600+ /* pr_info("n %u\n", n); */
1308ab2a 30601+ return n;
30602+}
30603+
1facf9fc 30604+/*
30605+ * the allocated memory has to be freed by
dece6358 30606+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 30607+ */
dece6358 30608+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 30609+{
1facf9fc 30610+ struct hlist_head *head;
dece6358 30611+ unsigned int u;
076b876e 30612+ size_t sz;
1facf9fc 30613+
076b876e
AM
30614+ sz = sizeof(*nhash->nh_head) * num_hash;
30615+ head = kmalloc(sz, gfp);
dece6358
AM
30616+ if (head) {
30617+ nhash->nh_num = num_hash;
30618+ nhash->nh_head = head;
30619+ for (u = 0; u < num_hash; u++)
1facf9fc 30620+ INIT_HLIST_HEAD(head++);
dece6358 30621+ return 0; /* success */
1facf9fc 30622+ }
1facf9fc 30623+
dece6358 30624+ return -ENOMEM;
1facf9fc 30625+}
30626+
dece6358
AM
30627+static void nhash_count(struct hlist_head *head)
30628+{
30629+#if 0
30630+ unsigned long n;
30631+ struct hlist_node *pos;
30632+
30633+ n = 0;
30634+ hlist_for_each(pos, head)
30635+ n++;
4a4d8108 30636+ pr_info("%lu\n", n);
dece6358
AM
30637+#endif
30638+}
30639+
30640+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 30641+{
c06a8ce3
AM
30642+ struct au_vdir_wh *pos;
30643+ struct hlist_node *node;
1facf9fc 30644+
c06a8ce3 30645+ hlist_for_each_entry_safe(pos, node, head, wh_hash)
1c60b727 30646+ kfree(pos);
1facf9fc 30647+}
30648+
dece6358 30649+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 30650+{
c06a8ce3
AM
30651+ struct au_vdir_dehstr *pos;
30652+ struct hlist_node *node;
1facf9fc 30653+
c06a8ce3 30654+ hlist_for_each_entry_safe(pos, node, head, hash)
1c60b727 30655+ au_cache_free_vdir_dehstr(pos);
1facf9fc 30656+}
30657+
dece6358
AM
30658+static void au_nhash_do_free(struct au_nhash *nhash,
30659+ void (*free)(struct hlist_head *head))
1facf9fc 30660+{
1308ab2a 30661+ unsigned int n;
1facf9fc 30662+ struct hlist_head *head;
1facf9fc 30663+
dece6358 30664+ n = nhash->nh_num;
1308ab2a 30665+ if (!n)
30666+ return;
30667+
dece6358 30668+ head = nhash->nh_head;
1308ab2a 30669+ while (n-- > 0) {
dece6358
AM
30670+ nhash_count(head);
30671+ free(head++);
1facf9fc 30672+ }
1c60b727 30673+ kfree(nhash->nh_head);
1facf9fc 30674+}
30675+
dece6358 30676+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 30677+{
dece6358
AM
30678+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
30679+}
1facf9fc 30680+
dece6358
AM
30681+static void au_nhash_de_free(struct au_nhash *delist)
30682+{
30683+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 30684+}
30685+
30686+/* ---------------------------------------------------------------------- */
30687+
30688+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
30689+ int limit)
30690+{
30691+ int num;
30692+ unsigned int u, n;
30693+ struct hlist_head *head;
c06a8ce3 30694+ struct au_vdir_wh *pos;
1facf9fc 30695+
30696+ num = 0;
30697+ n = whlist->nh_num;
30698+ head = whlist->nh_head;
1308ab2a 30699+ for (u = 0; u < n; u++, head++)
c06a8ce3
AM
30700+ hlist_for_each_entry(pos, head, wh_hash)
30701+ if (pos->wh_bindex == btgt && ++num > limit)
1facf9fc 30702+ return 1;
1facf9fc 30703+ return 0;
30704+}
30705+
30706+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 30707+ unsigned char *name,
1facf9fc 30708+ unsigned int len)
30709+{
dece6358
AM
30710+ unsigned int v;
30711+ /* const unsigned int magic_bit = 12; */
30712+
1308ab2a 30713+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
30714+
dece6358 30715+ v = 0;
f0c0a007
AM
30716+ if (len > 8)
30717+ len = 8;
dece6358
AM
30718+ while (len--)
30719+ v += *name++;
30720+ /* v = hash_long(v, magic_bit); */
30721+ v %= nhash->nh_num;
30722+ return nhash->nh_head + v;
30723+}
30724+
30725+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
30726+ int nlen)
30727+{
30728+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 30729+}
30730+
30731+/* returns found or not */
dece6358 30732+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 30733+{
30734+ struct hlist_head *head;
c06a8ce3 30735+ struct au_vdir_wh *pos;
1facf9fc 30736+ struct au_vdir_destr *str;
30737+
dece6358 30738+ head = au_name_hash(whlist, name, nlen);
c06a8ce3
AM
30739+ hlist_for_each_entry(pos, head, wh_hash) {
30740+ str = &pos->wh_str;
1facf9fc 30741+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
30742+ if (au_nhash_test_name(str, name, nlen))
30743+ return 1;
30744+ }
30745+ return 0;
30746+}
30747+
30748+/* returns found(true) or not */
30749+static int test_known(struct au_nhash *delist, char *name, int nlen)
30750+{
30751+ struct hlist_head *head;
c06a8ce3 30752+ struct au_vdir_dehstr *pos;
dece6358
AM
30753+ struct au_vdir_destr *str;
30754+
30755+ head = au_name_hash(delist, name, nlen);
c06a8ce3
AM
30756+ hlist_for_each_entry(pos, head, hash) {
30757+ str = pos->str;
dece6358
AM
30758+ AuDbg("%.*s\n", str->len, str->name);
30759+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 30760+ return 1;
30761+ }
30762+ return 0;
30763+}
30764+
dece6358
AM
30765+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
30766+ unsigned char d_type)
30767+{
30768+#ifdef CONFIG_AUFS_SHWH
30769+ wh->wh_ino = ino;
30770+ wh->wh_type = d_type;
30771+#endif
30772+}
30773+
30774+/* ---------------------------------------------------------------------- */
30775+
30776+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
30777+ unsigned int d_type, aufs_bindex_t bindex,
30778+ unsigned char shwh)
1facf9fc 30779+{
30780+ int err;
30781+ struct au_vdir_destr *str;
30782+ struct au_vdir_wh *wh;
30783+
dece6358 30784+ AuDbg("%.*s\n", nlen, name);
1308ab2a 30785+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
30786+
1facf9fc 30787+ err = -ENOMEM;
dece6358 30788+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 30789+ if (unlikely(!wh))
30790+ goto out;
30791+
30792+ err = 0;
30793+ wh->wh_bindex = bindex;
dece6358
AM
30794+ if (shwh)
30795+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 30796+ str = &wh->wh_str;
dece6358
AM
30797+ str->len = nlen;
30798+ memcpy(str->name, name, nlen);
30799+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 30800+ /* smp_mb(); */
30801+
4f0767ce 30802+out:
1facf9fc 30803+ return err;
30804+}
30805+
1facf9fc 30806+static int append_deblk(struct au_vdir *vdir)
30807+{
30808+ int err;
dece6358 30809+ unsigned long ul;
1facf9fc 30810+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
30811+ union au_vdir_deblk_p p, deblk_end;
30812+ unsigned char **o;
30813+
30814+ err = -ENOMEM;
e2f27e51
AM
30815+ o = au_krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
30816+ GFP_NOFS, /*may_shrink*/0);
1facf9fc 30817+ if (unlikely(!o))
30818+ goto out;
30819+
30820+ vdir->vd_deblk = o;
30821+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
30822+ if (p.deblk) {
30823+ ul = vdir->vd_nblk++;
30824+ vdir->vd_deblk[ul] = p.deblk;
30825+ vdir->vd_last.ul = ul;
30826+ vdir->vd_last.p.deblk = p.deblk;
30827+ deblk_end.deblk = p.deblk + deblk_sz;
30828+ err = set_deblk_end(&p, &deblk_end);
30829+ }
30830+
4f0767ce 30831+out:
1facf9fc 30832+ return err;
30833+}
30834+
dece6358
AM
30835+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
30836+ unsigned int d_type, struct au_nhash *delist)
30837+{
30838+ int err;
30839+ unsigned int sz;
30840+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
30841+ union au_vdir_deblk_p p, *room, deblk_end;
30842+ struct au_vdir_dehstr *dehstr;
30843+
30844+ p.deblk = last_deblk(vdir);
30845+ deblk_end.deblk = p.deblk + deblk_sz;
30846+ room = &vdir->vd_last.p;
30847+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
30848+ || !is_deblk_end(room, &deblk_end));
30849+
30850+ sz = calc_size(nlen);
30851+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
30852+ err = append_deblk(vdir);
30853+ if (unlikely(err))
30854+ goto out;
30855+
30856+ p.deblk = last_deblk(vdir);
30857+ deblk_end.deblk = p.deblk + deblk_sz;
30858+ /* smp_mb(); */
30859+ AuDebugOn(room->deblk != p.deblk);
30860+ }
30861+
30862+ err = -ENOMEM;
4a4d8108 30863+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
30864+ if (unlikely(!dehstr))
30865+ goto out;
30866+
30867+ dehstr->str = &room->de->de_str;
30868+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
30869+ room->de->de_ino = ino;
30870+ room->de->de_type = d_type;
30871+ room->de->de_str.len = nlen;
30872+ memcpy(room->de->de_str.name, name, nlen);
30873+
30874+ err = 0;
30875+ room->deblk += sz;
30876+ if (unlikely(set_deblk_end(room, &deblk_end)))
30877+ err = append_deblk(vdir);
30878+ /* smp_mb(); */
30879+
4f0767ce 30880+out:
dece6358
AM
30881+ return err;
30882+}
30883+
30884+/* ---------------------------------------------------------------------- */
30885+
1c60b727 30886+void au_vdir_free(struct au_vdir *vdir)
dece6358
AM
30887+{
30888+ unsigned char **deblk;
30889+
30890+ deblk = vdir->vd_deblk;
1c60b727
AM
30891+ while (vdir->vd_nblk--)
30892+ kfree(*deblk++);
30893+ kfree(vdir->vd_deblk);
30894+ au_cache_free_vdir(vdir);
dece6358
AM
30895+}
30896+
1308ab2a 30897+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 30898+{
30899+ struct au_vdir *vdir;
1308ab2a 30900+ struct super_block *sb;
1facf9fc 30901+ int err;
30902+
2000de60 30903+ sb = file->f_path.dentry->d_sb;
dece6358
AM
30904+ SiMustAnyLock(sb);
30905+
1facf9fc 30906+ err = -ENOMEM;
30907+ vdir = au_cache_alloc_vdir();
30908+ if (unlikely(!vdir))
30909+ goto out;
30910+
30911+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
30912+ if (unlikely(!vdir->vd_deblk))
30913+ goto out_free;
30914+
30915+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 30916+ if (!vdir->vd_deblk_sz) {
79b8bda9 30917+ /* estimate the appropriate size for deblk */
1308ab2a 30918+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 30919+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 30920+ }
1facf9fc 30921+ vdir->vd_nblk = 0;
30922+ vdir->vd_version = 0;
30923+ vdir->vd_jiffy = 0;
30924+ err = append_deblk(vdir);
30925+ if (!err)
30926+ return vdir; /* success */
30927+
1c60b727 30928+ kfree(vdir->vd_deblk);
1facf9fc 30929+
4f0767ce 30930+out_free:
1c60b727 30931+ au_cache_free_vdir(vdir);
4f0767ce 30932+out:
1facf9fc 30933+ vdir = ERR_PTR(err);
30934+ return vdir;
30935+}
30936+
30937+static int reinit_vdir(struct au_vdir *vdir)
30938+{
30939+ int err;
30940+ union au_vdir_deblk_p p, deblk_end;
30941+
30942+ while (vdir->vd_nblk > 1) {
1c60b727 30943+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
1facf9fc 30944+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
30945+ vdir->vd_nblk--;
30946+ }
30947+ p.deblk = vdir->vd_deblk[0];
30948+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
30949+ err = set_deblk_end(&p, &deblk_end);
30950+ /* keep vd_dblk_sz */
30951+ vdir->vd_last.ul = 0;
30952+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
30953+ vdir->vd_version = 0;
30954+ vdir->vd_jiffy = 0;
30955+ /* smp_mb(); */
30956+ return err;
30957+}
30958+
30959+/* ---------------------------------------------------------------------- */
30960+
1facf9fc 30961+#define AuFillVdir_CALLED 1
30962+#define AuFillVdir_WHABLE (1 << 1)
dece6358 30963+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 30964+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
7f207e10
AM
30965+#define au_fset_fillvdir(flags, name) \
30966+ do { (flags) |= AuFillVdir_##name; } while (0)
30967+#define au_fclr_fillvdir(flags, name) \
30968+ do { (flags) &= ~AuFillVdir_##name; } while (0)
1facf9fc 30969+
dece6358
AM
30970+#ifndef CONFIG_AUFS_SHWH
30971+#undef AuFillVdir_SHWH
30972+#define AuFillVdir_SHWH 0
30973+#endif
30974+
1facf9fc 30975+struct fillvdir_arg {
392086de 30976+ struct dir_context ctx;
1facf9fc 30977+ struct file *file;
30978+ struct au_vdir *vdir;
dece6358
AM
30979+ struct au_nhash delist;
30980+ struct au_nhash whlist;
1facf9fc 30981+ aufs_bindex_t bindex;
30982+ unsigned int flags;
30983+ int err;
30984+};
30985+
392086de 30986+static int fillvdir(struct dir_context *ctx, const char *__name, int nlen,
1facf9fc 30987+ loff_t offset __maybe_unused, u64 h_ino,
30988+ unsigned int d_type)
30989+{
392086de 30990+ struct fillvdir_arg *arg = container_of(ctx, struct fillvdir_arg, ctx);
1facf9fc 30991+ char *name = (void *)__name;
30992+ struct super_block *sb;
1facf9fc 30993+ ino_t ino;
dece6358 30994+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 30995+
1facf9fc 30996+ arg->err = 0;
2000de60 30997+ sb = arg->file->f_path.dentry->d_sb;
1facf9fc 30998+ au_fset_fillvdir(arg->flags, CALLED);
30999+ /* smp_mb(); */
dece6358 31000+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 31001+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
31002+ if (test_known(&arg->delist, name, nlen)
31003+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
31004+ goto out; /* already exists or whiteouted */
1facf9fc 31005+
dece6358 31006+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
31007+ if (!arg->err) {
31008+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
31009+ d_type = DT_UNKNOWN;
dece6358
AM
31010+ arg->err = append_de(arg->vdir, name, nlen, ino,
31011+ d_type, &arg->delist);
4a4d8108 31012+ }
1facf9fc 31013+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
31014+ name += AUFS_WH_PFX_LEN;
dece6358
AM
31015+ nlen -= AUFS_WH_PFX_LEN;
31016+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
31017+ goto out; /* already whiteouted */
1facf9fc 31018+
dece6358
AM
31019+ if (shwh)
31020+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
31021+ &ino);
4a4d8108
AM
31022+ if (!arg->err) {
31023+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
31024+ d_type = DT_UNKNOWN;
1facf9fc 31025+ arg->err = au_nhash_append_wh
dece6358
AM
31026+ (&arg->whlist, name, nlen, ino, d_type,
31027+ arg->bindex, shwh);
4a4d8108 31028+ }
1facf9fc 31029+ }
31030+
4f0767ce 31031+out:
1facf9fc 31032+ if (!arg->err)
31033+ arg->vdir->vd_jiffy = jiffies;
31034+ /* smp_mb(); */
31035+ AuTraceErr(arg->err);
31036+ return arg->err;
31037+}
31038+
dece6358
AM
31039+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
31040+ struct au_nhash *whlist, struct au_nhash *delist)
31041+{
31042+#ifdef CONFIG_AUFS_SHWH
31043+ int err;
31044+ unsigned int nh, u;
31045+ struct hlist_head *head;
c06a8ce3
AM
31046+ struct au_vdir_wh *pos;
31047+ struct hlist_node *n;
dece6358
AM
31048+ char *p, *o;
31049+ struct au_vdir_destr *destr;
31050+
31051+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
31052+
31053+ err = -ENOMEM;
537831f9 31054+ o = p = (void *)__get_free_page(GFP_NOFS);
dece6358
AM
31055+ if (unlikely(!p))
31056+ goto out;
31057+
31058+ err = 0;
31059+ nh = whlist->nh_num;
31060+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
31061+ p += AUFS_WH_PFX_LEN;
31062+ for (u = 0; u < nh; u++) {
31063+ head = whlist->nh_head + u;
c06a8ce3
AM
31064+ hlist_for_each_entry_safe(pos, n, head, wh_hash) {
31065+ destr = &pos->wh_str;
dece6358
AM
31066+ memcpy(p, destr->name, destr->len);
31067+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
c06a8ce3 31068+ pos->wh_ino, pos->wh_type, delist);
dece6358
AM
31069+ if (unlikely(err))
31070+ break;
31071+ }
31072+ }
31073+
1c60b727 31074+ free_page((unsigned long)o);
dece6358 31075+
4f0767ce 31076+out:
dece6358
AM
31077+ AuTraceErr(err);
31078+ return err;
31079+#else
31080+ return 0;
31081+#endif
31082+}
31083+
1facf9fc 31084+static int au_do_read_vdir(struct fillvdir_arg *arg)
31085+{
31086+ int err;
dece6358 31087+ unsigned int rdhash;
1facf9fc 31088+ loff_t offset;
5afbbe0d 31089+ aufs_bindex_t bbot, bindex, btop;
dece6358 31090+ unsigned char shwh;
1facf9fc 31091+ struct file *hf, *file;
31092+ struct super_block *sb;
31093+
1facf9fc 31094+ file = arg->file;
2000de60 31095+ sb = file->f_path.dentry->d_sb;
dece6358
AM
31096+ SiMustAnyLock(sb);
31097+
31098+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 31099+ if (!rdhash)
31100+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
31101+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
31102+ if (unlikely(err))
1facf9fc 31103+ goto out;
dece6358
AM
31104+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
31105+ if (unlikely(err))
1facf9fc 31106+ goto out_delist;
31107+
31108+ err = 0;
31109+ arg->flags = 0;
dece6358
AM
31110+ shwh = 0;
31111+ if (au_opt_test(au_mntflags(sb), SHWH)) {
31112+ shwh = 1;
31113+ au_fset_fillvdir(arg->flags, SHWH);
31114+ }
5afbbe0d
AM
31115+ btop = au_fbtop(file);
31116+ bbot = au_fbbot_dir(file);
31117+ for (bindex = btop; !err && bindex <= bbot; bindex++) {
4a4d8108 31118+ hf = au_hf_dir(file, bindex);
1facf9fc 31119+ if (!hf)
31120+ continue;
31121+
31122+ offset = vfsub_llseek(hf, 0, SEEK_SET);
31123+ err = offset;
31124+ if (unlikely(offset))
31125+ break;
31126+
31127+ arg->bindex = bindex;
31128+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358 31129+ if (shwh
5afbbe0d 31130+ || (bindex != bbot
dece6358 31131+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 31132+ au_fset_fillvdir(arg->flags, WHABLE);
31133+ do {
31134+ arg->err = 0;
31135+ au_fclr_fillvdir(arg->flags, CALLED);
31136+ /* smp_mb(); */
392086de 31137+ err = vfsub_iterate_dir(hf, &arg->ctx);
1facf9fc 31138+ if (err >= 0)
31139+ err = arg->err;
31140+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
392086de
AM
31141+
31142+ /*
31143+ * dir_relax() may be good for concurrency, but aufs should not
31144+ * use it since it will cause a lockdep problem.
31145+ */
1facf9fc 31146+ }
dece6358
AM
31147+
31148+ if (!err && shwh)
31149+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
31150+
31151+ au_nhash_wh_free(&arg->whlist);
1facf9fc 31152+
4f0767ce 31153+out_delist:
dece6358 31154+ au_nhash_de_free(&arg->delist);
4f0767ce 31155+out:
1facf9fc 31156+ return err;
31157+}
31158+
31159+static int read_vdir(struct file *file, int may_read)
31160+{
31161+ int err;
31162+ unsigned long expire;
31163+ unsigned char do_read;
392086de
AM
31164+ struct fillvdir_arg arg = {
31165+ .ctx = {
2000de60 31166+ .actor = fillvdir
392086de
AM
31167+ }
31168+ };
1facf9fc 31169+ struct inode *inode;
31170+ struct au_vdir *vdir, *allocated;
31171+
31172+ err = 0;
c06a8ce3 31173+ inode = file_inode(file);
1facf9fc 31174+ IMustLock(inode);
5afbbe0d 31175+ IiMustWriteLock(inode);
dece6358
AM
31176+ SiMustAnyLock(inode->i_sb);
31177+
1facf9fc 31178+ allocated = NULL;
31179+ do_read = 0;
31180+ expire = au_sbi(inode->i_sb)->si_rdcache;
31181+ vdir = au_ivdir(inode);
31182+ if (!vdir) {
31183+ do_read = 1;
1308ab2a 31184+ vdir = alloc_vdir(file);
1facf9fc 31185+ err = PTR_ERR(vdir);
31186+ if (IS_ERR(vdir))
31187+ goto out;
31188+ err = 0;
31189+ allocated = vdir;
31190+ } else if (may_read
31191+ && (inode->i_version != vdir->vd_version
31192+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
31193+ do_read = 1;
31194+ err = reinit_vdir(vdir);
31195+ if (unlikely(err))
31196+ goto out;
31197+ }
31198+
31199+ if (!do_read)
31200+ return 0; /* success */
31201+
31202+ arg.file = file;
31203+ arg.vdir = vdir;
31204+ err = au_do_read_vdir(&arg);
31205+ if (!err) {
392086de 31206+ /* file->f_pos = 0; */ /* todo: ctx->pos? */
1facf9fc 31207+ vdir->vd_version = inode->i_version;
31208+ vdir->vd_last.ul = 0;
31209+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
31210+ if (allocated)
31211+ au_set_ivdir(inode, allocated);
31212+ } else if (allocated)
1c60b727 31213+ au_vdir_free(allocated);
1facf9fc 31214+
4f0767ce 31215+out:
1facf9fc 31216+ return err;
31217+}
31218+
31219+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
31220+{
31221+ int err, rerr;
31222+ unsigned long ul, n;
31223+ const unsigned int deblk_sz = src->vd_deblk_sz;
31224+
31225+ AuDebugOn(tgt->vd_nblk != 1);
31226+
31227+ err = -ENOMEM;
31228+ if (tgt->vd_nblk < src->vd_nblk) {
31229+ unsigned char **p;
31230+
e2f27e51
AM
31231+ p = au_krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
31232+ GFP_NOFS, /*may_shrink*/0);
1facf9fc 31233+ if (unlikely(!p))
31234+ goto out;
31235+ tgt->vd_deblk = p;
31236+ }
31237+
1308ab2a 31238+ if (tgt->vd_deblk_sz != deblk_sz) {
31239+ unsigned char *p;
31240+
31241+ tgt->vd_deblk_sz = deblk_sz;
e2f27e51
AM
31242+ p = au_krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS,
31243+ /*may_shrink*/1);
1308ab2a 31244+ if (unlikely(!p))
31245+ goto out;
31246+ tgt->vd_deblk[0] = p;
31247+ }
1facf9fc 31248+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 31249+ tgt->vd_version = src->vd_version;
31250+ tgt->vd_jiffy = src->vd_jiffy;
31251+
31252+ n = src->vd_nblk;
31253+ for (ul = 1; ul < n; ul++) {
dece6358
AM
31254+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
31255+ GFP_NOFS);
31256+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 31257+ goto out;
1308ab2a 31258+ tgt->vd_nblk++;
1facf9fc 31259+ }
1308ab2a 31260+ tgt->vd_nblk = n;
31261+ tgt->vd_last.ul = tgt->vd_last.ul;
31262+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
31263+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
31264+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 31265+ /* smp_mb(); */
31266+ return 0; /* success */
31267+
4f0767ce 31268+out:
1facf9fc 31269+ rerr = reinit_vdir(tgt);
31270+ BUG_ON(rerr);
31271+ return err;
31272+}
31273+
31274+int au_vdir_init(struct file *file)
31275+{
31276+ int err;
31277+ struct inode *inode;
31278+ struct au_vdir *vdir_cache, *allocated;
31279+
392086de 31280+ /* test file->f_pos here instead of ctx->pos */
1facf9fc 31281+ err = read_vdir(file, !file->f_pos);
31282+ if (unlikely(err))
31283+ goto out;
31284+
31285+ allocated = NULL;
31286+ vdir_cache = au_fvdir_cache(file);
31287+ if (!vdir_cache) {
1308ab2a 31288+ vdir_cache = alloc_vdir(file);
1facf9fc 31289+ err = PTR_ERR(vdir_cache);
31290+ if (IS_ERR(vdir_cache))
31291+ goto out;
31292+ allocated = vdir_cache;
31293+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
392086de 31294+ /* test file->f_pos here instead of ctx->pos */
1facf9fc 31295+ err = reinit_vdir(vdir_cache);
31296+ if (unlikely(err))
31297+ goto out;
31298+ } else
31299+ return 0; /* success */
31300+
c06a8ce3 31301+ inode = file_inode(file);
1facf9fc 31302+ err = copy_vdir(vdir_cache, au_ivdir(inode));
31303+ if (!err) {
31304+ file->f_version = inode->i_version;
31305+ if (allocated)
31306+ au_set_fvdir_cache(file, allocated);
31307+ } else if (allocated)
1c60b727 31308+ au_vdir_free(allocated);
1facf9fc 31309+
4f0767ce 31310+out:
1facf9fc 31311+ return err;
31312+}
31313+
31314+static loff_t calc_offset(struct au_vdir *vdir)
31315+{
31316+ loff_t offset;
31317+ union au_vdir_deblk_p p;
31318+
31319+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
31320+ offset = vdir->vd_last.p.deblk - p.deblk;
31321+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
31322+ return offset;
31323+}
31324+
31325+/* returns true or false */
392086de 31326+static int seek_vdir(struct file *file, struct dir_context *ctx)
1facf9fc 31327+{
31328+ int valid;
31329+ unsigned int deblk_sz;
31330+ unsigned long ul, n;
31331+ loff_t offset;
31332+ union au_vdir_deblk_p p, deblk_end;
31333+ struct au_vdir *vdir_cache;
31334+
31335+ valid = 1;
31336+ vdir_cache = au_fvdir_cache(file);
31337+ offset = calc_offset(vdir_cache);
31338+ AuDbg("offset %lld\n", offset);
392086de 31339+ if (ctx->pos == offset)
1facf9fc 31340+ goto out;
31341+
31342+ vdir_cache->vd_last.ul = 0;
31343+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
392086de 31344+ if (!ctx->pos)
1facf9fc 31345+ goto out;
31346+
31347+ valid = 0;
31348+ deblk_sz = vdir_cache->vd_deblk_sz;
392086de 31349+ ul = div64_u64(ctx->pos, deblk_sz);
1facf9fc 31350+ AuDbg("ul %lu\n", ul);
31351+ if (ul >= vdir_cache->vd_nblk)
31352+ goto out;
31353+
31354+ n = vdir_cache->vd_nblk;
31355+ for (; ul < n; ul++) {
31356+ p.deblk = vdir_cache->vd_deblk[ul];
31357+ deblk_end.deblk = p.deblk + deblk_sz;
31358+ offset = ul;
31359+ offset *= deblk_sz;
392086de 31360+ while (!is_deblk_end(&p, &deblk_end) && offset < ctx->pos) {
1facf9fc 31361+ unsigned int l;
31362+
31363+ l = calc_size(p.de->de_str.len);
31364+ offset += l;
31365+ p.deblk += l;
31366+ }
31367+ if (!is_deblk_end(&p, &deblk_end)) {
31368+ valid = 1;
31369+ vdir_cache->vd_last.ul = ul;
31370+ vdir_cache->vd_last.p = p;
31371+ break;
31372+ }
31373+ }
31374+
4f0767ce 31375+out:
1facf9fc 31376+ /* smp_mb(); */
31377+ AuTraceErr(!valid);
31378+ return valid;
31379+}
31380+
392086de 31381+int au_vdir_fill_de(struct file *file, struct dir_context *ctx)
1facf9fc 31382+{
1facf9fc 31383+ unsigned int l, deblk_sz;
31384+ union au_vdir_deblk_p deblk_end;
31385+ struct au_vdir *vdir_cache;
31386+ struct au_vdir_de *de;
31387+
31388+ vdir_cache = au_fvdir_cache(file);
392086de 31389+ if (!seek_vdir(file, ctx))
1facf9fc 31390+ return 0;
31391+
31392+ deblk_sz = vdir_cache->vd_deblk_sz;
31393+ while (1) {
31394+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
31395+ deblk_end.deblk += deblk_sz;
31396+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
31397+ de = vdir_cache->vd_last.p.de;
31398+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
392086de 31399+ de->de_str.len, de->de_str.name, ctx->pos,
1facf9fc 31400+ (unsigned long)de->de_ino, de->de_type);
392086de
AM
31401+ if (unlikely(!dir_emit(ctx, de->de_str.name,
31402+ de->de_str.len, de->de_ino,
31403+ de->de_type))) {
1facf9fc 31404+ /* todo: ignore the error caused by udba? */
31405+ /* return err; */
31406+ return 0;
31407+ }
31408+
31409+ l = calc_size(de->de_str.len);
31410+ vdir_cache->vd_last.p.deblk += l;
392086de 31411+ ctx->pos += l;
1facf9fc 31412+ }
31413+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
31414+ vdir_cache->vd_last.ul++;
31415+ vdir_cache->vd_last.p.deblk
31416+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
392086de 31417+ ctx->pos = deblk_sz * vdir_cache->vd_last.ul;
1facf9fc 31418+ continue;
31419+ }
31420+ break;
31421+ }
31422+
31423+ /* smp_mb(); */
31424+ return 0;
31425+}
0b1ff5c3
JR
31426diff -urNp -x '*.orig' linux-4.14/fs/aufs/vfsub.c linux-4.14/fs/aufs/vfsub.c
31427--- linux-4.14/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
31428+++ linux-4.14/fs/aufs/vfsub.c 2021-02-24 21:42:43.444448075 +0100
8b6a4947 31429@@ -0,0 +1,894 @@
1facf9fc 31430+/*
a2654f78 31431+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 31432+ *
31433+ * This program, aufs is free software; you can redistribute it and/or modify
31434+ * it under the terms of the GNU General Public License as published by
31435+ * the Free Software Foundation; either version 2 of the License, or
31436+ * (at your option) any later version.
dece6358
AM
31437+ *
31438+ * This program is distributed in the hope that it will be useful,
31439+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31440+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31441+ * GNU General Public License for more details.
31442+ *
31443+ * You should have received a copy of the GNU General Public License
523b37e3 31444+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31445+ */
31446+
31447+/*
31448+ * sub-routines for VFS
31449+ */
31450+
8b6a4947 31451+#include <linux/mnt_namespace.h>
dece6358 31452+#include <linux/namei.h>
8cdd5066 31453+#include <linux/nsproxy.h>
dece6358
AM
31454+#include <linux/security.h>
31455+#include <linux/splice.h>
1facf9fc 31456+#include "aufs.h"
31457+
8cdd5066
JR
31458+#ifdef CONFIG_AUFS_BR_FUSE
31459+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb)
31460+{
8cdd5066
JR
31461+ if (!au_test_fuse(h_sb) || !au_userns)
31462+ return 0;
31463+
8b6a4947 31464+ return is_current_mnt_ns(mnt) ? 0 : -EACCES;
8cdd5066
JR
31465+}
31466+#endif
31467+
a2654f78
AM
31468+int vfsub_sync_filesystem(struct super_block *h_sb, int wait)
31469+{
31470+ int err;
31471+
31472+ lockdep_off();
31473+ down_read(&h_sb->s_umount);
31474+ err = __sync_filesystem(h_sb, wait);
31475+ up_read(&h_sb->s_umount);
31476+ lockdep_on();
31477+
31478+ return err;
31479+}
31480+
8cdd5066
JR
31481+/* ---------------------------------------------------------------------- */
31482+
1facf9fc 31483+int vfsub_update_h_iattr(struct path *h_path, int *did)
31484+{
31485+ int err;
31486+ struct kstat st;
31487+ struct super_block *h_sb;
31488+
31489+ /* for remote fs, leave work for its getattr or d_revalidate */
31490+ /* for bad i_attr fs, handle them in aufs_getattr() */
31491+ /* still some fs may acquire i_mutex. we need to skip them */
31492+ err = 0;
31493+ if (!did)
31494+ did = &err;
31495+ h_sb = h_path->dentry->d_sb;
31496+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
31497+ if (*did)
521ced18 31498+ err = vfsub_getattr(h_path, &st);
1facf9fc 31499+
31500+ return err;
31501+}
31502+
31503+/* ---------------------------------------------------------------------- */
31504+
4a4d8108 31505+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 31506+{
31507+ struct file *file;
31508+
b4510431 31509+ file = dentry_open(path, flags /* | __FMODE_NONOTIFY */,
7f207e10 31510+ current_cred());
2cbb1c4b
JR
31511+ if (!IS_ERR_OR_NULL(file)
31512+ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
5527c038 31513+ i_readcount_inc(d_inode(path->dentry));
4a4d8108 31514+
1308ab2a 31515+ return file;
31516+}
31517+
1facf9fc 31518+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
31519+{
31520+ struct file *file;
31521+
2cbb1c4b 31522+ lockdep_off();
7f207e10 31523+ file = filp_open(path,
2cbb1c4b 31524+ oflags /* | __FMODE_NONOTIFY */,
7f207e10 31525+ mode);
2cbb1c4b 31526+ lockdep_on();
1facf9fc 31527+ if (IS_ERR(file))
31528+ goto out;
31529+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
31530+
4f0767ce 31531+out:
1facf9fc 31532+ return file;
31533+}
31534+
b912730e
AM
31535+/*
31536+ * Ideally this function should call VFS:do_last() in order to keep all its
31537+ * checkings. But it is very hard for aufs to regenerate several VFS internal
31538+ * structure such as nameidata. This is a second (or third) best approach.
31539+ * cf. linux/fs/namei.c:do_last(), lookup_open() and atomic_open().
31540+ */
31541+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry,
31542+ struct vfsub_aopen_args *args, struct au_branch *br)
31543+{
31544+ int err;
31545+ struct file *file = args->file;
31546+ /* copied from linux/fs/namei.c:atomic_open() */
31547+ struct dentry *const DENTRY_NOT_SET = (void *)-1UL;
31548+
31549+ IMustLock(dir);
31550+ AuDebugOn(!dir->i_op->atomic_open);
31551+
31552+ err = au_br_test_oflag(args->open_flag, br);
31553+ if (unlikely(err))
31554+ goto out;
31555+
31556+ args->file->f_path.dentry = DENTRY_NOT_SET;
31557+ args->file->f_path.mnt = au_br_mnt(br);
31558+ err = dir->i_op->atomic_open(dir, dentry, file, args->open_flag,
31559+ args->create_mode, args->opened);
31560+ if (err >= 0) {
31561+ /* some filesystems don't set FILE_CREATED while succeeded? */
31562+ if (*args->opened & FILE_CREATED)
31563+ fsnotify_create(dir, dentry);
31564+ } else
31565+ goto out;
31566+
31567+
31568+ if (!err) {
31569+ /* todo: call VFS:may_open() here */
31570+ err = open_check_o_direct(file);
31571+ /* todo: ima_file_check() too? */
31572+ if (!err && (args->open_flag & __FMODE_EXEC))
31573+ err = deny_write_access(file);
31574+ if (unlikely(err))
31575+ /* note that the file is created and still opened */
31576+ goto out;
31577+ }
31578+
5afbbe0d 31579+ au_br_get(br);
b912730e
AM
31580+ fsnotify_open(file);
31581+
31582+out:
31583+ return err;
31584+}
31585+
1facf9fc 31586+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
31587+{
31588+ int err;
31589+
1facf9fc 31590+ err = kern_path(name, flags, path);
5527c038 31591+ if (!err && d_is_positive(path->dentry))
1facf9fc 31592+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
31593+ return err;
31594+}
31595+
febd17d6
JR
31596+struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
31597+ struct dentry *parent, int len)
31598+{
31599+ struct path path = {
31600+ .mnt = NULL
31601+ };
31602+
31603+ path.dentry = lookup_one_len_unlocked(name, parent, len);
31604+ if (IS_ERR(path.dentry))
31605+ goto out;
31606+ if (d_is_positive(path.dentry))
31607+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
31608+
31609+out:
31610+ AuTraceErrPtr(path.dentry);
31611+ return path.dentry;
31612+}
31613+
1facf9fc 31614+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
31615+ int len)
31616+{
31617+ struct path path = {
31618+ .mnt = NULL
31619+ };
31620+
1308ab2a 31621+ /* VFS checks it too, but by WARN_ON_ONCE() */
5527c038 31622+ IMustLock(d_inode(parent));
1facf9fc 31623+
31624+ path.dentry = lookup_one_len(name, parent, len);
31625+ if (IS_ERR(path.dentry))
31626+ goto out;
5527c038 31627+ if (d_is_positive(path.dentry))
1facf9fc 31628+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
31629+
4f0767ce 31630+out:
4a4d8108 31631+ AuTraceErrPtr(path.dentry);
1facf9fc 31632+ return path.dentry;
31633+}
31634+
b4510431 31635+void vfsub_call_lkup_one(void *args)
2cbb1c4b 31636+{
b4510431
AM
31637+ struct vfsub_lkup_one_args *a = args;
31638+ *a->errp = vfsub_lkup_one(a->name, a->parent);
2cbb1c4b
JR
31639+}
31640+
1facf9fc 31641+/* ---------------------------------------------------------------------- */
31642+
31643+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
31644+ struct dentry *d2, struct au_hinode *hdir2)
31645+{
31646+ struct dentry *d;
31647+
2cbb1c4b 31648+ lockdep_off();
1facf9fc 31649+ d = lock_rename(d1, d2);
2cbb1c4b 31650+ lockdep_on();
4a4d8108 31651+ au_hn_suspend(hdir1);
1facf9fc 31652+ if (hdir1 != hdir2)
4a4d8108 31653+ au_hn_suspend(hdir2);
1facf9fc 31654+
31655+ return d;
31656+}
31657+
31658+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
31659+ struct dentry *d2, struct au_hinode *hdir2)
31660+{
4a4d8108 31661+ au_hn_resume(hdir1);
1facf9fc 31662+ if (hdir1 != hdir2)
4a4d8108 31663+ au_hn_resume(hdir2);
2cbb1c4b 31664+ lockdep_off();
1facf9fc 31665+ unlock_rename(d1, d2);
2cbb1c4b 31666+ lockdep_on();
1facf9fc 31667+}
31668+
31669+/* ---------------------------------------------------------------------- */
31670+
b4510431 31671+int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl)
1facf9fc 31672+{
31673+ int err;
31674+ struct dentry *d;
31675+
31676+ IMustLock(dir);
31677+
31678+ d = path->dentry;
31679+ path->dentry = d->d_parent;
b752ccd1 31680+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 31681+ path->dentry = d;
31682+ if (unlikely(err))
31683+ goto out;
31684+
c1595e42 31685+ lockdep_off();
b4510431 31686+ err = vfs_create(dir, path->dentry, mode, want_excl);
c1595e42 31687+ lockdep_on();
1facf9fc 31688+ if (!err) {
31689+ struct path tmp = *path;
31690+ int did;
31691+
31692+ vfsub_update_h_iattr(&tmp, &did);
31693+ if (did) {
31694+ tmp.dentry = path->dentry->d_parent;
31695+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
31696+ }
31697+ /*ignore*/
31698+ }
31699+
4f0767ce 31700+out:
1facf9fc 31701+ return err;
31702+}
31703+
31704+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
31705+{
31706+ int err;
31707+ struct dentry *d;
31708+
31709+ IMustLock(dir);
31710+
31711+ d = path->dentry;
31712+ path->dentry = d->d_parent;
b752ccd1 31713+ err = security_path_symlink(path, d, symname);
1facf9fc 31714+ path->dentry = d;
31715+ if (unlikely(err))
31716+ goto out;
31717+
c1595e42 31718+ lockdep_off();
1facf9fc 31719+ err = vfs_symlink(dir, path->dentry, symname);
c1595e42 31720+ lockdep_on();
1facf9fc 31721+ if (!err) {
31722+ struct path tmp = *path;
31723+ int did;
31724+
31725+ vfsub_update_h_iattr(&tmp, &did);
31726+ if (did) {
31727+ tmp.dentry = path->dentry->d_parent;
31728+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
31729+ }
31730+ /*ignore*/
31731+ }
31732+
4f0767ce 31733+out:
1facf9fc 31734+ return err;
31735+}
31736+
31737+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
31738+{
31739+ int err;
31740+ struct dentry *d;
31741+
31742+ IMustLock(dir);
31743+
31744+ d = path->dentry;
31745+ path->dentry = d->d_parent;
027c5e7a 31746+ err = security_path_mknod(path, d, mode, new_encode_dev(dev));
1facf9fc 31747+ path->dentry = d;
31748+ if (unlikely(err))
31749+ goto out;
31750+
c1595e42 31751+ lockdep_off();
1facf9fc 31752+ err = vfs_mknod(dir, path->dentry, mode, dev);
c1595e42 31753+ lockdep_on();
1facf9fc 31754+ if (!err) {
31755+ struct path tmp = *path;
31756+ int did;
31757+
31758+ vfsub_update_h_iattr(&tmp, &did);
31759+ if (did) {
31760+ tmp.dentry = path->dentry->d_parent;
31761+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
31762+ }
31763+ /*ignore*/
31764+ }
31765+
4f0767ce 31766+out:
1facf9fc 31767+ return err;
31768+}
31769+
31770+static int au_test_nlink(struct inode *inode)
31771+{
31772+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
31773+
31774+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
31775+ || inode->i_nlink < link_max)
31776+ return 0;
31777+ return -EMLINK;
31778+}
31779+
523b37e3
AM
31780+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path,
31781+ struct inode **delegated_inode)
1facf9fc 31782+{
31783+ int err;
31784+ struct dentry *d;
31785+
31786+ IMustLock(dir);
31787+
5527c038 31788+ err = au_test_nlink(d_inode(src_dentry));
1facf9fc 31789+ if (unlikely(err))
31790+ return err;
31791+
b4510431 31792+ /* we don't call may_linkat() */
1facf9fc 31793+ d = path->dentry;
31794+ path->dentry = d->d_parent;
b752ccd1 31795+ err = security_path_link(src_dentry, path, d);
1facf9fc 31796+ path->dentry = d;
31797+ if (unlikely(err))
31798+ goto out;
31799+
2cbb1c4b 31800+ lockdep_off();
523b37e3 31801+ err = vfs_link(src_dentry, dir, path->dentry, delegated_inode);
2cbb1c4b 31802+ lockdep_on();
1facf9fc 31803+ if (!err) {
31804+ struct path tmp = *path;
31805+ int did;
31806+
31807+ /* fuse has different memory inode for the same inumber */
31808+ vfsub_update_h_iattr(&tmp, &did);
31809+ if (did) {
31810+ tmp.dentry = path->dentry->d_parent;
31811+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
31812+ tmp.dentry = src_dentry;
31813+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
31814+ }
31815+ /*ignore*/
31816+ }
31817+
4f0767ce 31818+out:
1facf9fc 31819+ return err;
31820+}
31821+
31822+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
523b37e3 31823+ struct inode *dir, struct path *path,
f2c43d5f 31824+ struct inode **delegated_inode, unsigned int flags)
1facf9fc 31825+{
31826+ int err;
31827+ struct path tmp = {
31828+ .mnt = path->mnt
31829+ };
31830+ struct dentry *d;
31831+
31832+ IMustLock(dir);
31833+ IMustLock(src_dir);
31834+
31835+ d = path->dentry;
31836+ path->dentry = d->d_parent;
31837+ tmp.dentry = src_dentry->d_parent;
38d290e6 31838+ err = security_path_rename(&tmp, src_dentry, path, d, /*flags*/0);
1facf9fc 31839+ path->dentry = d;
31840+ if (unlikely(err))
31841+ goto out;
31842+
2cbb1c4b 31843+ lockdep_off();
523b37e3 31844+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry,
f2c43d5f 31845+ delegated_inode, flags);
2cbb1c4b 31846+ lockdep_on();
1facf9fc 31847+ if (!err) {
31848+ int did;
31849+
31850+ tmp.dentry = d->d_parent;
31851+ vfsub_update_h_iattr(&tmp, &did);
31852+ if (did) {
31853+ tmp.dentry = src_dentry;
31854+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
31855+ tmp.dentry = src_dentry->d_parent;
31856+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
31857+ }
31858+ /*ignore*/
31859+ }
31860+
4f0767ce 31861+out:
1facf9fc 31862+ return err;
31863+}
31864+
31865+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
31866+{
31867+ int err;
31868+ struct dentry *d;
31869+
31870+ IMustLock(dir);
31871+
31872+ d = path->dentry;
31873+ path->dentry = d->d_parent;
b752ccd1 31874+ err = security_path_mkdir(path, d, mode);
1facf9fc 31875+ path->dentry = d;
31876+ if (unlikely(err))
31877+ goto out;
31878+
c1595e42 31879+ lockdep_off();
1facf9fc 31880+ err = vfs_mkdir(dir, path->dentry, mode);
c1595e42 31881+ lockdep_on();
1facf9fc 31882+ if (!err) {
31883+ struct path tmp = *path;
31884+ int did;
31885+
31886+ vfsub_update_h_iattr(&tmp, &did);
31887+ if (did) {
31888+ tmp.dentry = path->dentry->d_parent;
31889+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
31890+ }
31891+ /*ignore*/
31892+ }
31893+
4f0767ce 31894+out:
1facf9fc 31895+ return err;
31896+}
31897+
31898+int vfsub_rmdir(struct inode *dir, struct path *path)
31899+{
31900+ int err;
31901+ struct dentry *d;
31902+
31903+ IMustLock(dir);
31904+
31905+ d = path->dentry;
31906+ path->dentry = d->d_parent;
b752ccd1 31907+ err = security_path_rmdir(path, d);
1facf9fc 31908+ path->dentry = d;
31909+ if (unlikely(err))
31910+ goto out;
31911+
2cbb1c4b 31912+ lockdep_off();
1facf9fc 31913+ err = vfs_rmdir(dir, path->dentry);
2cbb1c4b 31914+ lockdep_on();
1facf9fc 31915+ if (!err) {
31916+ struct path tmp = {
31917+ .dentry = path->dentry->d_parent,
31918+ .mnt = path->mnt
31919+ };
31920+
31921+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
31922+ }
31923+
4f0767ce 31924+out:
1facf9fc 31925+ return err;
31926+}
31927+
31928+/* ---------------------------------------------------------------------- */
31929+
9dbd164d 31930+/* todo: support mmap_sem? */
1facf9fc 31931+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
31932+ loff_t *ppos)
31933+{
31934+ ssize_t err;
31935+
2cbb1c4b 31936+ lockdep_off();
1facf9fc 31937+ err = vfs_read(file, ubuf, count, ppos);
2cbb1c4b 31938+ lockdep_on();
1facf9fc 31939+ if (err >= 0)
31940+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
31941+ return err;
31942+}
31943+
31944+/* todo: kernel_read()? */
31945+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
31946+ loff_t *ppos)
31947+{
31948+ ssize_t err;
31949+ mm_segment_t oldfs;
b752ccd1
AM
31950+ union {
31951+ void *k;
31952+ char __user *u;
31953+ } buf;
1facf9fc 31954+
b752ccd1 31955+ buf.k = kbuf;
1facf9fc 31956+ oldfs = get_fs();
31957+ set_fs(KERNEL_DS);
b752ccd1 31958+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 31959+ set_fs(oldfs);
31960+ return err;
31961+}
31962+
31963+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
31964+ loff_t *ppos)
31965+{
31966+ ssize_t err;
31967+
2cbb1c4b 31968+ lockdep_off();
1facf9fc 31969+ err = vfs_write(file, ubuf, count, ppos);
2cbb1c4b 31970+ lockdep_on();
1facf9fc 31971+ if (err >= 0)
31972+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
31973+ return err;
31974+}
31975+
31976+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
31977+{
31978+ ssize_t err;
31979+ mm_segment_t oldfs;
b752ccd1
AM
31980+ union {
31981+ void *k;
31982+ const char __user *u;
31983+ } buf;
1facf9fc 31984+
b752ccd1 31985+ buf.k = kbuf;
1facf9fc 31986+ oldfs = get_fs();
31987+ set_fs(KERNEL_DS);
b752ccd1 31988+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 31989+ set_fs(oldfs);
31990+ return err;
31991+}
31992+
4a4d8108
AM
31993+int vfsub_flush(struct file *file, fl_owner_t id)
31994+{
31995+ int err;
31996+
31997+ err = 0;
523b37e3 31998+ if (file->f_op->flush) {
2000de60 31999+ if (!au_test_nfs(file->f_path.dentry->d_sb))
2cbb1c4b
JR
32000+ err = file->f_op->flush(file, id);
32001+ else {
32002+ lockdep_off();
32003+ err = file->f_op->flush(file, id);
32004+ lockdep_on();
32005+ }
4a4d8108
AM
32006+ if (!err)
32007+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
32008+ /*ignore*/
32009+ }
32010+ return err;
32011+}
32012+
392086de 32013+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx)
1facf9fc 32014+{
32015+ int err;
32016+
523b37e3 32017+ AuDbg("%pD, ctx{%pf, %llu}\n", file, ctx->actor, ctx->pos);
392086de 32018+
2cbb1c4b 32019+ lockdep_off();
392086de 32020+ err = iterate_dir(file, ctx);
2cbb1c4b 32021+ lockdep_on();
1facf9fc 32022+ if (err >= 0)
32023+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
1c60b727 32024+
1facf9fc 32025+ return err;
32026+}
32027+
32028+long vfsub_splice_to(struct file *in, loff_t *ppos,
32029+ struct pipe_inode_info *pipe, size_t len,
32030+ unsigned int flags)
32031+{
32032+ long err;
32033+
2cbb1c4b 32034+ lockdep_off();
0fc653ad 32035+ err = do_splice_to(in, ppos, pipe, len, flags);
2cbb1c4b 32036+ lockdep_on();
4a4d8108 32037+ file_accessed(in);
1facf9fc 32038+ if (err >= 0)
32039+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
32040+ return err;
32041+}
32042+
32043+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
32044+ loff_t *ppos, size_t len, unsigned int flags)
32045+{
32046+ long err;
32047+
2cbb1c4b 32048+ lockdep_off();
0fc653ad 32049+ err = do_splice_from(pipe, out, ppos, len, flags);
2cbb1c4b 32050+ lockdep_on();
1facf9fc 32051+ if (err >= 0)
32052+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
32053+ return err;
32054+}
32055+
53392da6
AM
32056+int vfsub_fsync(struct file *file, struct path *path, int datasync)
32057+{
32058+ int err;
32059+
32060+ /* file can be NULL */
32061+ lockdep_off();
32062+ err = vfs_fsync(file, datasync);
32063+ lockdep_on();
32064+ if (!err) {
32065+ if (!path) {
32066+ AuDebugOn(!file);
32067+ path = &file->f_path;
32068+ }
32069+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
32070+ }
32071+ return err;
32072+}
32073+
1facf9fc 32074+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
32075+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
32076+ struct file *h_file)
32077+{
32078+ int err;
32079+ struct inode *h_inode;
c06a8ce3 32080+ struct super_block *h_sb;
1facf9fc 32081+
1facf9fc 32082+ if (!h_file) {
c06a8ce3
AM
32083+ err = vfsub_truncate(h_path, length);
32084+ goto out;
1facf9fc 32085+ }
32086+
5527c038 32087+ h_inode = d_inode(h_path->dentry);
c06a8ce3
AM
32088+ h_sb = h_inode->i_sb;
32089+ lockdep_off();
32090+ sb_start_write(h_sb);
32091+ lockdep_on();
1facf9fc 32092+ err = locks_verify_truncate(h_inode, h_file, length);
32093+ if (!err)
953406b4 32094+ err = security_path_truncate(h_path);
2cbb1c4b
JR
32095+ if (!err) {
32096+ lockdep_off();
1facf9fc 32097+ err = do_truncate(h_path->dentry, length, attr, h_file);
2cbb1c4b
JR
32098+ lockdep_on();
32099+ }
c06a8ce3
AM
32100+ lockdep_off();
32101+ sb_end_write(h_sb);
32102+ lockdep_on();
1facf9fc 32103+
4f0767ce 32104+out:
1facf9fc 32105+ return err;
32106+}
32107+
32108+/* ---------------------------------------------------------------------- */
32109+
32110+struct au_vfsub_mkdir_args {
32111+ int *errp;
32112+ struct inode *dir;
32113+ struct path *path;
32114+ int mode;
32115+};
32116+
32117+static void au_call_vfsub_mkdir(void *args)
32118+{
32119+ struct au_vfsub_mkdir_args *a = args;
32120+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
32121+}
32122+
32123+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
32124+{
32125+ int err, do_sio, wkq_err;
32126+
32127+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
c1595e42
JR
32128+ if (!do_sio) {
32129+ lockdep_off();
1facf9fc 32130+ err = vfsub_mkdir(dir, path, mode);
c1595e42
JR
32131+ lockdep_on();
32132+ } else {
1facf9fc 32133+ struct au_vfsub_mkdir_args args = {
32134+ .errp = &err,
32135+ .dir = dir,
32136+ .path = path,
32137+ .mode = mode
32138+ };
32139+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
32140+ if (unlikely(wkq_err))
32141+ err = wkq_err;
32142+ }
32143+
32144+ return err;
32145+}
32146+
32147+struct au_vfsub_rmdir_args {
32148+ int *errp;
32149+ struct inode *dir;
32150+ struct path *path;
32151+};
32152+
32153+static void au_call_vfsub_rmdir(void *args)
32154+{
32155+ struct au_vfsub_rmdir_args *a = args;
32156+ *a->errp = vfsub_rmdir(a->dir, a->path);
32157+}
32158+
32159+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
32160+{
32161+ int err, do_sio, wkq_err;
32162+
32163+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
c1595e42
JR
32164+ if (!do_sio) {
32165+ lockdep_off();
1facf9fc 32166+ err = vfsub_rmdir(dir, path);
c1595e42
JR
32167+ lockdep_on();
32168+ } else {
1facf9fc 32169+ struct au_vfsub_rmdir_args args = {
32170+ .errp = &err,
32171+ .dir = dir,
32172+ .path = path
32173+ };
32174+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
32175+ if (unlikely(wkq_err))
32176+ err = wkq_err;
32177+ }
32178+
32179+ return err;
32180+}
32181+
32182+/* ---------------------------------------------------------------------- */
32183+
32184+struct notify_change_args {
32185+ int *errp;
32186+ struct path *path;
32187+ struct iattr *ia;
523b37e3 32188+ struct inode **delegated_inode;
1facf9fc 32189+};
32190+
32191+static void call_notify_change(void *args)
32192+{
32193+ struct notify_change_args *a = args;
32194+ struct inode *h_inode;
32195+
5527c038 32196+ h_inode = d_inode(a->path->dentry);
1facf9fc 32197+ IMustLock(h_inode);
32198+
32199+ *a->errp = -EPERM;
32200+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
c1595e42 32201+ lockdep_off();
523b37e3
AM
32202+ *a->errp = notify_change(a->path->dentry, a->ia,
32203+ a->delegated_inode);
c1595e42 32204+ lockdep_on();
1facf9fc 32205+ if (!*a->errp)
32206+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
32207+ }
32208+ AuTraceErr(*a->errp);
32209+}
32210+
523b37e3
AM
32211+int vfsub_notify_change(struct path *path, struct iattr *ia,
32212+ struct inode **delegated_inode)
1facf9fc 32213+{
32214+ int err;
32215+ struct notify_change_args args = {
523b37e3
AM
32216+ .errp = &err,
32217+ .path = path,
32218+ .ia = ia,
32219+ .delegated_inode = delegated_inode
1facf9fc 32220+ };
32221+
32222+ call_notify_change(&args);
32223+
32224+ return err;
32225+}
32226+
523b37e3
AM
32227+int vfsub_sio_notify_change(struct path *path, struct iattr *ia,
32228+ struct inode **delegated_inode)
1facf9fc 32229+{
32230+ int err, wkq_err;
32231+ struct notify_change_args args = {
523b37e3
AM
32232+ .errp = &err,
32233+ .path = path,
32234+ .ia = ia,
32235+ .delegated_inode = delegated_inode
1facf9fc 32236+ };
32237+
32238+ wkq_err = au_wkq_wait(call_notify_change, &args);
32239+ if (unlikely(wkq_err))
32240+ err = wkq_err;
32241+
32242+ return err;
32243+}
32244+
32245+/* ---------------------------------------------------------------------- */
32246+
32247+struct unlink_args {
32248+ int *errp;
32249+ struct inode *dir;
32250+ struct path *path;
523b37e3 32251+ struct inode **delegated_inode;
1facf9fc 32252+};
32253+
32254+static void call_unlink(void *args)
32255+{
32256+ struct unlink_args *a = args;
32257+ struct dentry *d = a->path->dentry;
32258+ struct inode *h_inode;
32259+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
c1595e42 32260+ && au_dcount(d) == 1);
1facf9fc 32261+
32262+ IMustLock(a->dir);
32263+
32264+ a->path->dentry = d->d_parent;
32265+ *a->errp = security_path_unlink(a->path, d);
32266+ a->path->dentry = d;
32267+ if (unlikely(*a->errp))
32268+ return;
32269+
32270+ if (!stop_sillyrename)
32271+ dget(d);
5527c038
JR
32272+ h_inode = NULL;
32273+ if (d_is_positive(d)) {
32274+ h_inode = d_inode(d);
027c5e7a 32275+ ihold(h_inode);
5527c038 32276+ }
1facf9fc 32277+
2cbb1c4b 32278+ lockdep_off();
523b37e3 32279+ *a->errp = vfs_unlink(a->dir, d, a->delegated_inode);
2cbb1c4b 32280+ lockdep_on();
1facf9fc 32281+ if (!*a->errp) {
32282+ struct path tmp = {
32283+ .dentry = d->d_parent,
32284+ .mnt = a->path->mnt
32285+ };
32286+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
32287+ }
32288+
32289+ if (!stop_sillyrename)
32290+ dput(d);
32291+ if (h_inode)
32292+ iput(h_inode);
32293+
32294+ AuTraceErr(*a->errp);
32295+}
32296+
32297+/*
32298+ * @dir: must be locked.
32299+ * @dentry: target dentry.
32300+ */
523b37e3
AM
32301+int vfsub_unlink(struct inode *dir, struct path *path,
32302+ struct inode **delegated_inode, int force)
1facf9fc 32303+{
32304+ int err;
32305+ struct unlink_args args = {
523b37e3
AM
32306+ .errp = &err,
32307+ .dir = dir,
32308+ .path = path,
32309+ .delegated_inode = delegated_inode
1facf9fc 32310+ };
32311+
32312+ if (!force)
32313+ call_unlink(&args);
32314+ else {
32315+ int wkq_err;
32316+
32317+ wkq_err = au_wkq_wait(call_unlink, &args);
32318+ if (unlikely(wkq_err))
32319+ err = wkq_err;
32320+ }
32321+
32322+ return err;
32323+}
0b1ff5c3
JR
32324diff -urNp -x '*.orig' linux-4.14/fs/aufs/vfsub.h linux-4.14/fs/aufs/vfsub.h
32325--- linux-4.14/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
32326+++ linux-4.14/fs/aufs/vfsub.h 2021-02-24 21:42:43.444448075 +0100
3c1bdaff 32327@@ -0,0 +1,360 @@
1facf9fc 32328+/*
a2654f78 32329+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 32330+ *
32331+ * This program, aufs is free software; you can redistribute it and/or modify
32332+ * it under the terms of the GNU General Public License as published by
32333+ * the Free Software Foundation; either version 2 of the License, or
32334+ * (at your option) any later version.
dece6358
AM
32335+ *
32336+ * This program is distributed in the hope that it will be useful,
32337+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
32338+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32339+ * GNU General Public License for more details.
32340+ *
32341+ * You should have received a copy of the GNU General Public License
523b37e3 32342+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 32343+ */
32344+
32345+/*
32346+ * sub-routines for VFS
32347+ */
32348+
32349+#ifndef __AUFS_VFSUB_H__
32350+#define __AUFS_VFSUB_H__
32351+
32352+#ifdef __KERNEL__
32353+
32354+#include <linux/fs.h>
b4510431 32355+#include <linux/mount.h>
8cdd5066 32356+#include <linux/posix_acl.h>
c1595e42 32357+#include <linux/xattr.h>
7f207e10 32358+#include "debug.h"
1facf9fc 32359+
7f207e10 32360+/* copied from linux/fs/internal.h */
2cbb1c4b 32361+/* todo: BAD approach!! */
c06a8ce3 32362+extern void __mnt_drop_write(struct vfsmount *);
b912730e 32363+extern int open_check_o_direct(struct file *f);
7f207e10
AM
32364+
32365+/* ---------------------------------------------------------------------- */
1facf9fc 32366+
32367+/* lock subclass for lower inode */
32368+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
32369+/* reduce? gave up. */
32370+enum {
c1595e42 32371+ AuLsc_I_Begin = I_MUTEX_PARENT2, /* 5 */
1facf9fc 32372+ AuLsc_I_PARENT, /* lower inode, parent first */
32373+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 32374+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 32375+ AuLsc_I_CHILD,
32376+ AuLsc_I_CHILD2,
32377+ AuLsc_I_End
32378+};
32379+
32380+/* to debug easier, do not make them inlined functions */
32381+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
febd17d6 32382+#define IMustLock(i) AuDebugOn(!inode_is_locked(i))
1facf9fc 32383+
3c1bdaff
AM
32384+/* why VFS doesn't define it? */
32385+static inline
32386+void vfsub_inode_lock_shared_nested(struct inode *inode, unsigned int sc)
32387+{
32388+ down_read_nested(&inode->i_rwsem, sc);
32389+}
32390+
1facf9fc 32391+/* ---------------------------------------------------------------------- */
32392+
7f207e10
AM
32393+static inline void vfsub_drop_nlink(struct inode *inode)
32394+{
32395+ AuDebugOn(!inode->i_nlink);
32396+ drop_nlink(inode);
32397+}
32398+
027c5e7a
AM
32399+static inline void vfsub_dead_dir(struct inode *inode)
32400+{
32401+ AuDebugOn(!S_ISDIR(inode->i_mode));
32402+ inode->i_flags |= S_DEAD;
32403+ clear_nlink(inode);
32404+}
32405+
392086de
AM
32406+static inline int vfsub_native_ro(struct inode *inode)
32407+{
8b6a4947 32408+ return sb_rdonly(inode->i_sb)
392086de
AM
32409+ || IS_RDONLY(inode)
32410+ /* || IS_APPEND(inode) */
32411+ || IS_IMMUTABLE(inode);
32412+}
32413+
8cdd5066
JR
32414+#ifdef CONFIG_AUFS_BR_FUSE
32415+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb);
32416+#else
32417+AuStubInt0(vfsub_test_mntns, struct vfsmount *mnt, struct super_block *h_sb);
32418+#endif
32419+
a2654f78
AM
32420+int vfsub_sync_filesystem(struct super_block *h_sb, int wait);
32421+
7f207e10
AM
32422+/* ---------------------------------------------------------------------- */
32423+
32424+int vfsub_update_h_iattr(struct path *h_path, int *did);
32425+struct file *vfsub_dentry_open(struct path *path, int flags);
32426+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
b912730e
AM
32427+struct vfsub_aopen_args {
32428+ struct file *file;
32429+ unsigned int open_flag;
32430+ umode_t create_mode;
32431+ int *opened;
32432+};
32433+struct au_branch;
32434+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry,
32435+ struct vfsub_aopen_args *args, struct au_branch *br);
1facf9fc 32436+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
b4510431 32437+
febd17d6
JR
32438+struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
32439+ struct dentry *parent, int len);
1facf9fc 32440+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
32441+ int len);
b4510431
AM
32442+
32443+struct vfsub_lkup_one_args {
32444+ struct dentry **errp;
32445+ struct qstr *name;
32446+ struct dentry *parent;
32447+};
32448+
32449+static inline struct dentry *vfsub_lkup_one(struct qstr *name,
32450+ struct dentry *parent)
32451+{
32452+ return vfsub_lookup_one_len(name->name, parent, name->len);
32453+}
32454+
32455+void vfsub_call_lkup_one(void *args);
32456+
32457+/* ---------------------------------------------------------------------- */
32458+
32459+static inline int vfsub_mnt_want_write(struct vfsmount *mnt)
32460+{
32461+ int err;
076b876e 32462+
b4510431
AM
32463+ lockdep_off();
32464+ err = mnt_want_write(mnt);
32465+ lockdep_on();
32466+ return err;
32467+}
32468+
32469+static inline void vfsub_mnt_drop_write(struct vfsmount *mnt)
32470+{
32471+ lockdep_off();
32472+ mnt_drop_write(mnt);
32473+ lockdep_on();
32474+}
1facf9fc 32475+
7e9cd9fe 32476+#if 0 /* reserved */
c06a8ce3
AM
32477+static inline void vfsub_mnt_drop_write_file(struct file *file)
32478+{
32479+ lockdep_off();
32480+ mnt_drop_write_file(file);
32481+ lockdep_on();
32482+}
7e9cd9fe 32483+#endif
c06a8ce3 32484+
1facf9fc 32485+/* ---------------------------------------------------------------------- */
32486+
32487+struct au_hinode;
32488+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
32489+ struct dentry *d2, struct au_hinode *hdir2);
32490+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
32491+ struct dentry *d2, struct au_hinode *hdir2);
32492+
537831f9
AM
32493+int vfsub_create(struct inode *dir, struct path *path, int mode,
32494+ bool want_excl);
1facf9fc 32495+int vfsub_symlink(struct inode *dir, struct path *path,
32496+ const char *symname);
32497+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
32498+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
523b37e3 32499+ struct path *path, struct inode **delegated_inode);
1facf9fc 32500+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
523b37e3 32501+ struct inode *hdir, struct path *path,
f2c43d5f 32502+ struct inode **delegated_inode, unsigned int flags);
1facf9fc 32503+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
32504+int vfsub_rmdir(struct inode *dir, struct path *path);
32505+
32506+/* ---------------------------------------------------------------------- */
32507+
32508+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
32509+ loff_t *ppos);
32510+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
32511+ loff_t *ppos);
32512+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
32513+ loff_t *ppos);
32514+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
32515+ loff_t *ppos);
4a4d8108 32516+int vfsub_flush(struct file *file, fl_owner_t id);
392086de
AM
32517+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx);
32518+
c06a8ce3
AM
32519+static inline loff_t vfsub_f_size_read(struct file *file)
32520+{
32521+ return i_size_read(file_inode(file));
32522+}
32523+
4a4d8108
AM
32524+static inline unsigned int vfsub_file_flags(struct file *file)
32525+{
32526+ unsigned int flags;
32527+
32528+ spin_lock(&file->f_lock);
32529+ flags = file->f_flags;
32530+ spin_unlock(&file->f_lock);
32531+
32532+ return flags;
32533+}
1308ab2a 32534+
f0c0a007
AM
32535+static inline int vfsub_file_execed(struct file *file)
32536+{
32537+ /* todo: direct access f_flags */
32538+ return !!(vfsub_file_flags(file) & __FMODE_EXEC);
32539+}
32540+
7e9cd9fe 32541+#if 0 /* reserved */
1facf9fc 32542+static inline void vfsub_file_accessed(struct file *h_file)
32543+{
32544+ file_accessed(h_file);
32545+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
32546+}
7e9cd9fe 32547+#endif
1facf9fc 32548+
79b8bda9 32549+#if 0 /* reserved */
1facf9fc 32550+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
32551+ struct dentry *h_dentry)
32552+{
32553+ struct path h_path = {
32554+ .dentry = h_dentry,
32555+ .mnt = h_mnt
32556+ };
92d182d2 32557+ touch_atime(&h_path);
1facf9fc 32558+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
32559+}
79b8bda9 32560+#endif
1facf9fc 32561+
0c3ec466
AM
32562+static inline int vfsub_update_time(struct inode *h_inode, struct timespec *ts,
32563+ int flags)
32564+{
5afbbe0d 32565+ return update_time(h_inode, ts, flags);
0c3ec466
AM
32566+ /* no vfsub_update_h_iattr() since we don't have struct path */
32567+}
32568+
8cdd5066
JR
32569+#ifdef CONFIG_FS_POSIX_ACL
32570+static inline int vfsub_acl_chmod(struct inode *h_inode, umode_t h_mode)
32571+{
32572+ int err;
32573+
32574+ err = posix_acl_chmod(h_inode, h_mode);
32575+ if (err == -EOPNOTSUPP)
32576+ err = 0;
32577+ return err;
32578+}
32579+#else
32580+AuStubInt0(vfsub_acl_chmod, struct inode *h_inode, umode_t h_mode);
32581+#endif
32582+
4a4d8108
AM
32583+long vfsub_splice_to(struct file *in, loff_t *ppos,
32584+ struct pipe_inode_info *pipe, size_t len,
32585+ unsigned int flags);
32586+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
32587+ loff_t *ppos, size_t len, unsigned int flags);
c06a8ce3
AM
32588+
32589+static inline long vfsub_truncate(struct path *path, loff_t length)
32590+{
32591+ long err;
076b876e 32592+
c06a8ce3
AM
32593+ lockdep_off();
32594+ err = vfs_truncate(path, length);
32595+ lockdep_on();
32596+ return err;
32597+}
32598+
4a4d8108
AM
32599+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
32600+ struct file *h_file);
53392da6 32601+int vfsub_fsync(struct file *file, struct path *path, int datasync);
4a4d8108 32602+
521ced18
JR
32603+/*
32604+ * re-use branch fs's ioctl(FICLONE) while aufs itself doesn't support such
32605+ * ioctl.
32606+ */
32607+static inline int vfsub_clone_file_range(struct file *src, struct file *dst,
32608+ u64 len)
32609+{
32610+ int err;
32611+
32612+ lockdep_off();
32613+ err = vfs_clone_file_range(src, 0, dst, 0, len);
32614+ lockdep_on();
32615+
32616+ return err;
32617+}
32618+
32619+/* copy_file_range(2) is a systemcall */
32620+static inline ssize_t vfsub_copy_file_range(struct file *src, loff_t src_pos,
32621+ struct file *dst, loff_t dst_pos,
32622+ size_t len, unsigned int flags)
32623+{
32624+ ssize_t ssz;
32625+
32626+ lockdep_off();
32627+ ssz = vfs_copy_file_range(src, src_pos, dst, dst_pos, len, flags);
32628+ lockdep_on();
32629+
32630+ return ssz;
32631+}
32632+
1facf9fc 32633+/* ---------------------------------------------------------------------- */
32634+
32635+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
32636+{
32637+ loff_t err;
32638+
2cbb1c4b 32639+ lockdep_off();
1facf9fc 32640+ err = vfs_llseek(file, offset, origin);
2cbb1c4b 32641+ lockdep_on();
1facf9fc 32642+ return err;
32643+}
32644+
32645+/* ---------------------------------------------------------------------- */
32646+
4a4d8108
AM
32647+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
32648+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
523b37e3
AM
32649+int vfsub_sio_notify_change(struct path *path, struct iattr *ia,
32650+ struct inode **delegated_inode);
32651+int vfsub_notify_change(struct path *path, struct iattr *ia,
32652+ struct inode **delegated_inode);
32653+int vfsub_unlink(struct inode *dir, struct path *path,
32654+ struct inode **delegated_inode, int force);
4a4d8108 32655+
521ced18
JR
32656+static inline int vfsub_getattr(const struct path *path, struct kstat *st)
32657+{
32658+ return vfs_getattr(path, st, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
32659+}
32660+
c1595e42
JR
32661+/* ---------------------------------------------------------------------- */
32662+
32663+static inline int vfsub_setxattr(struct dentry *dentry, const char *name,
32664+ const void *value, size_t size, int flags)
32665+{
32666+ int err;
32667+
32668+ lockdep_off();
32669+ err = vfs_setxattr(dentry, name, value, size, flags);
32670+ lockdep_on();
32671+
32672+ return err;
32673+}
32674+
32675+static inline int vfsub_removexattr(struct dentry *dentry, const char *name)
32676+{
32677+ int err;
32678+
32679+ lockdep_off();
32680+ err = vfs_removexattr(dentry, name);
32681+ lockdep_on();
32682+
32683+ return err;
32684+}
32685+
1facf9fc 32686+#endif /* __KERNEL__ */
32687+#endif /* __AUFS_VFSUB_H__ */
0b1ff5c3
JR
32688diff -urNp -x '*.orig' linux-4.14/fs/aufs/wbr_policy.c linux-4.14/fs/aufs/wbr_policy.c
32689--- linux-4.14/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
32690+++ linux-4.14/fs/aufs/wbr_policy.c 2021-02-24 21:42:43.444448075 +0100
f2c43d5f 32691@@ -0,0 +1,830 @@
1facf9fc 32692+/*
a2654f78 32693+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 32694+ *
32695+ * This program, aufs is free software; you can redistribute it and/or modify
32696+ * it under the terms of the GNU General Public License as published by
32697+ * the Free Software Foundation; either version 2 of the License, or
32698+ * (at your option) any later version.
dece6358
AM
32699+ *
32700+ * This program is distributed in the hope that it will be useful,
32701+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
32702+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32703+ * GNU General Public License for more details.
32704+ *
32705+ * You should have received a copy of the GNU General Public License
523b37e3 32706+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 32707+ */
32708+
32709+/*
32710+ * policies for selecting one among multiple writable branches
32711+ */
32712+
32713+#include <linux/statfs.h>
32714+#include "aufs.h"
32715+
32716+/* subset of cpup_attr() */
32717+static noinline_for_stack
32718+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
32719+{
32720+ int err, sbits;
32721+ struct iattr ia;
32722+ struct inode *h_isrc;
32723+
5527c038 32724+ h_isrc = d_inode(h_src);
1facf9fc 32725+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
32726+ ia.ia_mode = h_isrc->i_mode;
32727+ ia.ia_uid = h_isrc->i_uid;
32728+ ia.ia_gid = h_isrc->i_gid;
32729+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
5527c038 32730+ au_cpup_attr_flags(d_inode(h_path->dentry), h_isrc->i_flags);
523b37e3
AM
32731+ /* no delegation since it is just created */
32732+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL);
1facf9fc 32733+
32734+ /* is this nfs only? */
32735+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
32736+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
32737+ ia.ia_mode = h_isrc->i_mode;
523b37e3 32738+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL);
1facf9fc 32739+ }
32740+
32741+ return err;
32742+}
32743+
32744+#define AuCpdown_PARENT_OPQ 1
32745+#define AuCpdown_WHED (1 << 1)
32746+#define AuCpdown_MADE_DIR (1 << 2)
32747+#define AuCpdown_DIROPQ (1 << 3)
32748+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
7f207e10
AM
32749+#define au_fset_cpdown(flags, name) \
32750+ do { (flags) |= AuCpdown_##name; } while (0)
32751+#define au_fclr_cpdown(flags, name) \
32752+ do { (flags) &= ~AuCpdown_##name; } while (0)
1facf9fc 32753+
1facf9fc 32754+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
c2b27bf2 32755+ unsigned int *flags)
1facf9fc 32756+{
32757+ int err;
32758+ struct dentry *opq_dentry;
32759+
32760+ opq_dentry = au_diropq_create(dentry, bdst);
32761+ err = PTR_ERR(opq_dentry);
32762+ if (IS_ERR(opq_dentry))
32763+ goto out;
32764+ dput(opq_dentry);
c2b27bf2 32765+ au_fset_cpdown(*flags, DIROPQ);
1facf9fc 32766+
4f0767ce 32767+out:
1facf9fc 32768+ return err;
32769+}
32770+
32771+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
32772+ struct inode *dir, aufs_bindex_t bdst)
32773+{
32774+ int err;
32775+ struct path h_path;
32776+ struct au_branch *br;
32777+
32778+ br = au_sbr(dentry->d_sb, bdst);
32779+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
32780+ err = PTR_ERR(h_path.dentry);
32781+ if (IS_ERR(h_path.dentry))
32782+ goto out;
32783+
32784+ err = 0;
5527c038 32785+ if (d_is_positive(h_path.dentry)) {
86dc4139 32786+ h_path.mnt = au_br_mnt(br);
1facf9fc 32787+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
32788+ dentry);
32789+ }
32790+ dput(h_path.dentry);
32791+
4f0767ce 32792+out:
1facf9fc 32793+ return err;
32794+}
32795+
32796+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 32797+ struct au_pin *pin,
1facf9fc 32798+ struct dentry *h_parent, void *arg)
32799+{
32800+ int err, rerr;
5afbbe0d 32801+ aufs_bindex_t bopq, btop;
1facf9fc 32802+ struct path h_path;
32803+ struct dentry *parent;
32804+ struct inode *h_dir, *h_inode, *inode, *dir;
c2b27bf2 32805+ unsigned int *flags = arg;
1facf9fc 32806+
5afbbe0d 32807+ btop = au_dbtop(dentry);
1facf9fc 32808+ /* dentry is di-locked */
32809+ parent = dget_parent(dentry);
5527c038
JR
32810+ dir = d_inode(parent);
32811+ h_dir = d_inode(h_parent);
1facf9fc 32812+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
32813+ IMustLock(h_dir);
32814+
86dc4139 32815+ err = au_lkup_neg(dentry, bdst, /*wh*/0);
1facf9fc 32816+ if (unlikely(err < 0))
32817+ goto out;
32818+ h_path.dentry = au_h_dptr(dentry, bdst);
32819+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
32820+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
32821+ S_IRWXU | S_IRUGO | S_IXUGO);
32822+ if (unlikely(err))
32823+ goto out_put;
c2b27bf2 32824+ au_fset_cpdown(*flags, MADE_DIR);
1facf9fc 32825+
1facf9fc 32826+ bopq = au_dbdiropq(dentry);
c2b27bf2
AM
32827+ au_fclr_cpdown(*flags, WHED);
32828+ au_fclr_cpdown(*flags, DIROPQ);
1facf9fc 32829+ if (au_dbwh(dentry) == bdst)
c2b27bf2
AM
32830+ au_fset_cpdown(*flags, WHED);
32831+ if (!au_ftest_cpdown(*flags, PARENT_OPQ) && bopq <= bdst)
32832+ au_fset_cpdown(*flags, PARENT_OPQ);
5527c038 32833+ h_inode = d_inode(h_path.dentry);
febd17d6 32834+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
c2b27bf2
AM
32835+ if (au_ftest_cpdown(*flags, WHED)) {
32836+ err = au_cpdown_dir_opq(dentry, bdst, flags);
1facf9fc 32837+ if (unlikely(err)) {
febd17d6 32838+ inode_unlock(h_inode);
1facf9fc 32839+ goto out_dir;
32840+ }
32841+ }
32842+
5afbbe0d 32843+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, btop));
febd17d6 32844+ inode_unlock(h_inode);
1facf9fc 32845+ if (unlikely(err))
32846+ goto out_opq;
32847+
c2b27bf2 32848+ if (au_ftest_cpdown(*flags, WHED)) {
1facf9fc 32849+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
32850+ if (unlikely(err))
32851+ goto out_opq;
32852+ }
32853+
5527c038 32854+ inode = d_inode(dentry);
5afbbe0d
AM
32855+ if (au_ibbot(inode) < bdst)
32856+ au_set_ibbot(inode, bdst);
1facf9fc 32857+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
32858+ au_hi_flags(inode, /*isdir*/1));
076b876e 32859+ au_fhsm_wrote(dentry->d_sb, bdst, /*force*/0);
1facf9fc 32860+ goto out; /* success */
32861+
32862+ /* revert */
4f0767ce 32863+out_opq:
c2b27bf2 32864+ if (au_ftest_cpdown(*flags, DIROPQ)) {
febd17d6 32865+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
1facf9fc 32866+ rerr = au_diropq_remove(dentry, bdst);
febd17d6 32867+ inode_unlock(h_inode);
1facf9fc 32868+ if (unlikely(rerr)) {
523b37e3
AM
32869+ AuIOErr("failed removing diropq for %pd b%d (%d)\n",
32870+ dentry, bdst, rerr);
1facf9fc 32871+ err = -EIO;
32872+ goto out;
32873+ }
32874+ }
4f0767ce 32875+out_dir:
c2b27bf2 32876+ if (au_ftest_cpdown(*flags, MADE_DIR)) {
1facf9fc 32877+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
32878+ if (unlikely(rerr)) {
523b37e3
AM
32879+ AuIOErr("failed removing %pd b%d (%d)\n",
32880+ dentry, bdst, rerr);
1facf9fc 32881+ err = -EIO;
32882+ }
32883+ }
4f0767ce 32884+out_put:
1facf9fc 32885+ au_set_h_dptr(dentry, bdst, NULL);
5afbbe0d
AM
32886+ if (au_dbbot(dentry) == bdst)
32887+ au_update_dbbot(dentry);
4f0767ce 32888+out:
1facf9fc 32889+ dput(parent);
32890+ return err;
32891+}
32892+
32893+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
32894+{
32895+ int err;
c2b27bf2 32896+ unsigned int flags;
1facf9fc 32897+
c2b27bf2
AM
32898+ flags = 0;
32899+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &flags);
1facf9fc 32900+
32901+ return err;
32902+}
32903+
32904+/* ---------------------------------------------------------------------- */
32905+
32906+/* policies for create */
32907+
c2b27bf2 32908+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
4a4d8108
AM
32909+{
32910+ int err, i, j, ndentry;
32911+ aufs_bindex_t bopq;
32912+ struct au_dcsub_pages dpages;
32913+ struct au_dpage *dpage;
32914+ struct dentry **dentries, *parent, *d;
32915+
32916+ err = au_dpages_init(&dpages, GFP_NOFS);
32917+ if (unlikely(err))
32918+ goto out;
32919+ parent = dget_parent(dentry);
027c5e7a 32920+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0);
4a4d8108
AM
32921+ if (unlikely(err))
32922+ goto out_free;
32923+
32924+ err = bindex;
32925+ for (i = 0; i < dpages.ndpage; i++) {
32926+ dpage = dpages.dpages + i;
32927+ dentries = dpage->dentries;
32928+ ndentry = dpage->ndentry;
32929+ for (j = 0; j < ndentry; j++) {
32930+ d = dentries[j];
32931+ di_read_lock_parent2(d, !AuLock_IR);
32932+ bopq = au_dbdiropq(d);
32933+ di_read_unlock(d, !AuLock_IR);
32934+ if (bopq >= 0 && bopq < err)
32935+ err = bopq;
32936+ }
32937+ }
32938+
32939+out_free:
32940+ dput(parent);
32941+ au_dpages_free(&dpages);
32942+out:
32943+ return err;
32944+}
32945+
1facf9fc 32946+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
32947+{
32948+ for (; bindex >= 0; bindex--)
32949+ if (!au_br_rdonly(au_sbr(sb, bindex)))
32950+ return bindex;
32951+ return -EROFS;
32952+}
32953+
32954+/* top down parent */
392086de
AM
32955+static int au_wbr_create_tdp(struct dentry *dentry,
32956+ unsigned int flags __maybe_unused)
1facf9fc 32957+{
32958+ int err;
5afbbe0d 32959+ aufs_bindex_t btop, bindex;
1facf9fc 32960+ struct super_block *sb;
32961+ struct dentry *parent, *h_parent;
32962+
32963+ sb = dentry->d_sb;
5afbbe0d
AM
32964+ btop = au_dbtop(dentry);
32965+ err = btop;
32966+ if (!au_br_rdonly(au_sbr(sb, btop)))
1facf9fc 32967+ goto out;
32968+
32969+ err = -EROFS;
32970+ parent = dget_parent(dentry);
5afbbe0d 32971+ for (bindex = au_dbtop(parent); bindex < btop; bindex++) {
1facf9fc 32972+ h_parent = au_h_dptr(parent, bindex);
5527c038 32973+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 32974+ continue;
32975+
32976+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
32977+ err = bindex;
32978+ break;
32979+ }
32980+ }
32981+ dput(parent);
32982+
32983+ /* bottom up here */
4a4d8108 32984+ if (unlikely(err < 0)) {
5afbbe0d 32985+ err = au_wbr_bu(sb, btop - 1);
4a4d8108
AM
32986+ if (err >= 0)
32987+ err = au_wbr_nonopq(dentry, err);
32988+ }
1facf9fc 32989+
4f0767ce 32990+out:
1facf9fc 32991+ AuDbg("b%d\n", err);
32992+ return err;
32993+}
32994+
32995+/* ---------------------------------------------------------------------- */
32996+
32997+/* an exception for the policy other than tdp */
32998+static int au_wbr_create_exp(struct dentry *dentry)
32999+{
33000+ int err;
33001+ aufs_bindex_t bwh, bdiropq;
33002+ struct dentry *parent;
33003+
33004+ err = -1;
33005+ bwh = au_dbwh(dentry);
33006+ parent = dget_parent(dentry);
33007+ bdiropq = au_dbdiropq(parent);
33008+ if (bwh >= 0) {
33009+ if (bdiropq >= 0)
33010+ err = min(bdiropq, bwh);
33011+ else
33012+ err = bwh;
33013+ AuDbg("%d\n", err);
33014+ } else if (bdiropq >= 0) {
33015+ err = bdiropq;
33016+ AuDbg("%d\n", err);
33017+ }
33018+ dput(parent);
33019+
4a4d8108
AM
33020+ if (err >= 0)
33021+ err = au_wbr_nonopq(dentry, err);
33022+
1facf9fc 33023+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
33024+ err = -1;
33025+
33026+ AuDbg("%d\n", err);
33027+ return err;
33028+}
33029+
33030+/* ---------------------------------------------------------------------- */
33031+
33032+/* round robin */
33033+static int au_wbr_create_init_rr(struct super_block *sb)
33034+{
33035+ int err;
33036+
5afbbe0d 33037+ err = au_wbr_bu(sb, au_sbbot(sb));
1facf9fc 33038+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 33039+ /* smp_mb(); */
1facf9fc 33040+
33041+ AuDbg("b%d\n", err);
33042+ return err;
33043+}
33044+
392086de 33045+static int au_wbr_create_rr(struct dentry *dentry, unsigned int flags)
1facf9fc 33046+{
33047+ int err, nbr;
33048+ unsigned int u;
5afbbe0d 33049+ aufs_bindex_t bindex, bbot;
1facf9fc 33050+ struct super_block *sb;
33051+ atomic_t *next;
33052+
33053+ err = au_wbr_create_exp(dentry);
33054+ if (err >= 0)
33055+ goto out;
33056+
33057+ sb = dentry->d_sb;
33058+ next = &au_sbi(sb)->si_wbr_rr_next;
5afbbe0d
AM
33059+ bbot = au_sbbot(sb);
33060+ nbr = bbot + 1;
33061+ for (bindex = 0; bindex <= bbot; bindex++) {
392086de 33062+ if (!au_ftest_wbr(flags, DIR)) {
1facf9fc 33063+ err = atomic_dec_return(next) + 1;
33064+ /* modulo for 0 is meaningless */
33065+ if (unlikely(!err))
33066+ err = atomic_dec_return(next) + 1;
33067+ } else
33068+ err = atomic_read(next);
33069+ AuDbg("%d\n", err);
33070+ u = err;
33071+ err = u % nbr;
33072+ AuDbg("%d\n", err);
33073+ if (!au_br_rdonly(au_sbr(sb, err)))
33074+ break;
33075+ err = -EROFS;
33076+ }
33077+
4a4d8108
AM
33078+ if (err >= 0)
33079+ err = au_wbr_nonopq(dentry, err);
33080+
4f0767ce 33081+out:
1facf9fc 33082+ AuDbg("%d\n", err);
33083+ return err;
33084+}
33085+
33086+/* ---------------------------------------------------------------------- */
33087+
33088+/* most free space */
392086de 33089+static void au_mfs(struct dentry *dentry, struct dentry *parent)
1facf9fc 33090+{
33091+ struct super_block *sb;
33092+ struct au_branch *br;
33093+ struct au_wbr_mfs *mfs;
392086de 33094+ struct dentry *h_parent;
5afbbe0d 33095+ aufs_bindex_t bindex, bbot;
1facf9fc 33096+ int err;
33097+ unsigned long long b, bavail;
7f207e10 33098+ struct path h_path;
1facf9fc 33099+ /* reduce the stack usage */
33100+ struct kstatfs *st;
33101+
33102+ st = kmalloc(sizeof(*st), GFP_NOFS);
33103+ if (unlikely(!st)) {
33104+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
33105+ return;
33106+ }
33107+
33108+ bavail = 0;
33109+ sb = dentry->d_sb;
33110+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 33111+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 33112+ mfs->mfs_bindex = -EROFS;
33113+ mfs->mfsrr_bytes = 0;
392086de
AM
33114+ if (!parent) {
33115+ bindex = 0;
5afbbe0d 33116+ bbot = au_sbbot(sb);
392086de 33117+ } else {
5afbbe0d
AM
33118+ bindex = au_dbtop(parent);
33119+ bbot = au_dbtaildir(parent);
392086de
AM
33120+ }
33121+
5afbbe0d 33122+ for (; bindex <= bbot; bindex++) {
392086de
AM
33123+ if (parent) {
33124+ h_parent = au_h_dptr(parent, bindex);
5527c038 33125+ if (!h_parent || d_is_negative(h_parent))
392086de
AM
33126+ continue;
33127+ }
1facf9fc 33128+ br = au_sbr(sb, bindex);
33129+ if (au_br_rdonly(br))
33130+ continue;
33131+
33132+ /* sb->s_root for NFS is unreliable */
86dc4139 33133+ h_path.mnt = au_br_mnt(br);
7f207e10
AM
33134+ h_path.dentry = h_path.mnt->mnt_root;
33135+ err = vfs_statfs(&h_path, st);
1facf9fc 33136+ if (unlikely(err)) {
33137+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
33138+ continue;
33139+ }
33140+
33141+ /* when the available size is equal, select the lower one */
33142+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
33143+ || sizeof(b) < sizeof(st->f_bsize));
33144+ b = st->f_bavail * st->f_bsize;
33145+ br->br_wbr->wbr_bytes = b;
33146+ if (b >= bavail) {
33147+ bavail = b;
33148+ mfs->mfs_bindex = bindex;
33149+ mfs->mfs_jiffy = jiffies;
33150+ }
33151+ }
33152+
33153+ mfs->mfsrr_bytes = bavail;
33154+ AuDbg("b%d\n", mfs->mfs_bindex);
1c60b727 33155+ kfree(st);
1facf9fc 33156+}
33157+
392086de 33158+static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags)
1facf9fc 33159+{
33160+ int err;
392086de 33161+ struct dentry *parent;
1facf9fc 33162+ struct super_block *sb;
33163+ struct au_wbr_mfs *mfs;
33164+
33165+ err = au_wbr_create_exp(dentry);
33166+ if (err >= 0)
33167+ goto out;
33168+
33169+ sb = dentry->d_sb;
392086de
AM
33170+ parent = NULL;
33171+ if (au_ftest_wbr(flags, PARENT))
33172+ parent = dget_parent(dentry);
1facf9fc 33173+ mfs = &au_sbi(sb)->si_wbr_mfs;
33174+ mutex_lock(&mfs->mfs_lock);
33175+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
33176+ || mfs->mfs_bindex < 0
33177+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
392086de 33178+ au_mfs(dentry, parent);
1facf9fc 33179+ mutex_unlock(&mfs->mfs_lock);
33180+ err = mfs->mfs_bindex;
392086de 33181+ dput(parent);
1facf9fc 33182+
4a4d8108
AM
33183+ if (err >= 0)
33184+ err = au_wbr_nonopq(dentry, err);
33185+
4f0767ce 33186+out:
1facf9fc 33187+ AuDbg("b%d\n", err);
33188+ return err;
33189+}
33190+
33191+static int au_wbr_create_init_mfs(struct super_block *sb)
33192+{
33193+ struct au_wbr_mfs *mfs;
33194+
33195+ mfs = &au_sbi(sb)->si_wbr_mfs;
33196+ mutex_init(&mfs->mfs_lock);
33197+ mfs->mfs_jiffy = 0;
33198+ mfs->mfs_bindex = -EROFS;
33199+
33200+ return 0;
33201+}
33202+
33203+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
33204+{
33205+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
33206+ return 0;
33207+}
33208+
33209+/* ---------------------------------------------------------------------- */
33210+
f2c43d5f
AM
33211+/* top down regardless parent, and then mfs */
33212+static int au_wbr_create_tdmfs(struct dentry *dentry,
33213+ unsigned int flags __maybe_unused)
33214+{
33215+ int err;
33216+ aufs_bindex_t bwh, btail, bindex, bfound, bmfs;
33217+ unsigned long long watermark;
33218+ struct super_block *sb;
33219+ struct au_wbr_mfs *mfs;
33220+ struct au_branch *br;
33221+ struct dentry *parent;
33222+
33223+ sb = dentry->d_sb;
33224+ mfs = &au_sbi(sb)->si_wbr_mfs;
33225+ mutex_lock(&mfs->mfs_lock);
33226+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
33227+ || mfs->mfs_bindex < 0)
33228+ au_mfs(dentry, /*parent*/NULL);
33229+ watermark = mfs->mfsrr_watermark;
33230+ bmfs = mfs->mfs_bindex;
33231+ mutex_unlock(&mfs->mfs_lock);
33232+
33233+ /* another style of au_wbr_create_exp() */
33234+ bwh = au_dbwh(dentry);
33235+ parent = dget_parent(dentry);
33236+ btail = au_dbtaildir(parent);
33237+ if (bwh >= 0 && bwh < btail)
33238+ btail = bwh;
33239+
33240+ err = au_wbr_nonopq(dentry, btail);
33241+ if (unlikely(err < 0))
33242+ goto out;
33243+ btail = err;
33244+ bfound = -1;
33245+ for (bindex = 0; bindex <= btail; bindex++) {
33246+ br = au_sbr(sb, bindex);
33247+ if (au_br_rdonly(br))
33248+ continue;
33249+ if (br->br_wbr->wbr_bytes > watermark) {
33250+ bfound = bindex;
33251+ break;
33252+ }
33253+ }
33254+ err = bfound;
33255+ if (err < 0)
33256+ err = bmfs;
33257+
33258+out:
33259+ dput(parent);
33260+ AuDbg("b%d\n", err);
33261+ return err;
33262+}
33263+
33264+/* ---------------------------------------------------------------------- */
33265+
1facf9fc 33266+/* most free space and then round robin */
392086de 33267+static int au_wbr_create_mfsrr(struct dentry *dentry, unsigned int flags)
1facf9fc 33268+{
33269+ int err;
33270+ struct au_wbr_mfs *mfs;
33271+
392086de 33272+ err = au_wbr_create_mfs(dentry, flags);
1facf9fc 33273+ if (err >= 0) {
33274+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 33275+ mutex_lock(&mfs->mfs_lock);
1facf9fc 33276+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
392086de 33277+ err = au_wbr_create_rr(dentry, flags);
dece6358 33278+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 33279+ }
33280+
33281+ AuDbg("b%d\n", err);
33282+ return err;
33283+}
33284+
33285+static int au_wbr_create_init_mfsrr(struct super_block *sb)
33286+{
33287+ int err;
33288+
33289+ au_wbr_create_init_mfs(sb); /* ignore */
33290+ err = au_wbr_create_init_rr(sb);
33291+
33292+ return err;
33293+}
33294+
33295+/* ---------------------------------------------------------------------- */
33296+
33297+/* top down parent and most free space */
392086de 33298+static int au_wbr_create_pmfs(struct dentry *dentry, unsigned int flags)
1facf9fc 33299+{
33300+ int err, e2;
33301+ unsigned long long b;
5afbbe0d 33302+ aufs_bindex_t bindex, btop, bbot;
1facf9fc 33303+ struct super_block *sb;
33304+ struct dentry *parent, *h_parent;
33305+ struct au_branch *br;
33306+
392086de 33307+ err = au_wbr_create_tdp(dentry, flags);
1facf9fc 33308+ if (unlikely(err < 0))
33309+ goto out;
33310+ parent = dget_parent(dentry);
5afbbe0d
AM
33311+ btop = au_dbtop(parent);
33312+ bbot = au_dbtaildir(parent);
33313+ if (btop == bbot)
1facf9fc 33314+ goto out_parent; /* success */
33315+
392086de 33316+ e2 = au_wbr_create_mfs(dentry, flags);
1facf9fc 33317+ if (e2 < 0)
33318+ goto out_parent; /* success */
33319+
33320+ /* when the available size is equal, select upper one */
33321+ sb = dentry->d_sb;
33322+ br = au_sbr(sb, err);
33323+ b = br->br_wbr->wbr_bytes;
33324+ AuDbg("b%d, %llu\n", err, b);
33325+
5afbbe0d 33326+ for (bindex = btop; bindex <= bbot; bindex++) {
1facf9fc 33327+ h_parent = au_h_dptr(parent, bindex);
5527c038 33328+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 33329+ continue;
33330+
33331+ br = au_sbr(sb, bindex);
33332+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
33333+ b = br->br_wbr->wbr_bytes;
33334+ err = bindex;
33335+ AuDbg("b%d, %llu\n", err, b);
33336+ }
33337+ }
33338+
4a4d8108
AM
33339+ if (err >= 0)
33340+ err = au_wbr_nonopq(dentry, err);
33341+
4f0767ce 33342+out_parent:
1facf9fc 33343+ dput(parent);
4f0767ce 33344+out:
1facf9fc 33345+ AuDbg("b%d\n", err);
33346+ return err;
33347+}
33348+
33349+/* ---------------------------------------------------------------------- */
33350+
392086de
AM
33351+/*
33352+ * - top down parent
33353+ * - most free space with parent
33354+ * - most free space round-robin regardless parent
33355+ */
33356+static int au_wbr_create_pmfsrr(struct dentry *dentry, unsigned int flags)
33357+{
33358+ int err;
33359+ unsigned long long watermark;
33360+ struct super_block *sb;
33361+ struct au_branch *br;
33362+ struct au_wbr_mfs *mfs;
33363+
33364+ err = au_wbr_create_pmfs(dentry, flags | AuWbr_PARENT);
33365+ if (unlikely(err < 0))
33366+ goto out;
33367+
33368+ sb = dentry->d_sb;
33369+ br = au_sbr(sb, err);
33370+ mfs = &au_sbi(sb)->si_wbr_mfs;
33371+ mutex_lock(&mfs->mfs_lock);
33372+ watermark = mfs->mfsrr_watermark;
33373+ mutex_unlock(&mfs->mfs_lock);
33374+ if (br->br_wbr->wbr_bytes < watermark)
33375+ /* regardless the parent dir */
33376+ err = au_wbr_create_mfsrr(dentry, flags);
33377+
33378+out:
33379+ AuDbg("b%d\n", err);
33380+ return err;
33381+}
33382+
33383+/* ---------------------------------------------------------------------- */
33384+
1facf9fc 33385+/* policies for copyup */
33386+
33387+/* top down parent */
33388+static int au_wbr_copyup_tdp(struct dentry *dentry)
33389+{
392086de 33390+ return au_wbr_create_tdp(dentry, /*flags, anything is ok*/0);
1facf9fc 33391+}
33392+
33393+/* bottom up parent */
33394+static int au_wbr_copyup_bup(struct dentry *dentry)
33395+{
33396+ int err;
5afbbe0d 33397+ aufs_bindex_t bindex, btop;
1facf9fc 33398+ struct dentry *parent, *h_parent;
33399+ struct super_block *sb;
33400+
33401+ err = -EROFS;
33402+ sb = dentry->d_sb;
33403+ parent = dget_parent(dentry);
5afbbe0d
AM
33404+ btop = au_dbtop(parent);
33405+ for (bindex = au_dbtop(dentry); bindex >= btop; bindex--) {
1facf9fc 33406+ h_parent = au_h_dptr(parent, bindex);
5527c038 33407+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 33408+ continue;
33409+
33410+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
33411+ err = bindex;
33412+ break;
33413+ }
33414+ }
33415+ dput(parent);
33416+
33417+ /* bottom up here */
33418+ if (unlikely(err < 0))
5afbbe0d 33419+ err = au_wbr_bu(sb, btop - 1);
1facf9fc 33420+
33421+ AuDbg("b%d\n", err);
33422+ return err;
33423+}
33424+
33425+/* bottom up */
5afbbe0d 33426+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop)
1facf9fc 33427+{
33428+ int err;
33429+
5afbbe0d 33430+ err = au_wbr_bu(dentry->d_sb, btop);
4a4d8108 33431+ AuDbg("b%d\n", err);
5afbbe0d 33432+ if (err > btop)
4a4d8108 33433+ err = au_wbr_nonopq(dentry, err);
1facf9fc 33434+
33435+ AuDbg("b%d\n", err);
33436+ return err;
33437+}
33438+
076b876e
AM
33439+static int au_wbr_copyup_bu(struct dentry *dentry)
33440+{
33441+ int err;
5afbbe0d 33442+ aufs_bindex_t btop;
076b876e 33443+
5afbbe0d
AM
33444+ btop = au_dbtop(dentry);
33445+ err = au_wbr_do_copyup_bu(dentry, btop);
076b876e
AM
33446+ return err;
33447+}
33448+
1facf9fc 33449+/* ---------------------------------------------------------------------- */
33450+
33451+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
33452+ [AuWbrCopyup_TDP] = {
33453+ .copyup = au_wbr_copyup_tdp
33454+ },
33455+ [AuWbrCopyup_BUP] = {
33456+ .copyup = au_wbr_copyup_bup
33457+ },
33458+ [AuWbrCopyup_BU] = {
33459+ .copyup = au_wbr_copyup_bu
33460+ }
33461+};
33462+
33463+struct au_wbr_create_operations au_wbr_create_ops[] = {
33464+ [AuWbrCreate_TDP] = {
33465+ .create = au_wbr_create_tdp
33466+ },
33467+ [AuWbrCreate_RR] = {
33468+ .create = au_wbr_create_rr,
33469+ .init = au_wbr_create_init_rr
33470+ },
33471+ [AuWbrCreate_MFS] = {
33472+ .create = au_wbr_create_mfs,
33473+ .init = au_wbr_create_init_mfs,
33474+ .fin = au_wbr_create_fin_mfs
33475+ },
33476+ [AuWbrCreate_MFSV] = {
33477+ .create = au_wbr_create_mfs,
33478+ .init = au_wbr_create_init_mfs,
33479+ .fin = au_wbr_create_fin_mfs
33480+ },
33481+ [AuWbrCreate_MFSRR] = {
33482+ .create = au_wbr_create_mfsrr,
33483+ .init = au_wbr_create_init_mfsrr,
33484+ .fin = au_wbr_create_fin_mfs
33485+ },
33486+ [AuWbrCreate_MFSRRV] = {
33487+ .create = au_wbr_create_mfsrr,
33488+ .init = au_wbr_create_init_mfsrr,
33489+ .fin = au_wbr_create_fin_mfs
33490+ },
f2c43d5f
AM
33491+ [AuWbrCreate_TDMFS] = {
33492+ .create = au_wbr_create_tdmfs,
33493+ .init = au_wbr_create_init_mfs,
33494+ .fin = au_wbr_create_fin_mfs
33495+ },
33496+ [AuWbrCreate_TDMFSV] = {
33497+ .create = au_wbr_create_tdmfs,
33498+ .init = au_wbr_create_init_mfs,
33499+ .fin = au_wbr_create_fin_mfs
33500+ },
1facf9fc 33501+ [AuWbrCreate_PMFS] = {
33502+ .create = au_wbr_create_pmfs,
33503+ .init = au_wbr_create_init_mfs,
33504+ .fin = au_wbr_create_fin_mfs
33505+ },
33506+ [AuWbrCreate_PMFSV] = {
33507+ .create = au_wbr_create_pmfs,
33508+ .init = au_wbr_create_init_mfs,
33509+ .fin = au_wbr_create_fin_mfs
392086de
AM
33510+ },
33511+ [AuWbrCreate_PMFSRR] = {
33512+ .create = au_wbr_create_pmfsrr,
33513+ .init = au_wbr_create_init_mfsrr,
33514+ .fin = au_wbr_create_fin_mfs
33515+ },
33516+ [AuWbrCreate_PMFSRRV] = {
33517+ .create = au_wbr_create_pmfsrr,
33518+ .init = au_wbr_create_init_mfsrr,
33519+ .fin = au_wbr_create_fin_mfs
1facf9fc 33520+ }
33521+};
0b1ff5c3
JR
33522diff -urNp -x '*.orig' linux-4.14/fs/aufs/whout.c linux-4.14/fs/aufs/whout.c
33523--- linux-4.14/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
33524+++ linux-4.14/fs/aufs/whout.c 2021-02-24 21:42:43.447781402 +0100
f2c43d5f 33525@@ -0,0 +1,1061 @@
1facf9fc 33526+/*
a2654f78 33527+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 33528+ *
33529+ * This program, aufs is free software; you can redistribute it and/or modify
33530+ * it under the terms of the GNU General Public License as published by
33531+ * the Free Software Foundation; either version 2 of the License, or
33532+ * (at your option) any later version.
dece6358
AM
33533+ *
33534+ * This program is distributed in the hope that it will be useful,
33535+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
33536+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33537+ * GNU General Public License for more details.
33538+ *
33539+ * You should have received a copy of the GNU General Public License
523b37e3 33540+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 33541+ */
33542+
33543+/*
33544+ * whiteout for logical deletion and opaque directory
33545+ */
33546+
1facf9fc 33547+#include "aufs.h"
33548+
33549+#define WH_MASK S_IRUGO
33550+
33551+/*
33552+ * If a directory contains this file, then it is opaque. We start with the
33553+ * .wh. flag so that it is blocked by lookup.
33554+ */
0c3ec466
AM
33555+static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ,
33556+ sizeof(AUFS_WH_DIROPQ) - 1);
1facf9fc 33557+
33558+/*
33559+ * generate whiteout name, which is NOT terminated by NULL.
33560+ * @name: original d_name.name
33561+ * @len: original d_name.len
33562+ * @wh: whiteout qstr
33563+ * returns zero when succeeds, otherwise error.
33564+ * succeeded value as wh->name should be freed by kfree().
33565+ */
33566+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
33567+{
33568+ char *p;
33569+
33570+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
33571+ return -ENAMETOOLONG;
33572+
33573+ wh->len = name->len + AUFS_WH_PFX_LEN;
33574+ p = kmalloc(wh->len, GFP_NOFS);
33575+ wh->name = p;
33576+ if (p) {
33577+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
33578+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
33579+ /* smp_mb(); */
33580+ return 0;
33581+ }
33582+ return -ENOMEM;
33583+}
33584+
33585+/* ---------------------------------------------------------------------- */
33586+
33587+/*
33588+ * test if the @wh_name exists under @h_parent.
33589+ * @try_sio specifies the necessary of super-io.
33590+ */
076b876e 33591+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio)
1facf9fc 33592+{
33593+ int err;
33594+ struct dentry *wh_dentry;
1facf9fc 33595+
1facf9fc 33596+ if (!try_sio)
b4510431 33597+ wh_dentry = vfsub_lkup_one(wh_name, h_parent);
1facf9fc 33598+ else
076b876e 33599+ wh_dentry = au_sio_lkup_one(wh_name, h_parent);
1facf9fc 33600+ err = PTR_ERR(wh_dentry);
2000de60
JR
33601+ if (IS_ERR(wh_dentry)) {
33602+ if (err == -ENAMETOOLONG)
33603+ err = 0;
1facf9fc 33604+ goto out;
2000de60 33605+ }
1facf9fc 33606+
33607+ err = 0;
5527c038 33608+ if (d_is_negative(wh_dentry))
1facf9fc 33609+ goto out_wh; /* success */
33610+
33611+ err = 1;
7e9cd9fe 33612+ if (d_is_reg(wh_dentry))
1facf9fc 33613+ goto out_wh; /* success */
33614+
33615+ err = -EIO;
523b37e3 33616+ AuIOErr("%pd Invalid whiteout entry type 0%o.\n",
5527c038 33617+ wh_dentry, d_inode(wh_dentry)->i_mode);
1facf9fc 33618+
4f0767ce 33619+out_wh:
1facf9fc 33620+ dput(wh_dentry);
4f0767ce 33621+out:
1facf9fc 33622+ return err;
33623+}
33624+
33625+/*
33626+ * test if the @h_dentry sets opaque or not.
33627+ */
076b876e 33628+int au_diropq_test(struct dentry *h_dentry)
1facf9fc 33629+{
33630+ int err;
33631+ struct inode *h_dir;
33632+
5527c038 33633+ h_dir = d_inode(h_dentry);
076b876e 33634+ err = au_wh_test(h_dentry, &diropq_name,
1facf9fc 33635+ au_test_h_perm_sio(h_dir, MAY_EXEC));
33636+ return err;
33637+}
33638+
33639+/*
33640+ * returns a negative dentry whose name is unique and temporary.
33641+ */
33642+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
33643+ struct qstr *prefix)
33644+{
1facf9fc 33645+ struct dentry *dentry;
33646+ int i;
027c5e7a 33647+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1],
4a4d8108 33648+ *name, *p;
027c5e7a 33649+ /* strict atomic_t is unnecessary here */
1facf9fc 33650+ static unsigned short cnt;
33651+ struct qstr qs;
33652+
4a4d8108
AM
33653+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
33654+
1facf9fc 33655+ name = defname;
027c5e7a
AM
33656+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1;
33657+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) {
1facf9fc 33658+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 33659+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 33660+ goto out;
33661+ dentry = ERR_PTR(-ENOMEM);
33662+ name = kmalloc(qs.len + 1, GFP_NOFS);
33663+ if (unlikely(!name))
33664+ goto out;
33665+ }
33666+
33667+ /* doubly whiteout-ed */
33668+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
33669+ p = name + AUFS_WH_PFX_LEN * 2;
33670+ memcpy(p, prefix->name, prefix->len);
33671+ p += prefix->len;
33672+ *p++ = '.';
4a4d8108 33673+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 33674+
33675+ qs.name = name;
33676+ for (i = 0; i < 3; i++) {
b752ccd1 33677+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
076b876e 33678+ dentry = au_sio_lkup_one(&qs, h_parent);
5527c038 33679+ if (IS_ERR(dentry) || d_is_negative(dentry))
1facf9fc 33680+ goto out_name;
33681+ dput(dentry);
33682+ }
0c3ec466 33683+ /* pr_warn("could not get random name\n"); */
1facf9fc 33684+ dentry = ERR_PTR(-EEXIST);
33685+ AuDbg("%.*s\n", AuLNPair(&qs));
33686+ BUG();
33687+
4f0767ce 33688+out_name:
1facf9fc 33689+ if (name != defname)
1c60b727 33690+ kfree(name);
4f0767ce 33691+out:
4a4d8108 33692+ AuTraceErrPtr(dentry);
1facf9fc 33693+ return dentry;
1facf9fc 33694+}
33695+
33696+/*
33697+ * rename the @h_dentry on @br to the whiteouted temporary name.
33698+ */
33699+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
33700+{
33701+ int err;
33702+ struct path h_path = {
86dc4139 33703+ .mnt = au_br_mnt(br)
1facf9fc 33704+ };
523b37e3 33705+ struct inode *h_dir, *delegated;
1facf9fc 33706+ struct dentry *h_parent;
33707+
33708+ h_parent = h_dentry->d_parent; /* dir inode is locked */
5527c038 33709+ h_dir = d_inode(h_parent);
1facf9fc 33710+ IMustLock(h_dir);
33711+
33712+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
33713+ err = PTR_ERR(h_path.dentry);
33714+ if (IS_ERR(h_path.dentry))
33715+ goto out;
33716+
33717+ /* under the same dir, no need to lock_rename() */
523b37e3 33718+ delegated = NULL;
f2c43d5f
AM
33719+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path, &delegated,
33720+ /*flags*/0);
1facf9fc 33721+ AuTraceErr(err);
523b37e3
AM
33722+ if (unlikely(err == -EWOULDBLOCK)) {
33723+ pr_warn("cannot retry for NFSv4 delegation"
33724+ " for an internal rename\n");
33725+ iput(delegated);
33726+ }
1facf9fc 33727+ dput(h_path.dentry);
33728+
4f0767ce 33729+out:
4a4d8108 33730+ AuTraceErr(err);
1facf9fc 33731+ return err;
33732+}
33733+
33734+/* ---------------------------------------------------------------------- */
33735+/*
33736+ * functions for removing a whiteout
33737+ */
33738+
33739+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
33740+{
523b37e3
AM
33741+ int err, force;
33742+ struct inode *delegated;
1facf9fc 33743+
33744+ /*
33745+ * forces superio when the dir has a sticky bit.
33746+ * this may be a violation of unix fs semantics.
33747+ */
33748+ force = (h_dir->i_mode & S_ISVTX)
5527c038 33749+ && !uid_eq(current_fsuid(), d_inode(h_path->dentry)->i_uid);
523b37e3
AM
33750+ delegated = NULL;
33751+ err = vfsub_unlink(h_dir, h_path, &delegated, force);
33752+ if (unlikely(err == -EWOULDBLOCK)) {
33753+ pr_warn("cannot retry for NFSv4 delegation"
33754+ " for an internal unlink\n");
33755+ iput(delegated);
33756+ }
33757+ return err;
1facf9fc 33758+}
33759+
33760+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
33761+ struct dentry *dentry)
33762+{
33763+ int err;
33764+
33765+ err = do_unlink_wh(h_dir, h_path);
33766+ if (!err && dentry)
33767+ au_set_dbwh(dentry, -1);
33768+
33769+ return err;
33770+}
33771+
33772+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
33773+ struct au_branch *br)
33774+{
33775+ int err;
33776+ struct path h_path = {
86dc4139 33777+ .mnt = au_br_mnt(br)
1facf9fc 33778+ };
33779+
33780+ err = 0;
b4510431 33781+ h_path.dentry = vfsub_lkup_one(wh, h_parent);
1facf9fc 33782+ if (IS_ERR(h_path.dentry))
33783+ err = PTR_ERR(h_path.dentry);
33784+ else {
5527c038
JR
33785+ if (d_is_reg(h_path.dentry))
33786+ err = do_unlink_wh(d_inode(h_parent), &h_path);
1facf9fc 33787+ dput(h_path.dentry);
33788+ }
33789+
33790+ return err;
33791+}
33792+
33793+/* ---------------------------------------------------------------------- */
33794+/*
33795+ * initialize/clean whiteout for a branch
33796+ */
33797+
33798+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
33799+ const int isdir)
33800+{
33801+ int err;
523b37e3 33802+ struct inode *delegated;
1facf9fc 33803+
5527c038 33804+ if (d_is_negative(whpath->dentry))
1facf9fc 33805+ return;
33806+
86dc4139
AM
33807+ if (isdir)
33808+ err = vfsub_rmdir(h_dir, whpath);
523b37e3
AM
33809+ else {
33810+ delegated = NULL;
33811+ err = vfsub_unlink(h_dir, whpath, &delegated, /*force*/0);
33812+ if (unlikely(err == -EWOULDBLOCK)) {
33813+ pr_warn("cannot retry for NFSv4 delegation"
33814+ " for an internal unlink\n");
33815+ iput(delegated);
33816+ }
33817+ }
1facf9fc 33818+ if (unlikely(err))
523b37e3
AM
33819+ pr_warn("failed removing %pd (%d), ignored.\n",
33820+ whpath->dentry, err);
1facf9fc 33821+}
33822+
33823+static int test_linkable(struct dentry *h_root)
33824+{
5527c038 33825+ struct inode *h_dir = d_inode(h_root);
1facf9fc 33826+
33827+ if (h_dir->i_op->link)
33828+ return 0;
33829+
523b37e3
AM
33830+ pr_err("%pd (%s) doesn't support link(2), use noplink and rw+nolwh\n",
33831+ h_root, au_sbtype(h_root->d_sb));
1facf9fc 33832+ return -ENOSYS;
33833+}
33834+
33835+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
33836+static int au_whdir(struct inode *h_dir, struct path *path)
33837+{
33838+ int err;
33839+
33840+ err = -EEXIST;
5527c038 33841+ if (d_is_negative(path->dentry)) {
1facf9fc 33842+ int mode = S_IRWXU;
33843+
33844+ if (au_test_nfs(path->dentry->d_sb))
33845+ mode |= S_IXUGO;
86dc4139 33846+ err = vfsub_mkdir(h_dir, path, mode);
2000de60 33847+ } else if (d_is_dir(path->dentry))
1facf9fc 33848+ err = 0;
33849+ else
523b37e3 33850+ pr_err("unknown %pd exists\n", path->dentry);
1facf9fc 33851+
33852+ return err;
33853+}
33854+
33855+struct au_wh_base {
33856+ const struct qstr *name;
33857+ struct dentry *dentry;
33858+};
33859+
33860+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
33861+ struct path *h_path)
33862+{
33863+ h_path->dentry = base[AuBrWh_BASE].dentry;
33864+ au_wh_clean(h_dir, h_path, /*isdir*/0);
33865+ h_path->dentry = base[AuBrWh_PLINK].dentry;
33866+ au_wh_clean(h_dir, h_path, /*isdir*/1);
33867+ h_path->dentry = base[AuBrWh_ORPH].dentry;
33868+ au_wh_clean(h_dir, h_path, /*isdir*/1);
33869+}
33870+
33871+/*
33872+ * returns tri-state,
c1595e42 33873+ * minus: error, caller should print the message
1facf9fc 33874+ * zero: succuess
c1595e42 33875+ * plus: error, caller should NOT print the message
1facf9fc 33876+ */
33877+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
33878+ int do_plink, struct au_wh_base base[],
33879+ struct path *h_path)
33880+{
33881+ int err;
33882+ struct inode *h_dir;
33883+
5527c038 33884+ h_dir = d_inode(h_root);
1facf9fc 33885+ h_path->dentry = base[AuBrWh_BASE].dentry;
33886+ au_wh_clean(h_dir, h_path, /*isdir*/0);
33887+ h_path->dentry = base[AuBrWh_PLINK].dentry;
33888+ if (do_plink) {
33889+ err = test_linkable(h_root);
33890+ if (unlikely(err)) {
33891+ err = 1;
33892+ goto out;
33893+ }
33894+
33895+ err = au_whdir(h_dir, h_path);
33896+ if (unlikely(err))
33897+ goto out;
33898+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
33899+ } else
33900+ au_wh_clean(h_dir, h_path, /*isdir*/1);
33901+ h_path->dentry = base[AuBrWh_ORPH].dentry;
33902+ err = au_whdir(h_dir, h_path);
33903+ if (unlikely(err))
33904+ goto out;
33905+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
33906+
4f0767ce 33907+out:
1facf9fc 33908+ return err;
33909+}
33910+
33911+/*
33912+ * for the moment, aufs supports the branch filesystem which does not support
33913+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
33914+ * copyup failed. finally, such filesystem will not be used as the writable
33915+ * branch.
33916+ *
33917+ * returns tri-state, see above.
33918+ */
33919+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
33920+ int do_plink, struct au_wh_base base[],
33921+ struct path *h_path)
33922+{
33923+ int err;
33924+ struct inode *h_dir;
33925+
1308ab2a 33926+ WbrWhMustWriteLock(wbr);
33927+
1facf9fc 33928+ err = test_linkable(h_root);
33929+ if (unlikely(err)) {
33930+ err = 1;
33931+ goto out;
33932+ }
33933+
33934+ /*
33935+ * todo: should this create be done in /sbin/mount.aufs helper?
33936+ */
33937+ err = -EEXIST;
5527c038
JR
33938+ h_dir = d_inode(h_root);
33939+ if (d_is_negative(base[AuBrWh_BASE].dentry)) {
86dc4139
AM
33940+ h_path->dentry = base[AuBrWh_BASE].dentry;
33941+ err = vfsub_create(h_dir, h_path, WH_MASK, /*want_excl*/true);
7e9cd9fe 33942+ } else if (d_is_reg(base[AuBrWh_BASE].dentry))
1facf9fc 33943+ err = 0;
33944+ else
523b37e3 33945+ pr_err("unknown %pd2 exists\n", base[AuBrWh_BASE].dentry);
1facf9fc 33946+ if (unlikely(err))
33947+ goto out;
33948+
33949+ h_path->dentry = base[AuBrWh_PLINK].dentry;
33950+ if (do_plink) {
33951+ err = au_whdir(h_dir, h_path);
33952+ if (unlikely(err))
33953+ goto out;
33954+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
33955+ } else
33956+ au_wh_clean(h_dir, h_path, /*isdir*/1);
33957+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
33958+
33959+ h_path->dentry = base[AuBrWh_ORPH].dentry;
33960+ err = au_whdir(h_dir, h_path);
33961+ if (unlikely(err))
33962+ goto out;
33963+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
33964+
4f0767ce 33965+out:
1facf9fc 33966+ return err;
33967+}
33968+
33969+/*
33970+ * initialize the whiteout base file/dir for @br.
33971+ */
86dc4139 33972+int au_wh_init(struct au_branch *br, struct super_block *sb)
1facf9fc 33973+{
33974+ int err, i;
33975+ const unsigned char do_plink
33976+ = !!au_opt_test(au_mntflags(sb), PLINK);
1facf9fc 33977+ struct inode *h_dir;
86dc4139
AM
33978+ struct path path = br->br_path;
33979+ struct dentry *h_root = path.dentry;
1facf9fc 33980+ struct au_wbr *wbr = br->br_wbr;
33981+ static const struct qstr base_name[] = {
0c3ec466
AM
33982+ [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME,
33983+ sizeof(AUFS_BASE_NAME) - 1),
33984+ [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME,
33985+ sizeof(AUFS_PLINKDIR_NAME) - 1),
33986+ [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME,
33987+ sizeof(AUFS_ORPHDIR_NAME) - 1)
1facf9fc 33988+ };
33989+ struct au_wh_base base[] = {
33990+ [AuBrWh_BASE] = {
33991+ .name = base_name + AuBrWh_BASE,
33992+ .dentry = NULL
33993+ },
33994+ [AuBrWh_PLINK] = {
33995+ .name = base_name + AuBrWh_PLINK,
33996+ .dentry = NULL
33997+ },
33998+ [AuBrWh_ORPH] = {
33999+ .name = base_name + AuBrWh_ORPH,
34000+ .dentry = NULL
34001+ }
34002+ };
34003+
1308ab2a 34004+ if (wbr)
34005+ WbrWhMustWriteLock(wbr);
1facf9fc 34006+
1facf9fc 34007+ for (i = 0; i < AuBrWh_Last; i++) {
34008+ /* doubly whiteouted */
34009+ struct dentry *d;
34010+
34011+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
34012+ err = PTR_ERR(d);
34013+ if (IS_ERR(d))
34014+ goto out;
34015+
34016+ base[i].dentry = d;
34017+ AuDebugOn(wbr
34018+ && wbr->wbr_wh[i]
34019+ && wbr->wbr_wh[i] != base[i].dentry);
34020+ }
34021+
34022+ if (wbr)
34023+ for (i = 0; i < AuBrWh_Last; i++) {
34024+ dput(wbr->wbr_wh[i]);
34025+ wbr->wbr_wh[i] = NULL;
34026+ }
34027+
34028+ err = 0;
1e00d052 34029+ if (!au_br_writable(br->br_perm)) {
5527c038 34030+ h_dir = d_inode(h_root);
1facf9fc 34031+ au_wh_init_ro(h_dir, base, &path);
1e00d052 34032+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 34033+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
34034+ if (err > 0)
34035+ goto out;
34036+ else if (err)
34037+ goto out_err;
1e00d052 34038+ } else {
1facf9fc 34039+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
34040+ if (err > 0)
34041+ goto out;
34042+ else if (err)
34043+ goto out_err;
1facf9fc 34044+ }
34045+ goto out; /* success */
34046+
4f0767ce 34047+out_err:
523b37e3
AM
34048+ pr_err("an error(%d) on the writable branch %pd(%s)\n",
34049+ err, h_root, au_sbtype(h_root->d_sb));
4f0767ce 34050+out:
1facf9fc 34051+ for (i = 0; i < AuBrWh_Last; i++)
34052+ dput(base[i].dentry);
34053+ return err;
34054+}
34055+
34056+/* ---------------------------------------------------------------------- */
34057+/*
34058+ * whiteouts are all hard-linked usually.
34059+ * when its link count reaches a ceiling, we create a new whiteout base
34060+ * asynchronously.
34061+ */
34062+
34063+struct reinit_br_wh {
34064+ struct super_block *sb;
34065+ struct au_branch *br;
34066+};
34067+
34068+static void reinit_br_wh(void *arg)
34069+{
34070+ int err;
34071+ aufs_bindex_t bindex;
34072+ struct path h_path;
34073+ struct reinit_br_wh *a = arg;
34074+ struct au_wbr *wbr;
523b37e3 34075+ struct inode *dir, *delegated;
1facf9fc 34076+ struct dentry *h_root;
34077+ struct au_hinode *hdir;
34078+
34079+ err = 0;
34080+ wbr = a->br->br_wbr;
34081+ /* big aufs lock */
34082+ si_noflush_write_lock(a->sb);
34083+ if (!au_br_writable(a->br->br_perm))
34084+ goto out;
34085+ bindex = au_br_index(a->sb, a->br->br_id);
34086+ if (unlikely(bindex < 0))
34087+ goto out;
34088+
1308ab2a 34089+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
5527c038 34090+ dir = d_inode(a->sb->s_root);
1facf9fc 34091+ hdir = au_hi(dir, bindex);
34092+ h_root = au_h_dptr(a->sb->s_root, bindex);
86dc4139 34093+ AuDebugOn(h_root != au_br_dentry(a->br));
1facf9fc 34094+
5afbbe0d 34095+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 34096+ wbr_wh_write_lock(wbr);
34097+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
34098+ h_root, a->br);
34099+ if (!err) {
86dc4139
AM
34100+ h_path.dentry = wbr->wbr_whbase;
34101+ h_path.mnt = au_br_mnt(a->br);
523b37e3
AM
34102+ delegated = NULL;
34103+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated,
34104+ /*force*/0);
34105+ if (unlikely(err == -EWOULDBLOCK)) {
34106+ pr_warn("cannot retry for NFSv4 delegation"
34107+ " for an internal unlink\n");
34108+ iput(delegated);
34109+ }
1facf9fc 34110+ } else {
523b37e3 34111+ pr_warn("%pd is moved, ignored\n", wbr->wbr_whbase);
1facf9fc 34112+ err = 0;
34113+ }
34114+ dput(wbr->wbr_whbase);
34115+ wbr->wbr_whbase = NULL;
34116+ if (!err)
86dc4139 34117+ err = au_wh_init(a->br, a->sb);
1facf9fc 34118+ wbr_wh_write_unlock(wbr);
5afbbe0d 34119+ au_hn_inode_unlock(hdir);
1308ab2a 34120+ di_read_unlock(a->sb->s_root, AuLock_IR);
076b876e
AM
34121+ if (!err)
34122+ au_fhsm_wrote(a->sb, bindex, /*force*/0);
1facf9fc 34123+
4f0767ce 34124+out:
1facf9fc 34125+ if (wbr)
34126+ atomic_dec(&wbr->wbr_wh_running);
5afbbe0d 34127+ au_br_put(a->br);
1facf9fc 34128+ si_write_unlock(a->sb);
027c5e7a 34129+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
1c60b727 34130+ kfree(arg);
1facf9fc 34131+ if (unlikely(err))
34132+ AuIOErr("err %d\n", err);
34133+}
34134+
34135+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
34136+{
34137+ int do_dec, wkq_err;
34138+ struct reinit_br_wh *arg;
34139+
34140+ do_dec = 1;
34141+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
34142+ goto out;
34143+
34144+ /* ignore ENOMEM */
34145+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
34146+ if (arg) {
34147+ /*
34148+ * dec(wh_running), kfree(arg) and dec(br_count)
34149+ * in reinit function
34150+ */
34151+ arg->sb = sb;
34152+ arg->br = br;
5afbbe0d 34153+ au_br_get(br);
53392da6 34154+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0);
1facf9fc 34155+ if (unlikely(wkq_err)) {
34156+ atomic_dec(&br->br_wbr->wbr_wh_running);
5afbbe0d 34157+ au_br_put(br);
1c60b727 34158+ kfree(arg);
1facf9fc 34159+ }
34160+ do_dec = 0;
34161+ }
34162+
4f0767ce 34163+out:
1facf9fc 34164+ if (do_dec)
34165+ atomic_dec(&br->br_wbr->wbr_wh_running);
34166+}
34167+
34168+/* ---------------------------------------------------------------------- */
34169+
34170+/*
34171+ * create the whiteout @wh.
34172+ */
34173+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
34174+ struct dentry *wh)
34175+{
34176+ int err;
34177+ struct path h_path = {
34178+ .dentry = wh
34179+ };
34180+ struct au_branch *br;
34181+ struct au_wbr *wbr;
34182+ struct dentry *h_parent;
523b37e3 34183+ struct inode *h_dir, *delegated;
1facf9fc 34184+
34185+ h_parent = wh->d_parent; /* dir inode is locked */
5527c038 34186+ h_dir = d_inode(h_parent);
1facf9fc 34187+ IMustLock(h_dir);
34188+
34189+ br = au_sbr(sb, bindex);
86dc4139 34190+ h_path.mnt = au_br_mnt(br);
1facf9fc 34191+ wbr = br->br_wbr;
34192+ wbr_wh_read_lock(wbr);
34193+ if (wbr->wbr_whbase) {
523b37e3
AM
34194+ delegated = NULL;
34195+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path, &delegated);
34196+ if (unlikely(err == -EWOULDBLOCK)) {
34197+ pr_warn("cannot retry for NFSv4 delegation"
34198+ " for an internal link\n");
34199+ iput(delegated);
34200+ }
1facf9fc 34201+ if (!err || err != -EMLINK)
34202+ goto out;
34203+
34204+ /* link count full. re-initialize br_whbase. */
34205+ kick_reinit_br_wh(sb, br);
34206+ }
34207+
34208+ /* return this error in this context */
b4510431 34209+ err = vfsub_create(h_dir, &h_path, WH_MASK, /*want_excl*/true);
076b876e
AM
34210+ if (!err)
34211+ au_fhsm_wrote(sb, bindex, /*force*/0);
1facf9fc 34212+
4f0767ce 34213+out:
1facf9fc 34214+ wbr_wh_read_unlock(wbr);
34215+ return err;
34216+}
34217+
34218+/* ---------------------------------------------------------------------- */
34219+
34220+/*
34221+ * create or remove the diropq.
34222+ */
34223+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
34224+ unsigned int flags)
34225+{
34226+ struct dentry *opq_dentry, *h_dentry;
34227+ struct super_block *sb;
34228+ struct au_branch *br;
34229+ int err;
34230+
34231+ sb = dentry->d_sb;
34232+ br = au_sbr(sb, bindex);
34233+ h_dentry = au_h_dptr(dentry, bindex);
b4510431 34234+ opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry);
1facf9fc 34235+ if (IS_ERR(opq_dentry))
34236+ goto out;
34237+
34238+ if (au_ftest_diropq(flags, CREATE)) {
34239+ err = link_or_create_wh(sb, bindex, opq_dentry);
34240+ if (!err) {
34241+ au_set_dbdiropq(dentry, bindex);
34242+ goto out; /* success */
34243+ }
34244+ } else {
34245+ struct path tmp = {
34246+ .dentry = opq_dentry,
86dc4139 34247+ .mnt = au_br_mnt(br)
1facf9fc 34248+ };
5527c038 34249+ err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &tmp);
1facf9fc 34250+ if (!err)
34251+ au_set_dbdiropq(dentry, -1);
34252+ }
34253+ dput(opq_dentry);
34254+ opq_dentry = ERR_PTR(err);
34255+
4f0767ce 34256+out:
1facf9fc 34257+ return opq_dentry;
34258+}
34259+
34260+struct do_diropq_args {
34261+ struct dentry **errp;
34262+ struct dentry *dentry;
34263+ aufs_bindex_t bindex;
34264+ unsigned int flags;
34265+};
34266+
34267+static void call_do_diropq(void *args)
34268+{
34269+ struct do_diropq_args *a = args;
34270+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
34271+}
34272+
34273+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
34274+ unsigned int flags)
34275+{
34276+ struct dentry *diropq, *h_dentry;
34277+
34278+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 34279+ if (!au_test_h_perm_sio(d_inode(h_dentry), MAY_EXEC | MAY_WRITE))
1facf9fc 34280+ diropq = do_diropq(dentry, bindex, flags);
34281+ else {
34282+ int wkq_err;
34283+ struct do_diropq_args args = {
34284+ .errp = &diropq,
34285+ .dentry = dentry,
34286+ .bindex = bindex,
34287+ .flags = flags
34288+ };
34289+
34290+ wkq_err = au_wkq_wait(call_do_diropq, &args);
34291+ if (unlikely(wkq_err))
34292+ diropq = ERR_PTR(wkq_err);
34293+ }
34294+
34295+ return diropq;
34296+}
34297+
34298+/* ---------------------------------------------------------------------- */
34299+
34300+/*
34301+ * lookup whiteout dentry.
34302+ * @h_parent: lower parent dentry which must exist and be locked
34303+ * @base_name: name of dentry which will be whiteouted
34304+ * returns dentry for whiteout.
34305+ */
34306+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
34307+ struct au_branch *br)
34308+{
34309+ int err;
34310+ struct qstr wh_name;
34311+ struct dentry *wh_dentry;
34312+
34313+ err = au_wh_name_alloc(&wh_name, base_name);
34314+ wh_dentry = ERR_PTR(err);
34315+ if (!err) {
b4510431 34316+ wh_dentry = vfsub_lkup_one(&wh_name, h_parent);
1c60b727 34317+ kfree(wh_name.name);
1facf9fc 34318+ }
34319+ return wh_dentry;
34320+}
34321+
34322+/*
34323+ * link/create a whiteout for @dentry on @bindex.
34324+ */
34325+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
34326+ struct dentry *h_parent)
34327+{
34328+ struct dentry *wh_dentry;
34329+ struct super_block *sb;
34330+ int err;
34331+
34332+ sb = dentry->d_sb;
34333+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
5527c038 34334+ if (!IS_ERR(wh_dentry) && d_is_negative(wh_dentry)) {
1facf9fc 34335+ err = link_or_create_wh(sb, bindex, wh_dentry);
076b876e 34336+ if (!err) {
1facf9fc 34337+ au_set_dbwh(dentry, bindex);
076b876e
AM
34338+ au_fhsm_wrote(sb, bindex, /*force*/0);
34339+ } else {
1facf9fc 34340+ dput(wh_dentry);
34341+ wh_dentry = ERR_PTR(err);
34342+ }
34343+ }
34344+
34345+ return wh_dentry;
34346+}
34347+
34348+/* ---------------------------------------------------------------------- */
34349+
34350+/* Delete all whiteouts in this directory on branch bindex. */
34351+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
34352+ aufs_bindex_t bindex, struct au_branch *br)
34353+{
34354+ int err;
34355+ unsigned long ul, n;
34356+ struct qstr wh_name;
34357+ char *p;
34358+ struct hlist_head *head;
c06a8ce3 34359+ struct au_vdir_wh *pos;
1facf9fc 34360+ struct au_vdir_destr *str;
34361+
34362+ err = -ENOMEM;
537831f9 34363+ p = (void *)__get_free_page(GFP_NOFS);
1facf9fc 34364+ wh_name.name = p;
34365+ if (unlikely(!wh_name.name))
34366+ goto out;
34367+
34368+ err = 0;
34369+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
34370+ p += AUFS_WH_PFX_LEN;
34371+ n = whlist->nh_num;
34372+ head = whlist->nh_head;
34373+ for (ul = 0; !err && ul < n; ul++, head++) {
c06a8ce3
AM
34374+ hlist_for_each_entry(pos, head, wh_hash) {
34375+ if (pos->wh_bindex != bindex)
1facf9fc 34376+ continue;
34377+
c06a8ce3 34378+ str = &pos->wh_str;
1facf9fc 34379+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
34380+ memcpy(p, str->name, str->len);
34381+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
34382+ err = unlink_wh_name(h_dentry, &wh_name, br);
34383+ if (!err)
34384+ continue;
34385+ break;
34386+ }
34387+ AuIOErr("whiteout name too long %.*s\n",
34388+ str->len, str->name);
34389+ err = -EIO;
34390+ break;
34391+ }
34392+ }
1c60b727 34393+ free_page((unsigned long)wh_name.name);
1facf9fc 34394+
4f0767ce 34395+out:
1facf9fc 34396+ return err;
34397+}
34398+
34399+struct del_wh_children_args {
34400+ int *errp;
34401+ struct dentry *h_dentry;
1308ab2a 34402+ struct au_nhash *whlist;
1facf9fc 34403+ aufs_bindex_t bindex;
34404+ struct au_branch *br;
34405+};
34406+
34407+static void call_del_wh_children(void *args)
34408+{
34409+ struct del_wh_children_args *a = args;
1308ab2a 34410+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 34411+}
34412+
34413+/* ---------------------------------------------------------------------- */
34414+
34415+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
34416+{
34417+ struct au_whtmp_rmdir *whtmp;
dece6358 34418+ int err;
1308ab2a 34419+ unsigned int rdhash;
dece6358
AM
34420+
34421+ SiMustAnyLock(sb);
1facf9fc 34422+
be52b249 34423+ whtmp = kzalloc(sizeof(*whtmp), gfp);
dece6358
AM
34424+ if (unlikely(!whtmp)) {
34425+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 34426+ goto out;
dece6358 34427+ }
1facf9fc 34428+
1308ab2a 34429+ /* no estimation for dir size */
34430+ rdhash = au_sbi(sb)->si_rdhash;
34431+ if (!rdhash)
34432+ rdhash = AUFS_RDHASH_DEF;
34433+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
34434+ if (unlikely(err)) {
1c60b727 34435+ kfree(whtmp);
1308ab2a 34436+ whtmp = ERR_PTR(err);
34437+ }
dece6358 34438+
4f0767ce 34439+out:
dece6358 34440+ return whtmp;
1facf9fc 34441+}
34442+
34443+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
34444+{
027c5e7a 34445+ if (whtmp->br)
5afbbe0d 34446+ au_br_put(whtmp->br);
1facf9fc 34447+ dput(whtmp->wh_dentry);
34448+ iput(whtmp->dir);
dece6358 34449+ au_nhash_wh_free(&whtmp->whlist);
1c60b727 34450+ kfree(whtmp);
1facf9fc 34451+}
34452+
34453+/*
34454+ * rmdir the whiteouted temporary named dir @h_dentry.
34455+ * @whlist: whiteouted children.
34456+ */
34457+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
34458+ struct dentry *wh_dentry, struct au_nhash *whlist)
34459+{
34460+ int err;
2000de60 34461+ unsigned int h_nlink;
1facf9fc 34462+ struct path h_tmp;
34463+ struct inode *wh_inode, *h_dir;
34464+ struct au_branch *br;
34465+
5527c038 34466+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */
1facf9fc 34467+ IMustLock(h_dir);
34468+
34469+ br = au_sbr(dir->i_sb, bindex);
5527c038 34470+ wh_inode = d_inode(wh_dentry);
febd17d6 34471+ inode_lock_nested(wh_inode, AuLsc_I_CHILD);
1facf9fc 34472+
34473+ /*
34474+ * someone else might change some whiteouts while we were sleeping.
34475+ * it means this whlist may have an obsoleted entry.
34476+ */
34477+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
34478+ err = del_wh_children(wh_dentry, whlist, bindex, br);
34479+ else {
34480+ int wkq_err;
34481+ struct del_wh_children_args args = {
34482+ .errp = &err,
34483+ .h_dentry = wh_dentry,
1308ab2a 34484+ .whlist = whlist,
1facf9fc 34485+ .bindex = bindex,
34486+ .br = br
34487+ };
34488+
34489+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
34490+ if (unlikely(wkq_err))
34491+ err = wkq_err;
34492+ }
febd17d6 34493+ inode_unlock(wh_inode);
1facf9fc 34494+
34495+ if (!err) {
34496+ h_tmp.dentry = wh_dentry;
86dc4139 34497+ h_tmp.mnt = au_br_mnt(br);
2000de60 34498+ h_nlink = h_dir->i_nlink;
1facf9fc 34499+ err = vfsub_rmdir(h_dir, &h_tmp);
2000de60
JR
34500+ /* some fs doesn't change the parent nlink in some cases */
34501+ h_nlink -= h_dir->i_nlink;
1facf9fc 34502+ }
34503+
34504+ if (!err) {
5afbbe0d 34505+ if (au_ibtop(dir) == bindex) {
7f207e10 34506+ /* todo: dir->i_mutex is necessary */
1facf9fc 34507+ au_cpup_attr_timesizes(dir);
2000de60
JR
34508+ if (h_nlink)
34509+ vfsub_drop_nlink(dir);
1facf9fc 34510+ }
34511+ return 0; /* success */
34512+ }
34513+
523b37e3 34514+ pr_warn("failed removing %pd(%d), ignored\n", wh_dentry, err);
1facf9fc 34515+ return err;
34516+}
34517+
34518+static void call_rmdir_whtmp(void *args)
34519+{
34520+ int err;
e49829fe 34521+ aufs_bindex_t bindex;
1facf9fc 34522+ struct au_whtmp_rmdir *a = args;
34523+ struct super_block *sb;
34524+ struct dentry *h_parent;
34525+ struct inode *h_dir;
1facf9fc 34526+ struct au_hinode *hdir;
34527+
34528+ /* rmdir by nfsd may cause deadlock with this i_mutex */
febd17d6 34529+ /* inode_lock(a->dir); */
e49829fe 34530+ err = -EROFS;
1facf9fc 34531+ sb = a->dir->i_sb;
e49829fe
JR
34532+ si_read_lock(sb, !AuLock_FLUSH);
34533+ if (!au_br_writable(a->br->br_perm))
34534+ goto out;
34535+ bindex = au_br_index(sb, a->br->br_id);
34536+ if (unlikely(bindex < 0))
1facf9fc 34537+ goto out;
34538+
34539+ err = -EIO;
1facf9fc 34540+ ii_write_lock_parent(a->dir);
34541+ h_parent = dget_parent(a->wh_dentry);
5527c038 34542+ h_dir = d_inode(h_parent);
e49829fe 34543+ hdir = au_hi(a->dir, bindex);
86dc4139
AM
34544+ err = vfsub_mnt_want_write(au_br_mnt(a->br));
34545+ if (unlikely(err))
34546+ goto out_mnt;
5afbbe0d 34547+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
34548+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
34549+ a->br);
86dc4139
AM
34550+ if (!err)
34551+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry, &a->whlist);
5afbbe0d 34552+ au_hn_inode_unlock(hdir);
86dc4139
AM
34553+ vfsub_mnt_drop_write(au_br_mnt(a->br));
34554+
34555+out_mnt:
1facf9fc 34556+ dput(h_parent);
34557+ ii_write_unlock(a->dir);
4f0767ce 34558+out:
febd17d6 34559+ /* inode_unlock(a->dir); */
1facf9fc 34560+ au_whtmp_rmdir_free(a);
027c5e7a
AM
34561+ si_read_unlock(sb);
34562+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 34563+ if (unlikely(err))
34564+ AuIOErr("err %d\n", err);
34565+}
34566+
34567+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
34568+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
34569+{
34570+ int wkq_err;
e49829fe 34571+ struct super_block *sb;
1facf9fc 34572+
34573+ IMustLock(dir);
34574+
34575+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 34576+ sb = dir->i_sb;
1facf9fc 34577+ args->dir = au_igrab(dir);
e49829fe 34578+ args->br = au_sbr(sb, bindex);
5afbbe0d 34579+ au_br_get(args->br);
1facf9fc 34580+ args->wh_dentry = dget(wh_dentry);
53392da6 34581+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0);
1facf9fc 34582+ if (unlikely(wkq_err)) {
523b37e3 34583+ pr_warn("rmdir error %pd (%d), ignored\n", wh_dentry, wkq_err);
1facf9fc 34584+ au_whtmp_rmdir_free(args);
34585+ }
34586+}
0b1ff5c3
JR
34587diff -urNp -x '*.orig' linux-4.14/fs/aufs/whout.h linux-4.14/fs/aufs/whout.h
34588--- linux-4.14/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
34589+++ linux-4.14/fs/aufs/whout.h 2021-02-24 21:42:43.447781402 +0100
3c1bdaff 34590@@ -0,0 +1,85 @@
1facf9fc 34591+/*
a2654f78 34592+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 34593+ *
34594+ * This program, aufs is free software; you can redistribute it and/or modify
34595+ * it under the terms of the GNU General Public License as published by
34596+ * the Free Software Foundation; either version 2 of the License, or
34597+ * (at your option) any later version.
dece6358
AM
34598+ *
34599+ * This program is distributed in the hope that it will be useful,
34600+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
34601+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34602+ * GNU General Public License for more details.
34603+ *
34604+ * You should have received a copy of the GNU General Public License
523b37e3 34605+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 34606+ */
34607+
34608+/*
34609+ * whiteout for logical deletion and opaque directory
34610+ */
34611+
34612+#ifndef __AUFS_WHOUT_H__
34613+#define __AUFS_WHOUT_H__
34614+
34615+#ifdef __KERNEL__
34616+
1facf9fc 34617+#include "dir.h"
34618+
34619+/* whout.c */
34620+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
076b876e
AM
34621+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio);
34622+int au_diropq_test(struct dentry *h_dentry);
3c1bdaff 34623+struct au_branch;
1facf9fc 34624+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
34625+ struct qstr *prefix);
34626+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
34627+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
34628+ struct dentry *dentry);
86dc4139 34629+int au_wh_init(struct au_branch *br, struct super_block *sb);
1facf9fc 34630+
34631+/* diropq flags */
34632+#define AuDiropq_CREATE 1
34633+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
7f207e10
AM
34634+#define au_fset_diropq(flags, name) \
34635+ do { (flags) |= AuDiropq_##name; } while (0)
34636+#define au_fclr_diropq(flags, name) \
34637+ do { (flags) &= ~AuDiropq_##name; } while (0)
1facf9fc 34638+
34639+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
34640+ unsigned int flags);
34641+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
34642+ struct au_branch *br);
34643+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
34644+ struct dentry *h_parent);
34645+
34646+/* real rmdir for the whiteout-ed dir */
34647+struct au_whtmp_rmdir {
34648+ struct inode *dir;
e49829fe 34649+ struct au_branch *br;
1facf9fc 34650+ struct dentry *wh_dentry;
dece6358 34651+ struct au_nhash whlist;
1facf9fc 34652+};
34653+
34654+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
34655+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
34656+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
34657+ struct dentry *wh_dentry, struct au_nhash *whlist);
34658+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
34659+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
34660+
34661+/* ---------------------------------------------------------------------- */
34662+
34663+static inline struct dentry *au_diropq_create(struct dentry *dentry,
34664+ aufs_bindex_t bindex)
34665+{
34666+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
34667+}
34668+
34669+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
34670+{
34671+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
34672+}
34673+
34674+#endif /* __KERNEL__ */
34675+#endif /* __AUFS_WHOUT_H__ */
0b1ff5c3
JR
34676diff -urNp -x '*.orig' linux-4.14/fs/aufs/wkq.c linux-4.14/fs/aufs/wkq.c
34677--- linux-4.14/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
34678+++ linux-4.14/fs/aufs/wkq.c 2021-02-24 21:42:43.447781402 +0100
8b6a4947 34679@@ -0,0 +1,390 @@
1facf9fc 34680+/*
a2654f78 34681+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 34682+ *
34683+ * This program, aufs is free software; you can redistribute it and/or modify
34684+ * it under the terms of the GNU General Public License as published by
34685+ * the Free Software Foundation; either version 2 of the License, or
34686+ * (at your option) any later version.
dece6358
AM
34687+ *
34688+ * This program is distributed in the hope that it will be useful,
34689+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
34690+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34691+ * GNU General Public License for more details.
34692+ *
34693+ * You should have received a copy of the GNU General Public License
523b37e3 34694+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 34695+ */
34696+
34697+/*
34698+ * workqueue for asynchronous/super-io operations
34699+ * todo: try new dredential scheme
34700+ */
34701+
dece6358 34702+#include <linux/module.h>
1facf9fc 34703+#include "aufs.h"
34704+
9dbd164d 34705+/* internal workqueue named AUFS_WKQ_NAME */
b752ccd1 34706+
9dbd164d 34707+static struct workqueue_struct *au_wkq;
1facf9fc 34708+
34709+struct au_wkinfo {
34710+ struct work_struct wk;
7f207e10 34711+ struct kobject *kobj;
1facf9fc 34712+
34713+ unsigned int flags; /* see wkq.h */
34714+
34715+ au_wkq_func_t func;
34716+ void *args;
34717+
8b6a4947
AM
34718+#ifdef CONFIG_LOCKDEP
34719+ int dont_check;
34720+ struct held_lock **hlock;
34721+#endif
34722+
1facf9fc 34723+ struct completion *comp;
34724+};
34725+
34726+/* ---------------------------------------------------------------------- */
8b6a4947
AM
34727+/*
34728+ * Aufs passes some operations to the workqueue such as the internal copyup.
34729+ * This scheme looks rather unnatural for LOCKDEP debugging feature, since the
34730+ * job run by workqueue depends upon the locks acquired in the other task.
34731+ * Delegating a small operation to the workqueue, aufs passes its lockdep
34732+ * information too. And the job in the workqueue restores the info in order to
34733+ * pretend as if it acquired those locks. This is just to make LOCKDEP work
34734+ * correctly and expectedly.
34735+ */
34736+
34737+#ifndef CONFIG_LOCKDEP
34738+AuStubInt0(au_wkq_lockdep_alloc, struct au_wkinfo *wkinfo);
34739+AuStubVoid(au_wkq_lockdep_free, struct au_wkinfo *wkinfo);
34740+AuStubVoid(au_wkq_lockdep_pre, struct au_wkinfo *wkinfo);
34741+AuStubVoid(au_wkq_lockdep_post, struct au_wkinfo *wkinfo);
34742+AuStubVoid(au_wkq_lockdep_init, struct au_wkinfo *wkinfo);
34743+#else
34744+static void au_wkq_lockdep_init(struct au_wkinfo *wkinfo)
34745+{
34746+ wkinfo->hlock = NULL;
34747+ wkinfo->dont_check = 0;
34748+}
34749+
34750+/*
34751+ * 1: matched
34752+ * 0: unmatched
34753+ */
34754+static int au_wkq_lockdep_test(struct lock_class_key *key, const char *name)
34755+{
34756+ static DEFINE_SPINLOCK(spin);
34757+ static struct {
34758+ char *name;
34759+ struct lock_class_key *key;
34760+ } a[] = {
34761+ { .name = "&sbinfo->si_rwsem" },
34762+ { .name = "&finfo->fi_rwsem" },
34763+ { .name = "&dinfo->di_rwsem" },
34764+ { .name = "&iinfo->ii_rwsem" }
34765+ };
34766+ static int set;
34767+ int i;
34768+
34769+ /* lockless read from 'set.' see below */
34770+ if (set == ARRAY_SIZE(a)) {
34771+ for (i = 0; i < ARRAY_SIZE(a); i++)
34772+ if (a[i].key == key)
34773+ goto match;
34774+ goto unmatch;
34775+ }
34776+
34777+ spin_lock(&spin);
34778+ if (set)
34779+ for (i = 0; i < ARRAY_SIZE(a); i++)
34780+ if (a[i].key == key) {
34781+ spin_unlock(&spin);
34782+ goto match;
34783+ }
34784+ for (i = 0; i < ARRAY_SIZE(a); i++) {
34785+ if (a[i].key) {
34786+ if (unlikely(a[i].key == key)) { /* rare but possible */
34787+ spin_unlock(&spin);
34788+ goto match;
34789+ } else
34790+ continue;
34791+ }
34792+ if (strstr(a[i].name, name)) {
34793+ /*
34794+ * the order of these three lines is important for the
34795+ * lockless read above.
34796+ */
34797+ a[i].key = key;
34798+ spin_unlock(&spin);
34799+ set++;
34800+ /* AuDbg("%d, %s\n", set, name); */
34801+ goto match;
34802+ }
34803+ }
34804+ spin_unlock(&spin);
34805+ goto unmatch;
34806+
34807+match:
34808+ return 1;
34809+unmatch:
34810+ return 0;
34811+}
34812+
34813+static int au_wkq_lockdep_alloc(struct au_wkinfo *wkinfo)
34814+{
34815+ int err, n;
34816+ struct task_struct *curr;
34817+ struct held_lock **hl, *held_locks, *p;
34818+
34819+ err = 0;
34820+ curr = current;
34821+ wkinfo->dont_check = lockdep_recursing(curr);
34822+ if (wkinfo->dont_check)
34823+ goto out;
34824+ n = curr->lockdep_depth;
34825+ if (!n)
34826+ goto out;
34827+
34828+ err = -ENOMEM;
34829+ wkinfo->hlock = kmalloc_array(n + 1, sizeof(*wkinfo->hlock), GFP_NOFS);
34830+ if (unlikely(!wkinfo->hlock))
34831+ goto out;
34832+
34833+ err = 0;
34834+#if 0
34835+ if (0 && au_debug_test()) /* left for debugging */
34836+ lockdep_print_held_locks(curr);
34837+#endif
34838+ held_locks = curr->held_locks;
34839+ hl = wkinfo->hlock;
34840+ while (n--) {
34841+ p = held_locks++;
34842+ if (au_wkq_lockdep_test(p->instance->key, p->instance->name))
34843+ *hl++ = p;
34844+ }
34845+ *hl = NULL;
34846+
34847+out:
34848+ return err;
34849+}
34850+
34851+static void au_wkq_lockdep_free(struct au_wkinfo *wkinfo)
34852+{
34853+ kfree(wkinfo->hlock);
34854+}
34855+
34856+static void au_wkq_lockdep_pre(struct au_wkinfo *wkinfo)
34857+{
34858+ struct held_lock *p, **hl = wkinfo->hlock;
34859+ int subclass;
34860+
34861+ if (wkinfo->dont_check)
34862+ lockdep_off();
34863+ if (!hl)
34864+ return;
34865+ while ((p = *hl++)) { /* assignment */
34866+ subclass = lockdep_hlock_class(p)->subclass;
34867+ /* AuDbg("%s, %d\n", p->instance->name, subclass); */
34868+ if (p->read)
34869+ rwsem_acquire_read(p->instance, subclass, 0,
34870+ /*p->acquire_ip*/_RET_IP_);
34871+ else
34872+ rwsem_acquire(p->instance, subclass, 0,
34873+ /*p->acquire_ip*/_RET_IP_);
34874+ }
34875+}
34876+
34877+static void au_wkq_lockdep_post(struct au_wkinfo *wkinfo)
34878+{
34879+ struct held_lock *p, **hl = wkinfo->hlock;
34880+
34881+ if (wkinfo->dont_check)
34882+ lockdep_on();
34883+ if (!hl)
34884+ return;
34885+ while ((p = *hl++)) /* assignment */
34886+ rwsem_release(p->instance, 0, /*p->acquire_ip*/_RET_IP_);
34887+}
34888+#endif
1facf9fc 34889+
1facf9fc 34890+static void wkq_func(struct work_struct *wk)
34891+{
34892+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
34893+
2dfbb274 34894+ AuDebugOn(!uid_eq(current_fsuid(), GLOBAL_ROOT_UID));
7f207e10
AM
34895+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
34896+
8b6a4947 34897+ au_wkq_lockdep_pre(wkinfo);
1facf9fc 34898+ wkinfo->func(wkinfo->args);
8b6a4947 34899+ au_wkq_lockdep_post(wkinfo);
1facf9fc 34900+ if (au_ftest_wkq(wkinfo->flags, WAIT))
34901+ complete(wkinfo->comp);
34902+ else {
7f207e10 34903+ kobject_put(wkinfo->kobj);
9dbd164d 34904+ module_put(THIS_MODULE); /* todo: ?? */
1c60b727 34905+ kfree(wkinfo);
1facf9fc 34906+ }
34907+}
34908+
34909+/*
34910+ * Since struct completion is large, try allocating it dynamically.
34911+ */
c2b27bf2 34912+#if 1 /* defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS) */
1facf9fc 34913+#define AuWkqCompDeclare(name) struct completion *comp = NULL
34914+
34915+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
34916+{
34917+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
34918+ if (*comp) {
34919+ init_completion(*comp);
34920+ wkinfo->comp = *comp;
34921+ return 0;
34922+ }
34923+ return -ENOMEM;
34924+}
34925+
34926+static void au_wkq_comp_free(struct completion *comp)
34927+{
1c60b727 34928+ kfree(comp);
1facf9fc 34929+}
34930+
34931+#else
34932+
34933+/* no braces */
34934+#define AuWkqCompDeclare(name) \
34935+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
34936+ struct completion *comp = &_ ## name
34937+
34938+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
34939+{
34940+ wkinfo->comp = *comp;
34941+ return 0;
34942+}
34943+
34944+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
34945+{
34946+ /* empty */
34947+}
34948+#endif /* 4KSTACKS */
34949+
53392da6 34950+static void au_wkq_run(struct au_wkinfo *wkinfo)
1facf9fc 34951+{
53392da6
AM
34952+ if (au_ftest_wkq(wkinfo->flags, NEST)) {
34953+ if (au_wkq_test()) {
38d290e6
JR
34954+ AuWarn1("wkq from wkq, unless silly-rename on NFS,"
34955+ " due to a dead dir by UDBA?\n");
53392da6
AM
34956+ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT));
34957+ }
34958+ } else
34959+ au_dbg_verify_kthread();
34960+
34961+ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
a1f66529 34962+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
9dbd164d 34963+ queue_work(au_wkq, &wkinfo->wk);
4a4d8108
AM
34964+ } else {
34965+ INIT_WORK(&wkinfo->wk, wkq_func);
34966+ schedule_work(&wkinfo->wk);
34967+ }
1facf9fc 34968+}
34969+
7f207e10
AM
34970+/*
34971+ * Be careful. It is easy to make deadlock happen.
34972+ * processA: lock, wkq and wait
34973+ * processB: wkq and wait, lock in wkq
34974+ * --> deadlock
34975+ */
b752ccd1 34976+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 34977+{
34978+ int err;
34979+ AuWkqCompDeclare(comp);
34980+ struct au_wkinfo wkinfo = {
b752ccd1 34981+ .flags = flags,
1facf9fc 34982+ .func = func,
34983+ .args = args
34984+ };
34985+
34986+ err = au_wkq_comp_alloc(&wkinfo, &comp);
8b6a4947
AM
34987+ if (unlikely(err))
34988+ goto out;
34989+ err = au_wkq_lockdep_alloc(&wkinfo);
34990+ if (unlikely(err))
34991+ goto out_comp;
1facf9fc 34992+ if (!err) {
53392da6 34993+ au_wkq_run(&wkinfo);
1facf9fc 34994+ /* no timeout, no interrupt */
34995+ wait_for_completion(wkinfo.comp);
1facf9fc 34996+ }
8b6a4947 34997+ au_wkq_lockdep_free(&wkinfo);
1facf9fc 34998+
8b6a4947
AM
34999+out_comp:
35000+ au_wkq_comp_free(comp);
35001+out:
35002+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 35003+ return err;
1facf9fc 35004+}
35005+
027c5e7a
AM
35006+/*
35007+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a
35008+ * problem in a concurrent umounting.
35009+ */
53392da6
AM
35010+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
35011+ unsigned int flags)
1facf9fc 35012+{
35013+ int err;
35014+ struct au_wkinfo *wkinfo;
35015+
f0c0a007 35016+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
1facf9fc 35017+
35018+ /*
35019+ * wkq_func() must free this wkinfo.
35020+ * it highly depends upon the implementation of workqueue.
35021+ */
35022+ err = 0;
35023+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
35024+ if (wkinfo) {
7f207e10 35025+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
53392da6 35026+ wkinfo->flags = flags & ~AuWkq_WAIT;
1facf9fc 35027+ wkinfo->func = func;
35028+ wkinfo->args = args;
35029+ wkinfo->comp = NULL;
8b6a4947 35030+ au_wkq_lockdep_init(wkinfo);
7f207e10 35031+ kobject_get(wkinfo->kobj);
9dbd164d 35032+ __module_get(THIS_MODULE); /* todo: ?? */
1facf9fc 35033+
53392da6 35034+ au_wkq_run(wkinfo);
1facf9fc 35035+ } else {
35036+ err = -ENOMEM;
e49829fe 35037+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 35038+ }
35039+
35040+ return err;
35041+}
35042+
35043+/* ---------------------------------------------------------------------- */
35044+
35045+void au_nwt_init(struct au_nowait_tasks *nwt)
35046+{
f0c0a007
AM
35047+ atomic_set(&nwt->nw_len, 0);
35048+ /* smp_mb(); */ /* atomic_set */
1facf9fc 35049+ init_waitqueue_head(&nwt->nw_wq);
35050+}
35051+
35052+void au_wkq_fin(void)
35053+{
9dbd164d 35054+ destroy_workqueue(au_wkq);
1facf9fc 35055+}
35056+
35057+int __init au_wkq_init(void)
35058+{
9dbd164d 35059+ int err;
b752ccd1
AM
35060+
35061+ err = 0;
86dc4139 35062+ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, 0, WQ_DFL_ACTIVE);
9dbd164d
AM
35063+ if (IS_ERR(au_wkq))
35064+ err = PTR_ERR(au_wkq);
35065+ else if (!au_wkq)
35066+ err = -ENOMEM;
b752ccd1
AM
35067+
35068+ return err;
1facf9fc 35069+}
0b1ff5c3
JR
35070diff -urNp -x '*.orig' linux-4.14/fs/aufs/wkq.h linux-4.14/fs/aufs/wkq.h
35071--- linux-4.14/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
35072+++ linux-4.14/fs/aufs/wkq.h 2021-02-24 21:42:43.447781402 +0100
f0c0a007 35073@@ -0,0 +1,93 @@
1facf9fc 35074+/*
a2654f78 35075+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 35076+ *
35077+ * This program, aufs is free software; you can redistribute it and/or modify
35078+ * it under the terms of the GNU General Public License as published by
35079+ * the Free Software Foundation; either version 2 of the License, or
35080+ * (at your option) any later version.
dece6358
AM
35081+ *
35082+ * This program is distributed in the hope that it will be useful,
35083+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
35084+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35085+ * GNU General Public License for more details.
35086+ *
35087+ * You should have received a copy of the GNU General Public License
523b37e3 35088+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 35089+ */
35090+
35091+/*
35092+ * workqueue for asynchronous/super-io operations
35093+ * todo: try new credentials management scheme
35094+ */
35095+
35096+#ifndef __AUFS_WKQ_H__
35097+#define __AUFS_WKQ_H__
35098+
35099+#ifdef __KERNEL__
35100+
8b6a4947 35101+#include <linux/wait.h>
5afbbe0d 35102+
dece6358
AM
35103+struct super_block;
35104+
1facf9fc 35105+/* ---------------------------------------------------------------------- */
35106+
35107+/*
35108+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
35109+ */
35110+struct au_nowait_tasks {
f0c0a007 35111+ atomic_t nw_len;
1facf9fc 35112+ wait_queue_head_t nw_wq;
35113+};
35114+
35115+/* ---------------------------------------------------------------------- */
35116+
35117+typedef void (*au_wkq_func_t)(void *args);
35118+
35119+/* wkq flags */
35120+#define AuWkq_WAIT 1
9dbd164d 35121+#define AuWkq_NEST (1 << 1)
1facf9fc 35122+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
7f207e10
AM
35123+#define au_fset_wkq(flags, name) \
35124+ do { (flags) |= AuWkq_##name; } while (0)
35125+#define au_fclr_wkq(flags, name) \
35126+ do { (flags) &= ~AuWkq_##name; } while (0)
1facf9fc 35127+
9dbd164d
AM
35128+#ifndef CONFIG_AUFS_HNOTIFY
35129+#undef AuWkq_NEST
35130+#define AuWkq_NEST 0
35131+#endif
35132+
1facf9fc 35133+/* wkq.c */
b752ccd1 35134+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
53392da6
AM
35135+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
35136+ unsigned int flags);
1facf9fc 35137+void au_nwt_init(struct au_nowait_tasks *nwt);
35138+int __init au_wkq_init(void);
35139+void au_wkq_fin(void);
35140+
35141+/* ---------------------------------------------------------------------- */
35142+
53392da6
AM
35143+static inline int au_wkq_test(void)
35144+{
35145+ return current->flags & PF_WQ_WORKER;
35146+}
35147+
b752ccd1 35148+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 35149+{
b752ccd1 35150+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 35151+}
35152+
35153+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
35154+{
f0c0a007 35155+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 35156+ wake_up_all(&nwt->nw_wq);
35157+}
35158+
35159+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
35160+{
f0c0a007 35161+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
1facf9fc 35162+ return 0;
35163+}
35164+
35165+#endif /* __KERNEL__ */
35166+#endif /* __AUFS_WKQ_H__ */
0b1ff5c3
JR
35167diff -urNp -x '*.orig' linux-4.14/fs/aufs/xattr.c linux-4.14/fs/aufs/xattr.c
35168--- linux-4.14/fs/aufs/xattr.c 1970-01-01 01:00:00.000000000 +0100
35169+++ linux-4.14/fs/aufs/xattr.c 2021-02-24 21:42:43.447781402 +0100
8b6a4947 35170@@ -0,0 +1,355 @@
c1595e42 35171+/*
a2654f78 35172+ * Copyright (C) 2014-2017 Junjiro R. Okajima
c1595e42
JR
35173+ *
35174+ * This program, aufs is free software; you can redistribute it and/or modify
35175+ * it under the terms of the GNU General Public License as published by
35176+ * the Free Software Foundation; either version 2 of the License, or
35177+ * (at your option) any later version.
35178+ *
35179+ * This program is distributed in the hope that it will be useful,
35180+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
35181+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35182+ * GNU General Public License for more details.
35183+ *
35184+ * You should have received a copy of the GNU General Public License
35185+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
35186+ */
35187+
35188+/*
35189+ * handling xattr functions
35190+ */
35191+
a2654f78
AM
35192+#include <linux/fs.h>
35193+#include <linux/posix_acl_xattr.h>
c1595e42
JR
35194+#include <linux/xattr.h>
35195+#include "aufs.h"
35196+
35197+static int au_xattr_ignore(int err, char *name, unsigned int ignore_flags)
35198+{
35199+ if (!ignore_flags)
35200+ goto out;
35201+ switch (err) {
35202+ case -ENOMEM:
35203+ case -EDQUOT:
35204+ goto out;
35205+ }
35206+
35207+ if ((ignore_flags & AuBrAttr_ICEX) == AuBrAttr_ICEX) {
35208+ err = 0;
35209+ goto out;
35210+ }
35211+
35212+#define cmp(brattr, prefix) do { \
35213+ if (!strncmp(name, XATTR_##prefix##_PREFIX, \
35214+ XATTR_##prefix##_PREFIX_LEN)) { \
35215+ if (ignore_flags & AuBrAttr_ICEX_##brattr) \
35216+ err = 0; \
35217+ goto out; \
35218+ } \
35219+ } while (0)
35220+
35221+ cmp(SEC, SECURITY);
35222+ cmp(SYS, SYSTEM);
35223+ cmp(TR, TRUSTED);
35224+ cmp(USR, USER);
35225+#undef cmp
35226+
35227+ if (ignore_flags & AuBrAttr_ICEX_OTH)
35228+ err = 0;
35229+
35230+out:
35231+ return err;
35232+}
35233+
35234+static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1;
35235+
35236+static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src,
7e9cd9fe
AM
35237+ char *name, char **buf, unsigned int ignore_flags,
35238+ unsigned int verbose)
c1595e42
JR
35239+{
35240+ int err;
35241+ ssize_t ssz;
35242+ struct inode *h_idst;
35243+
35244+ ssz = vfs_getxattr_alloc(h_src, name, buf, 0, GFP_NOFS);
35245+ err = ssz;
35246+ if (unlikely(err <= 0)) {
c1595e42
JR
35247+ if (err == -ENODATA
35248+ || (err == -EOPNOTSUPP
b912730e 35249+ && ((ignore_flags & au_xattr_out_of_list)
5527c038 35250+ || (au_test_nfs_noacl(d_inode(h_src))
b912730e
AM
35251+ && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS)
35252+ || !strcmp(name,
35253+ XATTR_NAME_POSIX_ACL_DEFAULT))))
35254+ ))
c1595e42 35255+ err = 0;
b912730e
AM
35256+ if (err && (verbose || au_debug_test()))
35257+ pr_err("%s, err %d\n", name, err);
c1595e42
JR
35258+ goto out;
35259+ }
35260+
35261+ /* unlock it temporary */
5527c038 35262+ h_idst = d_inode(h_dst);
febd17d6 35263+ inode_unlock(h_idst);
c1595e42 35264+ err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0);
febd17d6 35265+ inode_lock_nested(h_idst, AuLsc_I_CHILD2);
c1595e42 35266+ if (unlikely(err)) {
7e9cd9fe
AM
35267+ if (verbose || au_debug_test())
35268+ pr_err("%s, err %d\n", name, err);
c1595e42
JR
35269+ err = au_xattr_ignore(err, name, ignore_flags);
35270+ }
35271+
35272+out:
35273+ return err;
35274+}
35275+
7e9cd9fe
AM
35276+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags,
35277+ unsigned int verbose)
c1595e42
JR
35278+{
35279+ int err, unlocked, acl_access, acl_default;
35280+ ssize_t ssz;
35281+ struct inode *h_isrc, *h_idst;
35282+ char *value, *p, *o, *e;
35283+
35284+ /* try stopping to update the source inode while we are referencing */
7e9cd9fe 35285+ /* there should not be the parent-child relationship between them */
5527c038
JR
35286+ h_isrc = d_inode(h_src);
35287+ h_idst = d_inode(h_dst);
febd17d6 35288+ inode_unlock(h_idst);
3c1bdaff 35289+ vfsub_inode_lock_shared_nested(h_isrc, AuLsc_I_CHILD);
febd17d6 35290+ inode_lock_nested(h_idst, AuLsc_I_CHILD2);
c1595e42
JR
35291+ unlocked = 0;
35292+
35293+ /* some filesystems don't list POSIX ACL, for example tmpfs */
35294+ ssz = vfs_listxattr(h_src, NULL, 0);
35295+ err = ssz;
35296+ if (unlikely(err < 0)) {
35297+ AuTraceErr(err);
35298+ if (err == -ENODATA
35299+ || err == -EOPNOTSUPP)
35300+ err = 0; /* ignore */
35301+ goto out;
35302+ }
35303+
35304+ err = 0;
35305+ p = NULL;
35306+ o = NULL;
35307+ if (ssz) {
35308+ err = -ENOMEM;
35309+ p = kmalloc(ssz, GFP_NOFS);
35310+ o = p;
35311+ if (unlikely(!p))
35312+ goto out;
35313+ err = vfs_listxattr(h_src, p, ssz);
35314+ }
3c1bdaff 35315+ inode_unlock_shared(h_isrc);
c1595e42
JR
35316+ unlocked = 1;
35317+ AuDbg("err %d, ssz %zd\n", err, ssz);
35318+ if (unlikely(err < 0))
35319+ goto out_free;
35320+
35321+ err = 0;
35322+ e = p + ssz;
35323+ value = NULL;
35324+ acl_access = 0;
35325+ acl_default = 0;
35326+ while (!err && p < e) {
35327+ acl_access |= !strncmp(p, XATTR_NAME_POSIX_ACL_ACCESS,
35328+ sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1);
35329+ acl_default |= !strncmp(p, XATTR_NAME_POSIX_ACL_DEFAULT,
35330+ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)
35331+ - 1);
7e9cd9fe
AM
35332+ err = au_do_cpup_xattr(h_dst, h_src, p, &value, ignore_flags,
35333+ verbose);
c1595e42
JR
35334+ p += strlen(p) + 1;
35335+ }
35336+ AuTraceErr(err);
35337+ ignore_flags |= au_xattr_out_of_list;
35338+ if (!err && !acl_access) {
35339+ err = au_do_cpup_xattr(h_dst, h_src,
35340+ XATTR_NAME_POSIX_ACL_ACCESS, &value,
7e9cd9fe 35341+ ignore_flags, verbose);
c1595e42
JR
35342+ AuTraceErr(err);
35343+ }
35344+ if (!err && !acl_default) {
35345+ err = au_do_cpup_xattr(h_dst, h_src,
35346+ XATTR_NAME_POSIX_ACL_DEFAULT, &value,
7e9cd9fe 35347+ ignore_flags, verbose);
c1595e42
JR
35348+ AuTraceErr(err);
35349+ }
35350+
8b6a4947 35351+ kfree(value);
c1595e42
JR
35352+
35353+out_free:
8b6a4947 35354+ kfree(o);
c1595e42
JR
35355+out:
35356+ if (!unlocked)
3c1bdaff 35357+ inode_unlock_shared(h_isrc);
c1595e42
JR
35358+ AuTraceErr(err);
35359+ return err;
35360+}
35361+
35362+/* ---------------------------------------------------------------------- */
35363+
a2654f78
AM
35364+static int au_smack_reentering(struct super_block *sb)
35365+{
35366+#if IS_ENABLED(CONFIG_SECURITY_SMACK)
35367+ /*
35368+ * as a part of lookup, smack_d_instantiate() is called, and it calls
35369+ * i_op->getxattr(). ouch.
35370+ */
35371+ return si_pid_test(sb);
35372+#else
35373+ return 0;
35374+#endif
35375+}
35376+
c1595e42
JR
35377+enum {
35378+ AU_XATTR_LIST,
35379+ AU_XATTR_GET
35380+};
35381+
35382+struct au_lgxattr {
35383+ int type;
35384+ union {
35385+ struct {
35386+ char *list;
35387+ size_t size;
35388+ } list;
35389+ struct {
35390+ const char *name;
35391+ void *value;
35392+ size_t size;
35393+ } get;
35394+ } u;
35395+};
35396+
35397+static ssize_t au_lgxattr(struct dentry *dentry, struct au_lgxattr *arg)
35398+{
35399+ ssize_t err;
a2654f78 35400+ int reenter;
c1595e42
JR
35401+ struct path h_path;
35402+ struct super_block *sb;
35403+
35404+ sb = dentry->d_sb;
a2654f78
AM
35405+ reenter = au_smack_reentering(sb);
35406+ if (!reenter) {
35407+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
35408+ if (unlikely(err))
35409+ goto out;
35410+ }
35411+ err = au_h_path_getattr(dentry, /*force*/1, &h_path, reenter);
c1595e42
JR
35412+ if (unlikely(err))
35413+ goto out_si;
35414+ if (unlikely(!h_path.dentry))
35415+ /* illegally overlapped or something */
35416+ goto out_di; /* pretending success */
35417+
35418+ /* always topmost entry only */
35419+ switch (arg->type) {
35420+ case AU_XATTR_LIST:
35421+ err = vfs_listxattr(h_path.dentry,
35422+ arg->u.list.list, arg->u.list.size);
35423+ break;
35424+ case AU_XATTR_GET:
5afbbe0d 35425+ AuDebugOn(d_is_negative(h_path.dentry));
c1595e42
JR
35426+ err = vfs_getxattr(h_path.dentry,
35427+ arg->u.get.name, arg->u.get.value,
35428+ arg->u.get.size);
35429+ break;
35430+ }
35431+
35432+out_di:
a2654f78
AM
35433+ if (!reenter)
35434+ di_read_unlock(dentry, AuLock_IR);
c1595e42 35435+out_si:
a2654f78
AM
35436+ if (!reenter)
35437+ si_read_unlock(sb);
c1595e42
JR
35438+out:
35439+ AuTraceErr(err);
35440+ return err;
35441+}
35442+
35443+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size)
35444+{
35445+ struct au_lgxattr arg = {
35446+ .type = AU_XATTR_LIST,
35447+ .u.list = {
35448+ .list = list,
35449+ .size = size
35450+ },
35451+ };
35452+
35453+ return au_lgxattr(dentry, &arg);
35454+}
35455+
f2c43d5f
AM
35456+static ssize_t au_getxattr(struct dentry *dentry,
35457+ struct inode *inode __maybe_unused,
35458+ const char *name, void *value, size_t size)
c1595e42
JR
35459+{
35460+ struct au_lgxattr arg = {
35461+ .type = AU_XATTR_GET,
35462+ .u.get = {
35463+ .name = name,
35464+ .value = value,
35465+ .size = size
35466+ },
35467+ };
35468+
35469+ return au_lgxattr(dentry, &arg);
35470+}
35471+
f2c43d5f
AM
35472+static int au_setxattr(struct dentry *dentry, struct inode *inode,
35473+ const char *name, const void *value, size_t size,
35474+ int flags)
c1595e42 35475+{
f2c43d5f 35476+ struct au_sxattr arg = {
c1595e42
JR
35477+ .type = AU_XATTR_SET,
35478+ .u.set = {
35479+ .name = name,
35480+ .value = value,
35481+ .size = size,
35482+ .flags = flags
35483+ },
35484+ };
35485+
f2c43d5f 35486+ return au_sxattr(dentry, inode, &arg);
c1595e42
JR
35487+}
35488+
35489+/* ---------------------------------------------------------------------- */
35490+
f2c43d5f
AM
35491+static int au_xattr_get(const struct xattr_handler *handler,
35492+ struct dentry *dentry, struct inode *inode,
35493+ const char *name, void *buffer, size_t size)
c1595e42 35494+{
f2c43d5f 35495+ return au_getxattr(dentry, inode, name, buffer, size);
c1595e42
JR
35496+}
35497+
f2c43d5f
AM
35498+static int au_xattr_set(const struct xattr_handler *handler,
35499+ struct dentry *dentry, struct inode *inode,
35500+ const char *name, const void *value, size_t size,
35501+ int flags)
c1595e42 35502+{
f2c43d5f 35503+ return au_setxattr(dentry, inode, name, value, size, flags);
c1595e42
JR
35504+}
35505+
35506+static const struct xattr_handler au_xattr_handler = {
f2c43d5f
AM
35507+ .name = "",
35508+ .prefix = "",
c1595e42
JR
35509+ .get = au_xattr_get,
35510+ .set = au_xattr_set
c1595e42
JR
35511+};
35512+
35513+static const struct xattr_handler *au_xattr_handlers[] = {
a2654f78
AM
35514+#ifdef CONFIG_FS_POSIX_ACL
35515+ &posix_acl_access_xattr_handler,
35516+ &posix_acl_default_xattr_handler,
35517+#endif
35518+ &au_xattr_handler, /* must be last */
f2c43d5f 35519+ NULL
c1595e42
JR
35520+};
35521+
35522+void au_xattr_init(struct super_block *sb)
35523+{
f2c43d5f 35524+ sb->s_xattr = au_xattr_handlers;
c1595e42 35525+}
0b1ff5c3
JR
35526diff -urNp -x '*.orig' linux-4.14/fs/aufs/xino.c linux-4.14/fs/aufs/xino.c
35527--- linux-4.14/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
35528+++ linux-4.14/fs/aufs/xino.c 2021-02-24 21:42:43.447781402 +0100
8b6a4947 35529@@ -0,0 +1,1418 @@
1facf9fc 35530+/*
a2654f78 35531+ * Copyright (C) 2005-2017 Junjiro R. Okajima
1facf9fc 35532+ *
35533+ * This program, aufs is free software; you can redistribute it and/or modify
35534+ * it under the terms of the GNU General Public License as published by
35535+ * the Free Software Foundation; either version 2 of the License, or
35536+ * (at your option) any later version.
dece6358
AM
35537+ *
35538+ * This program is distributed in the hope that it will be useful,
35539+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
35540+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35541+ * GNU General Public License for more details.
35542+ *
35543+ * You should have received a copy of the GNU General Public License
523b37e3 35544+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 35545+ */
35546+
35547+/*
35548+ * external inode number translation table and bitmap
35549+ */
35550+
35551+#include <linux/seq_file.h>
392086de 35552+#include <linux/statfs.h>
1facf9fc 35553+#include "aufs.h"
35554+
9dbd164d 35555+/* todo: unnecessary to support mmap_sem since kernel-space? */
5527c038 35556+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *kbuf, size_t size,
1facf9fc 35557+ loff_t *pos)
35558+{
35559+ ssize_t err;
35560+ mm_segment_t oldfs;
b752ccd1
AM
35561+ union {
35562+ void *k;
35563+ char __user *u;
35564+ } buf;
1facf9fc 35565+
b752ccd1 35566+ buf.k = kbuf;
1facf9fc 35567+ oldfs = get_fs();
35568+ set_fs(KERNEL_DS);
35569+ do {
35570+ /* todo: signal_pending? */
b752ccd1 35571+ err = func(file, buf.u, size, pos);
1facf9fc 35572+ } while (err == -EAGAIN || err == -EINTR);
35573+ set_fs(oldfs);
35574+
35575+#if 0 /* reserved for future use */
35576+ if (err > 0)
2000de60 35577+ fsnotify_access(file->f_path.dentry);
1facf9fc 35578+#endif
35579+
35580+ return err;
35581+}
35582+
35583+/* ---------------------------------------------------------------------- */
35584+
be52b249
AM
35585+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf,
35586+ size_t size, loff_t *pos);
35587+
5527c038 35588+static ssize_t do_xino_fwrite(vfs_writef_t func, struct file *file, void *kbuf,
1facf9fc 35589+ size_t size, loff_t *pos)
35590+{
35591+ ssize_t err;
35592+ mm_segment_t oldfs;
b752ccd1
AM
35593+ union {
35594+ void *k;
35595+ const char __user *u;
35596+ } buf;
be52b249
AM
35597+ int i;
35598+ const int prevent_endless = 10;
1facf9fc 35599+
be52b249 35600+ i = 0;
b752ccd1 35601+ buf.k = kbuf;
1facf9fc 35602+ oldfs = get_fs();
35603+ set_fs(KERNEL_DS);
1facf9fc 35604+ do {
b752ccd1 35605+ err = func(file, buf.u, size, pos);
be52b249
AM
35606+ if (err == -EINTR
35607+ && !au_wkq_test()
35608+ && fatal_signal_pending(current)) {
35609+ set_fs(oldfs);
35610+ err = xino_fwrite_wkq(func, file, kbuf, size, pos);
35611+ BUG_ON(err == -EINTR);
35612+ oldfs = get_fs();
35613+ set_fs(KERNEL_DS);
35614+ }
35615+ } while (i++ < prevent_endless
35616+ && (err == -EAGAIN || err == -EINTR));
1facf9fc 35617+ set_fs(oldfs);
35618+
35619+#if 0 /* reserved for future use */
35620+ if (err > 0)
2000de60 35621+ fsnotify_modify(file->f_path.dentry);
1facf9fc 35622+#endif
35623+
35624+ return err;
35625+}
35626+
35627+struct do_xino_fwrite_args {
35628+ ssize_t *errp;
5527c038 35629+ vfs_writef_t func;
1facf9fc 35630+ struct file *file;
35631+ void *buf;
35632+ size_t size;
35633+ loff_t *pos;
35634+};
35635+
35636+static void call_do_xino_fwrite(void *args)
35637+{
35638+ struct do_xino_fwrite_args *a = args;
35639+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
35640+}
35641+
be52b249
AM
35642+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf,
35643+ size_t size, loff_t *pos)
35644+{
35645+ ssize_t err;
35646+ int wkq_err;
35647+ struct do_xino_fwrite_args args = {
35648+ .errp = &err,
35649+ .func = func,
35650+ .file = file,
35651+ .buf = buf,
35652+ .size = size,
35653+ .pos = pos
35654+ };
35655+
35656+ /*
35657+ * it breaks RLIMIT_FSIZE and normal user's limit,
35658+ * users should care about quota and real 'filesystem full.'
35659+ */
35660+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
35661+ if (unlikely(wkq_err))
35662+ err = wkq_err;
35663+
35664+ return err;
35665+}
35666+
5527c038
JR
35667+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf,
35668+ size_t size, loff_t *pos)
1facf9fc 35669+{
35670+ ssize_t err;
35671+
b752ccd1
AM
35672+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
35673+ lockdep_off();
35674+ err = do_xino_fwrite(func, file, buf, size, pos);
35675+ lockdep_on();
8b6a4947
AM
35676+ } else {
35677+ lockdep_off();
be52b249 35678+ err = xino_fwrite_wkq(func, file, buf, size, pos);
8b6a4947
AM
35679+ lockdep_on();
35680+ }
1facf9fc 35681+
35682+ return err;
35683+}
35684+
35685+/* ---------------------------------------------------------------------- */
35686+
35687+/*
35688+ * create a new xinofile at the same place/path as @base_file.
35689+ */
35690+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
35691+{
35692+ struct file *file;
4a4d8108 35693+ struct dentry *base, *parent;
523b37e3 35694+ struct inode *dir, *delegated;
1facf9fc 35695+ struct qstr *name;
1308ab2a 35696+ struct path path;
4a4d8108 35697+ int err;
1facf9fc 35698+
2000de60 35699+ base = base_file->f_path.dentry;
1facf9fc 35700+ parent = base->d_parent; /* dir inode is locked */
5527c038 35701+ dir = d_inode(parent);
1facf9fc 35702+ IMustLock(dir);
35703+
35704+ file = ERR_PTR(-EINVAL);
35705+ name = &base->d_name;
4a4d8108
AM
35706+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
35707+ if (IS_ERR(path.dentry)) {
35708+ file = (void *)path.dentry;
523b37e3
AM
35709+ pr_err("%pd lookup err %ld\n",
35710+ base, PTR_ERR(path.dentry));
1facf9fc 35711+ goto out;
35712+ }
35713+
35714+ /* no need to mnt_want_write() since we call dentry_open() later */
4a4d8108 35715+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
1facf9fc 35716+ if (unlikely(err)) {
35717+ file = ERR_PTR(err);
523b37e3 35718+ pr_err("%pd create err %d\n", base, err);
1facf9fc 35719+ goto out_dput;
35720+ }
35721+
c06a8ce3 35722+ path.mnt = base_file->f_path.mnt;
4a4d8108 35723+ file = vfsub_dentry_open(&path,
7f207e10 35724+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 35725+ /* | __FMODE_NONOTIFY */);
1facf9fc 35726+ if (IS_ERR(file)) {
523b37e3 35727+ pr_err("%pd open err %ld\n", base, PTR_ERR(file));
1facf9fc 35728+ goto out_dput;
35729+ }
35730+
523b37e3
AM
35731+ delegated = NULL;
35732+ err = vfsub_unlink(dir, &file->f_path, &delegated, /*force*/0);
35733+ if (unlikely(err == -EWOULDBLOCK)) {
35734+ pr_warn("cannot retry for NFSv4 delegation"
35735+ " for an internal unlink\n");
35736+ iput(delegated);
35737+ }
1facf9fc 35738+ if (unlikely(err)) {
523b37e3 35739+ pr_err("%pd unlink err %d\n", base, err);
1facf9fc 35740+ goto out_fput;
35741+ }
35742+
35743+ if (copy_src) {
35744+ /* no one can touch copy_src xino */
c06a8ce3 35745+ err = au_copy_file(file, copy_src, vfsub_f_size_read(copy_src));
1facf9fc 35746+ if (unlikely(err)) {
523b37e3 35747+ pr_err("%pd copy err %d\n", base, err);
1facf9fc 35748+ goto out_fput;
35749+ }
35750+ }
35751+ goto out_dput; /* success */
35752+
4f0767ce 35753+out_fput:
1facf9fc 35754+ fput(file);
35755+ file = ERR_PTR(err);
4f0767ce 35756+out_dput:
4a4d8108 35757+ dput(path.dentry);
4f0767ce 35758+out:
1facf9fc 35759+ return file;
35760+}
35761+
35762+struct au_xino_lock_dir {
35763+ struct au_hinode *hdir;
35764+ struct dentry *parent;
febd17d6 35765+ struct inode *dir;
1facf9fc 35766+};
35767+
35768+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
35769+ struct au_xino_lock_dir *ldir)
35770+{
35771+ aufs_bindex_t brid, bindex;
35772+
35773+ ldir->hdir = NULL;
35774+ bindex = -1;
35775+ brid = au_xino_brid(sb);
35776+ if (brid >= 0)
35777+ bindex = au_br_index(sb, brid);
35778+ if (bindex >= 0) {
5527c038 35779+ ldir->hdir = au_hi(d_inode(sb->s_root), bindex);
5afbbe0d 35780+ au_hn_inode_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 35781+ } else {
2000de60 35782+ ldir->parent = dget_parent(xino->f_path.dentry);
febd17d6
JR
35783+ ldir->dir = d_inode(ldir->parent);
35784+ inode_lock_nested(ldir->dir, AuLsc_I_PARENT);
1facf9fc 35785+ }
35786+}
35787+
35788+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
35789+{
35790+ if (ldir->hdir)
5afbbe0d 35791+ au_hn_inode_unlock(ldir->hdir);
1facf9fc 35792+ else {
febd17d6 35793+ inode_unlock(ldir->dir);
1facf9fc 35794+ dput(ldir->parent);
35795+ }
35796+}
35797+
35798+/* ---------------------------------------------------------------------- */
35799+
35800+/* trucate xino files asynchronously */
35801+
35802+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
35803+{
35804+ int err;
392086de
AM
35805+ unsigned long jiffy;
35806+ blkcnt_t blocks;
5afbbe0d 35807+ aufs_bindex_t bi, bbot;
392086de 35808+ struct kstatfs *st;
1facf9fc 35809+ struct au_branch *br;
35810+ struct file *new_xino, *file;
35811+ struct super_block *h_sb;
35812+ struct au_xino_lock_dir ldir;
35813+
392086de 35814+ err = -ENOMEM;
be52b249 35815+ st = kmalloc(sizeof(*st), GFP_NOFS);
392086de
AM
35816+ if (unlikely(!st))
35817+ goto out;
35818+
1facf9fc 35819+ err = -EINVAL;
5afbbe0d
AM
35820+ bbot = au_sbbot(sb);
35821+ if (unlikely(bindex < 0 || bbot < bindex))
392086de 35822+ goto out_st;
1facf9fc 35823+ br = au_sbr(sb, bindex);
35824+ file = br->br_xino.xi_file;
35825+ if (!file)
392086de
AM
35826+ goto out_st;
35827+
35828+ err = vfs_statfs(&file->f_path, st);
35829+ if (unlikely(err))
35830+ AuErr1("statfs err %d, ignored\n", err);
35831+ jiffy = jiffies;
35832+ blocks = file_inode(file)->i_blocks;
35833+ pr_info("begin truncating xino(b%d), ib%llu, %llu/%llu free blks\n",
35834+ bindex, (u64)blocks, st->f_bfree, st->f_blocks);
1facf9fc 35835+
35836+ au_xino_lock_dir(sb, file, &ldir);
35837+ /* mnt_want_write() is unnecessary here */
35838+ new_xino = au_xino_create2(file, file);
35839+ au_xino_unlock_dir(&ldir);
35840+ err = PTR_ERR(new_xino);
392086de
AM
35841+ if (IS_ERR(new_xino)) {
35842+ pr_err("err %d, ignored\n", err);
35843+ goto out_st;
35844+ }
1facf9fc 35845+ err = 0;
35846+ fput(file);
35847+ br->br_xino.xi_file = new_xino;
35848+
86dc4139 35849+ h_sb = au_br_sb(br);
5afbbe0d 35850+ for (bi = 0; bi <= bbot; bi++) {
1facf9fc 35851+ if (unlikely(bi == bindex))
35852+ continue;
35853+ br = au_sbr(sb, bi);
86dc4139 35854+ if (au_br_sb(br) != h_sb)
1facf9fc 35855+ continue;
35856+
35857+ fput(br->br_xino.xi_file);
35858+ br->br_xino.xi_file = new_xino;
35859+ get_file(new_xino);
35860+ }
35861+
392086de
AM
35862+ err = vfs_statfs(&new_xino->f_path, st);
35863+ if (!err) {
35864+ pr_info("end truncating xino(b%d), ib%llu, %llu/%llu free blks\n",
35865+ bindex, (u64)file_inode(new_xino)->i_blocks,
35866+ st->f_bfree, st->f_blocks);
35867+ if (file_inode(new_xino)->i_blocks < blocks)
35868+ au_sbi(sb)->si_xino_jiffy = jiffy;
35869+ } else
35870+ AuErr1("statfs err %d, ignored\n", err);
35871+
35872+out_st:
1c60b727 35873+ kfree(st);
4f0767ce 35874+out:
1facf9fc 35875+ return err;
35876+}
35877+
35878+struct xino_do_trunc_args {
35879+ struct super_block *sb;
35880+ struct au_branch *br;
35881+};
35882+
35883+static void xino_do_trunc(void *_args)
35884+{
35885+ struct xino_do_trunc_args *args = _args;
35886+ struct super_block *sb;
35887+ struct au_branch *br;
35888+ struct inode *dir;
35889+ int err;
35890+ aufs_bindex_t bindex;
35891+
35892+ err = 0;
35893+ sb = args->sb;
5527c038 35894+ dir = d_inode(sb->s_root);
1facf9fc 35895+ br = args->br;
35896+
35897+ si_noflush_write_lock(sb);
35898+ ii_read_lock_parent(dir);
35899+ bindex = au_br_index(sb, br->br_id);
35900+ err = au_xino_trunc(sb, bindex);
1facf9fc 35901+ ii_read_unlock(dir);
35902+ if (unlikely(err))
392086de 35903+ pr_warn("err b%d, (%d)\n", bindex, err);
1facf9fc 35904+ atomic_dec(&br->br_xino_running);
5afbbe0d 35905+ au_br_put(br);
1facf9fc 35906+ si_write_unlock(sb);
027c5e7a 35907+ au_nwt_done(&au_sbi(sb)->si_nowait);
1c60b727 35908+ kfree(args);
1facf9fc 35909+}
35910+
392086de
AM
35911+static int xino_trunc_test(struct super_block *sb, struct au_branch *br)
35912+{
35913+ int err;
35914+ struct kstatfs st;
35915+ struct au_sbinfo *sbinfo;
35916+
35917+ /* todo: si_xino_expire and the ratio should be customizable */
35918+ sbinfo = au_sbi(sb);
35919+ if (time_before(jiffies,
35920+ sbinfo->si_xino_jiffy + sbinfo->si_xino_expire))
35921+ return 0;
35922+
35923+ /* truncation border */
35924+ err = vfs_statfs(&br->br_xino.xi_file->f_path, &st);
35925+ if (unlikely(err)) {
35926+ AuErr1("statfs err %d, ignored\n", err);
35927+ return 0;
35928+ }
35929+ if (div64_u64(st.f_bfree * 100, st.f_blocks) >= AUFS_XINO_DEF_TRUNC)
35930+ return 0;
35931+
35932+ return 1;
35933+}
35934+
1facf9fc 35935+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
35936+{
35937+ struct xino_do_trunc_args *args;
35938+ int wkq_err;
35939+
392086de 35940+ if (!xino_trunc_test(sb, br))
1facf9fc 35941+ return;
35942+
35943+ if (atomic_inc_return(&br->br_xino_running) > 1)
35944+ goto out;
35945+
35946+ /* lock and kfree() will be called in trunc_xino() */
35947+ args = kmalloc(sizeof(*args), GFP_NOFS);
35948+ if (unlikely(!args)) {
35949+ AuErr1("no memory\n");
f0c0a007 35950+ goto out;
1facf9fc 35951+ }
35952+
5afbbe0d 35953+ au_br_get(br);
1facf9fc 35954+ args->sb = sb;
35955+ args->br = br;
53392da6 35956+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0);
1facf9fc 35957+ if (!wkq_err)
35958+ return; /* success */
35959+
4a4d8108 35960+ pr_err("wkq %d\n", wkq_err);
5afbbe0d 35961+ au_br_put(br);
1c60b727 35962+ kfree(args);
1facf9fc 35963+
4f0767ce 35964+out:
e49829fe 35965+ atomic_dec(&br->br_xino_running);
1facf9fc 35966+}
35967+
35968+/* ---------------------------------------------------------------------- */
35969+
5527c038 35970+static int au_xino_do_write(vfs_writef_t write, struct file *file,
1facf9fc 35971+ ino_t h_ino, ino_t ino)
35972+{
35973+ loff_t pos;
35974+ ssize_t sz;
35975+
35976+ pos = h_ino;
35977+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
35978+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
35979+ return -EFBIG;
35980+ }
35981+ pos *= sizeof(ino);
35982+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
35983+ if (sz == sizeof(ino))
35984+ return 0; /* success */
35985+
35986+ AuIOErr("write failed (%zd)\n", sz);
35987+ return -EIO;
35988+}
35989+
35990+/*
35991+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
35992+ * at the position of @h_ino.
35993+ * even if @ino is zero, it is written to the xinofile and means no entry.
35994+ * if the size of the xino file on a specific filesystem exceeds the watermark,
35995+ * try truncating it.
35996+ */
35997+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
35998+ ino_t ino)
35999+{
36000+ int err;
36001+ unsigned int mnt_flags;
36002+ struct au_branch *br;
36003+
36004+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
36005+ || ((loff_t)-1) > 0);
dece6358 36006+ SiMustAnyLock(sb);
1facf9fc 36007+
36008+ mnt_flags = au_mntflags(sb);
36009+ if (!au_opt_test(mnt_flags, XINO))
36010+ return 0;
36011+
36012+ br = au_sbr(sb, bindex);
36013+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
36014+ h_ino, ino);
36015+ if (!err) {
36016+ if (au_opt_test(mnt_flags, TRUNC_XINO)
86dc4139 36017+ && au_test_fs_trunc_xino(au_br_sb(br)))
1facf9fc 36018+ xino_try_trunc(sb, br);
36019+ return 0; /* success */
36020+ }
36021+
36022+ AuIOErr("write failed (%d)\n", err);
36023+ return -EIO;
36024+}
36025+
36026+/* ---------------------------------------------------------------------- */
36027+
36028+/* aufs inode number bitmap */
36029+
36030+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
36031+static ino_t xib_calc_ino(unsigned long pindex, int bit)
36032+{
36033+ ino_t ino;
36034+
36035+ AuDebugOn(bit < 0 || page_bits <= bit);
36036+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
36037+ return ino;
36038+}
36039+
36040+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
36041+{
36042+ AuDebugOn(ino < AUFS_FIRST_INO);
36043+ ino -= AUFS_FIRST_INO;
36044+ *pindex = ino / page_bits;
36045+ *bit = ino % page_bits;
36046+}
36047+
36048+static int xib_pindex(struct super_block *sb, unsigned long pindex)
36049+{
36050+ int err;
36051+ loff_t pos;
36052+ ssize_t sz;
36053+ struct au_sbinfo *sbinfo;
36054+ struct file *xib;
36055+ unsigned long *p;
36056+
36057+ sbinfo = au_sbi(sb);
36058+ MtxMustLock(&sbinfo->si_xib_mtx);
36059+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
36060+ || !au_opt_test(sbinfo->si_mntflags, XINO));
36061+
36062+ if (pindex == sbinfo->si_xib_last_pindex)
36063+ return 0;
36064+
36065+ xib = sbinfo->si_xib;
36066+ p = sbinfo->si_xib_buf;
36067+ pos = sbinfo->si_xib_last_pindex;
36068+ pos *= PAGE_SIZE;
36069+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
36070+ if (unlikely(sz != PAGE_SIZE))
36071+ goto out;
36072+
36073+ pos = pindex;
36074+ pos *= PAGE_SIZE;
c06a8ce3 36075+ if (vfsub_f_size_read(xib) >= pos + PAGE_SIZE)
1facf9fc 36076+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
36077+ else {
36078+ memset(p, 0, PAGE_SIZE);
36079+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
36080+ }
36081+ if (sz == PAGE_SIZE) {
36082+ sbinfo->si_xib_last_pindex = pindex;
36083+ return 0; /* success */
36084+ }
36085+
4f0767ce 36086+out:
b752ccd1
AM
36087+ AuIOErr1("write failed (%zd)\n", sz);
36088+ err = sz;
36089+ if (sz >= 0)
36090+ err = -EIO;
36091+ return err;
36092+}
36093+
36094+/* ---------------------------------------------------------------------- */
36095+
36096+static void au_xib_clear_bit(struct inode *inode)
36097+{
36098+ int err, bit;
36099+ unsigned long pindex;
36100+ struct super_block *sb;
36101+ struct au_sbinfo *sbinfo;
36102+
36103+ AuDebugOn(inode->i_nlink);
36104+
36105+ sb = inode->i_sb;
36106+ xib_calc_bit(inode->i_ino, &pindex, &bit);
36107+ AuDebugOn(page_bits <= bit);
36108+ sbinfo = au_sbi(sb);
36109+ mutex_lock(&sbinfo->si_xib_mtx);
36110+ err = xib_pindex(sb, pindex);
36111+ if (!err) {
36112+ clear_bit(bit, sbinfo->si_xib_buf);
36113+ sbinfo->si_xib_next_bit = bit;
36114+ }
36115+ mutex_unlock(&sbinfo->si_xib_mtx);
36116+}
36117+
36118+/* for s_op->delete_inode() */
36119+void au_xino_delete_inode(struct inode *inode, const int unlinked)
36120+{
36121+ int err;
36122+ unsigned int mnt_flags;
5afbbe0d 36123+ aufs_bindex_t bindex, bbot, bi;
b752ccd1
AM
36124+ unsigned char try_trunc;
36125+ struct au_iinfo *iinfo;
36126+ struct super_block *sb;
36127+ struct au_hinode *hi;
36128+ struct inode *h_inode;
36129+ struct au_branch *br;
5527c038 36130+ vfs_writef_t xwrite;
b752ccd1 36131+
5afbbe0d
AM
36132+ AuDebugOn(au_is_bad_inode(inode));
36133+
b752ccd1
AM
36134+ sb = inode->i_sb;
36135+ mnt_flags = au_mntflags(sb);
36136+ if (!au_opt_test(mnt_flags, XINO)
36137+ || inode->i_ino == AUFS_ROOT_INO)
36138+ return;
36139+
36140+ if (unlinked) {
36141+ au_xigen_inc(inode);
36142+ au_xib_clear_bit(inode);
36143+ }
36144+
36145+ iinfo = au_ii(inode);
5afbbe0d 36146+ bindex = iinfo->ii_btop;
b752ccd1
AM
36147+ if (bindex < 0)
36148+ return;
1facf9fc 36149+
b752ccd1
AM
36150+ xwrite = au_sbi(sb)->si_xwrite;
36151+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
5afbbe0d
AM
36152+ hi = au_hinode(iinfo, bindex);
36153+ bbot = iinfo->ii_bbot;
36154+ for (; bindex <= bbot; bindex++, hi++) {
b752ccd1
AM
36155+ h_inode = hi->hi_inode;
36156+ if (!h_inode
36157+ || (!unlinked && h_inode->i_nlink))
36158+ continue;
1facf9fc 36159+
b752ccd1
AM
36160+ /* inode may not be revalidated */
36161+ bi = au_br_index(sb, hi->hi_id);
36162+ if (bi < 0)
36163+ continue;
1facf9fc 36164+
b752ccd1
AM
36165+ br = au_sbr(sb, bi);
36166+ err = au_xino_do_write(xwrite, br->br_xino.xi_file,
36167+ h_inode->i_ino, /*ino*/0);
36168+ if (!err && try_trunc
86dc4139 36169+ && au_test_fs_trunc_xino(au_br_sb(br)))
b752ccd1 36170+ xino_try_trunc(sb, br);
1facf9fc 36171+ }
1facf9fc 36172+}
36173+
36174+/* get an unused inode number from bitmap */
36175+ino_t au_xino_new_ino(struct super_block *sb)
36176+{
36177+ ino_t ino;
36178+ unsigned long *p, pindex, ul, pend;
36179+ struct au_sbinfo *sbinfo;
36180+ struct file *file;
36181+ int free_bit, err;
36182+
36183+ if (!au_opt_test(au_mntflags(sb), XINO))
36184+ return iunique(sb, AUFS_FIRST_INO);
36185+
36186+ sbinfo = au_sbi(sb);
36187+ mutex_lock(&sbinfo->si_xib_mtx);
36188+ p = sbinfo->si_xib_buf;
36189+ free_bit = sbinfo->si_xib_next_bit;
36190+ if (free_bit < page_bits && !test_bit(free_bit, p))
36191+ goto out; /* success */
36192+ free_bit = find_first_zero_bit(p, page_bits);
36193+ if (free_bit < page_bits)
36194+ goto out; /* success */
36195+
36196+ pindex = sbinfo->si_xib_last_pindex;
36197+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
36198+ err = xib_pindex(sb, ul);
36199+ if (unlikely(err))
36200+ goto out_err;
36201+ free_bit = find_first_zero_bit(p, page_bits);
36202+ if (free_bit < page_bits)
36203+ goto out; /* success */
36204+ }
36205+
36206+ file = sbinfo->si_xib;
c06a8ce3 36207+ pend = vfsub_f_size_read(file) / PAGE_SIZE;
1facf9fc 36208+ for (ul = pindex + 1; ul <= pend; ul++) {
36209+ err = xib_pindex(sb, ul);
36210+ if (unlikely(err))
36211+ goto out_err;
36212+ free_bit = find_first_zero_bit(p, page_bits);
36213+ if (free_bit < page_bits)
36214+ goto out; /* success */
36215+ }
36216+ BUG();
36217+
4f0767ce 36218+out:
1facf9fc 36219+ set_bit(free_bit, p);
7f207e10 36220+ sbinfo->si_xib_next_bit = free_bit + 1;
1facf9fc 36221+ pindex = sbinfo->si_xib_last_pindex;
36222+ mutex_unlock(&sbinfo->si_xib_mtx);
36223+ ino = xib_calc_ino(pindex, free_bit);
36224+ AuDbg("i%lu\n", (unsigned long)ino);
36225+ return ino;
4f0767ce 36226+out_err:
1facf9fc 36227+ mutex_unlock(&sbinfo->si_xib_mtx);
36228+ AuDbg("i0\n");
36229+ return 0;
36230+}
36231+
36232+/*
36233+ * read @ino from xinofile for the specified branch{@sb, @bindex}
36234+ * at the position of @h_ino.
36235+ * if @ino does not exist and @do_new is true, get new one.
36236+ */
36237+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
36238+ ino_t *ino)
36239+{
36240+ int err;
36241+ ssize_t sz;
36242+ loff_t pos;
36243+ struct file *file;
36244+ struct au_sbinfo *sbinfo;
36245+
36246+ *ino = 0;
36247+ if (!au_opt_test(au_mntflags(sb), XINO))
36248+ return 0; /* no xino */
36249+
36250+ err = 0;
36251+ sbinfo = au_sbi(sb);
36252+ pos = h_ino;
36253+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
36254+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
36255+ return -EFBIG;
36256+ }
36257+ pos *= sizeof(*ino);
36258+
36259+ file = au_sbr(sb, bindex)->br_xino.xi_file;
c06a8ce3 36260+ if (vfsub_f_size_read(file) < pos + sizeof(*ino))
1facf9fc 36261+ return 0; /* no ino */
36262+
36263+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
36264+ if (sz == sizeof(*ino))
36265+ return 0; /* success */
36266+
36267+ err = sz;
36268+ if (unlikely(sz >= 0)) {
36269+ err = -EIO;
36270+ AuIOErr("xino read error (%zd)\n", sz);
36271+ }
36272+
36273+ return err;
36274+}
36275+
36276+/* ---------------------------------------------------------------------- */
36277+
36278+/* create and set a new xino file */
36279+
36280+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
36281+{
36282+ struct file *file;
36283+ struct dentry *h_parent, *d;
b912730e 36284+ struct inode *h_dir, *inode;
1facf9fc 36285+ int err;
36286+
36287+ /*
36288+ * at mount-time, and the xino file is the default path,
4a4d8108 36289+ * hnotify is disabled so we have no notify events to ignore.
1facf9fc 36290+ * when a user specified the xino, we cannot get au_hdir to be ignored.
36291+ */
7f207e10 36292+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 36293+ /* | __FMODE_NONOTIFY */,
1facf9fc 36294+ S_IRUGO | S_IWUGO);
36295+ if (IS_ERR(file)) {
36296+ if (!silent)
4a4d8108 36297+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
1facf9fc 36298+ return file;
36299+ }
36300+
36301+ /* keep file count */
b912730e
AM
36302+ err = 0;
36303+ inode = file_inode(file);
2000de60 36304+ h_parent = dget_parent(file->f_path.dentry);
5527c038 36305+ h_dir = d_inode(h_parent);
febd17d6 36306+ inode_lock_nested(h_dir, AuLsc_I_PARENT);
1facf9fc 36307+ /* mnt_want_write() is unnecessary here */
523b37e3 36308+ /* no delegation since it is just created */
b912730e
AM
36309+ if (inode->i_nlink)
36310+ err = vfsub_unlink(h_dir, &file->f_path, /*delegated*/NULL,
36311+ /*force*/0);
febd17d6 36312+ inode_unlock(h_dir);
1facf9fc 36313+ dput(h_parent);
36314+ if (unlikely(err)) {
36315+ if (!silent)
4a4d8108 36316+ pr_err("unlink %s(%d)\n", fname, err);
1facf9fc 36317+ goto out;
36318+ }
36319+
36320+ err = -EINVAL;
2000de60 36321+ d = file->f_path.dentry;
1facf9fc 36322+ if (unlikely(sb == d->d_sb)) {
36323+ if (!silent)
4a4d8108 36324+ pr_err("%s must be outside\n", fname);
1facf9fc 36325+ goto out;
36326+ }
36327+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
36328+ if (!silent)
4a4d8108
AM
36329+ pr_err("xino doesn't support %s(%s)\n",
36330+ fname, au_sbtype(d->d_sb));
1facf9fc 36331+ goto out;
36332+ }
36333+ return file; /* success */
36334+
4f0767ce 36335+out:
1facf9fc 36336+ fput(file);
36337+ file = ERR_PTR(err);
36338+ return file;
36339+}
36340+
36341+/*
36342+ * find another branch who is on the same filesystem of the specified
5afbbe0d 36343+ * branch{@btgt}. search until @bbot.
1facf9fc 36344+ */
36345+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
5afbbe0d 36346+ aufs_bindex_t bbot)
1facf9fc 36347+{
36348+ aufs_bindex_t bindex;
36349+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
36350+
36351+ for (bindex = 0; bindex < btgt; bindex++)
36352+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
36353+ return bindex;
5afbbe0d 36354+ for (bindex++; bindex <= bbot; bindex++)
1facf9fc 36355+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
36356+ return bindex;
36357+ return -1;
36358+}
36359+
36360+/* ---------------------------------------------------------------------- */
36361+
36362+/*
36363+ * initialize the xinofile for the specified branch @br
36364+ * at the place/path where @base_file indicates.
36365+ * test whether another branch is on the same filesystem or not,
36366+ * if @do_test is true.
36367+ */
36368+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
36369+ struct file *base_file, int do_test)
36370+{
36371+ int err;
36372+ ino_t ino;
5afbbe0d 36373+ aufs_bindex_t bbot, bindex;
1facf9fc 36374+ struct au_branch *shared_br, *b;
36375+ struct file *file;
36376+ struct super_block *tgt_sb;
36377+
36378+ shared_br = NULL;
5afbbe0d 36379+ bbot = au_sbbot(sb);
1facf9fc 36380+ if (do_test) {
86dc4139 36381+ tgt_sb = au_br_sb(br);
5afbbe0d 36382+ for (bindex = 0; bindex <= bbot; bindex++) {
1facf9fc 36383+ b = au_sbr(sb, bindex);
86dc4139 36384+ if (tgt_sb == au_br_sb(b)) {
1facf9fc 36385+ shared_br = b;
36386+ break;
36387+ }
36388+ }
36389+ }
36390+
36391+ if (!shared_br || !shared_br->br_xino.xi_file) {
36392+ struct au_xino_lock_dir ldir;
36393+
36394+ au_xino_lock_dir(sb, base_file, &ldir);
36395+ /* mnt_want_write() is unnecessary here */
36396+ file = au_xino_create2(base_file, NULL);
36397+ au_xino_unlock_dir(&ldir);
36398+ err = PTR_ERR(file);
36399+ if (IS_ERR(file))
36400+ goto out;
36401+ br->br_xino.xi_file = file;
36402+ } else {
36403+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
36404+ get_file(br->br_xino.xi_file);
36405+ }
36406+
36407+ ino = AUFS_ROOT_INO;
36408+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
36409+ h_ino, ino);
b752ccd1
AM
36410+ if (unlikely(err)) {
36411+ fput(br->br_xino.xi_file);
36412+ br->br_xino.xi_file = NULL;
36413+ }
1facf9fc 36414+
4f0767ce 36415+out:
1facf9fc 36416+ return err;
36417+}
36418+
36419+/* ---------------------------------------------------------------------- */
36420+
36421+/* trucate a xino bitmap file */
36422+
36423+/* todo: slow */
36424+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
36425+{
36426+ int err, bit;
36427+ ssize_t sz;
36428+ unsigned long pindex;
36429+ loff_t pos, pend;
36430+ struct au_sbinfo *sbinfo;
5527c038 36431+ vfs_readf_t func;
1facf9fc 36432+ ino_t *ino;
36433+ unsigned long *p;
36434+
36435+ err = 0;
36436+ sbinfo = au_sbi(sb);
dece6358 36437+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 36438+ p = sbinfo->si_xib_buf;
36439+ func = sbinfo->si_xread;
c06a8ce3 36440+ pend = vfsub_f_size_read(file);
1facf9fc 36441+ pos = 0;
36442+ while (pos < pend) {
36443+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
36444+ err = sz;
36445+ if (unlikely(sz <= 0))
36446+ goto out;
36447+
36448+ err = 0;
36449+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
36450+ if (unlikely(*ino < AUFS_FIRST_INO))
36451+ continue;
36452+
36453+ xib_calc_bit(*ino, &pindex, &bit);
36454+ AuDebugOn(page_bits <= bit);
36455+ err = xib_pindex(sb, pindex);
36456+ if (!err)
36457+ set_bit(bit, p);
36458+ else
36459+ goto out;
36460+ }
36461+ }
36462+
4f0767ce 36463+out:
1facf9fc 36464+ return err;
36465+}
36466+
36467+static int xib_restore(struct super_block *sb)
36468+{
36469+ int err;
5afbbe0d 36470+ aufs_bindex_t bindex, bbot;
1facf9fc 36471+ void *page;
36472+
36473+ err = -ENOMEM;
36474+ page = (void *)__get_free_page(GFP_NOFS);
36475+ if (unlikely(!page))
36476+ goto out;
36477+
36478+ err = 0;
5afbbe0d
AM
36479+ bbot = au_sbbot(sb);
36480+ for (bindex = 0; !err && bindex <= bbot; bindex++)
1facf9fc 36481+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
36482+ err = do_xib_restore
36483+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
36484+ else
36485+ AuDbg("b%d\n", bindex);
1c60b727 36486+ free_page((unsigned long)page);
1facf9fc 36487+
4f0767ce 36488+out:
1facf9fc 36489+ return err;
36490+}
36491+
36492+int au_xib_trunc(struct super_block *sb)
36493+{
36494+ int err;
36495+ ssize_t sz;
36496+ loff_t pos;
36497+ struct au_xino_lock_dir ldir;
36498+ struct au_sbinfo *sbinfo;
36499+ unsigned long *p;
36500+ struct file *file;
36501+
dece6358
AM
36502+ SiMustWriteLock(sb);
36503+
1facf9fc 36504+ err = 0;
36505+ sbinfo = au_sbi(sb);
36506+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
36507+ goto out;
36508+
36509+ file = sbinfo->si_xib;
c06a8ce3 36510+ if (vfsub_f_size_read(file) <= PAGE_SIZE)
1facf9fc 36511+ goto out;
36512+
36513+ au_xino_lock_dir(sb, file, &ldir);
36514+ /* mnt_want_write() is unnecessary here */
36515+ file = au_xino_create2(sbinfo->si_xib, NULL);
36516+ au_xino_unlock_dir(&ldir);
36517+ err = PTR_ERR(file);
36518+ if (IS_ERR(file))
36519+ goto out;
36520+ fput(sbinfo->si_xib);
36521+ sbinfo->si_xib = file;
36522+
36523+ p = sbinfo->si_xib_buf;
36524+ memset(p, 0, PAGE_SIZE);
36525+ pos = 0;
36526+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
36527+ if (unlikely(sz != PAGE_SIZE)) {
36528+ err = sz;
36529+ AuIOErr("err %d\n", err);
36530+ if (sz >= 0)
36531+ err = -EIO;
36532+ goto out;
36533+ }
36534+
36535+ mutex_lock(&sbinfo->si_xib_mtx);
36536+ /* mnt_want_write() is unnecessary here */
36537+ err = xib_restore(sb);
36538+ mutex_unlock(&sbinfo->si_xib_mtx);
36539+
36540+out:
36541+ return err;
36542+}
36543+
36544+/* ---------------------------------------------------------------------- */
36545+
36546+/*
36547+ * xino mount option handlers
36548+ */
1facf9fc 36549+
36550+/* xino bitmap */
36551+static void xino_clear_xib(struct super_block *sb)
36552+{
36553+ struct au_sbinfo *sbinfo;
36554+
dece6358
AM
36555+ SiMustWriteLock(sb);
36556+
1facf9fc 36557+ sbinfo = au_sbi(sb);
36558+ sbinfo->si_xread = NULL;
36559+ sbinfo->si_xwrite = NULL;
36560+ if (sbinfo->si_xib)
36561+ fput(sbinfo->si_xib);
36562+ sbinfo->si_xib = NULL;
f0c0a007 36563+ if (sbinfo->si_xib_buf)
1c60b727 36564+ free_page((unsigned long)sbinfo->si_xib_buf);
1facf9fc 36565+ sbinfo->si_xib_buf = NULL;
36566+}
36567+
36568+static int au_xino_set_xib(struct super_block *sb, struct file *base)
36569+{
36570+ int err;
36571+ loff_t pos;
36572+ struct au_sbinfo *sbinfo;
36573+ struct file *file;
36574+
dece6358
AM
36575+ SiMustWriteLock(sb);
36576+
1facf9fc 36577+ sbinfo = au_sbi(sb);
36578+ file = au_xino_create2(base, sbinfo->si_xib);
36579+ err = PTR_ERR(file);
36580+ if (IS_ERR(file))
36581+ goto out;
36582+ if (sbinfo->si_xib)
36583+ fput(sbinfo->si_xib);
36584+ sbinfo->si_xib = file;
5527c038
JR
36585+ sbinfo->si_xread = vfs_readf(file);
36586+ sbinfo->si_xwrite = vfs_writef(file);
1facf9fc 36587+
36588+ err = -ENOMEM;
36589+ if (!sbinfo->si_xib_buf)
36590+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
36591+ if (unlikely(!sbinfo->si_xib_buf))
36592+ goto out_unset;
36593+
36594+ sbinfo->si_xib_last_pindex = 0;
36595+ sbinfo->si_xib_next_bit = 0;
c06a8ce3 36596+ if (vfsub_f_size_read(file) < PAGE_SIZE) {
1facf9fc 36597+ pos = 0;
36598+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
36599+ PAGE_SIZE, &pos);
36600+ if (unlikely(err != PAGE_SIZE))
36601+ goto out_free;
36602+ }
36603+ err = 0;
36604+ goto out; /* success */
36605+
4f0767ce 36606+out_free:
f0c0a007 36607+ if (sbinfo->si_xib_buf)
1c60b727 36608+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
36609+ sbinfo->si_xib_buf = NULL;
36610+ if (err >= 0)
36611+ err = -EIO;
4f0767ce 36612+out_unset:
b752ccd1
AM
36613+ fput(sbinfo->si_xib);
36614+ sbinfo->si_xib = NULL;
36615+ sbinfo->si_xread = NULL;
36616+ sbinfo->si_xwrite = NULL;
4f0767ce 36617+out:
b752ccd1 36618+ return err;
1facf9fc 36619+}
36620+
b752ccd1
AM
36621+/* xino for each branch */
36622+static void xino_clear_br(struct super_block *sb)
36623+{
5afbbe0d 36624+ aufs_bindex_t bindex, bbot;
b752ccd1 36625+ struct au_branch *br;
1facf9fc 36626+
5afbbe0d
AM
36627+ bbot = au_sbbot(sb);
36628+ for (bindex = 0; bindex <= bbot; bindex++) {
b752ccd1
AM
36629+ br = au_sbr(sb, bindex);
36630+ if (!br || !br->br_xino.xi_file)
36631+ continue;
36632+
36633+ fput(br->br_xino.xi_file);
36634+ br->br_xino.xi_file = NULL;
36635+ }
36636+}
36637+
36638+static int au_xino_set_br(struct super_block *sb, struct file *base)
1facf9fc 36639+{
36640+ int err;
b752ccd1 36641+ ino_t ino;
5afbbe0d 36642+ aufs_bindex_t bindex, bbot, bshared;
b752ccd1
AM
36643+ struct {
36644+ struct file *old, *new;
36645+ } *fpair, *p;
36646+ struct au_branch *br;
36647+ struct inode *inode;
5527c038 36648+ vfs_writef_t writef;
1facf9fc 36649+
b752ccd1
AM
36650+ SiMustWriteLock(sb);
36651+
36652+ err = -ENOMEM;
5afbbe0d
AM
36653+ bbot = au_sbbot(sb);
36654+ fpair = kcalloc(bbot + 1, sizeof(*fpair), GFP_NOFS);
b752ccd1 36655+ if (unlikely(!fpair))
1facf9fc 36656+ goto out;
36657+
5527c038 36658+ inode = d_inode(sb->s_root);
b752ccd1
AM
36659+ ino = AUFS_ROOT_INO;
36660+ writef = au_sbi(sb)->si_xwrite;
5afbbe0d 36661+ for (bindex = 0, p = fpair; bindex <= bbot; bindex++, p++) {
b752ccd1
AM
36662+ bshared = is_sb_shared(sb, bindex, bindex - 1);
36663+ if (bshared >= 0) {
36664+ /* shared xino */
36665+ *p = fpair[bshared];
36666+ get_file(p->new);
36667+ }
36668+
36669+ if (!p->new) {
36670+ /* new xino */
5afbbe0d 36671+ br = au_sbr(sb, bindex);
b752ccd1
AM
36672+ p->old = br->br_xino.xi_file;
36673+ p->new = au_xino_create2(base, br->br_xino.xi_file);
36674+ err = PTR_ERR(p->new);
36675+ if (IS_ERR(p->new)) {
36676+ p->new = NULL;
36677+ goto out_pair;
36678+ }
36679+ }
36680+
36681+ err = au_xino_do_write(writef, p->new,
36682+ au_h_iptr(inode, bindex)->i_ino, ino);
36683+ if (unlikely(err))
36684+ goto out_pair;
36685+ }
36686+
5afbbe0d 36687+ for (bindex = 0, p = fpair; bindex <= bbot; bindex++, p++) {
b752ccd1
AM
36688+ br = au_sbr(sb, bindex);
36689+ if (br->br_xino.xi_file)
36690+ fput(br->br_xino.xi_file);
36691+ get_file(p->new);
36692+ br->br_xino.xi_file = p->new;
36693+ }
1facf9fc 36694+
4f0767ce 36695+out_pair:
5afbbe0d 36696+ for (bindex = 0, p = fpair; bindex <= bbot; bindex++, p++)
b752ccd1
AM
36697+ if (p->new)
36698+ fput(p->new);
36699+ else
36700+ break;
1c60b727 36701+ kfree(fpair);
4f0767ce 36702+out:
1facf9fc 36703+ return err;
36704+}
b752ccd1
AM
36705+
36706+void au_xino_clr(struct super_block *sb)
36707+{
36708+ struct au_sbinfo *sbinfo;
36709+
36710+ au_xigen_clr(sb);
36711+ xino_clear_xib(sb);
36712+ xino_clear_br(sb);
36713+ sbinfo = au_sbi(sb);
36714+ /* lvalue, do not call au_mntflags() */
36715+ au_opt_clr(sbinfo->si_mntflags, XINO);
36716+}
36717+
36718+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
36719+{
36720+ int err, skip;
36721+ struct dentry *parent, *cur_parent;
36722+ struct qstr *dname, *cur_name;
36723+ struct file *cur_xino;
36724+ struct inode *dir;
36725+ struct au_sbinfo *sbinfo;
36726+
36727+ SiMustWriteLock(sb);
36728+
36729+ err = 0;
36730+ sbinfo = au_sbi(sb);
2000de60 36731+ parent = dget_parent(xino->file->f_path.dentry);
b752ccd1
AM
36732+ if (remount) {
36733+ skip = 0;
2000de60 36734+ dname = &xino->file->f_path.dentry->d_name;
b752ccd1
AM
36735+ cur_xino = sbinfo->si_xib;
36736+ if (cur_xino) {
2000de60
JR
36737+ cur_parent = dget_parent(cur_xino->f_path.dentry);
36738+ cur_name = &cur_xino->f_path.dentry->d_name;
b752ccd1 36739+ skip = (cur_parent == parent
38d290e6 36740+ && au_qstreq(dname, cur_name));
b752ccd1
AM
36741+ dput(cur_parent);
36742+ }
36743+ if (skip)
36744+ goto out;
36745+ }
36746+
36747+ au_opt_set(sbinfo->si_mntflags, XINO);
5527c038 36748+ dir = d_inode(parent);
febd17d6 36749+ inode_lock_nested(dir, AuLsc_I_PARENT);
b752ccd1
AM
36750+ /* mnt_want_write() is unnecessary here */
36751+ err = au_xino_set_xib(sb, xino->file);
36752+ if (!err)
36753+ err = au_xigen_set(sb, xino->file);
36754+ if (!err)
36755+ err = au_xino_set_br(sb, xino->file);
febd17d6 36756+ inode_unlock(dir);
b752ccd1
AM
36757+ if (!err)
36758+ goto out; /* success */
36759+
36760+ /* reset all */
36761+ AuIOErr("failed creating xino(%d).\n", err);
c1595e42
JR
36762+ au_xigen_clr(sb);
36763+ xino_clear_xib(sb);
b752ccd1 36764+
4f0767ce 36765+out:
b752ccd1
AM
36766+ dput(parent);
36767+ return err;
36768+}
36769+
36770+/* ---------------------------------------------------------------------- */
36771+
36772+/*
36773+ * create a xinofile at the default place/path.
36774+ */
36775+struct file *au_xino_def(struct super_block *sb)
36776+{
36777+ struct file *file;
36778+ char *page, *p;
36779+ struct au_branch *br;
36780+ struct super_block *h_sb;
36781+ struct path path;
5afbbe0d 36782+ aufs_bindex_t bbot, bindex, bwr;
b752ccd1
AM
36783+
36784+ br = NULL;
5afbbe0d 36785+ bbot = au_sbbot(sb);
b752ccd1 36786+ bwr = -1;
5afbbe0d 36787+ for (bindex = 0; bindex <= bbot; bindex++) {
b752ccd1
AM
36788+ br = au_sbr(sb, bindex);
36789+ if (au_br_writable(br->br_perm)
86dc4139 36790+ && !au_test_fs_bad_xino(au_br_sb(br))) {
b752ccd1
AM
36791+ bwr = bindex;
36792+ break;
36793+ }
36794+ }
36795+
7f207e10
AM
36796+ if (bwr >= 0) {
36797+ file = ERR_PTR(-ENOMEM);
537831f9 36798+ page = (void *)__get_free_page(GFP_NOFS);
7f207e10
AM
36799+ if (unlikely(!page))
36800+ goto out;
86dc4139 36801+ path.mnt = au_br_mnt(br);
7f207e10
AM
36802+ path.dentry = au_h_dptr(sb->s_root, bwr);
36803+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
36804+ file = (void *)p;
36805+ if (!IS_ERR(p)) {
36806+ strcat(p, "/" AUFS_XINO_FNAME);
36807+ AuDbg("%s\n", p);
36808+ file = au_xino_create(sb, p, /*silent*/0);
36809+ if (!IS_ERR(file))
36810+ au_xino_brid_set(sb, br->br_id);
36811+ }
1c60b727 36812+ free_page((unsigned long)page);
7f207e10
AM
36813+ } else {
36814+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
36815+ if (IS_ERR(file))
36816+ goto out;
2000de60 36817+ h_sb = file->f_path.dentry->d_sb;
7f207e10
AM
36818+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
36819+ pr_err("xino doesn't support %s(%s)\n",
36820+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
36821+ fput(file);
36822+ file = ERR_PTR(-EINVAL);
36823+ }
36824+ if (!IS_ERR(file))
36825+ au_xino_brid_set(sb, -1);
36826+ }
0c5527e5 36827+
7f207e10
AM
36828+out:
36829+ return file;
36830+}
36831+
36832+/* ---------------------------------------------------------------------- */
36833+
36834+int au_xino_path(struct seq_file *seq, struct file *file)
36835+{
36836+ int err;
36837+
36838+ err = au_seq_path(seq, &file->f_path);
79b8bda9 36839+ if (unlikely(err))
7f207e10
AM
36840+ goto out;
36841+
7f207e10
AM
36842+#define Deleted "\\040(deleted)"
36843+ seq->count -= sizeof(Deleted) - 1;
36844+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
36845+ sizeof(Deleted) - 1));
36846+#undef Deleted
36847+
36848+out:
36849+ return err;
36850+}
521ced18
JR
36851+
36852+/* ---------------------------------------------------------------------- */
36853+
36854+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex,
36855+ ino_t h_ino, int idx)
36856+{
36857+ struct au_xino_file *xino;
36858+
36859+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
36860+ xino = &au_sbr(sb, bindex)->br_xino;
36861+ AuDebugOn(idx < 0 || xino->xi_nondir.total <= idx);
36862+
36863+ spin_lock(&xino->xi_nondir.spin);
36864+ AuDebugOn(xino->xi_nondir.array[idx] != h_ino);
36865+ xino->xi_nondir.array[idx] = 0;
36866+ spin_unlock(&xino->xi_nondir.spin);
36867+ wake_up_all(&xino->xi_nondir.wqh);
36868+}
36869+
36870+static int au_xinondir_find(struct au_xino_file *xino, ino_t h_ino)
36871+{
36872+ int found, total, i;
36873+
36874+ found = -1;
36875+ total = xino->xi_nondir.total;
36876+ for (i = 0; i < total; i++) {
36877+ if (xino->xi_nondir.array[i] != h_ino)
36878+ continue;
36879+ found = i;
36880+ break;
36881+ }
36882+
36883+ return found;
36884+}
36885+
36886+static int au_xinondir_expand(struct au_xino_file *xino)
36887+{
36888+ int err, sz;
36889+ ino_t *p;
36890+
36891+ BUILD_BUG_ON(KMALLOC_MAX_SIZE > INT_MAX);
36892+
36893+ err = -ENOMEM;
36894+ sz = xino->xi_nondir.total * sizeof(ino_t);
36895+ if (unlikely(sz > KMALLOC_MAX_SIZE / 2))
36896+ goto out;
36897+ p = au_kzrealloc(xino->xi_nondir.array, sz, sz << 1, GFP_ATOMIC,
36898+ /*may_shrink*/0);
36899+ if (p) {
36900+ xino->xi_nondir.array = p;
36901+ xino->xi_nondir.total <<= 1;
36902+ AuDbg("xi_nondir.total %d\n", xino->xi_nondir.total);
36903+ err = 0;
36904+ }
36905+
36906+out:
36907+ return err;
36908+}
36909+
36910+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
36911+ int *idx)
36912+{
36913+ int err, found, empty;
36914+ struct au_xino_file *xino;
36915+
36916+ err = 0;
36917+ *idx = -1;
36918+ if (!au_opt_test(au_mntflags(sb), XINO))
36919+ goto out; /* no xino */
36920+
36921+ xino = &au_sbr(sb, bindex)->br_xino;
36922+
0b1ff5c3
JR
36923+again:
36924+ spin_lock(&xino->xi_nondir.spin);
36925+ found = au_xinondir_find(xino, h_ino);
36926+ if (found == -1) {
36927+ empty = au_xinondir_find(xino, /*h_ino*/0);
36928+ if (empty == -1) {
36929+ empty = xino->xi_nondir.total;
36930+ err = au_xinondir_expand(xino);
36931+ if (unlikely(err))
36932+ goto out_unlock;
36933+ }
36934+ xino->xi_nondir.array[empty] = h_ino;
36935+ *idx = empty;
36936+ } else {
36937+ spin_unlock(&xino->xi_nondir.spin);
36938+ wait_event(xino->xi_nondir.wqh,
36939+ xino->xi_nondir.array[found] != h_ino);
36940+ goto again;
36941+ }
36942+
36943+out_unlock:
36944+ spin_unlock(&xino->xi_nondir.spin);
36945+out:
36946+ return err;
36947+}
36948diff -urNp -x '*.orig' linux-4.14/fs/dcache.c linux-4.14/fs/dcache.c
36949--- linux-4.14/fs/dcache.c 2021-02-24 21:42:35.464465471 +0100
36950+++ linux-4.14/fs/dcache.c 2021-02-24 21:42:43.437781422 +0100
36951@@ -1217,7 +1217,7 @@ enum d_walk_ret {
36952 *
36953 * The @enter() and @finish() callbacks are called with d_lock held.
36954 */
36955-static void d_walk(struct dentry *parent, void *data,
36956+void d_walk(struct dentry *parent, void *data,
36957 enum d_walk_ret (*enter)(void *, struct dentry *),
36958 void (*finish)(void *))
36959 {
36960@@ -1325,6 +1325,7 @@ rename_retry:
36961 seq = 1;
36962 goto again;
36963 }
36964+EXPORT_SYMBOL_GPL(d_walk);
36965
36966 struct check_mount {
36967 struct vfsmount *mnt;
36968@@ -2950,6 +2951,7 @@ void d_exchange(struct dentry *dentry1,
36969
36970 write_sequnlock(&rename_lock);
36971 }
36972+EXPORT_SYMBOL_GPL(d_exchange);
36973
36974 /**
36975 * d_ancestor - search for an ancestor
36976diff -urNp -x '*.orig' linux-4.14/fs/exec.c linux-4.14/fs/exec.c
36977--- linux-4.14/fs/exec.c 2021-02-24 21:42:35.467798797 +0100
36978+++ linux-4.14/fs/exec.c 2021-02-24 21:42:43.437781422 +0100
36979@@ -109,6 +109,7 @@ bool path_noexec(const struct path *path
36980 return (path->mnt->mnt_flags & MNT_NOEXEC) ||
36981 (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
36982 }
36983+EXPORT_SYMBOL_GPL(path_noexec);
36984
36985 #ifdef CONFIG_USELIB
36986 /*
36987diff -urNp -x '*.orig' linux-4.14/fs/fcntl.c linux-4.14/fs/fcntl.c
36988--- linux-4.14/fs/fcntl.c 2021-02-24 21:42:35.474465447 +0100
36989+++ linux-4.14/fs/fcntl.c 2021-02-24 21:42:43.437781422 +0100
36990@@ -32,7 +32,7 @@
36991
36992 #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
36993
36994-static int setfl(int fd, struct file * filp, unsigned long arg)
36995+int setfl(int fd, struct file * filp, unsigned long arg)
36996 {
36997 struct inode * inode = file_inode(filp);
36998 int error = 0;
36999@@ -63,6 +63,8 @@ static int setfl(int fd, struct file * f
37000
37001 if (filp->f_op->check_flags)
37002 error = filp->f_op->check_flags(arg);
37003+ if (!error && filp->f_op->setfl)
37004+ error = filp->f_op->setfl(filp, arg);
37005 if (error)
37006 return error;
37007
37008@@ -83,6 +85,7 @@ static int setfl(int fd, struct file * f
37009 out:
37010 return error;
37011 }
37012+EXPORT_SYMBOL_GPL(setfl);
37013
37014 static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
37015 int force)
37016diff -urNp -x '*.orig' linux-4.14/fs/file_table.c linux-4.14/fs/file_table.c
37017--- linux-4.14/fs/file_table.c 2017-11-12 19:46:13.000000000 +0100
37018+++ linux-4.14/fs/file_table.c 2021-02-24 21:42:43.437781422 +0100
37019@@ -148,6 +148,7 @@ over:
37020 }
37021 return ERR_PTR(-ENFILE);
37022 }
37023+EXPORT_SYMBOL_GPL(get_empty_filp);
37024
37025 /**
37026 * alloc_file - allocate and initialize a 'struct file'
37027@@ -258,6 +259,7 @@ void flush_delayed_fput(void)
37028 {
37029 delayed_fput(NULL);
37030 }
37031+EXPORT_SYMBOL_GPL(flush_delayed_fput);
37032
37033 static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput);
37034
37035@@ -300,6 +302,7 @@ void __fput_sync(struct file *file)
37036 }
37037
37038 EXPORT_SYMBOL(fput);
37039+EXPORT_SYMBOL_GPL(__fput_sync);
37040
37041 void put_filp(struct file *file)
37042 {
37043@@ -308,6 +311,7 @@ void put_filp(struct file *file)
37044 file_free(file);
37045 }
37046 }
37047+EXPORT_SYMBOL_GPL(put_filp);
37048
37049 void __init files_init(void)
37050 {
37051diff -urNp -x '*.orig' linux-4.14/fs/inode.c linux-4.14/fs/inode.c
37052--- linux-4.14/fs/inode.c 2021-02-24 21:42:35.481132097 +0100
37053+++ linux-4.14/fs/inode.c 2021-02-24 21:42:43.437781422 +0100
37054@@ -1664,7 +1664,7 @@ EXPORT_SYMBOL(generic_update_time);
37055 * This does the actual work of updating an inodes time or version. Must have
37056 * had called mnt_want_write() before calling this.
37057 */
37058-static int update_time(struct inode *inode, struct timespec *time, int flags)
37059+int update_time(struct inode *inode, struct timespec *time, int flags)
37060 {
37061 int (*update_time)(struct inode *, struct timespec *, int);
37062
37063@@ -1673,6 +1673,7 @@ static int update_time(struct inode *ino
37064
37065 return update_time(inode, time, flags);
37066 }
37067+EXPORT_SYMBOL_GPL(update_time);
37068
37069 /**
37070 * touch_atime - update the access time
37071diff -urNp -x '*.orig' linux-4.14/fs/namespace.c linux-4.14/fs/namespace.c
37072--- linux-4.14/fs/namespace.c 2021-02-24 21:42:35.481132097 +0100
37073+++ linux-4.14/fs/namespace.c 2021-02-24 21:42:43.437781422 +0100
37074@@ -517,6 +517,7 @@ void __mnt_drop_write(struct vfsmount *m
37075 mnt_dec_writers(real_mount(mnt));
37076 preempt_enable();
37077 }
37078+EXPORT_SYMBOL_GPL(__mnt_drop_write);
37079
37080 /**
37081 * mnt_drop_write - give up write access to a mount
37082@@ -855,6 +856,13 @@ static inline int check_mnt(struct mount
37083 return mnt->mnt_ns == current->nsproxy->mnt_ns;
37084 }
37085
37086+/* for aufs, CONFIG_AUFS_BR_FUSE */
37087+int is_current_mnt_ns(struct vfsmount *mnt)
37088+{
37089+ return check_mnt(real_mount(mnt));
37090+}
37091+EXPORT_SYMBOL_GPL(is_current_mnt_ns);
37092+
37093 /*
37094 * vfsmount lock must be held for write
37095 */
37096@@ -1918,6 +1926,7 @@ int iterate_mounts(int (*f)(struct vfsmo
37097 }
37098 return 0;
37099 }
37100+EXPORT_SYMBOL_GPL(iterate_mounts);
37101
37102 static void cleanup_group_ids(struct mount *mnt, struct mount *end)
37103 {
37104diff -urNp -x '*.orig' linux-4.14/fs/notify/group.c linux-4.14/fs/notify/group.c
37105--- linux-4.14/fs/notify/group.c 2017-11-12 19:46:13.000000000 +0100
37106+++ linux-4.14/fs/notify/group.c 2021-02-24 21:42:43.437781422 +0100
37107@@ -22,6 +22,7 @@
37108 #include <linux/srcu.h>
37109 #include <linux/rculist.h>
37110 #include <linux/wait.h>
37111+#include <linux/module.h>
37112
37113 #include <linux/fsnotify_backend.h>
37114 #include "fsnotify.h"
37115@@ -109,6 +110,7 @@ void fsnotify_get_group(struct fsnotify_
37116 {
37117 atomic_inc(&group->refcnt);
37118 }
37119+EXPORT_SYMBOL_GPL(fsnotify_get_group);
37120
37121 /*
37122 * Drop a reference to a group. Free it if it's through.
37123@@ -118,6 +120,7 @@ void fsnotify_put_group(struct fsnotify_
37124 if (atomic_dec_and_test(&group->refcnt))
37125 fsnotify_final_destroy_group(group);
37126 }
37127+EXPORT_SYMBOL_GPL(fsnotify_put_group);
37128
37129 /*
37130 * Create a new fsnotify_group and hold a reference for the group returned.
37131@@ -147,6 +150,7 @@ struct fsnotify_group *fsnotify_alloc_gr
37132
37133 return group;
37134 }
37135+EXPORT_SYMBOL_GPL(fsnotify_alloc_group);
37136
37137 int fsnotify_fasync(int fd, struct file *file, int on)
37138 {
37139diff -urNp -x '*.orig' linux-4.14/fs/notify/mark.c linux-4.14/fs/notify/mark.c
37140--- linux-4.14/fs/notify/mark.c 2021-02-24 21:42:35.491132073 +0100
37141+++ linux-4.14/fs/notify/mark.c 2021-02-24 21:42:43.437781422 +0100
37142@@ -124,6 +124,7 @@ static void __fsnotify_recalc_mask(struc
37143 else if (conn->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT)
37144 real_mount(conn->mnt)->mnt_fsnotify_mask = new_mask;
37145 }
37146+EXPORT_SYMBOL_GPL(fsnotify_put_mark);
37147
37148 /*
37149 * Calculate mask of events for a list of marks. The caller must make sure
37150@@ -392,6 +393,7 @@ void fsnotify_destroy_mark(struct fsnoti
37151 mutex_unlock(&group->mark_mutex);
37152 fsnotify_free_mark(mark);
37153 }
37154+EXPORT_SYMBOL_GPL(fsnotify_destroy_mark);
37155
37156 /*
37157 * Sorting function for lists of fsnotify marks.
37158@@ -604,6 +606,7 @@ err:
37159 fsnotify_put_mark(mark);
37160 return ret;
37161 }
37162+EXPORT_SYMBOL_GPL(fsnotify_add_mark);
37163
37164 int fsnotify_add_mark(struct fsnotify_mark *mark, struct inode *inode,
37165 struct vfsmount *mnt, int allow_dups)
37166@@ -739,6 +742,7 @@ void fsnotify_init_mark(struct fsnotify_
37167 fsnotify_get_group(group);
37168 mark->group = group;
37169 }
37170+EXPORT_SYMBOL_GPL(fsnotify_init_mark);
37171
37172 /*
37173 * Destroy all marks in destroy_list, waits for SRCU period to finish before
37174diff -urNp -x '*.orig' linux-4.14/fs/open.c linux-4.14/fs/open.c
37175--- linux-4.14/fs/open.c 2021-02-24 21:42:35.494465399 +0100
37176+++ linux-4.14/fs/open.c 2021-02-24 21:42:43.437781422 +0100
37177@@ -64,6 +64,7 @@ int do_truncate(struct dentry *dentry, l
37178 inode_unlock(dentry->d_inode);
37179 return ret;
37180 }
37181+EXPORT_SYMBOL_GPL(do_truncate);
37182
37183 long vfs_truncate(const struct path *path, loff_t length)
37184 {
37185@@ -710,6 +711,7 @@ int open_check_o_direct(struct file *f)
37186 }
37187 return 0;
37188 }
37189+EXPORT_SYMBOL_GPL(open_check_o_direct);
37190
37191 static int do_dentry_open(struct file *f,
37192 struct inode *inode,
37193diff -urNp -x '*.orig' linux-4.14/fs/proc/base.c linux-4.14/fs/proc/base.c
37194--- linux-4.14/fs/proc/base.c 2021-02-24 21:42:35.494465399 +0100
37195+++ linux-4.14/fs/proc/base.c 2021-02-24 21:42:43.434448095 +0100
37196@@ -2030,7 +2030,7 @@ static int map_files_get_link(struct den
37197 down_read(&mm->mmap_sem);
37198 vma = find_exact_vma(mm, vm_start, vm_end);
37199 if (vma && vma->vm_file) {
37200- *path = vma->vm_file->f_path;
37201+ *path = vma_pr_or_file(vma)->f_path;
37202 path_get(path);
37203 rc = 0;
37204 }
37205diff -urNp -x '*.orig' linux-4.14/fs/proc/nommu.c linux-4.14/fs/proc/nommu.c
37206--- linux-4.14/fs/proc/nommu.c 2017-11-12 19:46:13.000000000 +0100
37207+++ linux-4.14/fs/proc/nommu.c 2021-02-24 21:42:43.434448095 +0100
37208@@ -45,7 +45,10 @@ static int nommu_region_show(struct seq_
37209 file = region->vm_file;
37210
37211 if (file) {
37212- struct inode *inode = file_inode(region->vm_file);
37213+ struct inode *inode;
37214+
37215+ file = vmr_pr_or_file(region);
37216+ inode = file_inode(file);
37217 dev = inode->i_sb->s_dev;
37218 ino = inode->i_ino;
37219 }
37220diff -urNp -x '*.orig' linux-4.14/fs/proc/task_mmu.c linux-4.14/fs/proc/task_mmu.c
37221--- linux-4.14/fs/proc/task_mmu.c 2021-02-24 21:42:35.497798724 +0100
37222+++ linux-4.14/fs/proc/task_mmu.c 2021-02-24 21:42:43.434448095 +0100
37223@@ -310,7 +310,10 @@ show_map_vma(struct seq_file *m, struct
37224 const char *name = NULL;
37225
37226 if (file) {
37227- struct inode *inode = file_inode(vma->vm_file);
37228+ struct inode *inode;
37229+
37230+ file = vma_pr_or_file(vma);
37231+ inode = file_inode(file);
37232 dev = inode->i_sb->s_dev;
37233 ino = inode->i_ino;
37234 pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
37235@@ -1775,7 +1778,7 @@ static int show_numa_map(struct seq_file
37236 struct proc_maps_private *proc_priv = &numa_priv->proc_maps;
37237 struct vm_area_struct *vma = v;
37238 struct numa_maps *md = &numa_priv->md;
37239- struct file *file = vma->vm_file;
37240+ struct file *file = vma_pr_or_file(vma);
37241 struct mm_struct *mm = vma->vm_mm;
37242 struct mm_walk walk = {
37243 .hugetlb_entry = gather_hugetlb_stats,
37244diff -urNp -x '*.orig' linux-4.14/fs/proc/task_nommu.c linux-4.14/fs/proc/task_nommu.c
37245--- linux-4.14/fs/proc/task_nommu.c 2017-11-12 19:46:13.000000000 +0100
37246+++ linux-4.14/fs/proc/task_nommu.c 2021-02-24 21:42:43.434448095 +0100
37247@@ -156,7 +156,10 @@ static int nommu_vma_show(struct seq_fil
37248 file = vma->vm_file;
37249
37250 if (file) {
37251- struct inode *inode = file_inode(vma->vm_file);
37252+ struct inode *inode;
37253+
37254+ file = vma_pr_or_file(vma);
37255+ inode = file_inode(file);
37256 dev = inode->i_sb->s_dev;
37257 ino = inode->i_ino;
37258 pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
37259diff -urNp -x '*.orig' linux-4.14/fs/read_write.c linux-4.14/fs/read_write.c
37260--- linux-4.14/fs/read_write.c 2021-02-24 21:42:35.497798724 +0100
37261+++ linux-4.14/fs/read_write.c 2021-02-24 21:42:43.437781422 +0100
37262@@ -454,6 +454,7 @@ ssize_t vfs_read(struct file *file, char
37263
37264 return ret;
37265 }
37266+EXPORT_SYMBOL_GPL(vfs_read);
37267
37268 static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
37269 {
37270@@ -484,6 +485,30 @@ ssize_t __vfs_write(struct file *file, c
37271 return -EINVAL;
37272 }
37273
37274+vfs_readf_t vfs_readf(struct file *file)
37275+{
37276+ const struct file_operations *fop = file->f_op;
37277+
37278+ if (fop->read)
37279+ return fop->read;
37280+ if (fop->read_iter)
37281+ return new_sync_read;
37282+ return ERR_PTR(-ENOSYS);
37283+}
37284+EXPORT_SYMBOL_GPL(vfs_readf);
37285+
37286+vfs_writef_t vfs_writef(struct file *file)
37287+{
37288+ const struct file_operations *fop = file->f_op;
37289+
37290+ if (fop->write)
37291+ return fop->write;
37292+ if (fop->write_iter)
37293+ return new_sync_write;
37294+ return ERR_PTR(-ENOSYS);
37295+}
37296+EXPORT_SYMBOL_GPL(vfs_writef);
37297+
37298 ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
37299 {
37300 mm_segment_t old_fs;
37301@@ -552,6 +577,7 @@ ssize_t vfs_write(struct file *file, con
37302
37303 return ret;
37304 }
37305+EXPORT_SYMBOL_GPL(vfs_write);
37306
37307 static inline loff_t file_pos_read(struct file *file)
37308 {
37309diff -urNp -x '*.orig' linux-4.14/fs/splice.c linux-4.14/fs/splice.c
37310--- linux-4.14/fs/splice.c 2021-02-24 21:42:35.497798724 +0100
37311+++ linux-4.14/fs/splice.c 2021-02-24 21:42:43.437781422 +0100
37312@@ -837,8 +837,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
37313 /*
37314 * Attempt to initiate a splice from pipe to file.
37315 */
37316-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
37317- loff_t *ppos, size_t len, unsigned int flags)
37318+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
37319+ loff_t *ppos, size_t len, unsigned int flags)
37320 {
37321 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
37322 loff_t *, size_t, unsigned int);
37323@@ -850,13 +850,14 @@ static long do_splice_from(struct pipe_i
37324
37325 return splice_write(pipe, out, ppos, len, flags);
37326 }
37327+EXPORT_SYMBOL_GPL(do_splice_from);
37328
37329 /*
37330 * Attempt to initiate a splice from a file to a pipe.
37331 */
37332-static long do_splice_to(struct file *in, loff_t *ppos,
37333- struct pipe_inode_info *pipe, size_t len,
37334- unsigned int flags)
37335+long do_splice_to(struct file *in, loff_t *ppos,
37336+ struct pipe_inode_info *pipe, size_t len,
37337+ unsigned int flags)
37338 {
37339 ssize_t (*splice_read)(struct file *, loff_t *,
37340 struct pipe_inode_info *, size_t, unsigned int);
37341@@ -879,6 +880,7 @@ static long do_splice_to(struct file *in
37342
37343 return splice_read(in, ppos, pipe, len, flags);
37344 }
37345+EXPORT_SYMBOL_GPL(do_splice_to);
37346
37347 /**
37348 * splice_direct_to_actor - splices data directly between two non-pipes
37349diff -urNp -x '*.orig' linux-4.14/fs/sync.c linux-4.14/fs/sync.c
37350--- linux-4.14/fs/sync.c 2017-11-12 19:46:13.000000000 +0100
37351+++ linux-4.14/fs/sync.c 2021-02-24 21:42:43.437781422 +0100
37352@@ -28,7 +28,7 @@
37353 * wait == 1 case since in that case write_inode() functions do
37354 * sync_dirty_buffer() and thus effectively write one block at a time.
37355 */
37356-static int __sync_filesystem(struct super_block *sb, int wait)
37357+int __sync_filesystem(struct super_block *sb, int wait)
37358 {
37359 if (wait)
37360 sync_inodes_sb(sb);
37361@@ -39,6 +39,7 @@ static int __sync_filesystem(struct supe
37362 sb->s_op->sync_fs(sb, wait);
37363 return __sync_blockdev(sb->s_bdev, wait);
37364 }
37365+EXPORT_SYMBOL_GPL(__sync_filesystem);
37366
37367 /*
37368 * Write out and wait upon all dirty data associated with this
37369diff -urNp -x '*.orig' linux-4.14/fs/xattr.c linux-4.14/fs/xattr.c
37370--- linux-4.14/fs/xattr.c 2021-02-24 21:42:35.501132049 +0100
37371+++ linux-4.14/fs/xattr.c 2021-02-24 21:42:43.437781422 +0100
37372@@ -334,6 +334,7 @@ vfs_getxattr_alloc(struct dentry *dentry
37373 *xattr_value = value;
37374 return error;
37375 }
37376+EXPORT_SYMBOL_GPL(vfs_getxattr_alloc);
37377
37378 ssize_t
37379 __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
37380diff -urNp -x '*.orig' linux-4.14/include/linux/file.h linux-4.14/include/linux/file.h
37381--- linux-4.14/include/linux/file.h 2017-11-12 19:46:13.000000000 +0100
37382+++ linux-4.14/include/linux/file.h 2021-02-24 21:42:43.434448095 +0100
37383@@ -20,6 +20,7 @@ struct dentry;
37384 struct path;
37385 extern struct file *alloc_file(const struct path *, fmode_t mode,
37386 const struct file_operations *fop);
37387+extern struct file *get_empty_filp(void);
37388
37389 static inline void fput_light(struct file *file, int fput_needed)
37390 {
37391diff -urNp -x '*.orig' linux-4.14/include/linux/fs.h linux-4.14/include/linux/fs.h
37392--- linux-4.14/include/linux/fs.h 2021-02-24 21:42:35.511132025 +0100
37393+++ linux-4.14/include/linux/fs.h 2021-02-24 21:42:43.447781402 +0100
37394@@ -1271,6 +1271,7 @@ extern void fasync_free(struct fasync_st
37395 /* can be called from interrupts */
37396 extern void kill_fasync(struct fasync_struct **, int, int);
37397
37398+extern int setfl(int fd, struct file * filp, unsigned long arg);
37399 extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force);
37400 extern int f_setown(struct file *filp, unsigned long arg, int force);
37401 extern void f_delown(struct file *filp);
37402@@ -1718,6 +1719,7 @@ struct file_operations {
37403 ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
37404 unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
37405 int (*check_flags)(int);
37406+ int (*setfl)(struct file *, unsigned long);
37407 int (*flock) (struct file *, int, struct file_lock *);
37408 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
37409 ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
37410@@ -1788,6 +1790,12 @@ ssize_t rw_copy_check_uvector(int type,
37411 struct iovec *fast_pointer,
37412 struct iovec **ret_pointer);
37413
37414+typedef ssize_t (*vfs_readf_t)(struct file *, char __user *, size_t, loff_t *);
37415+typedef ssize_t (*vfs_writef_t)(struct file *, const char __user *, size_t,
37416+ loff_t *);
37417+vfs_readf_t vfs_readf(struct file *file);
37418+vfs_writef_t vfs_writef(struct file *file);
37419+
37420 extern ssize_t __vfs_read(struct file *, char __user *, size_t, loff_t *);
37421 extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
37422 extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);
37423@@ -1840,6 +1848,10 @@ struct super_operations {
37424 struct shrink_control *);
37425 long (*free_cached_objects)(struct super_block *,
37426 struct shrink_control *);
37427+#if defined(CONFIG_BLK_DEV_LOOP) || defined(CONFIG_BLK_DEV_LOOP_MODULE)
37428+ /* and aufs */
37429+ struct file *(*real_loop)(struct file *);
37430+#endif
37431 };
37432
37433 /*
37434@@ -2196,6 +2208,7 @@ extern int current_umask(void);
37435 extern void ihold(struct inode * inode);
37436 extern void iput(struct inode *);
37437 extern int generic_update_time(struct inode *, struct timespec *, int);
37438+extern int update_time(struct inode *, struct timespec *, int);
37439
37440 /* /sys/fs */
37441 extern struct kobject *fs_kobj;
37442@@ -2476,6 +2489,7 @@ static inline bool sb_is_blkdev_sb(struc
37443 return false;
37444 }
37445 #endif
37446+extern int __sync_filesystem(struct super_block *, int);
37447 extern int sync_filesystem(struct super_block *);
37448 extern const struct file_operations def_blk_fops;
37449 extern const struct file_operations def_chr_fops;
37450diff -urNp -x '*.orig' linux-4.14/include/linux/lockdep.h linux-4.14/include/linux/lockdep.h
37451--- linux-4.14/include/linux/lockdep.h 2017-11-12 19:46:13.000000000 +0100
37452+++ linux-4.14/include/linux/lockdep.h 2021-02-24 21:42:43.434448095 +0100
37453@@ -406,6 +406,8 @@ static inline int lockdep_match_key(stru
37454 return lock->key == key;
37455 }
37456
37457+struct lock_class *lockdep_hlock_class(struct held_lock *hlock);
37458+
37459 /*
37460 * Acquire a lock.
37461 *
37462@@ -530,6 +532,7 @@ struct lock_class_key { };
37463
37464 #define lockdep_depth(tsk) (0)
37465
37466+#define lockdep_is_held(lock) (1)
37467 #define lockdep_is_held_type(l, r) (1)
37468
37469 #define lockdep_assert_held(l) do { (void)(l); } while (0)
37470diff -urNp -x '*.orig' linux-4.14/include/linux/mm.h linux-4.14/include/linux/mm.h
37471--- linux-4.14/include/linux/mm.h 2021-02-24 21:42:35.517798675 +0100
37472+++ linux-4.14/include/linux/mm.h 2021-02-24 21:42:43.434448095 +0100
37473@@ -1370,6 +1370,28 @@ static inline int fixup_user_fault(struc
37474 }
37475 #endif
37476
37477+extern void vma_do_file_update_time(struct vm_area_struct *, const char[], int);
37478+extern struct file *vma_do_pr_or_file(struct vm_area_struct *, const char[],
37479+ int);
37480+extern void vma_do_get_file(struct vm_area_struct *, const char[], int);
37481+extern void vma_do_fput(struct vm_area_struct *, const char[], int);
37482+
37483+#define vma_file_update_time(vma) vma_do_file_update_time(vma, __func__, \
37484+ __LINE__)
37485+#define vma_pr_or_file(vma) vma_do_pr_or_file(vma, __func__, \
37486+ __LINE__)
37487+#define vma_get_file(vma) vma_do_get_file(vma, __func__, __LINE__)
37488+#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__)
37489+
37490+#ifndef CONFIG_MMU
37491+extern struct file *vmr_do_pr_or_file(struct vm_region *, const char[], int);
37492+extern void vmr_do_fput(struct vm_region *, const char[], int);
37493+
37494+#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \
37495+ __LINE__)
37496+#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__)
37497+#endif /* !CONFIG_MMU */
37498+
37499 extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len,
37500 unsigned int gup_flags);
37501 extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
37502diff -urNp -x '*.orig' linux-4.14/include/linux/mm_types.h linux-4.14/include/linux/mm_types.h
37503--- linux-4.14/include/linux/mm_types.h 2021-02-24 21:42:35.517798675 +0100
37504+++ linux-4.14/include/linux/mm_types.h 2021-02-24 21:42:43.434448095 +0100
37505@@ -258,6 +258,7 @@ struct vm_region {
37506 unsigned long vm_top; /* region allocated to here */
37507 unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */
37508 struct file *vm_file; /* the backing file or NULL */
37509+ struct file *vm_prfile; /* the virtual backing file or NULL */
37510
37511 int vm_usage; /* region usage count (access under nommu_region_sem) */
37512 bool vm_icache_flushed : 1; /* true if the icache has been flushed for
37513@@ -332,6 +333,7 @@ struct vm_area_struct {
37514 unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
37515 units */
37516 struct file * vm_file; /* File we map to (can be NULL). */
37517+ struct file *vm_prfile; /* shadow of vm_file */
37518 void * vm_private_data; /* was vm_pte (shared mem) */
37519
37520 atomic_long_t swap_readahead_info;
37521diff -urNp -x '*.orig' linux-4.14/include/linux/mnt_namespace.h linux-4.14/include/linux/mnt_namespace.h
37522--- linux-4.14/include/linux/mnt_namespace.h 2017-11-12 19:46:13.000000000 +0100
37523+++ linux-4.14/include/linux/mnt_namespace.h 2021-02-24 21:42:43.434448095 +0100
37524@@ -6,11 +6,14 @@
37525 struct mnt_namespace;
37526 struct fs_struct;
37527 struct user_namespace;
37528+struct vfsmount;
37529
37530 extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
37531 struct user_namespace *, struct fs_struct *);
37532 extern void put_mnt_ns(struct mnt_namespace *ns);
37533
37534+extern int is_current_mnt_ns(struct vfsmount *mnt);
37535+
37536 extern const struct file_operations proc_mounts_operations;
37537 extern const struct file_operations proc_mountinfo_operations;
37538 extern const struct file_operations proc_mountstats_operations;
37539diff -urNp -x '*.orig' linux-4.14/include/linux/splice.h linux-4.14/include/linux/splice.h
37540--- linux-4.14/include/linux/splice.h 2017-11-12 19:46:13.000000000 +0100
37541+++ linux-4.14/include/linux/splice.h 2021-02-24 21:42:43.434448095 +0100
37542@@ -87,4 +87,10 @@ extern void splice_shrink_spd(struct spl
37543
37544 extern const struct pipe_buf_operations page_cache_pipe_buf_ops;
37545 extern const struct pipe_buf_operations default_pipe_buf_ops;
521ced18 37546+
0b1ff5c3
JR
37547+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
37548+ loff_t *ppos, size_t len, unsigned int flags);
37549+extern long do_splice_to(struct file *in, loff_t *ppos,
37550+ struct pipe_inode_info *pipe, size_t len,
37551+ unsigned int flags);
37552 #endif
37553diff -urNp -x '*.orig' linux-4.14/include/uapi/linux/aufs_type.h linux-4.14/include/uapi/linux/aufs_type.h
37554--- linux-4.14/include/uapi/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
37555+++ linux-4.14/include/uapi/linux/aufs_type.h 2021-02-24 21:42:43.447781402 +0100
8b6a4947 37556@@ -0,0 +1,447 @@
7f207e10 37557+/*
a2654f78 37558+ * Copyright (C) 2005-2017 Junjiro R. Okajima
7f207e10
AM
37559+ *
37560+ * This program, aufs is free software; you can redistribute it and/or modify
37561+ * it under the terms of the GNU General Public License as published by
37562+ * the Free Software Foundation; either version 2 of the License, or
37563+ * (at your option) any later version.
37564+ *
37565+ * This program is distributed in the hope that it will be useful,
37566+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
37567+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37568+ * GNU General Public License for more details.
37569+ *
37570+ * You should have received a copy of the GNU General Public License
523b37e3 37571+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
37572+ */
37573+
37574+#ifndef __AUFS_TYPE_H__
37575+#define __AUFS_TYPE_H__
37576+
f6c5ef8b
AM
37577+#define AUFS_NAME "aufs"
37578+
9dbd164d 37579+#ifdef __KERNEL__
f6c5ef8b
AM
37580+/*
37581+ * define it before including all other headers.
37582+ * sched.h may use pr_* macros before defining "current", so define the
37583+ * no-current version first, and re-define later.
37584+ */
37585+#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__
37586+#include <linux/sched.h>
37587+#undef pr_fmt
a2a7ad62
AM
37588+#define pr_fmt(fmt) \
37589+ AUFS_NAME " %s:%d:%.*s[%d]: " fmt, __func__, __LINE__, \
37590+ (int)sizeof(current->comm), current->comm, current->pid
9dbd164d
AM
37591+#else
37592+#include <stdint.h>
37593+#include <sys/types.h>
f6c5ef8b 37594+#endif /* __KERNEL__ */
7f207e10 37595+
f6c5ef8b
AM
37596+#include <linux/limits.h>
37597+
8b6a4947 37598+#define AUFS_VERSION "4.x-rcN-20171106"
7f207e10
AM
37599+
37600+/* todo? move this to linux-2.6.19/include/magic.h */
37601+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
37602+
37603+/* ---------------------------------------------------------------------- */
37604+
37605+#ifdef CONFIG_AUFS_BRANCH_MAX_127
9dbd164d 37606+typedef int8_t aufs_bindex_t;
7f207e10
AM
37607+#define AUFS_BRANCH_MAX 127
37608+#else
9dbd164d 37609+typedef int16_t aufs_bindex_t;
7f207e10
AM
37610+#ifdef CONFIG_AUFS_BRANCH_MAX_511
37611+#define AUFS_BRANCH_MAX 511
37612+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
37613+#define AUFS_BRANCH_MAX 1023
37614+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
37615+#define AUFS_BRANCH_MAX 32767
37616+#endif
37617+#endif
37618+
37619+#ifdef __KERNEL__
37620+#ifndef AUFS_BRANCH_MAX
37621+#error unknown CONFIG_AUFS_BRANCH_MAX value
37622+#endif
37623+#endif /* __KERNEL__ */
37624+
37625+/* ---------------------------------------------------------------------- */
37626+
7f207e10
AM
37627+#define AUFS_FSTYPE AUFS_NAME
37628+
37629+#define AUFS_ROOT_INO 2
37630+#define AUFS_FIRST_INO 11
37631+
37632+#define AUFS_WH_PFX ".wh."
37633+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
37634+#define AUFS_WH_TMP_LEN 4
86dc4139 37635+/* a limit for rmdir/rename a dir and copyup */
7f207e10
AM
37636+#define AUFS_MAX_NAMELEN (NAME_MAX \
37637+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
37638+ - 1 /* dot */\
37639+ - AUFS_WH_TMP_LEN) /* hex */
37640+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
37641+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
392086de
AM
37642+#define AUFS_XINO_DEF_SEC 30 /* seconds */
37643+#define AUFS_XINO_DEF_TRUNC 45 /* percentage */
7f207e10
AM
37644+#define AUFS_DIRWH_DEF 3
37645+#define AUFS_RDCACHE_DEF 10 /* seconds */
027c5e7a 37646+#define AUFS_RDCACHE_MAX 3600 /* seconds */
7f207e10
AM
37647+#define AUFS_RDBLK_DEF 512 /* bytes */
37648+#define AUFS_RDHASH_DEF 32
37649+#define AUFS_WKQ_NAME AUFS_NAME "d"
027c5e7a
AM
37650+#define AUFS_MFS_DEF_SEC 30 /* seconds */
37651+#define AUFS_MFS_MAX_SEC 3600 /* seconds */
076b876e 37652+#define AUFS_FHSM_CACHE_DEF_SEC 30 /* seconds */
86dc4139 37653+#define AUFS_PLINK_WARN 50 /* number of plinks in a single bucket */
7f207e10
AM
37654+
37655+/* pseudo-link maintenace under /proc */
37656+#define AUFS_PLINK_MAINT_NAME "plink_maint"
37657+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
37658+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
37659+
8b6a4947
AM
37660+/* dirren, renamed dir */
37661+#define AUFS_DR_INFO_PFX AUFS_WH_PFX ".dr."
37662+#define AUFS_DR_BRHINO_NAME AUFS_WH_PFX "hino"
37663+/* whiteouted doubly */
37664+#define AUFS_WH_DR_INFO_PFX AUFS_WH_PFX AUFS_DR_INFO_PFX
37665+#define AUFS_WH_DR_BRHINO AUFS_WH_PFX AUFS_DR_BRHINO_NAME
37666+
7f207e10
AM
37667+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
37668+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
37669+
37670+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
37671+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
37672+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
37673+
37674+/* doubly whiteouted */
37675+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
37676+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
37677+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
37678+
1e00d052 37679+/* branch permissions and attributes */
7f207e10
AM
37680+#define AUFS_BRPERM_RW "rw"
37681+#define AUFS_BRPERM_RO "ro"
37682+#define AUFS_BRPERM_RR "rr"
076b876e
AM
37683+#define AUFS_BRATTR_COO_REG "coo_reg"
37684+#define AUFS_BRATTR_COO_ALL "coo_all"
37685+#define AUFS_BRATTR_FHSM "fhsm"
37686+#define AUFS_BRATTR_UNPIN "unpin"
c1595e42
JR
37687+#define AUFS_BRATTR_ICEX "icex"
37688+#define AUFS_BRATTR_ICEX_SEC "icexsec"
37689+#define AUFS_BRATTR_ICEX_SYS "icexsys"
37690+#define AUFS_BRATTR_ICEX_TR "icextr"
37691+#define AUFS_BRATTR_ICEX_USR "icexusr"
37692+#define AUFS_BRATTR_ICEX_OTH "icexoth"
1e00d052
AM
37693+#define AUFS_BRRATTR_WH "wh"
37694+#define AUFS_BRWATTR_NLWH "nolwh"
076b876e
AM
37695+#define AUFS_BRWATTR_MOO "moo"
37696+
37697+#define AuBrPerm_RW 1 /* writable, hardlinkable wh */
37698+#define AuBrPerm_RO (1 << 1) /* readonly */
37699+#define AuBrPerm_RR (1 << 2) /* natively readonly */
37700+#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR)
37701+
37702+#define AuBrAttr_COO_REG (1 << 3) /* copy-up on open */
37703+#define AuBrAttr_COO_ALL (1 << 4)
37704+#define AuBrAttr_COO_Mask (AuBrAttr_COO_REG | AuBrAttr_COO_ALL)
37705+
37706+#define AuBrAttr_FHSM (1 << 5) /* file-based hsm */
37707+#define AuBrAttr_UNPIN (1 << 6) /* rename-able top dir of
c1595e42
JR
37708+ branch. meaningless since
37709+ linux-3.18-rc1 */
37710+
37711+/* ignore error in copying XATTR */
37712+#define AuBrAttr_ICEX_SEC (1 << 7)
37713+#define AuBrAttr_ICEX_SYS (1 << 8)
37714+#define AuBrAttr_ICEX_TR (1 << 9)
37715+#define AuBrAttr_ICEX_USR (1 << 10)
37716+#define AuBrAttr_ICEX_OTH (1 << 11)
37717+#define AuBrAttr_ICEX (AuBrAttr_ICEX_SEC \
37718+ | AuBrAttr_ICEX_SYS \
37719+ | AuBrAttr_ICEX_TR \
37720+ | AuBrAttr_ICEX_USR \
37721+ | AuBrAttr_ICEX_OTH)
37722+
37723+#define AuBrRAttr_WH (1 << 12) /* whiteout-able */
076b876e
AM
37724+#define AuBrRAttr_Mask AuBrRAttr_WH
37725+
c1595e42
JR
37726+#define AuBrWAttr_NoLinkWH (1 << 13) /* un-hardlinkable whiteouts */
37727+#define AuBrWAttr_MOO (1 << 14) /* move-up on open */
076b876e
AM
37728+#define AuBrWAttr_Mask (AuBrWAttr_NoLinkWH | AuBrWAttr_MOO)
37729+
37730+#define AuBrAttr_CMOO_Mask (AuBrAttr_COO_Mask | AuBrWAttr_MOO)
37731+
c1595e42 37732+/* #warning test userspace */
076b876e
AM
37733+#ifdef __KERNEL__
37734+#ifndef CONFIG_AUFS_FHSM
37735+#undef AuBrAttr_FHSM
37736+#define AuBrAttr_FHSM 0
37737+#endif
c1595e42
JR
37738+#ifndef CONFIG_AUFS_XATTR
37739+#undef AuBrAttr_ICEX
37740+#define AuBrAttr_ICEX 0
37741+#undef AuBrAttr_ICEX_SEC
37742+#define AuBrAttr_ICEX_SEC 0
37743+#undef AuBrAttr_ICEX_SYS
37744+#define AuBrAttr_ICEX_SYS 0
37745+#undef AuBrAttr_ICEX_TR
37746+#define AuBrAttr_ICEX_TR 0
37747+#undef AuBrAttr_ICEX_USR
37748+#define AuBrAttr_ICEX_USR 0
37749+#undef AuBrAttr_ICEX_OTH
37750+#define AuBrAttr_ICEX_OTH 0
37751+#endif
076b876e
AM
37752+#endif
37753+
37754+/* the longest combination */
c1595e42
JR
37755+/* AUFS_BRATTR_ICEX and AUFS_BRATTR_ICEX_TR don't affect here */
37756+#define AuBrPermStrSz sizeof(AUFS_BRPERM_RW \
37757+ "+" AUFS_BRATTR_COO_REG \
37758+ "+" AUFS_BRATTR_FHSM \
37759+ "+" AUFS_BRATTR_UNPIN \
7e9cd9fe
AM
37760+ "+" AUFS_BRATTR_ICEX_SEC \
37761+ "+" AUFS_BRATTR_ICEX_SYS \
37762+ "+" AUFS_BRATTR_ICEX_USR \
37763+ "+" AUFS_BRATTR_ICEX_OTH \
076b876e
AM
37764+ "+" AUFS_BRWATTR_NLWH)
37765+
37766+typedef struct {
37767+ char a[AuBrPermStrSz];
37768+} au_br_perm_str_t;
37769+
37770+static inline int au_br_writable(int brperm)
37771+{
37772+ return brperm & AuBrPerm_RW;
37773+}
37774+
37775+static inline int au_br_whable(int brperm)
37776+{
37777+ return brperm & (AuBrPerm_RW | AuBrRAttr_WH);
37778+}
37779+
37780+static inline int au_br_wh_linkable(int brperm)
37781+{
37782+ return !(brperm & AuBrWAttr_NoLinkWH);
37783+}
37784+
37785+static inline int au_br_cmoo(int brperm)
37786+{
37787+ return brperm & AuBrAttr_CMOO_Mask;
37788+}
37789+
37790+static inline int au_br_fhsm(int brperm)
37791+{
37792+ return brperm & AuBrAttr_FHSM;
37793+}
7f207e10
AM
37794+
37795+/* ---------------------------------------------------------------------- */
37796+
37797+/* ioctl */
37798+enum {
37799+ /* readdir in userspace */
37800+ AuCtl_RDU,
37801+ AuCtl_RDU_INO,
37802+
076b876e
AM
37803+ AuCtl_WBR_FD, /* pathconf wrapper */
37804+ AuCtl_IBUSY, /* busy inode */
37805+ AuCtl_MVDOWN, /* move-down */
37806+ AuCtl_BR, /* info about branches */
37807+ AuCtl_FHSM_FD /* connection for fhsm */
7f207e10
AM
37808+};
37809+
37810+/* borrowed from linux/include/linux/kernel.h */
37811+#ifndef ALIGN
37812+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
37813+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
37814+#endif
37815+
37816+/* borrowed from linux/include/linux/compiler-gcc3.h */
37817+#ifndef __aligned
37818+#define __aligned(x) __attribute__((aligned(x)))
53392da6
AM
37819+#endif
37820+
37821+#ifdef __KERNEL__
37822+#ifndef __packed
7f207e10
AM
37823+#define __packed __attribute__((packed))
37824+#endif
53392da6 37825+#endif
7f207e10
AM
37826+
37827+struct au_rdu_cookie {
9dbd164d
AM
37828+ uint64_t h_pos;
37829+ int16_t bindex;
37830+ uint8_t flags;
37831+ uint8_t pad;
37832+ uint32_t generation;
7f207e10
AM
37833+} __aligned(8);
37834+
37835+struct au_rdu_ent {
9dbd164d
AM
37836+ uint64_t ino;
37837+ int16_t bindex;
37838+ uint8_t type;
37839+ uint8_t nlen;
37840+ uint8_t wh;
7f207e10
AM
37841+ char name[0];
37842+} __aligned(8);
37843+
37844+static inline int au_rdu_len(int nlen)
37845+{
37846+ /* include the terminating NULL */
37847+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
9dbd164d 37848+ sizeof(uint64_t));
7f207e10
AM
37849+}
37850+
37851+union au_rdu_ent_ul {
37852+ struct au_rdu_ent __user *e;
9dbd164d 37853+ uint64_t ul;
7f207e10
AM
37854+};
37855+
37856+enum {
37857+ AufsCtlRduV_SZ,
37858+ AufsCtlRduV_End
37859+};
37860+
37861+struct aufs_rdu {
37862+ /* input */
37863+ union {
9dbd164d
AM
37864+ uint64_t sz; /* AuCtl_RDU */
37865+ uint64_t nent; /* AuCtl_RDU_INO */
7f207e10
AM
37866+ };
37867+ union au_rdu_ent_ul ent;
9dbd164d 37868+ uint16_t verify[AufsCtlRduV_End];
7f207e10
AM
37869+
37870+ /* input/output */
9dbd164d 37871+ uint32_t blk;
7f207e10
AM
37872+
37873+ /* output */
37874+ union au_rdu_ent_ul tail;
37875+ /* number of entries which were added in a single call */
9dbd164d
AM
37876+ uint64_t rent;
37877+ uint8_t full;
37878+ uint8_t shwh;
7f207e10
AM
37879+
37880+ struct au_rdu_cookie cookie;
37881+} __aligned(8);
37882+
1e00d052
AM
37883+/* ---------------------------------------------------------------------- */
37884+
8b6a4947
AM
37885+/* dirren. the branch is identified by the filename who contains this */
37886+struct au_drinfo {
37887+ uint64_t ino;
37888+ union {
37889+ uint8_t oldnamelen;
37890+ uint64_t _padding;
37891+ };
37892+ uint8_t oldname[0];
37893+} __aligned(8);
37894+
37895+struct au_drinfo_fdata {
37896+ uint32_t magic;
37897+ struct au_drinfo drinfo;
37898+} __aligned(8);
37899+
37900+#define AUFS_DRINFO_MAGIC_V1 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x01)
37901+/* future */
37902+#define AUFS_DRINFO_MAGIC_V2 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x02)
37903+
37904+/* ---------------------------------------------------------------------- */
37905+
1e00d052 37906+struct aufs_wbr_fd {
9dbd164d
AM
37907+ uint32_t oflags;
37908+ int16_t brid;
1e00d052
AM
37909+} __aligned(8);
37910+
37911+/* ---------------------------------------------------------------------- */
37912+
027c5e7a 37913+struct aufs_ibusy {
9dbd164d
AM
37914+ uint64_t ino, h_ino;
37915+ int16_t bindex;
027c5e7a
AM
37916+} __aligned(8);
37917+
1e00d052
AM
37918+/* ---------------------------------------------------------------------- */
37919+
392086de
AM
37920+/* error code for move-down */
37921+/* the actual message strings are implemented in aufs-util.git */
37922+enum {
37923+ EAU_MVDOWN_OPAQUE = 1,
37924+ EAU_MVDOWN_WHITEOUT,
37925+ EAU_MVDOWN_UPPER,
37926+ EAU_MVDOWN_BOTTOM,
37927+ EAU_MVDOWN_NOUPPER,
37928+ EAU_MVDOWN_NOLOWERBR,
37929+ EAU_Last
37930+};
37931+
c2b27bf2 37932+/* flags for move-down */
392086de
AM
37933+#define AUFS_MVDOWN_DMSG 1
37934+#define AUFS_MVDOWN_OWLOWER (1 << 1) /* overwrite lower */
37935+#define AUFS_MVDOWN_KUPPER (1 << 2) /* keep upper */
37936+#define AUFS_MVDOWN_ROLOWER (1 << 3) /* do even if lower is RO */
37937+#define AUFS_MVDOWN_ROLOWER_R (1 << 4) /* did on lower RO */
37938+#define AUFS_MVDOWN_ROUPPER (1 << 5) /* do even if upper is RO */
37939+#define AUFS_MVDOWN_ROUPPER_R (1 << 6) /* did on upper RO */
37940+#define AUFS_MVDOWN_BRID_UPPER (1 << 7) /* upper brid */
37941+#define AUFS_MVDOWN_BRID_LOWER (1 << 8) /* lower brid */
076b876e
AM
37942+#define AUFS_MVDOWN_FHSM_LOWER (1 << 9) /* find fhsm attr for lower */
37943+#define AUFS_MVDOWN_STFS (1 << 10) /* req. stfs */
37944+#define AUFS_MVDOWN_STFS_FAILED (1 << 11) /* output: stfs is unusable */
37945+#define AUFS_MVDOWN_BOTTOM (1 << 12) /* output: no more lowers */
c2b27bf2 37946+
076b876e 37947+/* index for move-down */
392086de
AM
37948+enum {
37949+ AUFS_MVDOWN_UPPER,
37950+ AUFS_MVDOWN_LOWER,
37951+ AUFS_MVDOWN_NARRAY
37952+};
37953+
076b876e
AM
37954+/*
37955+ * additional info of move-down
37956+ * number of free blocks and inodes.
37957+ * subset of struct kstatfs, but smaller and always 64bit.
37958+ */
37959+struct aufs_stfs {
37960+ uint64_t f_blocks;
37961+ uint64_t f_bavail;
37962+ uint64_t f_files;
37963+ uint64_t f_ffree;
37964+};
37965+
37966+struct aufs_stbr {
37967+ int16_t brid; /* optional input */
37968+ int16_t bindex; /* output */
37969+ struct aufs_stfs stfs; /* output when AUFS_MVDOWN_STFS set */
37970+} __aligned(8);
37971+
c2b27bf2 37972+struct aufs_mvdown {
076b876e
AM
37973+ uint32_t flags; /* input/output */
37974+ struct aufs_stbr stbr[AUFS_MVDOWN_NARRAY]; /* input/output */
37975+ int8_t au_errno; /* output */
37976+} __aligned(8);
37977+
37978+/* ---------------------------------------------------------------------- */
37979+
37980+union aufs_brinfo {
37981+ /* PATH_MAX may differ between kernel-space and user-space */
37982+ char _spacer[4096];
392086de 37983+ struct {
076b876e
AM
37984+ int16_t id;
37985+ int perm;
37986+ char path[0];
37987+ };
c2b27bf2
AM
37988+} __aligned(8);
37989+
37990+/* ---------------------------------------------------------------------- */
37991+
7f207e10
AM
37992+#define AuCtlType 'A'
37993+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
37994+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
1e00d052
AM
37995+#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \
37996+ struct aufs_wbr_fd)
027c5e7a 37997+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
392086de
AM
37998+#define AUFS_CTL_MVDOWN _IOWR(AuCtlType, AuCtl_MVDOWN, \
37999+ struct aufs_mvdown)
076b876e
AM
38000+#define AUFS_CTL_BRINFO _IOW(AuCtlType, AuCtl_BR, union aufs_brinfo)
38001+#define AUFS_CTL_FHSM_FD _IOW(AuCtlType, AuCtl_FHSM_FD, int)
7f207e10
AM
38002+
38003+#endif /* __AUFS_TYPE_H__ */
0b1ff5c3
JR
38004diff -urNp -x '*.orig' linux-4.14/kernel/fork.c linux-4.14/kernel/fork.c
38005--- linux-4.14/kernel/fork.c 2021-02-24 21:42:35.541131952 +0100
38006+++ linux-4.14/kernel/fork.c 2021-02-24 21:42:43.434448095 +0100
38007@@ -670,7 +670,7 @@ static __latent_entropy int dup_mmap(str
38008 struct inode *inode = file_inode(file);
38009 struct address_space *mapping = file->f_mapping;
5527c038 38010
0b1ff5c3
JR
38011- get_file(file);
38012+ vma_get_file(tmp);
38013 if (tmp->vm_flags & VM_DENYWRITE)
38014 atomic_dec(&inode->i_writecount);
38015 i_mmap_lock_write(mapping);
38016diff -urNp -x '*.orig' linux-4.14/kernel/locking/lockdep.c linux-4.14/kernel/locking/lockdep.c
38017--- linux-4.14/kernel/locking/lockdep.c 2021-02-24 21:42:35.544465277 +0100
38018+++ linux-4.14/kernel/locking/lockdep.c 2021-02-24 21:42:43.437781422 +0100
38019@@ -143,7 +143,7 @@ static struct lock_list list_entries[MAX
38020 unsigned long nr_lock_classes;
38021 static struct lock_class lock_classes[MAX_LOCKDEP_KEYS];
38022
38023-static inline struct lock_class *hlock_class(struct held_lock *hlock)
38024+inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
5527c038 38025 {
0b1ff5c3
JR
38026 if (!hlock->class_idx) {
38027 /*
38028@@ -154,6 +154,8 @@ static inline struct lock_class *hlock_c
38029 }
38030 return lock_classes + hlock->class_idx - 1;
38031 }
38032+EXPORT_SYMBOL_GPL(lockdep_hlock_class);
38033+#define hlock_class(hlock) lockdep_hlock_class(hlock)
5527c038 38034
0b1ff5c3
JR
38035 #ifdef CONFIG_LOCK_STAT
38036 static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats);
38037diff -urNp -x '*.orig' linux-4.14/kernel/task_work.c linux-4.14/kernel/task_work.c
38038--- linux-4.14/kernel/task_work.c 2021-02-24 21:42:35.551131928 +0100
38039+++ linux-4.14/kernel/task_work.c 2021-02-24 21:42:43.437781422 +0100
38040@@ -116,3 +116,4 @@ void task_work_run(void)
38041 } while (work);
38042 }
38043 }
38044+EXPORT_SYMBOL_GPL(task_work_run);
38045diff -urNp -x '*.orig' linux-4.14/mm/Makefile linux-4.14/mm/Makefile
38046--- linux-4.14/mm/Makefile 2021-02-24 21:42:35.564465229 +0100
38047+++ linux-4.14/mm/Makefile 2021-02-24 21:42:43.434448095 +0100
38048@@ -39,7 +39,7 @@ obj-y := filemap.o mempool.o oom_kill.
38049 mm_init.o mmu_context.o percpu.o slab_common.o \
38050 compaction.o vmacache.o swap_slots.o \
38051 interval_tree.o list_lru.o workingset.o \
38052- debug.o $(mmu-y)
38053+ prfile.o debug.o $(mmu-y)
5527c038 38054
0b1ff5c3 38055 obj-y += init-mm.o
cfa908e9 38056
0b1ff5c3
JR
38057diff -urNp -x '*.orig' linux-4.14/mm/filemap.c linux-4.14/mm/filemap.c
38058--- linux-4.14/mm/filemap.c 2021-02-24 21:42:35.564465229 +0100
38059+++ linux-4.14/mm/filemap.c 2021-02-24 21:42:43.434448095 +0100
38060@@ -2612,7 +2612,7 @@ int filemap_page_mkwrite(struct vm_fault
38061 int ret = VM_FAULT_LOCKED;
5527c038 38062
0b1ff5c3
JR
38063 sb_start_pagefault(inode->i_sb);
38064- file_update_time(vmf->vma->vm_file);
38065+ vma_file_update_time(vmf->vma);
38066 lock_page(page);
38067 if (page->mapping != inode->i_mapping) {
38068 unlock_page(page);
38069diff -urNp -x '*.orig' linux-4.14/mm/mmap.c linux-4.14/mm/mmap.c
38070--- linux-4.14/mm/mmap.c 2021-02-24 21:42:35.567798554 +0100
38071+++ linux-4.14/mm/mmap.c 2021-02-24 21:42:43.434448095 +0100
38072@@ -166,7 +166,7 @@ static struct vm_area_struct *remove_vma
38073 if (vma->vm_ops && vma->vm_ops->close)
38074 vma->vm_ops->close(vma);
38075 if (vma->vm_file)
38076- fput(vma->vm_file);
38077+ vma_fput(vma);
38078 mpol_put(vma_policy(vma));
38079 kmem_cache_free(vm_area_cachep, vma);
38080 return next;
38081@@ -891,7 +891,7 @@ again:
38082 if (remove_next) {
38083 if (file) {
38084 uprobe_munmap(next, next->vm_start, next->vm_end);
38085- fput(file);
38086+ vma_fput(vma);
38087 }
38088 if (next->anon_vma)
38089 anon_vma_merge(vma, next);
38090@@ -1773,8 +1773,8 @@ out:
38091 return addr;
5527c038 38092
0b1ff5c3
JR
38093 unmap_and_free_vma:
38094+ vma_fput(vma);
38095 vma->vm_file = NULL;
38096- fput(file);
5527c038 38097
0b1ff5c3
JR
38098 /* Undo any partial mapping done by a device driver. */
38099 unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end);
38100@@ -2603,7 +2603,7 @@ int __split_vma(struct mm_struct *mm, st
38101 goto out_free_mpol;
5527c038 38102
0b1ff5c3
JR
38103 if (new->vm_file)
38104- get_file(new->vm_file);
38105+ vma_get_file(new);
5527c038 38106
0b1ff5c3
JR
38107 if (new->vm_ops && new->vm_ops->open)
38108 new->vm_ops->open(new);
38109@@ -2622,7 +2622,7 @@ int __split_vma(struct mm_struct *mm, st
38110 if (new->vm_ops && new->vm_ops->close)
38111 new->vm_ops->close(new);
38112 if (new->vm_file)
38113- fput(new->vm_file);
38114+ vma_fput(new);
38115 unlink_anon_vmas(new);
38116 out_free_mpol:
38117 mpol_put(vma_policy(new));
38118@@ -2784,7 +2784,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsign
38119 struct vm_area_struct *vma;
38120 unsigned long populate = 0;
38121 unsigned long ret = -EINVAL;
38122- struct file *file;
38123+ struct file *file, *prfile;
5527c038 38124
0b1ff5c3
JR
38125 pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.txt.\n",
38126 current->comm, current->pid);
38127@@ -2859,10 +2859,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsign
38128 }
38129 }
38130
38131- file = get_file(vma->vm_file);
38132+ vma_get_file(vma);
38133+ file = vma->vm_file;
38134+ prfile = vma->vm_prfile;
38135 ret = do_mmap_pgoff(vma->vm_file, start, size,
38136 prot, flags, pgoff, &populate, NULL);
38137+ if (!IS_ERR_VALUE(ret) && file && prfile) {
38138+ struct vm_area_struct *new_vma;
38139+
38140+ new_vma = find_vma(mm, ret);
38141+ if (!new_vma->vm_prfile)
38142+ new_vma->vm_prfile = prfile;
38143+ if (new_vma != vma)
38144+ get_file(prfile);
38145+ }
38146+ /*
38147+ * two fput()s instead of vma_fput(vma),
38148+ * coz vma may not be available anymore.
38149+ */
5527c038 38150 fput(file);
0b1ff5c3
JR
38151+ if (prfile)
38152+ fput(prfile);
38153 out:
38154 up_write(&mm->mmap_sem);
38155 if (populate)
38156@@ -3174,7 +3191,7 @@ struct vm_area_struct *copy_vma(struct v
38157 if (anon_vma_clone(new_vma, vma))
38158 goto out_free_mempol;
38159 if (new_vma->vm_file)
38160- get_file(new_vma->vm_file);
38161+ vma_get_file(new_vma);
38162 if (new_vma->vm_ops && new_vma->vm_ops->open)
38163 new_vma->vm_ops->open(new_vma);
38164 vma_link(mm, new_vma, prev, rb_link, rb_parent);
38165diff -urNp -x '*.orig' linux-4.14/mm/nommu.c linux-4.14/mm/nommu.c
38166--- linux-4.14/mm/nommu.c 2021-02-24 21:42:35.567798554 +0100
38167+++ linux-4.14/mm/nommu.c 2021-02-24 21:42:43.434448095 +0100
38168@@ -645,7 +645,7 @@ static void __put_nommu_region(struct vm
38169 up_write(&nommu_region_sem);
5527c038 38170
0b1ff5c3
JR
38171 if (region->vm_file)
38172- fput(region->vm_file);
38173+ vmr_fput(region);
5527c038 38174
0b1ff5c3
JR
38175 /* IO memory and memory shared directly out of the pagecache
38176 * from ramfs/tmpfs mustn't be released here */
38177@@ -803,7 +803,7 @@ static void delete_vma(struct mm_struct
38178 if (vma->vm_ops && vma->vm_ops->close)
38179 vma->vm_ops->close(vma);
38180 if (vma->vm_file)
38181- fput(vma->vm_file);
38182+ vma_fput(vma);
38183 put_nommu_region(vma->vm_region);
38184 kmem_cache_free(vm_area_cachep, vma);
5527c038 38185 }
0b1ff5c3
JR
38186@@ -1325,7 +1325,7 @@ unsigned long do_mmap(struct file *file,
38187 goto error_just_free;
38188 }
38189 }
38190- fput(region->vm_file);
38191+ vmr_fput(region);
38192 kmem_cache_free(vm_region_jar, region);
38193 region = pregion;
38194 result = start;
38195@@ -1400,10 +1400,10 @@ error_just_free:
38196 up_write(&nommu_region_sem);
38197 error:
38198 if (region->vm_file)
38199- fput(region->vm_file);
38200+ vmr_fput(region);
38201 kmem_cache_free(vm_region_jar, region);
38202 if (vma->vm_file)
38203- fput(vma->vm_file);
38204+ vma_fput(vma);
38205 kmem_cache_free(vm_area_cachep, vma);
38206 return ret;
5527c038 38207
0b1ff5c3
JR
38208diff -urNp -x '*.orig' linux-4.14/mm/prfile.c linux-4.14/mm/prfile.c
38209--- linux-4.14/mm/prfile.c 1970-01-01 01:00:00.000000000 +0100
38210+++ linux-4.14/mm/prfile.c 2021-02-24 21:42:43.434448095 +0100
38211@@ -0,0 +1,85 @@
38212+/*
38213+ * Mainly for aufs which mmap(2) different file and wants to print different
38214+ * path in /proc/PID/maps.
38215+ * Call these functions via macros defined in linux/mm.h.
38216+ *
38217+ * See Documentation/filesystems/aufs/design/06mmap.txt
38218+ *
38219+ * Copyright (c) 2014-2017 Junjro R. Okajima
38220+ * Copyright (c) 2014 Ian Campbell
38221+ */
5527c038 38222+
0b1ff5c3
JR
38223+#include <linux/mm.h>
38224+#include <linux/file.h>
38225+#include <linux/fs.h>
5527c038 38226+
0b1ff5c3
JR
38227+/* #define PRFILE_TRACE */
38228+static inline void prfile_trace(struct file *f, struct file *pr,
38229+ const char func[], int line, const char func2[])
38230+{
38231+#ifdef PRFILE_TRACE
38232+ if (pr)
38233+ pr_info("%s:%d: %s, %pD2\n", func, line, func2, f);
38234+#endif
38235+}
5527c038 38236+
0b1ff5c3
JR
38237+void vma_do_file_update_time(struct vm_area_struct *vma, const char func[],
38238+ int line)
5527c038 38239+{
0b1ff5c3 38240+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
5527c038 38241+
0b1ff5c3
JR
38242+ prfile_trace(f, pr, func, line, __func__);
38243+ file_update_time(f);
38244+ if (f && pr)
38245+ file_update_time(pr);
5527c038 38246+}
5527c038 38247+
0b1ff5c3
JR
38248+struct file *vma_do_pr_or_file(struct vm_area_struct *vma, const char func[],
38249+ int line)
38250+{
38251+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
5527c038 38252+
0b1ff5c3
JR
38253+ prfile_trace(f, pr, func, line, __func__);
38254+ return (f && pr) ? pr : f;
38255+}
5527c038 38256+
0b1ff5c3
JR
38257+void vma_do_get_file(struct vm_area_struct *vma, const char func[], int line)
38258+{
38259+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
38260+
38261+ prfile_trace(f, pr, func, line, __func__);
38262+ get_file(f);
38263+ if (f && pr)
38264+ get_file(pr);
38265+}
38266+
38267+void vma_do_fput(struct vm_area_struct *vma, const char func[], int line)
38268+{
38269+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
38270+
38271+ prfile_trace(f, pr, func, line, __func__);
38272+ fput(f);
38273+ if (f && pr)
38274+ fput(pr);
38275+}
38276+
38277+#ifndef CONFIG_MMU
38278+struct file *vmr_do_pr_or_file(struct vm_region *region, const char func[],
38279+ int line)
38280+{
38281+ struct file *f = region->vm_file, *pr = region->vm_prfile;
38282+
38283+ prfile_trace(f, pr, func, line, __func__);
38284+ return (f && pr) ? pr : f;
38285+}
38286+
38287+void vmr_do_fput(struct vm_region *region, const char func[], int line)
38288+{
38289+ struct file *f = region->vm_file, *pr = region->vm_prfile;
38290+
38291+ prfile_trace(f, pr, func, line, __func__);
38292+ fput(f);
38293+ if (f && pr)
38294+ fput(pr);
38295+}
38296+#endif /* !CONFIG_MMU */
38297diff -urNp -x '*.orig' linux-4.14/security/commoncap.c linux-4.14/security/commoncap.c
38298--- linux-4.14/security/commoncap.c 2021-02-24 21:42:35.641131710 +0100
38299+++ linux-4.14/security/commoncap.c 2021-02-24 21:42:43.437781422 +0100
38300@@ -1270,12 +1270,14 @@ int cap_mmap_addr(unsigned long addr)
38301 }
38302 return ret;
38303 }
38304+EXPORT_SYMBOL_GPL(cap_mmap_addr);
5527c038 38305
0b1ff5c3
JR
38306 int cap_mmap_file(struct file *file, unsigned long reqprot,
38307 unsigned long prot, unsigned long flags)
38308 {
38309 return 0;
38310 }
38311+EXPORT_SYMBOL_GPL(cap_mmap_file);
5527c038 38312
0b1ff5c3 38313 #ifdef CONFIG_SECURITY
5527c038 38314
0b1ff5c3
JR
38315diff -urNp -x '*.orig' linux-4.14/security/device_cgroup.c linux-4.14/security/device_cgroup.c
38316--- linux-4.14/security/device_cgroup.c 2021-02-24 21:42:35.641131710 +0100
38317+++ linux-4.14/security/device_cgroup.c 2021-02-24 21:42:43.437781422 +0100
38318@@ -8,6 +8,7 @@
38319 #include <linux/device_cgroup.h>
38320 #include <linux/cgroup.h>
38321 #include <linux/ctype.h>
38322+#include <linux/export.h>
38323 #include <linux/list.h>
38324 #include <linux/uaccess.h>
38325 #include <linux/seq_file.h>
38326@@ -850,6 +851,7 @@ int __devcgroup_inode_permission(struct
38327 return __devcgroup_check_permission(type, imajor(inode), iminor(inode),
38328 access);
38329 }
38330+EXPORT_SYMBOL_GPL(__devcgroup_inode_permission);
38331
38332 int devcgroup_inode_mknod(int mode, dev_t dev)
38333 {
38334diff -urNp -x '*.orig' linux-4.14/security/security.c linux-4.14/security/security.c
38335--- linux-4.14/security/security.c 2021-02-24 21:42:35.641131710 +0100
38336+++ linux-4.14/security/security.c 2021-02-24 21:42:43.437781422 +0100
38337@@ -532,6 +532,7 @@ int security_path_rmdir(const struct pat
38338 return 0;
38339 return call_int_hook(path_rmdir, 0, dir, dentry);
38340 }
38341+EXPORT_SYMBOL_GPL(security_path_rmdir);
38342
38343 int security_path_unlink(const struct path *dir, struct dentry *dentry)
38344 {
38345@@ -548,6 +549,7 @@ int security_path_symlink(const struct p
38346 return 0;
38347 return call_int_hook(path_symlink, 0, dir, dentry, old_name);
38348 }
38349+EXPORT_SYMBOL_GPL(security_path_symlink);
38350
38351 int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
38352 struct dentry *new_dentry)
38353@@ -556,6 +558,7 @@ int security_path_link(struct dentry *ol
38354 return 0;
38355 return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
38356 }
38357+EXPORT_SYMBOL_GPL(security_path_link);
38358
38359 int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
38360 const struct path *new_dir, struct dentry *new_dentry,
38361@@ -583,6 +586,7 @@ int security_path_truncate(const struct
38362 return 0;
38363 return call_int_hook(path_truncate, 0, path);
38364 }
38365+EXPORT_SYMBOL_GPL(security_path_truncate);
38366
38367 int security_path_chmod(const struct path *path, umode_t mode)
38368 {
38369@@ -590,6 +594,7 @@ int security_path_chmod(const struct pat
38370 return 0;
38371 return call_int_hook(path_chmod, 0, path, mode);
38372 }
38373+EXPORT_SYMBOL_GPL(security_path_chmod);
38374
38375 int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
38376 {
38377@@ -597,6 +602,7 @@ int security_path_chown(const struct pat
38378 return 0;
38379 return call_int_hook(path_chown, 0, path, uid, gid);
38380 }
38381+EXPORT_SYMBOL_GPL(security_path_chown);
38382
38383 int security_path_chroot(const struct path *path)
38384 {
38385@@ -682,6 +688,7 @@ int security_inode_readlink(struct dentr
38386 return 0;
38387 return call_int_hook(inode_readlink, 0, dentry);
38388 }
38389+EXPORT_SYMBOL_GPL(security_inode_readlink);
38390
38391 int security_inode_follow_link(struct dentry *dentry, struct inode *inode,
38392 bool rcu)
38393@@ -697,6 +704,7 @@ int security_inode_permission(struct ino
38394 return 0;
38395 return call_int_hook(inode_permission, 0, inode, mask);
38396 }
38397+EXPORT_SYMBOL_GPL(security_inode_permission);
38398
38399 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
38400 {
38401@@ -868,6 +876,7 @@ int security_file_permission(struct file
38402
38403 return fsnotify_perm(file, mask);
38404 }
38405+EXPORT_SYMBOL_GPL(security_file_permission);
38406
38407 int security_file_alloc(struct file *file)
38408 {
38409@@ -927,6 +936,7 @@ int security_mmap_file(struct file *file
38410 return ret;
38411 return ima_file_mmap(file, prot);
38412 }
38413+EXPORT_SYMBOL_GPL(security_mmap_file);
38414
38415 int security_mmap_addr(unsigned long addr)
38416 {
This page took 8.373267 seconds and 4 git commands to generate.